diff -Nru libqalculate-3.6.0/ChangeLog libqalculate-3.7.0/ChangeLog --- libqalculate-3.6.0/ChangeLog 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/ChangeLog 2020-01-21 22:54:40.000000000 +0000 @@ -1,3 +1,97 @@ +2019-01-16 Hanna Knutsson + + * Fix sign of real part when multiplying complex number by infinity + +2019-01-15 Hanna Knutsson + + * Fix segfault when simplifying sin((infinity-i)+(-infinity+i)) and similar + +2019-01-11 Hanna Knutsson + + * Rename IdentityFunction class to avoid crash in Cantor because of conflict with Poppler library class with same name + +2019-01-07 Hanna Knutsson + + * Fix integral of asin(x)^-2 + * Fix integral of a^(b+cx)/x (where a<0) + * Fix integrate(1/(a+b*i*x^(1/3)),c,0) + +2019-01-06 Hanna Knutsson + + * Retrieve exchange rate for BYN (Belarusian ruble) from nbrb.by + +2019-01-04 Hanna Knutsson + + * Fix segfault when solving sqrt(x)!=-1 and similar + +2019-12-30 Hanna Knutsson + + * (-x)^a*x^b=-(-x)^(a+b) if b is odd + * tan((2n+1)*pi/2) might be either plus or minus infinity for each n (let function fail) + +2019-12-27 Hanna Knutsson + + * Add base units (or local currency) to expression when "to"-expression specifies unit conversion and original expression does not include any units + +2019-12-20 Hanna Knutsson + + * Fix display of factorized 5/7234234234*x+5/9234234*y and similar (a(bx+y) where a and/or b are rational number displayed approximately) + * Fix cosh(x)^2+sinh(x)^2 + +2019-12-14 Hanna Knutsson + + * bernoulli() function (number or polynomial) + * Support second argument in zeta() for Hurwitz zeta + * Exact values in zeta() for negative integers and even integers + +2019-12-11 Hanna Knutsson + + * Improved interval handling in besselj() and bessely(), and in gamma(), zeta(), and airy() when argument is negative + +2019-12-10 Hanna Knutsson + + * Fix never ending loop in isolate x with interval() containing interval + * Improvements for x^(ax)=b + * Simplify output of sin(x)=a and cos(x)=a, when a=0 or a=1 + +2019-12-08 Hanna Knutsson + + * Fixes and improvements for lambertw(x)=a + * Support complex arguments with non-zero imaginary and real parts in Si(), Ci(), Shi(), and Chi() + +2019-12-04 Hanna Knutsson + + * Split up big source files + +2019-12-03 Hanna Knutsson + + * Support complex numbers in Ei() (and li()) + * Extend supported arguments for Li() + * zeta() for all reals + +2019-12-02 Hanna Knutsson + + * Support complex numbers in erf(), erfi(), and erfc() + * Integrals of fresnelc() and fresnels() + * Integrals of 1/sin(ax)^n and 1/cos(ax)^n where n>2 + * Improved handling of angle arguments + +2019-11-30 Hanna Knutsson + + * Imaginary error function + * Fresnel integrals S and C + * Add id property to ExpressionItem to remove the need to add a variable for each new math function to Calculator class + +2019-11-29 Hanna Knutsson + + * Support for calculation of Lambert W for all branches and complex numbers + +2019-11-27 Hanna Knutsson + + * Integral of a^(b*x)*c^(-d*x^2) + * Improve handling of definite integrals with abs() + * Fix definite integral for ln(abs(ax^b+c)) where and ax^b+b=0 and a*x^b is not an integer for lower or upper limit of x (0*infinity in result) + 2019-11-24 Hanna Knutsson * Innumerous integration enhancements and fixes diff -Nru libqalculate-3.6.0/configure.ac libqalculate-3.7.0/configure.ac --- libqalculate-3.6.0/configure.ac 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/configure.ac 2020-01-21 22:54:43.000000000 +0000 @@ -6,7 +6,7 @@ dnl | initialize autotools |--------------------------------------------------- dnl ---------------------- -AC_INIT([libqalculate], [3.6.0]) +AC_INIT([libqalculate], [3.7.0]) AC_CONFIG_SRCDIR(libqalculate/Calculator.cc) AM_INIT_AUTOMAKE AM_CONFIG_HEADER(config.h) @@ -80,7 +80,7 @@ dnl libtool versioning for libqalculate dnl increment if the interface has additions, changes, removals. -QALCULATE_CURRENT=26 +QALCULATE_CURRENT=27 dnl increment any time the source changes; set to dnl 0 if you increment CURRENT @@ -89,7 +89,7 @@ dnl increment if any interfaces have been added; set to 0 dnl if any interfaces have been removed. removal has dnl precedence over adding, so set to 0 if both happened. -QALCULATE_AGE=5 +QALCULATE_AGE=6 AC_SUBST(QALCULATE_CURRENT) AC_SUBST(QALCULATE_REVISION) @@ -129,7 +129,7 @@ AC_SUBST(LIBXML_CFLAGS) AC_SUBST(LIBXML_LIBS) -AM_ICONV_LINK() +AM_ICONV() dnl -------------------------------- dnl | check for readline |----------------------------------------- @@ -247,8 +247,6 @@ dnl Please keep this in alphabetical order ALL_LINGUAS="fr nl sv zh_CN" -AM_GNU_GETTEXT(external) -AM_GNU_GETTEXT_VERSION([0.19.8]) dnl AM_GLIB_GNU_GETTEXT sets $DATADIRNAME AC_MSG_CHECKING(locale directory) diff -Nru libqalculate-3.6.0/data/currencies.xml.in libqalculate-3.7.0/data/currencies.xml.in --- libqalculate-3.6.0/data/currencies.xml.in 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/data/currencies.xml.in 2020-01-21 22:54:40.000000000 +0000 @@ -245,6 +245,11 @@ <_names>ar:BBD <_countries>Barbados + + <_title>Belarusian Ruble + <_names>ar:BYN + <_countries>Belarus + <_title>Belarusian Ruble p. (obsolete) <_names>ar:BYR diff -Nru libqalculate-3.6.0/data/eurofxref-daily.xml libqalculate-3.7.0/data/eurofxref-daily.xml --- libqalculate-3.6.0/data/eurofxref-daily.xml 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/data/eurofxref-daily.xml 2020-01-21 22:54:40.000000000 +0000 @@ -5,39 +5,39 @@ European Central Bank - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff -Nru libqalculate-3.6.0/data/functions.xml.in libqalculate-3.7.0/data/functions.xml.in --- libqalculate-3.6.0/data/functions.xml.in 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/data/functions.xml.in 2020-01-21 22:54:40.000000000 +0000 @@ -1,5 +1,5 @@ - + <_title>Matrices & Vectors @@ -683,6 +683,17 @@ <_title>2nd value + + <_title>Bernoulli Number/Polynomial + <_description>Returns the nth Bernoulli number or polynomial (if the second argument is non-zero). + <_names>r:bernoulli + + <_title>Index (n) + + + <_title>Variable + + <_title>Fibonacci Number <_names>r:fibonacci @@ -842,6 +853,10 @@ <_title>Complementary Error Function <_names>r:erfc + + <_title>Imaginary Error Function + <_names>r:erfi + <_title>Polylogarithm <_names>rc:Li,polylog @@ -878,10 +893,14 @@ <_title>Riemann Zeta + <_description>Calculates Hurwitz zeta function if the second argument is not 1. <_names>r:zeta <_title>Integral point + + <_title>Hurwitz zeta argument + <_title>Kronecker Delta @@ -2880,6 +2899,16 @@ <_names>rc:Chi,coshint <_description>The integral of cosh(x)/x. + + <_title>Fresnel Integral S + <_names>r:fresnels + <_description>The integral of sin(pi*x^2/2). + + + <_title>Fresnel Integral C + <_names>r:fresnelc + <_description>The integral of cos(pi*x^2/2). + <_title>Upper Incomplete Gamma Function <_names>r:igamma diff -Nru libqalculate-3.6.0/debian/changelog libqalculate-3.7.0/debian/changelog --- libqalculate-3.6.0/debian/changelog 2019-12-14 21:49:48.000000000 +0000 +++ libqalculate-3.7.0/debian/changelog 2020-01-21 22:54:43.000000000 +0000 @@ -1,11 +1,40 @@ -libqalculate (3.6.0-2ppa~eoan) eoan; urgency=medium +libqalculate (3.7.0-1ppa~ubuntu19.10.1) eoan; urgency=low + + * Auto build. + + -- Peter J. Mello Tue, 21 Jan 2020 22:54:43 +0000 + +libqalculate (3.7.0-1) unstable; urgency=medium + + * New upstream release: v3.7.0 + + -- Peter J. Mello Tue, 21 Jan 2020 14:45:03 -0800 + +libqalculate (3.6.0-2) unstable; urgency=medium - * New upstream release. * d/control: Drop Build-Dependency on libxml-parser-perl (Closes: #947144) * d/control: Add Build-Dependency on pkg-kde-tools for symbols files help -- Peter J. Mello Sat, 14 Dec 2019 13:49:48 -0800 +libqalculate (3.6.0-1) unstable; urgency=medium + + * New upstream release: v3.6.0 + + -- Peter J. Mello Tue, 26 Nov 2019 04:11:04 -0800 + +libqalculate (3.5.0-1) unstable; urgency=medium + + * New upstream release: v3.5.0 + + -- Peter J. Mello Thu, 24 Oct 2019 03:12:19 -0800 + +libqalculate (3.4.0-1) unstable; urgency=medium + + * New upstream release: v3.4.0 + + -- Peter J. Mello Tue, 17 Sep 2019 04:10:34 -0700 + libqalculate (3.3.0-1) unstable; urgency=medium * New upstream release diff -Nru libqalculate-3.6.0/debian/git-build-recipe.manifest libqalculate-3.7.0/debian/git-build-recipe.manifest --- libqalculate-3.6.0/debian/git-build-recipe.manifest 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/debian/git-build-recipe.manifest 2020-01-21 22:54:43.000000000 +0000 @@ -0,0 +1,3 @@ +# git-build-recipe format 0.4 deb-version {debversion}ppa +lp:~plasma-applet-qalculate/qalculate/+git/libqalculate git-commit:f53c7a88d2960bcd6165570dcce0ab0fd59120b6 +nest-part packaging lp:~plasma-applet-qalculate/qalculate/+git/libqalculate-packaging debian debian git-commit:761c9d80862034305730fbe946b8d10dae6e3e7e diff -Nru libqalculate-3.6.0/debian/patches/000-fix_autogen.patch libqalculate-3.7.0/debian/patches/000-fix_autogen.patch --- libqalculate-3.6.0/debian/patches/000-fix_autogen.patch 2019-12-14 21:49:48.000000000 +0000 +++ libqalculate-3.7.0/debian/patches/000-fix_autogen.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -Description: Fix autogen, cannot use both IT_PROG_INTLTOOL and AM_GNU_GETTEXT - Patch inspired from libpeas 1.8.1-2 -Author: Vincent Legout -Last-Updated: 2019-05-10 - ---- a/configure.ac -+++ b/configure.ac -@@ -247,8 +247,6 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GET - - dnl Please keep this in alphabetical order - ALL_LINGUAS="fr nl sv zh_CN" --AM_GNU_GETTEXT(external) --AM_GNU_GETTEXT_VERSION([0.19.8]) - - dnl AM_GLIB_GNU_GETTEXT sets $DATADIRNAME - AC_MSG_CHECKING(locale directory) ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -19,7 +19,6 @@ qalc_LDADD = \ - @LIBCURL_LIBS@ \ - @ICU_LIBS@ \ - @READLINE_LIBS@ \ -- @LTLIBINTL@ \ - @LTLIBICONV@ \ - ../libqalculate/libqalculate.la - -@@ -29,7 +28,6 @@ defs2doc_LDADD = \ - @LIBXML_LIBS@ \ - @LIBCURL_LIBS@ \ - @ICU_LIBS@ \ -- @LTLIBINTL@ \ - @LTLIBICONV@ \ - ../libqalculate/libqalculate.la - -@@ -39,7 +37,6 @@ test_LDADD = \ - @LIBXML_LIBS@ \ - @LIBCURL_LIBS@ \ - @ICU_LIBS@ \ -- @LTLIBINTL@ \ - @LTLIBICONV@ \ - ../libqalculate/libqalculate.la - ---- a/libqalculate/Makefile.am -+++ b/libqalculate/Makefile.am -@@ -22,7 +22,7 @@ libqalculateinclude_HEADERS = \ - libqalculate_la_LDFLAGS = -version-info $(QALCULATE_CURRENT):$(QALCULATE_REVISION):$(QALCULATE_AGE) -no-undefined - - libqalculate_la_LIBADD = \ -- @LIBCURL_LIBS@ @LIBXML_LIBS@ @ICU_LIBS@ @LTLIBINTL@ @LTLIBICONV@ -+ @LIBCURL_LIBS@ @LIBXML_LIBS@ @ICU_LIBS@ @LTLIBICONV@ - - AM_CPPFLAGS = \ - -I$(top_srcdir) \ diff -Nru libqalculate-3.6.0/debian/patches/series libqalculate-3.7.0/debian/patches/series --- libqalculate-3.6.0/debian/patches/series 2019-12-14 21:49:48.000000000 +0000 +++ libqalculate-3.7.0/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -000-fix_autogen.patch diff -Nru libqalculate-3.6.0/debian/source/format libqalculate-3.7.0/debian/source/format --- libqalculate-3.6.0/debian/source/format 2019-12-14 21:49:48.000000000 +0000 +++ libqalculate-3.7.0/debian/source/format 2020-01-21 22:54:43.000000000 +0000 @@ -1 +1 @@ -3.0 (quilt) +3.0 (native) diff -Nru libqalculate-3.6.0/docs/reference/Doxyfile libqalculate-3.7.0/docs/reference/Doxyfile --- libqalculate-3.6.0/docs/reference/Doxyfile 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/docs/reference/Doxyfile 2020-01-21 22:54:40.000000000 +0000 @@ -32,7 +32,7 @@ # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = libqalculate-3.6.0 +PROJECT_NAME = libqalculate-3.7.0 # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version @@ -859,7 +859,7 @@ # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = ../../libqalculate/BuiltinFunctions.h +EXCLUDE = ../../libqalculate/BuiltinFunctions.h, ../../libqalculate/Calculator_p.h, ../../libqalculate/MathStructure-support.h # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded @@ -875,7 +875,7 @@ # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the diff -Nru libqalculate-3.6.0/.gitignore libqalculate-3.7.0/.gitignore --- libqalculate-3.6.0/.gitignore 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/.gitignore 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -*.lo -*.o -*.la -Makefile -Makefile.in -*~ -data/*.xml -*.gmo -config.* -.kdev4 -aclocal.m4 -autom4te* -configure -depcomp -docs/reference/html* -intltool*.in -install-sh -libqalculate.kdev4 -libqalculate.pc -libqalculate/.* -libtool -ltmain.sh -missing -mkinstalldirs -po-defs/.* -po/POTFILES -po/stamp-it -src/.* -src/qalc -stamp-h1 diff -Nru libqalculate-3.6.0/libqalculate/bernoulli_numbers.h libqalculate-3.7.0/libqalculate/bernoulli_numbers.h --- libqalculate-3.6.0/libqalculate/bernoulli_numbers.h 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/bernoulli_numbers.h 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,261 @@ +#ifndef BERNOULLI_NUMBERS_H +#define BERNOULLI_NUMBERS_H + +/* Numerators and denominators of even Bernoulli numbers 2-498 + from "The First 498 Bernoulli Numbers" by Simon Plouffe (http://www.gutenberg.org/ebooks/2586) +*/ + +static const char *bernoulli_numbers[] = { +"1","6", +"-1","30", +"1","42", +"-1","30", +"5","66", +"-691","2730", +"7","6", +"-3617","510", +"43867","798", +"-174611","330", +"854513","138", +"-236364091","2730", +"8553103","6", +"-23749461029","870", +"8615841276005","14322", +"-7709321041217","510", +"2577687858367","6", +"-26315271553053477373","1919190", +"2929993913841559","6", +"-261082718496449122051","13530", +"1520097643918070802691","1806", +"-27833269579301024235023","690", +"596451111593912163277961","282", +"-5609403368997817686249127547","46410", +"495057205241079648212477525","66", +"-801165718135489957347924991853","1590", +"29149963634884862421418123812691","798", +"-2479392929313226753685415739663229","870", +"84483613348880041862046775994036021","354", +"-1215233140483755572040304994079820246041491","56786730", +"12300585434086858541953039857403386151","6", +"-106783830147866529886385444979142647942017","510", +"1472600022126335654051619428551932342241899101","64722", +"-78773130858718728141909149208474606244347001","30", +"1505381347333367003803076567377857208511438160235","4686", +"-5827954961669944110438277244641067365282488301844260429","140100870", +"34152417289221168014330073731472635186688307783087","6", +"-24655088825935372707687196040585199904365267828865801","30", +"414846365575400828295179035549542073492199375372400483487","3318", +"-4603784299479457646935574969019046849794257872751288919656867","230010", +"1677014149185145836823154509786269900207736027570253414881613","498", +"-2024576195935290360231131160111731009989917391198090877281083932477","3404310", +"660714619417678653573847847426261496277830686653388931761996983","6", +"-1311426488674017507995511424019311843345750275572028644296919890574047","61410", +"1179057279021082799884123351249215083775254949669647116231545215727922535","272118", +"-1295585948207537527989427828538576749659341483719435143023316326829946247","1410", +"1220813806579744469607301679413201203958508415202696621436215105284649447","6", +"-211600449597266513097597728109824233673043954389060234150638733420050668349987259","4501770", +"67908260672905495624051117546403605607342195728504487509073961249992947058239","6", +"-94598037819122125295227433069493721872702841533066936133385696204311395415197247711","33330", +"3204019410860907078243020782116241775491817197152717450679002501086861530836678158791","4326", +"-319533631363830011287103352796174274671189606078272738327103470162849568365549721224053","1590", +"36373903172617414408151820151593427169231298640581690038930816378281879873386202346572901","642", +"-3469342247847828789552088659323852541399766785760491146870005891371501266319724897592306597338057","209191710", +"7645992940484742892248134246724347500528752413412307906683593870759797606269585779977930217515","1518", +"-2650879602155099713352597214685162014443151499192509896451788427680966756514875515366781203552600109","1671270", +"21737832319369163333310761086652991475721156679090831360806110114933605484234593650904188618562649","42", +"-309553916571842976912513458033841416869004128064329844245504045721008957524571968271388199595754752259","1770", +"366963119969713111534947151585585006684606361080699204301059440676414485045806461889371776354517095799","6", +"-51507486535079109061843996857849983274095170353262675213092869167199297474922985358811329367077682677803282070131","2328255930", +"49633666079262581912532637475990757438722790311060139770309311793150683214100431329033113678098037968564431","6", +"-95876775334247128750774903107542444620578830013297336819553512729358593354435944413631943610268472689094609001","30", +"5556330281949274850616324408918951380525567307126747246796782304333594286400508981287241419934529638692081513802696639","4357878", +"-267754707742548082886954405585282394779291459592551740629978686063357792734863530145362663093519862048495908453718017","510", +"1928215175136130915645299522271596435307611010164728458783733020528548622403504078595174411693893882739334735142562418015","8646", +"-410951945846993378209020486523571938123258077870477502433469747962650070754704863812646392801863686694106805747335370312946831","4206930", +"264590171870717725633635737248879015151254525593168688411918554840667765591690540727987316391252434348664694639349484190167","6", +"-84290226343367405131287578060366193649336612397547435767189206912230442242628212786558235455817749737691517685781164837036649737","4110", +"2694866548990880936043851683724113040849078494664282483862150893060478501559546243423633375693325757795709438325907154973590288136429","274386", +"-3289490986435898803930699548851884006880537476931130981307467085162504802973618096693859598125274741604181467826651144393874696601946049","679470", +"14731853280888589565870080442453214239804217023990642676194878997407546061581643106569966189211748270209483494554402556608073385149191","6", +"-3050244698373607565035155836901726357405007104256566761884191852434851033744761276392695669329626855965183503295793517411526056244431024612640493","2381714790", +"4120570026280114871526113315907864026165545608808541153973817680034790262683524284855810008621905238290240143481403022987037271683989824863","6", +"-1691737145614018979865561095112166189607682852147301400816480675916957871178648433284821493606361235973346584667336181793937950344828557898347149","4470", +"463365579389162741443284425811806264982233725425295799852299807325379315501572305760030594769688296308375193913787703707693010224101613904227979066275","2162622", +"-3737018141155108502105892888491282165837489531488932951768507127182409731328472084456653639812530140212355374618917309552824925858430886313795805601","30", +"10259718682038021051027794238379184461025738652460569233992776489750881337506863808448685054322627708245455888249006715516690124228801409697850408284121","138", +"-81718086083262628510756459753673452313595710396116467582152090596092548699138346942995509488284650803976836337164670494733866559829768848363506624334818961419869","1794590070", +"171672676901153210072183083506103395137513922274029564150500135265308148197358551999205867870374013289728260984269623579880772408522396975250682773558018919","6", +"-4240860794203310376065563492361156949989398087086373214710625778458441940477839981850928830420029285687066701804645453159767402961229305942765784122421197736180867","230010", +"1584451495144416428390934243279426140836596476080786316960222380784239380974799880364363647978168634590418215854419793716549388865905348534375629928732008786233507729","130074", +"-20538064609143216265571979586692646837805331023148645068133372383930344948316600591203926388540940814833173322793804325084945094828524860626092013547281335356200073083","2490", +"5734032969370860921631095311392645731505222358555208498573088911303001784652122964703205752709194193095246308611264121678834250704468082648313788124754168671815815821441","1002", +"-13844828515176396081238346585063517228531109156984345249260453934317772754836791258987516540324983611569758649525983347408589045734176589270143058509026392246407576578281097477","3404310", +"195334207626637530414976779238462234481410337350988427215139995707346979124686918267688171536352650572535330369818176979951931477427594872783018749894699157917782460035894085","66", +"-11443702211333328447187179942991846613008046506032421731755258148665287832264931024781365962633301701773088470841621804328201008020129996955549467573217659587609679405537739509973","5190", +"4166161554662042831884959593250717297395614318182561412048180684077407803317591270831194619293832107482426945655143357909807251852859279483176373435697607639883085093246499347128331","2478", +"-1369347910486705707645621362512824332220360774476594348356938715366608044588614657557436131706543948464159947970464346070253278291989696390096800799614617317655510118710460076077638883999","1043970", +"1124251816617941290026484851206299982774720467712867275292043701618829826708395745459654170718363182143418314514085426692857018428614935412736063946853033094328968069656979232446257101741","1074", +"-6173136454016248924640522272263470960199559328290655337530202055853397791747341312347030141906500993752700612233695954532816018207721731818225290076670213481102834647254685911917265818955932383093313","7225713885390", +"4277269279349192541137304400628629348327468135828402291661683018622451659989595510712915810436238721139546963558655260384328988773219688091443529626531335687951612545946030357929306651006711","6", +"-857321333523056180131194437347933216431403305730705359015465649285681432317514010686029079324479659634642384809061711319481020030715989009140595170556956196762318625529645723516532076273012244047","1410", +"22258646098436968050639602221816385181596567918515338169946670500599612225742487595012775838387331550474751212260636163500086787417640903770807353228157478339547041472679880890292167353534100797481","42", +"-14158277750623758793309386870401397333112823632717478051426522029712001260747920789473711562165031101665618225654329210473605281619696918061316240634857984019071572591940586875558943580878119388321001","30", +"5411555842544259796131885546196787277987837486638756184149141588783989774511509608733429067517383750706299486822702171672522203106730993581242777825864203487238429479957280273093904025319950569633979493395","12606", +"-346465752997582699690191405750952366871923192340955593486485715370392154894102000406980162521728492501917598012711402163530166516991115122131398542029056286959857727373568402417020319761912636411646719477318166587","868841610", +"2269186825161532962833665086968359967389321429297588337232986752409765414223476696863199759981611817660735753831323900456495253961837175924312108872915089534970310604331636484174526399721365966337809334021247","6", +"-62753135110461193672553106699893713603153054153311895305590639107017824640241378480484625554578576142115835788960865534532214560982925549798683762705231316611716668749347221458005671217067357943416524984438771831113","171390", +"88527914861348004968400581010530565220544526400339548429439843908721196349579494069282285662653465989920237253162555666526385826449862863083834096823053048072002986184254693991336699593468906111158296442729034119206322233","244713882", +"-498384049428333414764928632140399662108495887457206674968055822617263669621523687568865802302210999132601412697613279391058654527145340515840099290478026350382802884371712359337984274122861159800280019110197888555893671151","1366530", +"2250525326187264545900714460628885135841050444551247116222631411681549780530233516069957534394574922579290608180427520318235621123686109474343887857944611842438698399885295153935574958275021715116120056995036417537079471","6", +"-110636644250856903590976481422794879200517231299540994715372334521128669716264196333811025709747746193210786820114369025849897345722531098042760530922656878891556664782168465095563132092311332073097630676251482491663634626858373","281190", +"2525292668891404920279427026668969389456388249389889339455604316691573384284678293620100066924361693666444722338743839198221347931651916807651198800935942493038194104759967208073711284671045255047521429204396148980705984836743","6", +"-12407390668433023412711473483696990726334795896412761472587854072142800403373577087021298541061094633377354326966623278849423631924808044397822651135905640812063181221280972334965193338438214107578486417026806166184210160001817890901","27030", +"4708181368529492614110644197951837317202610608341257204206693195241245204360822875910613010433572133227831741097261618833206537519198885812254347219150482005543422997225440204041473518187636442241332621804718967775203938403965710395632762155","9225988926", +"-1856110669947388268389361040689764027464160460436671923253131176853224087741924378432403442710398247642246902212818749685974336641529240178398124235555437625251481044526024910356131819016670047949661636539964662370375622630863327168696307","3210", +"4005748930070152861935826766476856180706477227448622268042052745245798242539770546339789899546160341590069109467023517085578618986055969187202731878271685432460708841118506310943865592568791360294244451765746911808994482063783730693703607","6", +"-11993122770108617858536443322964878003618156069559794803117809279608039120818829088000103355036592864877954563564831932363414886811786054601318517206937549605059298307895591515771731031691422489377098686236263367916404512751010916862894129855138281961","15270994830", +"5646413644023523531472659729552574911763686780871700375627426663366507837122353997075891736706811337698248660838754243486778190331522785903661556458651175061469825204821206611273990250663647381261360659950519735730925202117606150672170127523599","6", +"-8717064809960074651332043679796544474420053189621803209941154764877242575579617540185166306094852502223738126111951612525627910517501081576202264770178546608710937474005742969950212404955732473198451623024108934373488641161751158901712323446768306053","7590", +"13368053158552172665210852539359893340369870651951497976111882891296650008003955172160792457229376320993686817755409436399268291095350295968657381088168219133490277914269064723832062615431730061224649980566693258603099340996988542301914519271322675688591","9366", +"-3018240015081392087620978688311925380399983229633120268872695911807562982111154053235820050168829922189401964755775948260724401542319799566237745986245598102255191922935742610508280966462644022540839619861091049093129359799053781543195492373882916779852781709","1671270", +"3168221108903401670436878558215734893322849540781208738796672473984272484396317849596978630272031342024194689871467916186898192771267438982228710525079886956295106197431401217357893460897221381410667385636049264583380749631776691121592016493432807733153743581","1362", +"-1906502909997888166123201923177385833567729039151413143876271870599057704445939156075718972624235764657102074902610737729027517674632609562387841658709266014329005407533521950744449109807215808770201247724932231495252981632908042371307965561986133763291349835081839","625170", +"12620737044909818561832856090355555624016887319605261762997689571062646649745107532482632213152948299491122977690702642386377706799989565320538433072623252159464115918057294711396625436506736041542403370025258477205101808063594056759977272469883621048184279331863155","3102", +"-2277782962749544647786193093844710000584561145527861043594866852071596440076587235747852022645695523676561694856919437156369375152041285055935622032497285897151359345040171955786899011718891877065760345722163063921177723102631428767500963315657655779698470644544064472947","412410", +"480867224771001697116513683699011649496855159878152931805742068517626950204279499281932407966997815888727039144001177194783700618900740782637516562256421883686495287564849123342843286211825800198337962453448529082007644439295666002669973893196613894216505936316966183107269","63042", +"-321467133590936589398380572003196190798000628347443663674019204361034039315014370869884972981404460888272855773233080186485230316544246541168364468343631969225480324799028067015621769939718443419712110857965409179947456994970687005134042835903494172569465751671057323145801","30", +"21954828084819816230623427376391154946628510524415478471365831649487269438565442138452375719697629394886161086199009071745032148355699097673730377547354631757000924688032674454208386076360699273002129330161098228962653466112032300056534380609136268347425707537340996253935261001","1434", +"-212191008579182060478563837945461872287372869333130175188325135660897759482730035448146388858205966593247205572842356279587190846758925659038643395344396334821348861518596112373605365460921821915409949436456394757252173113308288776951844012432992719925522001911419529928297005743854184672707","9538864545210", +"4535049728315239205021018362829154800039522502549714840841943960634084990270225535043892135549408608572877513963384530325758104248133124392959997485849004663162061065909846598215984547677506961593292880902830325868627515047168286738527241360778218692535254144583771935549805772798793","138", +"-1480677868678810347062135814574727890490996459903153909612611791768134015908900253197632543925157559965099005581639883558125985134242978146873558628010545299879178299856929100217178891524159543673803785481607540954533057560554704283718320006046424881681934129216249889269701182688055001","30", +"262668605206102118430195944953058387315319589613263079853189811674338644589939356676047394737425651989092115424635212785341601958591806782599345416064945113338168378810138043832891536358769753916174695061208903056552776976154338169779827414504134808495078925108569042616724875466536400029203","3486", +"-3507445546375253318342667741949651253516986113349672180095468758145505921133172244240023419466113277413785800736682458966212429373095894934752041434119711352215164597094886530278429206637066302031501412499166263642447542289785723225064437740655097573160922291075175522551466276032634749948001","30", +"3053985414762198703102020975667535181880294373982570358384262712216099013630127381226064671248970168701164841859177635139561220373102316273710980757409295039231697360536736113380473515993580188204966808323201772081668695321316425977503713933894934399351348240918411922863059423248058823372368106375","16566", +"-89774288871630307843644520580598652632613559409413344033893019938898862113876440183943307724290509165539815764354254584162176909463971675189351699717189454959415964995262823025743004001915975128242680213612581748367743077774468104545056300803334120339537905702856877606246855867891786763741486735368783092237","303940201110", +"2884759276650094186013272224259584433367802183845217969121665253431996536437413850716488026971480747022580182931940812035472752343853999483816456012957551120812115224018480617695398681102870535795278832047330709610952952566962354787854087985127629191094880078635434933391568643930279007460403102076327","6", +"-104203435297641800915507592803138769896333127491490532929531166632958450572751929026080533456531382568746630428805839898606131705503722712567379172835813497582706763790263297372586804372654090271412733654409742029405259156130663560412599913831518338400385290760913773448329773518728092595019422753511174189569","131070", +"56081693586889462275051589447484617682656486262465693822181172785524218338951641908717980184709547885060218908068568000776767834360070429300833879662707069272458173745883316346369196270761641325176838738153606175963665383216626724969370509650128327157862121275587666040290047452303859942885949047756404247033","42", +"-5218507479961513801890596392421261361036935624312258325065379143295948300812040703848766095836974598734762472300638625802884257082786883956679824964010841565051175167717451747328911935282639583972372470105587187736495055501208701522099921363239317373617854217050435670713936357978555246779460902210809009009539232173","2291190", +"6225500408881102797510043328034969466304425964851480796588968345345616249056035479080489691323529597769377127237910326626106353639640430862662758276037155818313797361926063056784629357346246050085674910484712331211955483400507386944492614175497512823803191508029088188458205305675244351279445756172428826335261196513","1578", +"-2597900408162896058710572658949818524468219266931291835479959418094890120803707468900281325124704535527442908101022615930505212028093980003061941163493997948367473301269937152541190254678821414979800759785215240308773060568770563333752614741579673909061322574414039421772773951907381124389083123642187877106727324831409104559","374416770", +"74333782054653889423743469213152655799143173104421681719953140280099539295673341397636592724713785397334372991707306538931885461890982390991361955644690371434518008626267056713898856350449471518770634624568188698734199687848634136577815884007651660546155376602651878199847336975669075705029220024942988801596540479832623","6", +"-181215287752963297591649028858266281596159320543301504003425598637697061538040522696126018237983659329700516696739148841351912957174525785315414144429136591554131215700560325949733256954674813149699783016318415338094395743152932542723256830883071638325957369194991055197776850603497527503600109515880553950890416293966947553269","8070", +"3046520935696995573515824242272701117754774305790084108344788704634810391537752246673386049133783821395486096239148415641722199623177956366799133314531041402021345562799254459886856571341036470447536143349353694309187363616222605848012490292828963830868021774140963898080446961958927794750526681977409210580806334902707423302910890705","73743978", +"-5389479287019828859012200442343326192355509012382167997444221939499202340581932428533725140323939479047999949436682248001244967154707104896269136682582392582110484972339408510822230035412430172890925658230152084954903826143390588854318458185729506889417244891371385482660658834892925089584501833253476537744400283864408173645832802729","69870", +"876921640102601760383168273082801324788039055564836901409234298002253995782034121007322766508391364331313364222035613918206397636790569250311165509441010945170696883786500399759308075144882184008248023432975450281978336106603716700929424210717924897570827498252893067062775490058563356806930680935200945326351681714440032862515566687","6", +"-1388182772753480224524259543538426023294781120119840766760993950456297256537536762358314128425435909635398077811882539199662711471185655335807263675649242817349083277475519035786895107126764049407549359856712249235123586468592541328115099760851178135792262280438168965402774928136789551166963401124472782522202058296880872854126156007513528607131","4940319930", +"3288574272791325983707258196648395370596305758341699742238893225440550539879910098002426164478935667759666907669638986616709137799200377160559516125812795457124992507785560266265469172399329113247421069765604730822849303184464007727659407021486798188927253139176046166778181472669994161900278671855691024038916704559966546186751742476372279","6", +"-8490228242595311199119920565849009760217791023572798918266374350550246366225435144540895862924269878096526376888988896473279190955432566511173411205746712397692187887537779437718173050158951105924254322875775498449791436769311967741327489636985694874281460516082075289295724305512800386456299241907049270636679469815489106102786158831873003971980149529","7828173870", +"25875593499348128833220857256544133843109199942629172661571575831896009002717379314993110538912888759932261638883397790531299585084426973156913779915781848556311555818927755071422637872741239146696501724664788565419251002500248036396312656297993421996811407029386847063439782311617981818206546311041142991312322619717261878315979033851316268092742291","11886", +"-132959963583526612558423182997702578242047892089625754241387587021938995020766563989990185987109982064786136276402406795608981540644133005568845598733701027267134930895872207756078937107416605123323092749911180763524271940975157312568091937739185681066178901105822385739566191012805835839265694429000135104051173197039224461050364993416415448157657001","30", +"1262786340764743836543650366374180273258073609841543441787781675688541881984249268360325012510167918286412665710785332495002470256724535451201518584261363284544626088778140281353574806840036456927404244048497506339393258324386379574048562781825209799628261527492591555049229691481538713081331723845462120745928641410668923052992096071568118182416749081409","138", +"-4426158122015997656918081228667589801499808940970897924307086870252646875948841652238923933674489065786806672342321537012751674084821846458685429618183214525289276658012594349154796284960120596423811831259041410965661717709958659062147534583171671141655182016580199364485449629732438469542501153689517957906763036169880300563526920600913900347892060168169080524563821","231026334630", +"158378960459933745353732673983377704622086418682000111407542005580986544145352715435649528631197645211762019722767661122078958064217177336225880988737955740461066476486097551548991955116319546315427449493825430704787375985685635337262886136570504412827663590990198163434342208367501561777230870660164068668650416176368657029205310526817730948015526849382859712055","3894", +"-769496271232217048566454403451119653773906354892060893481293713784107951847019857310739767770463076516560575249619621659718985646126964039659981825577646225301189082287264198134787013538174178383958494473734277012586809351930781277345290942985827690026019144748986116319143448962997698665018791994064217597704711709748695678908604180272686662449493086793580970828093","8790", +"344977368185637380304333898730614153996525419281986770522385915720139215554847760949870834982202303432587625997234795118134923343663265548204594792841811439303451011251437993865656175552484850145014444202587617378736472160288579064961864004275382498994164923679644150818450558302750885234058860046684381556954878962153088786251490404112306387375170114820733240249707147","1806", +"-1888575590158495996440108433926788958859450449505827069108529221911737605491094242128180304966356165162290173103044092702582217959772178183606221416867140355106476799094653551123469827906281690228047604677838808485752658196964935031379587556530427680306537879720377479310817318584744711522453387072627648438830200285728320936098194745411999104991803838665658699650727659349","4470", +"5683175611528696607080062478072501820703250802520963611339740016328084145085898175251616359343168595858108624167762131679681416977895536025003761007598913177279789271071880600643885302907670572288368816385439218707793725555126269377090645484013184046265389329719449523663221529092764894703813815177897980268745011893371899061378940560801507189664711567121796987700152153839","6", +"-1863878995204859011995045341848156066182191846635905937518715320655775958174360523134990756922303410810482600528769479642021001218415879006164302955370460829146434807964717737195356935144151583424833154250047747433575584999029126775186293388721514970183351129809976971603227633930434923843984829580311593372565398574762880028289167635570012415606941367995702212211519561707046505473575241","866054419230", +"29732914652005326308069038299046877228165947489285775398232775554326821654997284254954541436759755619186929818878962419179787160694148360451817997811323189321730570436847238527392204080083670713746104123180927363450365552833743396887002966884296848913481132785586683120732369858597153076261127975076406564459518695821788635361711463230165952857117226399909961673058570176834883271","6", +"-5896752302971586952817880137553548037522952101385717862219869597959540714708235406233632122536677446426246295692119684486036889235399687553979484886254426933587637080451003789769961323298135257953657891721726854085498886402779031921701364180427128346719739542203363106920603436185256970882544947794042043194815113693600814746189709447821507079960920412101317160689806936226622681106017","510", +"689735739192864790938869842200448522491622174065530181755219067505817267965189978776569968680399983089600630968341102178380777713630583306140103562669027424552384203113812510243331805627699809267240054344772443480095752572066698167737729190346148297831547431732607091731942172905658944645576233950351675859756367833238423434368779109181349635099892383418900862720397266277623080279813067604999","25233558", +"-1310028313878567907114692495908315703121191755911131111984360268010339291958527789632281425987720420051304810543373657881574797353695997625625576992435250954115647419075544944736054854015711074248873686155373327776946348644567049129984144807198780234107278733859628145334731952115798551768101817753443736023659080348249001450368140437083583099127029870537678245450148711191680759214684176445667","20010", +"3260606235276851195099437047707916012280054709370077715052312896011476347066426313756906147929976324639617487079038182718315850586912998681890040154101217023601746358548442139356881761209491879344448144235471024519916730280314406401197057752850694124801781598205133338269426259564611182358074475139266646779460335469700559434884540406485299632013344690352700850048935613677493364152601347478976955","20526", +"-219310221923496085124921823808404575155215719519880743817262187359846676808720933963496193287320441312135479981243085410780329920552595746251706979452929554249409283208988310305531179583355242953344731240610852110199480347842183280905881606393786883347661578747110380713468900860626627458517735797820729101052113795399477516376330508889102106163067720003973339359314302749857453315620772706780505888813811597","561706691910", +"5831963211655227469096364047000879785191356939385161602680269994879257080042651495531334620369899431331189755049833242684170073167978643108706019166324688447112227778757784415956624614457808484212568132108937476630344240535741105415692911032767001030027558118855855057952089777910853586423077582781831060554157175555095233630076901455631073919888020711465283697536929732899568769525385745975473155407","6", +"-23306762036180954707239902303733182709978468580325093149239040051634149745258544596562134540960231525935441270015799599621135682414015382311861534597843756730857227145200622246509066032795288017634942726754909458234645264430702930529842456653080378544365215066466596986953601385998432554535709196917229350478449221406496506432167664369239478872974247912601100426306339312275565475595669640092216631914518917","9510", +"28122967090195287981055019523746421026174611154606607881410834553821571195600077156388139504050817072318352135336014937133504488344591033637378875175488860842142200215544952457462251551728305545862703146471647483394138505742989863336231595764600339418866218322681285266901817977284569573044604541872422517736195703069383015638214571378546092320911382385141634160156861783095114673655212399723765743717305197851","4494", +"-3721822981147963543473628721718160389675395897437503779226807860482566691214705959016239951890193486758232537597591642279654459920857716018601998378015710967458002507660860624568924448328452560808376796224541899685756821793434321138838512925307216420554703983171171540795387100799809353390519107647717976213032752752815159815739322121041527686676774334782328158773314452206678687770745486976844581551304048486668867","230010", +"11947011202513683767723104489271471097868501873399758887514336934592822829976646702161909309680237660201998669294617552009638464244432709441651377979627696796385888263305915811924616794303093449550416640107641304231571552322204363229110497299236034396583681906657985198177302972578027688117382447661848083476283296893356637990999976607059658190271101386708876477455968880271181353449021120174672279118531405266405457","282", +"-3829393826694851442367963605345986414644123194149055126713238369521199883032584377556163984602775965899294620028160948209504229098195604243661949859717087550540749941206115020546490009175884700307199551574107407855402424207686775155726579245497021834551699678553804651177095786249593672236240744422195553711332954204942399883879329051596664648871055498926334411033125995310873151284771962309916237507813788879633942447325937291","34098248730", +"1808383072515392862130370135635372000131626793093148880779287649928820293768508592707521055628027708276165829705670838064031068574527612930799078981578676791129015219438793213734036863426110360623900757855812426023541159774905365518756692026508213803668789819570234151094586211640196633499617063941661470860479560003474875427679061750173843509685528353151826146684405535206504936136026796030365288231301797295663647612503","6", +"-2038920955732166704563544675871539298534664548832344594940419211031004686244887980129990722833481906996574995006272283772989552251711645339529824674672295721387444989765197094356625686277258759887529063884063441729464466695304817154879753936013360244814470171255312860420052459456595966677396165132301906628818307744454944935388834925108370678592735494494812411438800013100442226704887804736057100084506757161238437561170752083","2490", +"16450740261761201488286514086666341385844412580813949724000155038308870188720719658119876451207931032748030811189911338403495201879917853940007778344522354341186748832271809821828409298207968739139227014609598106703237472043228932298563800984396865943755795758369082954888437302866500408097109163018555655697695594114688192421141599313689189778427690359665256283948257291245464556741556264558183330312680675299274129472749543281530376155","7305236862", +"-31404740573139387013607323899060788461129734403267877740839079468522117216337083625061725107066347029224470970177830290797457104821060170534363148276651160571699094881049180803660482733644591278636224534484481850814754420273709821201199908209760469191567840252247706876075856090781209456764232767086688491357087469900906692342923336064928179724546370791109956974800789303951709599892246386582961297095349501749155074025993332911366367","5010", +"105959450712139358561614326750678748291627849550191512662380413294068107407247886566713525350838198788534238121678429166419664041236233803606051817627731575939553790154021616196778501189528768078400811107009317850171384096998455082824610437919969197421385189475358775596537026092374519645052975059595487888618614275545703577191947383711761849232715855501325445057452043875112980841528855594013764288125280661970576229405994478822053767","6", +"-110968358518556750910569006059104612436322304793290197896476208195051113971187304256671882613201063543710887491006989203213468862095728086421327649757926706375373160032479060881414285316805050049998250096629298691714712337731033133063244894833650574221421335477496494331790029997128928883270452912343595756835759921082499027715633187483508227173954421007445739076452215234463953952029377612275096135644427285378787750547213980148328191792731369493029","2203871994870", +"871667613876289947152259213998641324359438367113245978510277002562210922288209180150151793852558736029189876363096736208315035600167649273464678134646229708161579214485318416128870291425640987624153304026736765522468963515580422620761261195314156252082303726799452238319359220112879725078451979791840912313059346932550771416018721541922207119333620480831014488368439858212426770461809324187079997350701358985200574078187666941445255865364959","6", +"-139969199374294532188729693702577000000465664934371179035889932037927222630615161871008568258760858093560212970955512057983700284904139662988796471588843837914664871339017278834524915750717069973487760152722966363103180527139199261072959205960570607504345672675033426810959288741490491658133099197637151741354653719448795255505120643394167214213806837785207626077991226383344774422283805854628774864645574223075309564129905544107459811288704862611","330", +"999866869350557363722458479004395830847953169240152118030482972984856254139343285563059710426142001310818604300278555911104883557186325333153917124330048368249458087059040520529706556642732809436335612822769043297715578151918469336944179483860946506334004186007324467864842978559250174108263899703085692274142353761805113570952308838426945093917953996642662776561930695988488695006166233701104386823791719249365863288962981240951731129450241042813203","798", +"-19435667946412236600006355752680318177378018998686558693047046847185922842569405850478643326624807107024135785299799674685846584030230598008329461654964640062557602833521189158599030670653044302429200521250792329717629531968392422269289900710918148435060503372045597753741275339144955223007618411222546697775810780747446478661790743019087588298611993809224843559412437328287256779856482337754827908028601591041648043989896358637724179061858684905231780173","5190", +"23574815095404701575006138342677814737611117002189168884514625588124591088321558700476292561495266316421750730681754426899890383276767887403267480686627676268685966493677023072554534770488586483642062259843015737466820417963854802166458232968082382836216212063844897312505105552626378830504014452088433926239997258280111620289793360632141212087877945966075033938687737132829040482438463044913103827680386355585682702291192692673999705957317036687127526488661","2082", +"-1946958244926408519819928540035312319794025231154312283846941445533833885684884185938663359749293528922631351379885288320544746558558870084671027543542465268801245629638273090846490014696481293058172945225573249920181321736453062629022981688433233577329127459928765113606300176648832109875139888454987326886636880988465878410619882237596781152380489370724295257792104332503696582825373077048086525583941198173749084587321884232599450628448598711165788748886648206781","56213430", +"502172089109637973079905157308517324166048351810351159422375337574332573514046742139861365117790762795398322755462389540876498686325519933386024542998456467504352201616875674226702066988781736776780983675270711591178536297327588046501114273115924942240089195877277170211145955479537604561876530663522061491492548171664129861255728492613537859772665546205365872403842851465588616941966018356565181922169705164734493393477247978508055348618032704534473742084629023675","4686", +"-123595612458163473336102111542838674764831835495331502431774135351050074096606458390189947949855899933224956382090454659506523733852842909886351324966274684823091833542355636103776512914842749831251392589846063826895163366115470020631076054800071496634622909233303706997995125130120515859762839469193960001284685791277467069230539953616534532549898448827387071275667857164787765007253139087944551495091418632200084873393873944046407490699550148256008464127109223283763137247","368521410", +"44586958800126786790452414833451737276485269217604041493957832153847748776691019563443875873891685730191225792159808508144405955278309411839337401759278396174609624192685884123993968501104767184346477939067903846512439522927159649898761965816525286791728854346485686727420275292569511311545587705052888988969140031330003151200601432709893613802729701685072968681090703554561525613786761794587069881004247080811531298610122589066840923344874780872870506826198179146216889","42", +"-18249520604687390491188873019557839254274215818941916557220148305863171323999328631073000715354712349442824804877473011208435647924577393976121564194070391790525169749128982828132077146902780721841387850162775862442199934474879939605150425883830706636702361084052335568869843628198626221242494076538767614229186803516353130263179834649242288787960314531149564506544752097614513847899020629776701115098262552562151629993531946710430672386743677617308205579019072302696542508379","5370", +"23698146493089350432280213985162669959262841111102470546871456237323693618435911411642184657663645971277792033537906347762183635901158641375259341789919760310568146035244593237879245436647800609988327386298127942914981131212727307691555784531721623262685912374782653802898934200911324353096490548706043962852465907958751649549222286885339380268684947173053181005751121488921877337975992137735046528729900037937548187674111044469106308867226010497700021930277136809473041010432321","2154", +"-778920925563520089023277887716919839298513486135455047496265119151473505464734957690937635048394537294415972122421086877478533967411348994474171388256074145035237797802154822761617528172700015731068657547092679836095543042179681364991968425138238530710252585175316218097390905698054739393609117605669741881868029805237983772228322424502491583995084065878787104609542382045050185577023575049548616444750140539582676309391395859436260664778641733708499657047550739325300732722680932200039559718809","21626561658972270", +"715341102258098940319912343996707811685084551356244645540933308810413928160891724298276851619649551829973697033587181069271380692407132317161739109284011945227649892560360729074672778640720680874112214109997197387525352062913504682830983772725393570468326491083187300331970668449041594296073065276692887678729691114916079642579900288026881432235979137544823640729868705093774645241454622836223176904124630526882732099120398430089179339282190314646212515622936459121100998906169917551","6", +"-18399470428456050908014333117886494595730651014055636288722717429950917809500136272557117402977052839042105693597404693257617634201600598895359708213302738206862242849606975947076539483777341046657860376203296993121539300815161693660027527850273081527494673550440357634430596208643360358204371232957151165657607509017253243152916116719712350843286172274487990507840124030754833011930721808729659207188165402273267771908929719004881279785191361391914450528631012111465559730900716078151518537","46110", +"20813243679670197402657864594700362248333105628735574505407748752194329210363364029904045498683920274785904391711886368296491226342074760936891789529952828353712861964615536938434038079631985205838319830159148784466890765577478710750411239086707279314113340423502528151089538256774657292895067372560433868261285932669643784461912885034984352745012134324851266880718011466493208024572308839966018431480701067038072465848677106468318507151450224167148317101357641051334844151154035628560478914687","15414", +"-110725230879881321879568054811797526267115166186538309029826133137308115277324207270571040263441920262386242076342056949047866353534514266980024412370434220187359560062050493440457221035440089226046696014690219122751069156630764313360960761587856716000690131098571105908045239988081704908481660126863809763243757816063349431021332536632587298653399772920535661074013239670953426088742833252653499763654446938447050846790045870317112050534444840968778815676707175954631059728590843972403931253118799","23970", +"1054364681019267121830159662373420279818225480653781839149178920561555806813202030269003305294989784104213489890426332509828119920399712689187184649711689415835280384720994979874232796860338473523737136345243289020296312370876276856303158404225225651223912805235434755784151235675589206423964860803286777387807480810963355146229723274524146948489417884118537852386976826754447246469153480716621041563108596300892747446848622658459755002905969181236655822204297783975692352381312064835994355860201685","66", +"-56868988747972506254659596935683883463716573524427146597376366171981802233487630537261600452515928180502785214820124586232687460333822056190451678107485446400177877446417556715711032055230455854240595868388654451080202675047744244991416192115524025084813812227930163123287145588705727429456779082968390877093897979160965323905993195706278985485896440595636775123847679345910845046714163301325224520710766325936895600819434580574518875433796519293151389916795779147962584026929392606854485528272956190655743","1018290", +"27233521998844117466571164441681703778822231688822656418920849017523981696494911618651082582707143082377020546888216407884466480834780583096823087696141619926246646927066679156637706667759198043548965512948036645725109831717082230384665542660596536212413188407637782216353393129995452568219713750918323446571634462816666446106121343241772625570723451925602179037604045813434065564118195563426039220880907100156027093090547687363620867038635244235643402355449232121698090257432456131056504444320853157345201","138", +"-21144886325968847421136862640933605790730878065158231117894812330764874940817232709655287449203776974910988576503561661800249278991319113309582335281592647442495030553208258548341339318764197461147432848991686338242711098654931144304725148541437215370995347051713517773502906169174089944259231510484935144428438091067266131242394201122670888252772064856423958372374082615970685597386991737179844349495505700142239123902982043714578671787314293339023048726217119025452344630237832665698519639606247957083240801","30", +"4202152324841490851582198491734154054898910989229835692416027795481485467411812516892366095348619673337490550280425989691409092856177027846893427878738640633197809375983848427036487478678839362355759610808529212110936501477008097429319817529927993776215011685533261432410077791728458394351343228912812829117361997697793433448908490531697660725893829519644454139967318758247135377025444352170089166553939801451419735179550891309557305319624844923751198154628001739638691998206529289924753014269328705445340396548203417533","1651635762", +"-585016197049150516429606755440285431916223316191798033687181061470667150509536113671258201054717866226570169976401850360230659699699301963057743166370714339259000981058060988677132844370590538962044247092297537672905410985648312911796535010450651733583075122028847986584025427113069993778348629306554503407744980050377057969061170508810412927919930789637438916383763636475443274955653725558963454824998976936559504337387796596709727547538729277633022545136032386860825147973153846428111580196229784765036789760566304701","63030", +"78631979609289345055469501119395008379118096513723589634568877004799927202495863945986283823608714469880713486237817037414979036031006235383025032476262083964387973243898060840722936009590301165543812264089314197515688838727901018644687053389435289951515626740339208758682375061416597195951759290458697298602770109818453665947288873748972700580769864649544946817207071904078063454972954577208463927530056857030200986057709786810533019838606174872050746460837475834260566055441410395805129523481902672214740177851314801113","2298", +"-110754162756402172153014550168566972984876925083693264831143127544432717811904992984077240231351850620045442158975752476209437945003921292257289655906112174208294630503691959241009346814626779961417257948400146389011140929210993075671069409245612465372014808443841918963732454979635619634196765514065569765406021995951240364020270070411437377187081353045931837302854850452592893523482298799136698133585855070465304605234654821626817847160151252277371211732021978740981118935331815732788765628347320001270460720535171080710693555387","868841610", +"2879114883186609620826723532068276104139845449825894019948530676086618349883233245139084663416929458760597036667413717978530021472148264070597286070616857893183807259158771980877711836973364470227289919568822358886590073234578910075775184060367188577311832614887005612354400063672439629984465735358226535865532910705094242132700635264096296205052370626838252677418749801518077664289390262828965585623070897002640768910479324438878660938953441067263764560452279108930457475258025425810584201571774449957241464340109525100976383","6", +"-21299114788094757397153706724714536413292077775222009197296487570276368549767668483739905654759629794289722059088574391474394384116388842393472198779890845792835783368209072403070166818305644992935634095949389005892015797599060514475400351300665686095027668428158520105490245612578226308332064019874832238296603858849991741989885454092253889660892754436759635904520725519771622791567806625636568537908996210911982475409155309551762403125143065067389753960600797968698009862634474184891040512288957749239742206998790145616588343479389","11670", +"1039554412204304060999050471842935871664238236129525031050621197904673190252061816306076783004652192616133527774723493749394461545816137751676691165637363944930483826319036927422553141330104483296290342476507053344206817648719129001417301179730182909494636606795995576156560517060235847592695182729113023238975218843912996538779543747649999358252604590089345118921257104639445913236211149024538216358616556115899687337155136781007563112551684977465108319504450250735437471011340987371661862741413337000516697089619657504784045957077408711185","148218378", +"-4666956320257517816926480178489878702719387148900232522527912339796188714409776663856362141719980502875970806945762712937180144475887677992558175799481301586019202060028185307056311432687319799854135340241062231395259919629305490635354239890090217072557890791528689479267987496699263598146171495893203013485575227547175970131771602894568516495986613037151863666577390670765165933422564746168996994413125484969251071189411262200344536746879649016328422523901374916569404613335757056186544409616787583076594896302119414868190918059336879970513","171390", +"640808912350356174378073333715330795309912947431801296035514496305956924194050478724997308276302531933458844716623312895516343306208024932183790655351844102967791249508631724180677304236114904329953319103713608769803340518450516179464461284806009110502342220743568034682133273443656465906102058462073733441986152637932219455262690498783033366796807895595451968974170018589790265173871732540219203496470134837096254721957294282692027321105998231580155273075570903000709400332769684568638209079266772432973508791091418552966827434770217964847","6", +"-98872162196656114876533219362632891391774839342005000436956938726481191695417122725991435991920485003784886516420949151408274403750897124053086048470809705387715020563676318491207223028465413318847625119271235350352217955302858427960756286710348612322463571556662841990100314844270405671459605112346068263402145070889841697007530455932282600691314028702416310723147417755942945877131986599840610369192441659461647425950295710718456957848137284733782503430592302360661270817820862416426647830439342025098395116603056716015807642935747540566951812504354652379","233649143825370", +"10161900313215566319953421591388637402328180425349211048816698980319072816903521145345726221163084105611450343443221137527690722856383209708142471452342875346539666863558482835019156804751669116932322755085721460877938790181414341174421583630169802248409852214724801939766701626707662229904797008779706437578874336997303238218116573968772216970036489561373747407630110362020821819680854208929607112013855668348426244596961480597381595137016528270815603652018778457314919825182032768360703403384404569260876760458965758437801728169587522360995301639","6", +"-63783639210289998710088973624588233946566075008131539459746377225328551512763402330278905606150965942861218654753440979855135225080751599455762303374322801376784474875903535720147084146967619965166480436166324915138652313161158459147438440579563255414402868679468643443725452316589751257887343519347376962412796543353378510329227640325960354800434372777469890448460017461964152127411007649663198873691188302850776549851095445319674329831032713432828366945325817352958745749412125525231627662590308189489017131904402298383855303749523779093820302379681027746367","9315635010", +"1174239835539994552190497513182360535032387583605057260007722004883059102557958144704940674287492304226247212849059989833910250445125922032127665436388239538661698487981932513000579577766999325929606223291472664224576178291713742872723127632853994169543584403270186239889883934311766077803787140536031309605772620994720158177432481254737877501095184402972656917745175226661913130878960138618730840741958163788195850901560843232573640710143138001159729682511610291187234554610346621711370121346135534129198492308718185558865166313048808914617330314355609497","42", +"-3459038918426949807320150484933956945853243159595350413053075601122470521916955664973829953506019998422380872167968566067266857401026670310184013796611289015884412134623896705526558633772056365694507697389600886696154015160862337140032194111117938579681157914085424486545326355341017764587852271884318010152210498883089816668030790992239717499457275164513815414692072356653908445653642502944394623033131400812242246305136709927393331111317205972671896631185417486747798871333208226992838344653421293924893416433794558513589011611309370041563779286876725823001","30", +"170003857441113621055924711218201581479060969973774823543550655221015298985029713903581691625806778175064153013683952617568923683195904825491671562597778394848940698100060988046881674679194048284424046096930240621809667552628402886187489064670995742803216624905991737595831860741767548013712391467620520309900241319253287943675129083092747241525094828376937402590205346662298390862562643436019735148452642958172300132516340448730506554851256643796686115524433824609798825320819953662000059899761347431172299049404919145053054118348793890650129877368554102264664237","354", +"-31826882167847269036795264135997035261326106742393531631262513546951621739538129483912871462979086464612269631159787510831358937051013784806855551647371523568233230776308094926266913151377871925647720334390123342313810138336493293789276924639127443823386014514502682882716709333886588047556737429630427737978891250291212164857441066067952971934975332936367526583068834875982474415309122221371543750940258579267452360489050995048217629796997409692793673935051432353130414145045187876172429836566644615416398029958336369046123993446514393441794181039041943485420490171529217309","15755919270", +"47002375233508680615492575022874518250580216595322188118729388581779057270357890909757660925961204865010764157357677339640679419801075529375841405834200075859710151539426985792722765113963198773076233038710305332376160833224527455197843754378242330663125902354233318353062799203163603734366135826055833545210943663972100422012871119726280972153082552774282015316310107675884741591238987329522432070124995685585469794166878230612009713252291615918394199230644202167695522574730295764175556463982949470912949002495605091357997599244798045099081157657094553333043809915382015","5478", +"-1104074382679040449322457640474906559564674033012018040552761693975196623398701263395843134574919063111979334979001689856745801791431844835192880349897217288293513020820761816536292340772895413243616457931467439624320619545324679396693426479472670415005491693729301629890910865952928640236591593400805258179861429283108782677380853799729252550169975507441841656878779871922009807575659278905966164200037561186284335874588669047079319694680280463911923325143499841983743646211629813016265241858462427586701167961402272877528256110590588675820001821779929699856406082793746601","30", +"830966056816864165219563221691255172504816245427194942775778460297239574008254673723276280782798993878568376502765275874049468633347470545478154168815827272595416765071482194437630416545142455883532025709379623773918422191234979559992742090527602639659473260751398640580101548381014113971979542275363074811349527026580264739170503267212543977947471780118824749687917395812884246155157646166836076504356150965742303158590029916282708649948973023160673477590749360021799996465506161348017383225242179003450331850903647117458837892565999818223864269663453594385683125383821474811083023","5213334", +"-18840632174653835864968232583541556084424607654449238363350816356454780409921315489669153042640423571904583615446707687427327682018540206290243741793046153140931788677169249364676259458302231885326120895149522010431725107071591063425627272025446059167464033814661996655342902404678020463898666363623366708637084399729725592271785009331862696316729612579245598615561813162507665448387066401343329999818243511962109583265019621658883154231991893552479038765074765515515428784392050898556152995633956321371743766583910838111997813677461374152418833832478425757962198139801618258600291701","27030", +"177948829071244383748461224300047737954439245366393998814954157666837290036442548237545354559654248140762601235025124016956688571054331709927511568833209554328300942088687575803158770352778902946800416194092364129368960809507136675944946524355529271391513095831833834095214141413201872443533465259338559071060276534081662109185490926535115165429017697889522123426359409741271701359896235732490827288153220352311977810488328925043422296933754175073177948425972950246944493271200423473793223213272148300689418662045121140562185310116950518967585206995379939580805302928813353440147414740763","57822", +"-6126914449391766463123273102284652981370509248391971126816109275821466096976801669348238710361647712578179757979414761992440067232917335164055107920780363262942782633482006999971350591213671109122331751122081373688391335194625200099100643843244514246383231743873282258287892336340426940736781587230644995704054335003998425945469627545685623200550970324534080404065484535299953386337281009271537528001339179644699195404880031646796095372570028624110131487675467842335793522121252328612723178264941963550114480615755660790108038424472918326815297861578110970433546154844146996383907171442617576638221916277","446617991732222310", +"370417641649773203811105792421530317349989434553176611030631322780037740921920903496806496686319103807921979015270437429241936687918394087764863038019578527638851481686403847480960464641545840936004289242306394237365086284210791291343989458767793541220855587660095196948191905734357956461535121861354233393019487098593606068830314737953863466706245485662337370451037774820208643752612698330292374600196793018724057118532300846184682702881492970790966220893763118615367891028920559173128847556946881708070136133779182213573320504698972245409107308503781210793753700634159761806826499289415831","6", +"-900309704889057549412703055487959300250691255243632314995356843469409197586598181836315775665695203810817228257767800995208832223406044287944134381117528642679552487333128252142131375359121793415508211496537834167452784284536412724329064314223405159310288664698829339128075019109308684058290006604682848685269913509631592635991061291910848588896849609801431590823098722376633326783362640890294817117428008250878447534568070706275064939211743430644145531251375121140903646902567865610094036531542192311798685900713287395549217317410664958760801352234360088468504559813801913565013476710034147368107","3210", +"54022537803660305299034619951080701815883244369748020425073564798052876966542443431399087275857901045210724481101594546860129641620399468102807793533371090463155019439376300426001111110082554857406340378848339696012824680258786824575893953186081095194738031315027987901599699063076400850373460929533644671669856383541718682959908309284048987253429549866158169260473899283324734840555471844451471581906629081405048357875350755464695286397907639138344100989311969291336190793916170606327076279174475858929332637620247498179721571404122810497608597392310341741689230018260320576738940580419471886026121","42", +"-178631832601908536171004558032761096296603555642069337022466657948224618220000462860819307447255038425012723042570990636159393162920489265496945881843415223197089039558399046230412722134470564185454526546692168928856644009854678892565378884116563496393911506002791803756925372034984042436244890477408434546164564440123159575118382731762120541349243900708792397436983071602078285813659425066659156365690242457074462226267478374244243395380526750495191218544888861880143020865916520055167383158922400486128739977249726236354738468036532667283720083951543434880992597829033564904575040629182418739065389001","30", +"791452428000395052990463674367408774641299277169449382275797418384963666743647706199968141726577699871535620647877271680371011363641725875016441804003162706216814077280766553803448788712737779201122868425785256450531121303233116813021906603098871081632396261587905577208955217566658493203885877312418398060846091120975165767009344894679683148265158035296420969642632188332444968324025169811975004853721487927435823390089679208323886268818820308870377103259885100640557295098484358112295185600733503211183865432570364543715288518332255545140994972346903247999234036372815320143622542006284391778075614230370915","28446", +"-14750577990707069090892640643627890396790588057597932870361312797605339877218555318290483697927533647647152620207786705312787195868985834595937926758107692208298403338603695989231215167692521223914659443461688651180043473122600527834618929052569980773595567060954830287077779819370475900148020136696922033144977602316267162377565896641961582226753571000379259049438007003714263998786954349001656043288757745179230747108219268158244213583535560775121257993743283335146172958812409641851314398652207671071800026121000251318559834563893238437683153099891646143428578083417759291169439869395337214083816200847999672131739013721","112409792943630", +"3747779487230132491900784839670360702621969953197210049501251358419118141986190115493564102700854690955620245536804192644210548283959203482329576239229460642292110251158496706142540965642461705544532623844725391336993674360586090434899264849404330015359243509766947985382840962057755044491819343032537950612194324352600097426145059000885091707883730246793387324549656578506520410600783165826659781478577755966537904539285939024535631431583555662911156572916830417427298791392192762504813321994018595884981406242206002171583618182559028568019214315784771237935918859841167713230012475726056827372638626381963585567","6", +"-90024360230387232926513776967323326794697521699014742623495978698606015115117275163938036449925194916848722477911818639649193586017040660336424190717814222779195576374240102808595115759449145109628358599211511306846046027111627976699604296466038648254628913968475783753631135765609682725844055075467512860033319632741902401109514097069147699670253945763189080474357381924555174022637039432337932007567967360013189225484557699891500723386807516891972255376800483482791579348941380904127063436404359870716285253826928676282091132256974170075250937201408937099856598602948280585945432968199829410867368026769199252595801","30", +"268255361246337126367778228815259545045868431029437849645589178925638795843497414272945160749514714084165426561127725005493039810079480452517290207498185200717509668055892683546318815665341535697032808106797631781867079778636900617376382054640817598394038676153517033958597909974830544311249490853122270098045783563026899566057862076965478508567587449877041567729076139718636854981066664507897053160317558190734639340443419436918626125596334898307900637096349388220502296543130848656587202710882968136604232104512201075293126007959863944130551986019010434312311477565523149656237135607816533477227160969517648113475415388407","18438", +"-1971549561515498045945281707781358725202052418820469210287100375124408635052889958528421462206148998040363604314916692108315970766317682360194568697651597939992942608607863240436440670587263898825900455009148047595679837461799849465343687138591048044960789240368282898014290879082621858961237901928382366671020037189395193173411370422088058940123720113875828797411348581899556685938975754080936775135639140747303520886284176117348920517204041675362641162399925576576653291783247744987573436710429594592096815313807926352292662762861675065257056115521036077036706726455044401225578559120921795944351508096992367201543994966078858397","27695910", +"934217844394639862121876161182125782629662966798874841047916685310521671553962326103991809647198275117953002131456853984058360472753503867675200497447364861473654065939291320525986944570166180778722315422080724702421323386482784126733369118721815203984881266971497573448614086191554625693617723971683850141789064565402372607797348631247017594179350444633051496340472506374723019936564961282558140233726105870589191017887960191293607258806456016263231512800235871497605920995641449875958591869460832774676734017514779283735936104646380107986104389604327378999649850427118391694149262577932479289635308490619974233553612397882181813","2658", +"-158845135682583637310050414378214595799174539534413035558457927180260655307343938945950776141757261524377755785578389794390713400424204955224064287421714210308705949074744929596932632241358688262813726174958748320025797188191224303535908875129465586234092629175800592249211106320935394054787272761311671502199224520443098879151573888801771623192883526328927129807622792528335792700318705689540933290598347707055522491251314640804320693900281215224262309217387438431268666875059083616022905739177343532424279695920452691897028237708410245697642781733124304062104070106669202262888345577753573178251769219880004565578924500260455594131928657","90709710", +"52820988550912804071451884491873707077611397679084704441786148606552305037050330902476831330763618274617948135285949957728028695870688501651855365293214261665763024004555565085202897776922988749231163862901818153108264790734253251559229193150038194654616836673701295399639842711610882623238385854157477150420529686140635722118527587063478286467506193498289348590140209058848431175257465051090606564081140432276211107220257560552836024246626312132223879207171064190421730933829702220468746118116687590172977326777807226148473634828964585294322560361223896420954749054906526495733099883401725824247665659378641424764700866014787892724263","6", +"-33509969560310951077673300385182939173120218233464878294252193880216174489593173505823838246617056145585882555706860451887313675357842060706217782059762885287365030658978615168275599290138352468354789757259008089648541137547348110439089815672768327313180473534796888815851856313394644427062261422524265399511451721069073409293158382781768172256354047772889044225230507510811482737634673210381142106400974943160605739571810507050337114409751599167906471400307782233953490003352622899793151422802066630790773271959078676470883432223098011999197297967048507289842238199051754189231014498571762573655266437187969662451821328060350075608863875769571341","750400230", +"9391055572765375337084396117314557817718180166181509161271561059129443589397485081513018424705071474206174166639082356181454829444072491877870552062694059378849770958442322223463829270989901750468144609171516219648902784638712130372569713998758894226403154437364546237046936234486878313444740508912905759996491085406313529674400225188471243945850641568659710670402270969430805001894842922440442618558016542494360661268867597331176547554831945263940482855409773467788716571946235493331362953065136196925332392537268524281812660120686916907551456071718059004900562940126515655638458838017179782433551203385736031994621640626329584486625252298313721425","41089818", +"-8036788600329789637554905408606434751151763343827636999239373595458189088012226087443084910869936431803106244357312755090962116368482475276694252905815888538084063223859971526076599239358507163699508542178943276854150562290682856423508900798777112787185623445870747150615150782172422604213843730688721433197193927654307261557625517124764287228841421171512634534585391620401335799765458353101463743603983062786131145017655611914534755704275915462765633857066185411573999789535405190641054970837982446446314245641839258145246102021303507933166787126508119006984137728812640057612823780541560848078401500756860998000273851310662643557278203530509156427","6810", +"36887651095190359395978631707450897701552180104326675120919609694820560648030474979171133539537862210662044736026621541679008373532300695155313150561362479551904410240432070856446263923979299500092444516028968803538104878672539814981236198854450478175391010338000353791751383268673072000938944246515277386132140583257856132696558562847161814996976075174769694748695438632575090586824991284249542651404132205213670261425227222486264304182560679963038720949995579422933796694986011135385677383318542530506241731018476230796808445574699332521366132935744942092063737117719972419446305379041821531028902499051591918182645467840089773846410376436748099927","6", +"-9231251497205337786805280106627035365614237424730160108604924651736976180075798896215248792654225922031690989989936814428616639799004585592248516552105228745115600772090469618649949110864874437364870818222898493364585027928374556652768749981360929058298243205794495656723748164403781748730579086335638752417431277593473211309077070359896017274789066550552469547698979828077256389389589765286385150263946322137435703489322701057413339409715907420401015745559280769997899350755949293570194811595617539775432300877948131084500469766803745905331871839118178605120693482483577762003279580322707699760471279269534859347690610372106577357727353920929624706796074041823","285702690", +"1027825635381261025084137509518564962560728450132223539521526948817353636181702656928583828828717439941582449877622669707429906934288552278291471518913824570952553234368789724603442838567318141441615655257676812187239952554217908948438076178377910225560489116748839886969453337695309781684455928141552611581080216941930192968523416897195063762538557409287539980661256894009392408089358915496977576627225148859236468505369342003480428366798569334698706219583396397757047422466674537196192952267180837549901710490935337309113676890484857602521544773316821275084647927509602731787989854783170081148513873085444058741939360926584684355544622280387129474006982319","6", +"-6550760154113509955322519520324689762818345309330319372044343946911206397745316500483812442237014438941335293944750087907405849513426436624910542114024406950056919447434524096723352448017446297358873710248617421245570015225121262135612027972284197922153718331776532945085169610851088437877134878008919341980631531214431991715959299563428081327762284421994333768251921757188656927704213872171465925501861603885110199062495929817244864046765240300372782070942306808931353298237329193104023648523727135025613272860312485759776097808925561726646874622086120677449738708016595010877049123286575216517173385795826972669505322466175106064791167244415577645190187783109558537","7150110", +"6368886588855890529015573157270243329857473927510055032448029799766753973277733490743802481131249684574480516536707396064341401134831688716527812955468642497995612469570965195817160487421985680788793411096140356661976146745150228102075529102340373723482996983265766606390143860966670113764902836475227042342140853703902690953653738071098617987052339494008437294258743953709135498602090607507693690330811502343804351805921729587694688949530767925472547494085687987805410410505963373499481785590861551304643751957929639863906451583045448988420712969430083368919548554903489673904877295745230080254098114031395040280378645921227902389659674535661931328259201472684713522055433","1288550298", +"-188572988301799749241127705615416162812212213841895020766690762649760470928083270444552850572643956114497215752611047787304109375175847805695151784532184851620320647579855705925496701761448465808354795813973779680808888167818764964700925538842134054390992956001669225520942778629366261309269472085949866705644243058822229069911401050274835800403163105897188918692416516840686738234446171587614205164199212128303162013809506690718962024295099161224082167003915292076143373222944136866167556404170101140178710147326875675233494871699877286279336655831877302931691870727029196060937873178589575033953909097962613832380524097498719417990532304114093172036385627503846689476887699","7010970", +"413664867987222956244209355804553132010737311619873937552617773013514076367023256312176160835062661892330568050774492900833764272232882273128949537336490168744752502048943049241434525025420643944559491826884487174091266835019079457750298308269731643882842579624683236689298288625957015934020852065186333120537819299541510992711232749590370342660947186143661434743740645683801183663840994358198551336011498396150912151423938206307866725487635171065947029616755552973030152102744795495331947296938243287814790516243968203740094323906300807997945263580249967044922095488324059855868304323339162224087731767838889133184638682384777584272685488996638922752221799803151101166568141","2802", +"-1031107841715829258343463911912030698033011526937248355743056689674697602723540112990172956648590063031143260600724004347065027947507100488450593390705595096537384272550134562580809036689346664720973019306107636742232165503223693884139986374204369981544077656811163988149479258369895200746359684803254154401124622678491322587940166253688363451761279210145812935556959005617096357884154904315169217040557989251752098016262897990226072225936970292748900280469462419239068829802849814616525273947160256662458312243507612184481586372693712226732955571148746164223940290646509705984881548422992991644255618458312931517172972824955609103863870050004830358982153156128215328921678827090764016307","1261596819210", +"301188512670574409973522039731799774332284237966284386701245748565406164428681036128926063056095855532173991462477799681429260898037617758622985941710976235577943559100259786932475830383970536995316845412258295246742979426181833225367398491810295210078233611825547244385629725708901995508766557190851612705431746456650510895626334976810141560416672624945285953742157497174172068239724208754377218814505115022247180573164262593883452362474468782982223281207823275802362572430210812017251300349771480681113489830696638136842926883664618708287688430079713258060558978096084995295625323965331459365135957743350303225791768643943305879602716567061428469743627314569410061103860282955485","66", +"-770937004570847542710916650565931789612450235859854061364164699012203056638918055135259895416107273426948797500232897203853071790393885116465171393875976673693385000879337198213556447794398434782352654738563122022624642967864571454383814267648876048449590603480115693689162580755992686116534563663816203506520969500954741353683081691871170841572853932684457019190727452579388269518761070066012225637906766598808889134766906870857170491069727522854987604110140202165701028056317715546755482888281141979064206161119893213557441124682697844058662867837317718568074632672139404775850673801367503450134341628737627508058275331031355246875710092188894581462212753275513865164976897399277601","30", +"6129522921698903924225094098894493975355342495202583967070268649960491527425425546286128994652359747795614576729300901193288468364098351921425898605865990737737763196859623939630382031884908027628137877044490771874628629780057338048896492947577968007519815003168246395643465584343043193237880881635998419368585273823574720837496255282601496997088803126305575254814207239481124819310777601851780008004534530982225452330277362311532174615219685651873091360796309808900938980799843045197724124205459703692404692815206856959614667498156439854860378606039596585529438689777885628862162187008631192421450307071680585728728072572580947780239520470275779631590328798136283209653623721740978652009","42", +"-173794233423007364057178441776478220477329295247992746246194028033098955394598434863688615219916214324301023001093357893746330083903744204991166650812061841423746487587175286790822799578241212757499312100323647899801856816587814694250535160608651214203178715194330829602196319299830498255481024809653516681647938371069642056989453238492194899464534194575984259211778777474726825907276342679607943595029925764974686120493830750858815144111018156639748863065679944594300279690320295481014774768770077734050367942856894507914571711299927762683035011101547081082113463840150439878440505062095907817860452253434600485043521832982039217192780017205043143542812887267054217968944656636429743815938366731","207930", +"13873674832923745170636547493407974778812031787162484396922203584245099363875266410392579249977654901546226138255725682890165166445534326211967788770965050606335620329629392266509006667636060346080828403980900870728472844701200849051031032721110383896992993960600720447264177011379489696922012639234054945046493515830646916075528778995875263891724422324224871104321292779816866047869594198817075501831319907776354543266924566231340617726210269713505336228589002649382821152876769886796237625064939931597087898226387660507299139385252112368241337865982079462586705656758449262979906152409703115811425535504703782935179149721682887228861005266932595149810184020272544138033841220106232249961984874041","2874", +"-26012984231082938122321205711106137025736836308811099420978321017146930273005671218213801512995150233049010223325808387207760652312185884489040204754381130425223206104908949348483694397053700779323806598166397483624967026385155584314813089275200872985931085543928822164664368156111249818285706698582816847860316768251385568355911376789419906820360322920270272727732554866797105317523759568495736021299387762599572352567156747373223964524139683333489545030164669822955224449969772265055374313158826483073058617899550929715104043848380098396583498089878468223019258239295983312553586622706514962679548326500707178484227310027019877548445744372693423428185302230083093969160616600533454208539007576331211435405256579","925269860885370", +"990616118004405209547336756803741296643221987382321931721822820900299097210222317336001831102939236490395767769383589450743538317573906480157831910388399026009549363482047723522295682385225255084608513720106406633464966275709378145660935302980557499077874664887504148114522460257788204486783699727500508138689641080038916313291730518751063292404119140988768624151887967557709255327422581104429283482510069570158085040668138860662778558327704232203358594262804010229103345601462990376149249652299540260177492690219461257167020609270211173637016502365724336529333125021542322561542486553234490872949324335738034611680591470710376104053043734142034650737431499785882884589522913671849942865299633710178111","6", +"-674583921974243806727583626605726893305001263343470277847644141353711283719144748396214643464815527720051176636837830641202715031912558545751272265963459158832678711777574436725109883048688054377892408030247686556398952252471378342025741011438575099484896341336771053946168596117603779433009583486087778261092733102095362575294914815257723299413552987428930625441349976483182063565793384408266465380474529520534826114954047630754878668040735849610788709880820541989250906334800119386014176221640220454426941644202670624599594997416757514254570930031264863092952803531973860879930032899029342578124854325385199562765121526103213588359312368828453688417972133504757523704888418645741605357575301183566273541023","690", +"369763997577304898527792056092078784633064579850215089906718927953975408532819407204558577594984146089620623998022051043813802512840569387856574528038951679028036813020229062675066916989178254799161955591299056486170972788431152654760791766791190599466061280142672740585701636947897534361260451582259758691868004875864277790983654375073056163053627813804545640618169241729192679530964042280652574338325670662894789508966565337142721844903092886592945025900894162911247219665577745221033424450158824779569415157792860757313903143859765449917326253963605938268777389669269349544451932422774330893531316131993509969738757701435869993709233337662014445697606454995935095546520785205839498933104702647973917548450654482159","63346038", +"-1054181687381409638131616910853911354455980657913781692616470855145305376442167447677966359041858772154880528891461759759408670524036867330393458847554077805022113371551512761301353668641881943315640673862411986402084705908271833037248441148559758203373649679290148162009307104085713861437407027770249084665069566424802818695978402723455508336525572007924797995088668996393412803006736971627889522618048536287908252622198057721526239638561752413227961375709262141133204448616567780414625262935283998346756442958214463663418419136319815181399963230777047415998079220041299699187067412714951204651656933821520847527577289722382000754063804433988042815372396860021515945936788059415457004917777955610189853432234056001","30", +"490708060345718168482949551065008296976352341812156850912460754793773228598743021163789697895339848508047563198613297970895771272423084451586762411542433689884882582217920150615320261296412657655420294950882472519077107436411891314989684272827405143453664676299901282427746214002776016429289992734596941647026794542862610180682813869753438462413802302318288921935542654412271101075502309306996459972517715826132089736597584320511669263794701105417099176436055541622722611853665479429929243382275785136760788118477444370781356616739167758192241507716005871662971992278037186350173271291067722673038829083878521474773044108789762491726385320922397469619970046438378452390321367551511627206765616414040686450916033159995734945","2300826", +"-295710682036368660462889828594612232955924955002201524705248520206592222985898208468564409024643552663319217301279279456599515167727625150606450018918397365866826625510003837807762234721907229268939728260753209578951485832358379661753320905096937054954098245328282838820612002927999827875337943367582502020545668956501113411001279555402079055392887648432396357270387066730514118593546561439603919778742559512015901475146476123141564243291327909428505227081149290897384800809797729594081307795911125761034063373560371910341119307145118793762233074626775908914657621875311827273319354160489425009975655550242275976199551186361927525119846700395907422799296606519248369841030425783198567324724905036753320437659605858401058641353","226590", +"48304952056070024985817756788239978908682438355340656791822950062590796355241246689448963611728938505601369463215719576289607035969877364225474402150107267021033472617633002498666739540719726067208908400868629471652429458078768484626439283884479517280978247192859399400878296914805548929586054952054550941690046726387385343252474507896205536559285343999286125673465838911018803676968634234058996143076453319007358347695097769648224143191413651220988411012365741972645136470905240747776225223601701498704103140362659865756058524036705273180849600017203422636276522059566343973347678362590339657974928808786150211385800610012387411013195229675295096785833478392423958039918096194458403331849842918089944679987935690252652536647","6", +"-25535109222241698972694173193973518774716242178265877234279078154218306288190453574391345349607020347701104389306082727640662249328994752154372973422361999092715922759633521270378541507790769763357456276378726595626459724623679603915577643947700472106673593583118436960062894166402312867190376592931480464022802240967436286930003098509086131781553808335933575272888361402715107788113154287996385861486207257531899222760762747086758473894396360217594584387656887231071811145643960111628458232775253525983817907496407600357182919744162523813712195436135703038816616947504736640465073624938220282345566631808140813969037396579578863663701714202683178828730441933582773514024218332915875259194767588507001149870106803558286434937883617","510", +"1098651228481515846116735605942901657544418942763685605483819128454976385464899434737242367240952385067444749008365642568063670579728409673461751272924549125285602795045413203741844230426358616759853983294227411821897092348333446120995756339616373490620446536298890167517709746328742870299157366295356390032576984786436553789735950197578753614711411671045054914305425293539519785975913292188458435472840034103326532984267720997838197057411785852422605414587329459898626238314431604983174665957920693815755227736013545929781603072985638923688324355299338791368472239159091263112230452362400314432752766640687084000308229806355172210181524971644942859893996940410875091940649202106109066788663807627887433701124817799811432100659519242101309","3499986" +}; + +#endif + diff -Nru libqalculate-3.6.0/libqalculate/BuiltinFunctions-algebra.cc libqalculate-3.7.0/libqalculate/BuiltinFunctions-algebra.cc --- libqalculate-3.6.0/libqalculate/BuiltinFunctions-algebra.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/BuiltinFunctions-algebra.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,1139 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Number.h" +#include "Calculator.h" +#include "Variable.h" +#include "Unit.h" + +#include +#include +#include +#include + +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +SumFunction::SumFunction() : MathFunction("sum", 3, 4) { + Argument *arg = new IntegerArgument(); + arg->setHandleVector(false); + setArgumentDefinition(2, arg); + arg = new IntegerArgument(); + arg->setHandleVector(false); + setArgumentDefinition(3, arg); + setArgumentDefinition(4, new SymbolicArgument()); + setDefaultValue(4, "undefined"); + setCondition("\\z >= \\y"); +} +int SumFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + + MathStructure m1(vargs[0]); + EvaluationOptions eo2 = eo; + eo2.calculate_functions = false; + eo2.expand = false; + Number i_nr(vargs[1].number()); + if(eo2.approximation == APPROXIMATION_TRY_EXACT) { + Number nr(vargs[2].number()); + nr.subtract(i_nr); + if(nr.isGreaterThan(100)) eo2.approximation = APPROXIMATION_APPROXIMATE; + } + CALCULATOR->beginTemporaryStopMessages(); + m1.eval(eo2); + int im = 0; + if(CALCULATOR->endTemporaryStopMessages(NULL, &im) > 0 || im > 0) m1 = vargs[0]; + eo2.calculate_functions = eo.calculate_functions; + eo2.expand = eo.expand; + mstruct.clear(); + MathStructure mstruct_calc; + bool started = false; + while(i_nr.isLessThanOrEqualTo(vargs[2].number())) { + if(CALCULATOR->aborted()) { + if(!started) { + return 0; + } else if(i_nr != vargs[2].number()) { + MathStructure mmin(i_nr); + mstruct.add(MathStructure(this, &vargs[0], &mmin, &vargs[2], &vargs[3], NULL), true); + return 1; + } + } + mstruct_calc.set(m1); + mstruct_calc.replace(vargs[3], i_nr); + mstruct_calc.eval(eo2); + if(started) { + mstruct.calculateAdd(mstruct_calc, eo2); + } else { + mstruct = mstruct_calc; + mstruct.calculatesub(eo2, eo2); + started = true; + } + i_nr += 1; + } + return 1; + +} +ProductFunction::ProductFunction() : MathFunction("product", 3, 4) { + Argument *arg = new IntegerArgument(); + arg->setHandleVector(false); + setArgumentDefinition(2, arg); + arg = new IntegerArgument(); + arg->setHandleVector(false); + setArgumentDefinition(3, arg); + setArgumentDefinition(4, new SymbolicArgument()); + setDefaultValue(4, "undefined"); + setCondition("\\z >= \\y"); +} +int ProductFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + + MathStructure m1(vargs[0]); + EvaluationOptions eo2 = eo; + eo2.calculate_functions = false; + eo2.expand = false; + Number i_nr(vargs[1].number()); + if(eo2.approximation == APPROXIMATION_TRY_EXACT) { + Number nr(vargs[2].number()); + nr.subtract(i_nr); + if(nr.isGreaterThan(100)) eo2.approximation = APPROXIMATION_APPROXIMATE; + } + CALCULATOR->beginTemporaryStopMessages(); + m1.eval(eo2); + int im = 0; + if(CALCULATOR->endTemporaryStopMessages(NULL, &im) || im > 0) m1 = vargs[0]; + eo2.calculate_functions = eo.calculate_functions; + eo2.expand = eo.expand; + mstruct.clear(); + MathStructure mstruct_calc; + bool started = false; + while(i_nr.isLessThanOrEqualTo(vargs[2].number())) { + if(CALCULATOR->aborted()) { + if(!started) { + return 0; + } else if(i_nr != vargs[2].number()) { + MathStructure mmin(i_nr); + mstruct.multiply(MathStructure(this, &vargs[0], &mmin, &vargs[2], &vargs[3], NULL), true); + return 1; + } + } + mstruct_calc.set(m1); + mstruct_calc.replace(vargs[3], i_nr); + mstruct_calc.eval(eo2); + if(started) { + mstruct.calculateMultiply(mstruct_calc, eo2); + } else { + mstruct = mstruct_calc; + mstruct.calculatesub(eo2, eo2); + started = true; + } + i_nr += 1; + } + return 1; + +} + +SolveFunction::SolveFunction() : MathFunction("solve", 1, 2) { + setArgumentDefinition(2, new SymbolicArgument()); + setDefaultValue(2, "undefined"); +} +bool is_comparison_structure(const MathStructure &mstruct, const MathStructure &xvar, bool *bce = NULL, bool do_bce_or = false); +bool is_comparison_structure(const MathStructure &mstruct, const MathStructure &xvar, bool *bce, bool do_bce_or) { + if(mstruct.isComparison()) { + if(bce) *bce = mstruct.comparisonType() == COMPARISON_EQUALS && mstruct[0] == xvar; + return true; + } + if(bce && do_bce_or && mstruct.isLogicalOr()) { + *bce = true; + for(size_t i = 0; i < mstruct.size(); i++) { + bool bcei = false; + if(!is_comparison_structure(mstruct[i], xvar, &bcei, false)) return false; + if(!bcei) *bce = false; + } + return true; + } + if(bce) *bce = false; + if(mstruct.isLogicalAnd()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(is_comparison_structure(mstruct[i], xvar)) return true; + } + return true; + } else if(mstruct.isLogicalOr()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(!is_comparison_structure(mstruct[i], xvar)) return false; + } + return true; + } + return false; +} + +MathStructure *solve_handle_logical_and(MathStructure &mstruct, MathStructure **mtruefor, ComparisonType ct, bool &b_partial, const MathStructure &x_var) { + MathStructure *mcondition = NULL; + for(size_t i2 = 0; i2 < mstruct.size(); ) { + if(ct == COMPARISON_EQUALS) { + if(mstruct[i2].isComparison() && ct == mstruct[i2].comparisonType() && mstruct[i2][0].contains(x_var)) { + if(mstruct[i2][0] == x_var) { + if(mstruct.size() == 2) { + if(i2 == 0) { + mstruct[1].ref(); + mcondition = &mstruct[1]; + } else { + mstruct[0].ref(); + mcondition = &mstruct[0]; + } + } else { + mcondition = new MathStructure(); + mcondition->set_nocopy(mstruct); + mcondition->delChild(i2 + 1); + } + mstruct.setToChild(i2 + 1, true); + break; + } else { + b_partial = true; + i2++; + } + } else { + i2++; + } + } else { + if(mstruct[i2].isComparison() && mstruct[i2][0].contains(x_var)) { + i2++; + } else { + mstruct[i2].ref(); + if(mcondition) { + mcondition->add_nocopy(&mstruct[i2], OPERATION_LOGICAL_AND, true); + } else { + mcondition = &mstruct[i2]; + } + mstruct.delChild(i2 + 1); + } + } + } + if(ct == COMPARISON_EQUALS) { + if(mstruct.isLogicalAnd()) { + MathStructure *mtmp = new MathStructure(); + mtmp->set_nocopy(mstruct); + if(!(*mtruefor)) { + *mtruefor = mtmp; + } else { + (*mtruefor)->add_nocopy(mtmp, OPERATION_LOGICAL_OR, true); + } + mstruct.clear(true); + } + } else { + if(mstruct.size() == 1) { + mstruct.setToChild(1, true); + if(ct != COMPARISON_EQUALS) mstruct.setProtected(); + } else if(mstruct.size() == 0) { + mstruct.clear(true); + if(!(*mtruefor)) { + *mtruefor = mcondition; + } else { + (*mtruefor)->add_nocopy(mcondition, OPERATION_LOGICAL_OR, true); + } + mcondition = NULL; + } else if(ct != COMPARISON_EQUALS) { + for(size_t i = 0; i < mstruct.size(); i++) { + mstruct[i].setProtected(); + } + } + } + return mcondition; +} + +void simplify_constant(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &y_var, const MathStructure &c_var, bool in_comparison = false, bool in_or = false, bool in_and = false); +void simplify_constant(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &y_var, const MathStructure &c_var, bool in_comparison, bool in_or, bool in_and) { + if(!in_comparison && mstruct.isComparison()) { + if(mstruct[0] == c_var) { + if(in_or) mstruct.clear(true); + else mstruct.set(1, 1, 0); + } else if(mstruct[0] == y_var) { + if(mstruct[1].contains(y_var, true) <= 0) simplify_constant(mstruct[1], x_var, y_var, c_var, true); + } else if(mstruct[0].contains(y_var, true) <= 0 && mstruct.contains(c_var, true) > 0) { + if(in_or) mstruct.clear(true); + else mstruct.set(1, 1, 0); + } + } + if(in_comparison) { + if(mstruct.contains(y_var, true) <= 0 && mstruct.contains(x_var, true) <= 0 && mstruct.contains(c_var, true) > 0) { + mstruct = c_var; + return; + } + } + if(in_comparison) { + int n_c = 0, b_cx = false; + size_t i_c = 0; + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].contains(c_var, true) > 0) { + n_c++; + i_c = i; + if(!b_cx && mstruct[i].contains(x_var, true) > 0) { + b_cx = true; + } + } + } + if(!b_cx && n_c >= 1 && (mstruct.isAddition() || mstruct.isMultiplication())) { + bool b_c = false; + for(size_t i = 0; i < mstruct.size();) { + if(mstruct[i].contains(c_var, true) > 0) { + if(b_c) { + mstruct.delChild(i + 1); + } else { + b_c = true; + mstruct[i] = c_var; + i++; + } + } else if(mstruct[i].contains(x_var, true) <= 0) { + mstruct.delChild(i + 1); + } else { + i++; + } + } + if(mstruct.size() == 1) mstruct.setToChild(1, true); + } else if(n_c == 1) { + if(b_cx) simplify_constant(mstruct[i_c], x_var, y_var, c_var, true); + else mstruct[i_c] = c_var; + } + } else { + for(size_t i = 0; i < mstruct.size(); i++) { + simplify_constant(mstruct[i], x_var, y_var, c_var, false, mstruct.isLogicalOr(), mstruct.isLogicalAnd()); + } + } +} + +int test_equation(MathStructure &mstruct, const EvaluationOptions &eo, const MathStructure &x_var, const MathStructure &y_var, const MathStructure &x_value, const MathStructure &y_value) { + if(mstruct.isComparison() && mstruct.comparisonType() == COMPARISON_EQUALS && mstruct[0] == y_var) { + MathStructure mtest(mstruct); + mtest.replace(x_var, x_value); + MathStructure mtest2(y_var); + mtest2.transform(COMPARISON_EQUALS, y_value); + CALCULATOR->beginTemporaryStopMessages(); + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + mtest.calculateFunctions(eo2); + mtest2.calculateFunctions(eo2); + int b = test_comparisons(mtest, mtest2, y_var, eo); + CALCULATOR->endTemporaryStopMessages(); + if(!b) mstruct.clear(true); + return b; + } + bool b_ret = 0; + for(size_t i = 0; i < mstruct.size(); i++) { + int b = test_equation(mstruct[i], eo, x_var, y_var, x_value, y_value); + if(b < 0) return b; + else if(b > 0) b_ret = 1; + } + return b_ret; +} + +int solve_equation(MathStructure &mstruct, const MathStructure &m_eqn, const MathStructure &y_var, const EvaluationOptions &eo, bool dsolve = false, const MathStructure &x_var = m_undefined, const MathStructure &c_var = m_undefined, const MathStructure &x_value = m_undefined, const MathStructure &y_value = m_undefined) { + + int itry = 0; + int ierror = 0; + int first_error = 0; + + Assumptions *assumptions = NULL; + bool assumptions_added = false; + AssumptionSign as = ASSUMPTION_SIGN_UNKNOWN; + AssumptionType at = ASSUMPTION_TYPE_NUMBER; + MathStructure msave; + string strueforall; + + while(true) { + + if(itry == 1) { + if(ierror == 1) { + if(!dsolve) CALCULATOR->error(true, _("No equality or inequality to solve. The entered expression to solve is not correct (ex. \"x + 5 = 3\" is correct)"), NULL); + return -1; + } else { + first_error = ierror; + msave = mstruct; + } + } + + itry++; + + if(itry == 2) { + if(y_var.isVariable() && y_var.variable()->subtype() == SUBTYPE_UNKNOWN_VARIABLE) { + assumptions = ((UnknownVariable*) y_var.variable())->assumptions(); + if(!assumptions) { + assumptions = new Assumptions(); + assumptions->setSign(CALCULATOR->defaultAssumptions()->sign()); + assumptions->setType(CALCULATOR->defaultAssumptions()->type()); + ((UnknownVariable*) y_var.variable())->setAssumptions(assumptions); + assumptions_added = true; + } + } else { + assumptions = CALCULATOR->defaultAssumptions(); + } + if(assumptions->sign() != ASSUMPTION_SIGN_UNKNOWN) { + as = assumptions->sign(); + assumptions->setSign(ASSUMPTION_SIGN_UNKNOWN); + } else { + itry++; + } + } + if(itry == 3) { + if(assumptions->type() > ASSUMPTION_TYPE_NUMBER) { + at = assumptions->type(); + assumptions->setType(ASSUMPTION_TYPE_NUMBER); + as = assumptions->sign(); + assumptions->setSign(ASSUMPTION_SIGN_UNKNOWN); + } else { + itry++; + } + } + + if(itry > 3) { + if(as != ASSUMPTION_SIGN_UNKNOWN) assumptions->setSign(as); + if(at > ASSUMPTION_TYPE_NUMBER) assumptions->setType(at); + if(assumptions_added) ((UnknownVariable*) y_var.variable())->setAssumptions(NULL); + switch(first_error) { + case 2: { + CALCULATOR->error(true, _("The comparison is true for all %s (with current assumptions)."), format_and_print(y_var).c_str(), NULL); + break; + } + case 3: { + CALCULATOR->error(true, _("No possible solution was found (with current assumptions)."), NULL); + break; + } + case 4: { + CALCULATOR->error(true, _("Was unable to completely isolate %s."), format_and_print(y_var).c_str(), NULL); + break; + } + case 7: { + CALCULATOR->error(false, _("The comparison is true for all %s if %s."), format_and_print(y_var).c_str(), strueforall.c_str(), NULL); + break; + } + default: { + CALCULATOR->error(true, _("Was unable to isolate %s."), format_and_print(y_var).c_str(), NULL); + break; + } + } + mstruct = msave; + return -1; + } + + ComparisonType ct = COMPARISON_EQUALS; + + bool b = false; + bool b_partial = false; + + if(m_eqn.isComparison()) { + ct = m_eqn.comparisonType(); + mstruct = m_eqn; + b = true; + } else if(m_eqn.isLogicalAnd() && m_eqn.size() > 0 && m_eqn[0].isComparison()) { + ct = m_eqn[0].comparisonType(); + for(size_t i = 0; i < m_eqn.size(); i++) { + if(m_eqn[i].isComparison() && m_eqn[i].contains(y_var, true) > 0) { + ct = m_eqn[i].comparisonType(); + break; + } + } + mstruct = m_eqn; + b = true; + } else if(m_eqn.isLogicalOr() && m_eqn.size() > 0 && m_eqn[0].isComparison()) { + ct = m_eqn[0].comparisonType(); + mstruct = m_eqn; + b = true; + } else if(m_eqn.isLogicalOr() && m_eqn.size() > 0 && m_eqn[0].isLogicalAnd() && m_eqn[0].size() > 0 && m_eqn[0][0].isComparison()) { + ct = m_eqn[0][0].comparisonType(); + for(size_t i = 0; i < m_eqn[0].size(); i++) { + if(m_eqn[0][i].isComparison() && m_eqn[0][i].contains(y_var, true) > 0) { + ct = m_eqn[0][i].comparisonType(); + break; + } + } + mstruct = m_eqn; + b = true; + } else if(m_eqn.isVariable() && m_eqn.variable()->isKnown() && (eo.approximation != APPROXIMATION_EXACT || !m_eqn.variable()->isApproximate()) && ((KnownVariable*) m_eqn.variable())->get().isComparison()) { + mstruct = ((KnownVariable*) m_eqn.variable())->get(); + mstruct.unformat(); + ct = m_eqn.comparisonType(); + b = true; + } else { + EvaluationOptions eo2 = eo; + eo2.test_comparisons = false; + eo2.assume_denominators_nonzero = false; + eo2.isolate_x = false; + mstruct = m_eqn; + mstruct.eval(eo2); + if(mstruct.isComparison()) { + ct = mstruct.comparisonType(); + b = true; + } else if(mstruct.isLogicalAnd() && mstruct.size() > 0 && mstruct[0].isComparison()) { + ct = mstruct[0].comparisonType(); + b = true; + } else if(mstruct.isLogicalOr() && mstruct.size() > 0 && mstruct[0].isComparison()) { + ct = mstruct[0].comparisonType(); + b = true; + } else if(mstruct.isLogicalOr() && mstruct.size() > 0 && mstruct[0].isLogicalAnd() && mstruct[0].size() > 0 && mstruct[0][0].isComparison()) { + ct = mstruct[0][0].comparisonType(); + b = true; + } + } + + if(!b) { + ierror = 1; + continue; + } + + EvaluationOptions eo2 = eo; + eo2.isolate_var = &y_var; + eo2.isolate_x = true; + eo2.test_comparisons = true; + mstruct.eval(eo2); + if(dsolve) { + if(x_value.isUndefined() || y_value.isUndefined()) { + simplify_constant(mstruct, x_var, y_var, c_var); + mstruct.eval(eo2); + } else { + int test_r = test_equation(mstruct, eo2, x_var, y_var, x_value, y_value); + if(test_r < 0) { + ierror = 8; + continue; + } else if(test_r > 0) { + mstruct.eval(eo2); + } + } + } + + if(mstruct.isOne()) { + ierror = 2; + continue; + } else if(mstruct.isZero()) { + ierror = 3; + continue; + } + + if(mstruct.isComparison()) { + if((ct == COMPARISON_EQUALS && mstruct.comparisonType() != COMPARISON_EQUALS) || !mstruct.contains(y_var)) { + if(itry == 1) { + strueforall = format_and_print(mstruct); + } + ierror = 7; + continue; + } else if(ct == COMPARISON_EQUALS && mstruct[0] != y_var) { + ierror = 4; + continue; + } + if(ct == COMPARISON_EQUALS) { + mstruct.setToChild(2, true); + } else { + mstruct.setProtected(); + } + if(itry > 1) { + assumptions->setSign(as); + if(itry == 2) { + CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL); + } else if(itry == 3) { + assumptions->setType(at); + CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed type and sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL); + } + if(assumptions_added) ((UnknownVariable*) y_var.variable())->setAssumptions(NULL); + } + return 1; + } else if(mstruct.isLogicalAnd()) { + MathStructure *mtruefor = NULL; + bool b_partial; + MathStructure mcopy(mstruct); + MathStructure *mcondition = solve_handle_logical_and(mstruct, &mtruefor, ct, b_partial, y_var); + if((!mstruct.isComparison() && !mstruct.isLogicalAnd()) || (ct == COMPARISON_EQUALS && (!mstruct.isComparison() || mstruct.comparisonType() != COMPARISON_EQUALS || mstruct[0] != y_var)) || !mstruct.contains(y_var)) { + if(mtruefor) delete mtruefor; + if(mcondition) delete mcondition; + if(b_partial) { + ierror = 4; + } else { + ierror = 5; + } + mstruct = mcopy; + continue; + } + if(itry > 1) { + assumptions->setSign(as); + if(itry == 2) { + CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL); + } else if(itry == 3) { + assumptions->setType(at); + CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed type and sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL); + } + if(assumptions_added) ((UnknownVariable*) y_var.variable())->setAssumptions(NULL); + } + if(mcondition) { + CALCULATOR->error(false, _("The solution requires that %s."), format_and_print(*mcondition).c_str(), NULL); + delete mcondition; + } + if(mtruefor) { + CALCULATOR->error(false, _("The comparison is true for all %s if %s."), format_and_print(y_var).c_str(), format_and_print(*mtruefor).c_str(), NULL); + delete mtruefor; + } + if(ct == COMPARISON_EQUALS) mstruct.setToChild(2, true); + return 1; + } else if(mstruct.isLogicalOr()) { + MathStructure mcopy(mstruct); + MathStructure *mtruefor = NULL; + vector mconditions; + for(size_t i = 0; i < mstruct.size(); ) { + MathStructure *mcondition = NULL; + bool b_and = false; + if(mstruct[i].isLogicalAnd()) { + mcondition = solve_handle_logical_and(mstruct[i], &mtruefor, ct, b_partial, y_var); + b_and = true; + } + if(!mstruct[i].isZero()) { + for(size_t i2 = 0; i2 < i; i2++) { + if(mstruct[i2] == mstruct[i]) { + mstruct[i].clear(); + if(mcondition && mconditions[i2]) { + mconditions[i2]->add_nocopy(mcondition, OPERATION_LOGICAL_OR, true); + } + break; + } + } + } + bool b_del = false; + if((!mstruct[i].isComparison() && !mstruct[i].isLogicalAnd()) || (ct == COMPARISON_EQUALS && (!mstruct[i].isComparison() || mstruct[i].comparisonType() != COMPARISON_EQUALS)) || !mstruct[i].contains(y_var)) { + b_del = true; + } else if(ct == COMPARISON_EQUALS && mstruct[i][0] != y_var) { + b_partial = true; + b_del = true; + } + if(b_del) { + if(!mstruct[i].isZero()) { + mstruct[i].ref(); + if(!mtruefor) { + mtruefor = &mstruct[i]; + } else { + mtruefor->add_nocopy(&mstruct[i], OPERATION_LOGICAL_OR, true); + } + } + mstruct.delChild(i + 1); + } else { + mconditions.push_back(mcondition); + if(!b_and && ct != COMPARISON_EQUALS) mstruct[i].setProtected(); + i++; + } + } + if(ct == COMPARISON_EQUALS) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isComparison() && mstruct[i].comparisonType() == ct) mstruct[i].setToChild(2, true); + } + } + if(mstruct.size() == 1) { + mstruct.setToChild(1, true); + } else if(mstruct.size() == 0) { + if(mtruefor) delete mtruefor; + if(b_partial) ierror = 4; + else ierror = 5; + mstruct = mcopy; + continue; + } else { + mstruct.setType(STRUCT_VECTOR); + } + if(itry > 1) { + assumptions->setSign(as); + if(itry == 2) { + CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL); + } else if(itry == 3) { + assumptions->setType(at); + CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed type and sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL); + } + if(assumptions_added) ((UnknownVariable*) y_var.variable())->setAssumptions(NULL); + } + + if(mconditions.size() == 1) { + if(mconditions[0]) { + CALCULATOR->error(false, _("The solution requires that %s."), format_and_print(mconditions[0]).c_str(), NULL); + delete mconditions[0]; + } + } else { + string sconditions; + for(size_t i = 0; i < mconditions.size(); i++) { + if(mconditions[i]) { + CALCULATOR->error(false, _("Solution %s requires that %s."), i2s(i + 1).c_str(), format_and_print(mconditions[i]).c_str(), NULL); + delete mconditions[i]; + } + } + } + if(mtruefor) { + CALCULATOR->error(false, _("The comparison is true for all %s if %s."), format_and_print(y_var).c_str(), format_and_print(*mtruefor).c_str(), NULL); + delete mtruefor; + } + return 1; + } else { + ierror = 6; + } + } + return -1; + +} + +int SolveFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + return solve_equation(mstruct, vargs[0], vargs[1], eo); +} + +SolveMultipleFunction::SolveMultipleFunction() : MathFunction("multisolve", 2) { + setArgumentDefinition(1, new VectorArgument()); + VectorArgument *arg = new VectorArgument(); + arg->addArgument(new SymbolicArgument()); + arg->setReoccuringArguments(true); + setArgumentDefinition(2, arg); + setCondition("dimension(\\x) = dimension(\\y)"); +} +int SolveMultipleFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + + mstruct.clearVector(); + + if(vargs[1].size() < 1) return 1; + + vector eleft; + eleft.resize(vargs[0].size(), true); + vector eorder; + bool b = false; + for(size_t i = 0; i < vargs[1].size(); i++) { + b = false; + for(size_t i2 = 0; i2 < vargs[0].size(); i2++) { + if(eleft[i2] && vargs[0][i2].contains(vargs[1][i], true)) { + eorder.push_back(i2); + eleft[i2] = false; + b = true; + break; + } + } + if(!b) { + eorder.clear(); + for(size_t i2 = 0; i2 < vargs[0].size(); i2++) { + eorder.push_back(i2); + } + break; + } + } + + for(size_t i = 0; i < eorder.size(); i++) { + MathStructure msolve(vargs[0][eorder[i]]); + EvaluationOptions eo2 = eo; + eo2.isolate_var = &vargs[1][i]; + for(size_t i2 = 0; i2 < i; i2++) { + msolve.replace(vargs[1][i2], mstruct[i2]); + } + msolve.eval(eo2); + + if(msolve.isComparison()) { + if(msolve[0] != vargs[1][i]) { + if(!b) { + CALCULATOR->error(true, _("Unable to isolate %s.\n\nYou might need to place the equations and variables in an appropriate order so that each equation at least contains the corresponding variable (if automatic reordering failed)."), format_and_print(vargs[1][i]).c_str(), NULL); + } else { + CALCULATOR->error(true, _("Unable to isolate %s."), format_and_print(vargs[1][i]).c_str(), NULL); + } + return 0; + } else { + if(msolve.comparisonType() == COMPARISON_EQUALS) { + mstruct.addChild(msolve[1]); + } else { + CALCULATOR->error(true, _("Inequalities is not allowed in %s()."), preferredName().name.c_str(), NULL); + return 0; + } + } + } else if(msolve.isLogicalOr()) { + for(size_t i2 = 0; i2 < msolve.size(); i2++) { + if(!msolve[i2].isComparison() || msolve[i2].comparisonType() != COMPARISON_EQUALS || msolve[i2][0] != vargs[1][i]) { + CALCULATOR->error(true, _("Unable to isolate %s."), format_and_print(vargs[1][i]).c_str(), NULL); + return 0; + } else { + msolve[i2].setToChild(2, true); + } + } + msolve.setType(STRUCT_VECTOR); + mstruct.addChild(msolve); + } else { + CALCULATOR->error(true, _("Unable to isolate %s."), format_and_print(vargs[1][i]).c_str(), NULL); + return 0; + } + for(size_t i2 = 0; i2 < i; i2++) { + for(size_t i3 = 0; i3 <= i; i3++) { + if(i2 != i3) { + mstruct[i2].replace(vargs[1][i3], mstruct[i3]); + } + } + } + } + + return 1; + +} + +MathStructure *find_deqn(MathStructure &mstruct); +MathStructure *find_deqn(MathStructure &mstruct) { + if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_DIFFERENTIATE) return &mstruct; + for(size_t i = 0; i < mstruct.size(); i++) { + MathStructure *m = find_deqn(mstruct[i]); + if(m) return m; + } + return NULL; +} + +bool contains_ignore_diff(const MathStructure &m, const MathStructure &mstruct, const MathStructure &mdiff); +bool contains_ignore_diff(const MathStructure &m, const MathStructure &mstruct, const MathStructure &mdiff) { + if(m.equals(mstruct)) return true; + if(m.equals(mdiff)) return false; + for(size_t i = 0; i < m.size(); i++) { + if(contains_ignore_diff(m[i], mstruct, mdiff)) return true; + } + if(m.isVariable() && m.variable()->isKnown()) { + return contains_ignore_diff(((KnownVariable*) m.variable())->get(), mstruct, mdiff); + } else if(m.isVariable()) { + if(mstruct.isNumber() || !m.representsNumber()) return true; + } else if(m.isAborted()) { + return true; + } + return false; +} + +void add_C(MathStructure &m_eqn, const MathStructure &m_x, const MathStructure &m_y, const MathStructure &x_value, const MathStructure &y_value) { + if(!y_value.isUndefined() && !x_value.isUndefined()) { + MathStructure m_c(m_eqn); + m_c.replace(m_x, x_value); + m_c.replace(m_y, y_value); + m_c.setType(STRUCT_ADDITION); + m_c[1].negate(); + m_c.childUpdated(2); + m_eqn[1] += m_c; + } else { + m_eqn[1] += CALCULATOR->getVariableById(VARIABLE_ID_C); + } + m_eqn.childrenUpdated(); +} + +bool dsolve(MathStructure &m_eqn, const EvaluationOptions &eo, const MathStructure &m_diff, const MathStructure &y_value, const MathStructure &x_value) { + MathStructure m_y(m_diff[0]), m_x(m_diff[1]); + bool b = false; + if(m_eqn[0] == m_diff) { + if(m_eqn[1].containsRepresentativeOf(m_y, true, true) == 0) { + // y'=f(x) + MathStructure m_fx(m_eqn[1]); + if(m_fx.integrate(m_x, eo, true, false) > 0) { + m_eqn[0] = m_y; + m_eqn[1] = m_fx; + b = true; + } + } else if(m_eqn[1].containsRepresentativeOf(m_x, true, true) == 0) { + MathStructure m_fy(m_eqn[1]); + m_fy.inverse(); + if(m_fy.integrate(m_y, eo, true, false) > 0) { + m_eqn[0] = m_fy; + m_eqn[1] = m_x; + b = true; + } + } else if(m_eqn[1].isMultiplication() && m_eqn[1].size() >= 2) { + b = true; + MathStructure m_fx(1, 1, 0), m_fy(1, 1, 0); + for(size_t i = 0; i < m_eqn[1].size(); i++) { + if(m_eqn[1][i].containsRepresentativeOf(m_y, true, true) != 0) { + if(m_eqn[1][i].containsRepresentativeOf(m_x, true, true) != 0) { + b = false; + break; + } + if(m_fy.isOne()) m_fy = m_eqn[1][i]; + else m_fy.multiply(m_eqn[1][i], true); + } else { + if(m_fx.isOne()) m_fx = m_eqn[1][i]; + else m_fx.multiply(m_eqn[1][i], true); + } + } + if(b) { + // y'=f(x)*f(y) + m_fy.inverse(); + if(m_fy.integrate(m_y, eo, true, false) > 0 && m_fx.integrate(m_x, eo, true, false) > 0) { + m_eqn[0] = m_fy; + m_eqn[1] = m_fx; + } else { + b = false; + } + } + } else { + MathStructure mfactor(m_eqn); + mfactor[1].factorize(eo, false, 0, 0, false, false, NULL, m_x); + if(mfactor[1].isMultiplication() && mfactor[1].size() >= 2) { + mfactor.childUpdated(2); + if(dsolve(mfactor, eo, m_diff, y_value, x_value)) { + m_eqn = mfactor; + return 1; + } + } + if(m_eqn[1].isAddition()) { + MathStructure m_left; + MathStructure m_muly; + MathStructure m_mul_exp; + MathStructure m_exp; + b = true; + for(size_t i = 0; i < m_eqn[1].size(); i++) { + if(m_eqn[1][i] == m_y) { + if(m_muly.isZero()) m_muly = m_one; + else m_muly.add(m_one, true); + } else if(m_eqn[1][i].containsRepresentativeOf(m_y, true, true) != 0) { + if(m_left.isZero() && m_eqn[1][i].isPower() && m_eqn[1][i][0] == m_y && (m_mul_exp.isZero() || m_eqn[1][i][1] == m_exp)) { + if(m_mul_exp.isZero()) { + m_exp = m_eqn[1][i][1]; + m_mul_exp = m_one; + } else { + m_mul_exp.add(m_one, true); + } + } else if(m_eqn[1][i].isMultiplication()) { + size_t i_my = 0; + bool b2 = false, b2_exp = false; + for(size_t i2 = 0; i2 < m_eqn[1][i].size(); i2++) { + if(!b2 && m_eqn[1][i][i2] == m_y) { + i_my = i2; + b2 = true; + } else if(!b2 && m_left.isZero() && m_eqn[1][i][i2].isPower() && m_eqn[1][i][i2][0] == m_y && (m_mul_exp.isZero() || m_eqn[1][i][i2][1] == m_exp)) { + i_my = i2; + b2 = true; + b2_exp = true; + } else if(m_eqn[1][i][i2].containsRepresentativeOf(m_y, true, true) != 0) { + b2 = false; + break; + } + } + if(b2) { + MathStructure m_a(m_eqn[1][i]); + m_a.delChild(i_my + 1, true); + if(b2_exp) { + if(m_mul_exp.isZero()) { + m_exp = m_eqn[1][i][i_my][1]; + m_mul_exp = m_a; + } else { + m_mul_exp.add(m_a, true); + } + } else { + if(m_muly.isZero()) m_muly = m_a; + else m_muly.add(m_a, true); + } + } else { + b = false; + break; + } + } else { + b = false; + break; + } + } else { + if(!m_mul_exp.isZero()) { + b = false; + break; + } + if(m_left.isZero()) m_left = m_eqn[1][i]; + else m_left.add(m_eqn[1][i], true); + } + } + if(b && !m_muly.isZero()) { + if(!m_mul_exp.isZero()) { + if(m_exp.isOne() || !m_left.isZero()) return false; + // y' = f(x)*y+g(x)*y^c + b = false; + m_muly.calculateNegate(eo); + MathStructure m_y1_integ(m_muly); + if(m_y1_integ.integrate(m_x, eo, true, false) > 0) { + m_exp.negate(); + m_exp += m_one; + MathStructure m_y1_exp(m_exp); + m_y1_exp *= m_y1_integ; + m_y1_exp.transform(STRUCT_POWER, CALCULATOR->getVariableById(VARIABLE_ID_E)); + m_y1_exp.swapChildren(1, 2); + MathStructure m_y1_exp_integ(m_y1_exp); + m_y1_exp_integ *= m_mul_exp; + if(m_y1_exp_integ.integrate(m_x, eo, true, false) > 0) { + m_eqn[1] = m_exp; + m_eqn[1] *= m_y1_exp_integ; + m_eqn[0] = m_y; + m_eqn[0] ^= m_exp; + m_eqn[0] *= m_y1_exp; + add_C(m_eqn, m_x, m_y, x_value, y_value); + m_eqn[0].delChild(m_eqn[0].size()); + m_eqn[1] /= m_y1_exp; + m_eqn.childrenUpdated(); + return 1; + } + } + } else if(m_left.isZero()) { + // y'=f(x)*y+g(x)*y + MathStructure mtest(m_eqn); + MathStructure m_fy(m_y); + m_fy.inverse(); + MathStructure m_fx(m_muly); + if(m_fy.integrate(m_y, eo, true, false) > 0 && m_fx.integrate(m_x, eo, true, false) > 0) { + m_eqn[0] = m_fy; + m_eqn[1] = m_fx; + b = true; + } + } else { + // y'=f(x)*y+g(x) + MathStructure integ_fac(m_muly); + integ_fac.negate(); + if(integ_fac.integrate(m_x, eo, true, false) > 0) { + UnknownVariable *var = new UnknownVariable("", "u"); + Assumptions *ass = new Assumptions(); + if(false) { + ass->setType(ASSUMPTION_TYPE_REAL); + } + var->setAssumptions(ass); + MathStructure m_u(var); + m_u.inverse(); + if(m_u.integrate(var, eo, false, false) > 0) { + MathStructure m_eqn2(integ_fac); + m_eqn2.transform(COMPARISON_EQUALS, m_u); + m_eqn2.isolate_x(eo, var); + if(m_eqn2.isComparison() && m_eqn2.comparisonType() == COMPARISON_EQUALS && m_eqn2[0] == var) { + integ_fac = m_eqn2[1]; + MathStructure m_fx(m_left); + m_fx *= integ_fac; + if(m_fx.integrate(m_x, eo, true, false) > 0) { + m_eqn[0] = m_y; + m_eqn[0] *= integ_fac; + m_eqn[1] = m_fx; + add_C(m_eqn, m_x, m_y, x_value, y_value); + m_eqn[0] = m_y; + m_eqn[1] /= integ_fac; + m_eqn.childrenUpdated(); + return 1; + } + } else if(m_eqn2.isLogicalOr() && m_eqn2.size() >= 2) { + b = true; + for(size_t i = 0; i < m_eqn2.size(); i++) { + if(!m_eqn2[i].isComparison() || m_eqn2[i].comparisonType() != COMPARISON_EQUALS || m_eqn2[i][0] != var) { + b = false; + break; + } + } + if(b) { + MathStructure m_eqn_new; + m_eqn_new.setType(STRUCT_LOGICAL_OR); + for(size_t i = 0; i < m_eqn2.size(); i++) { + integ_fac = m_eqn2[i][1]; + MathStructure m_fx(m_left); + m_fx *= integ_fac; + if(m_fx.integrate(m_x, eo, true, false) > 0) { + MathStructure m_fy(m_y); + m_fy *= integ_fac; + m_eqn_new.addChild(m_fy); + m_eqn_new.last().transform(COMPARISON_EQUALS, m_fx); + add_C(m_eqn_new.last(), m_x, m_y, x_value, y_value); + m_eqn_new.last()[0] = m_y; + m_eqn_new.last()[1] /= integ_fac; + m_eqn_new.last().childrenUpdated(); + m_eqn_new.childUpdated(m_eqn_new.size()); + } else { + b = false; + break; + } + } + if(b) { + m_eqn_new.childrenUpdated(); + m_eqn = m_eqn_new; + return 1; + } + } + } + } + var->destroy(); + } + } + } else { + b = false; + } + } + } + if(b) { + add_C(m_eqn, m_x, m_y, x_value, y_value); + return 1; + } + } + return false; +} + +DSolveFunction::DSolveFunction() : MathFunction("dsolve", 1, 3) { + setDefaultValue(2, "undefined"); + setDefaultValue(3, "0"); +} +int DSolveFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + MathStructure m_eqn(vargs[0]); + EvaluationOptions eo2 = eo; + eo2.isolate_x = false; + eo2.protected_function = CALCULATOR->getFunctionById(FUNCTION_ID_DIFFERENTIATE); + m_eqn.eval(eo2); + MathStructure *m_diff_p = NULL; + if(m_eqn.isLogicalAnd()) { + for(size_t i = 0; i < m_eqn.size(); i++) { + if(m_eqn[i].isComparison() && m_eqn.comparisonType() == COMPARISON_EQUALS) { + m_diff_p = find_deqn(m_eqn[i]); + if(m_diff_p) break; + } + } + } else if(m_eqn.isComparison() && m_eqn.comparisonType() == COMPARISON_EQUALS) { + m_diff_p = find_deqn(m_eqn); + } + if(!m_diff_p) { + CALCULATOR->error(true, _("No differential equation found."), NULL); + mstruct = m_eqn; return -1; + } + MathStructure m_diff(*m_diff_p); + if(m_diff.size() < 3 || (!m_diff[0].isSymbolic() && !m_diff[0].isVariable()) || (!m_diff[1].isSymbolic() && !m_diff[1].isVariable()) || !m_diff[2].isInteger() || !m_diff[2].number().isPositive() || !m_diff[2].number().isLessThanOrEqualTo(10)) { + CALCULATOR->error(true, _("No differential equation found."), NULL); + mstruct = m_eqn; return -1; + } + if(m_diff[2].number().intValue() != 1) { + CALCULATOR->error(true, _("Unable to solve differential equation."), NULL); + mstruct = m_eqn; + return -1; + } + m_eqn.isolate_x(eo2, m_diff); + mstruct = m_eqn; + if(eo.approximation == APPROXIMATION_TRY_EXACT) eo2.approximation = APPROXIMATION_EXACT; + if(m_eqn.isLogicalAnd()) { + for(size_t i = 0; i < m_eqn.size(); i++) { + if(m_eqn[i].isComparison() && m_eqn[i].comparisonType() == COMPARISON_EQUALS && m_eqn[i][0] == m_diff) { + dsolve(m_eqn[i], eo2, m_diff, vargs[1], vargs[2]); + } + } + } else if(m_eqn.isLogicalOr()) { + for(size_t i = 0; i < m_eqn.size(); i++) { + if(m_eqn[i].isComparison() && m_eqn[i].comparisonType() == COMPARISON_EQUALS && m_eqn[i][0] == m_diff) { + dsolve(m_eqn[i], eo2, m_diff, vargs[1], vargs[2]); + } else if(m_eqn[i].isLogicalAnd()) { + for(size_t i2 = 0; i2 < m_eqn[i].size(); i2++) { + if(m_eqn[i][i2].isComparison() && m_eqn[i][i2].comparisonType() == COMPARISON_EQUALS && m_eqn[i][i2][0] == m_diff) { + dsolve(m_eqn[i][i2], eo2, m_diff, vargs[1], vargs[2]); + } + } + } + } + } else if(m_eqn.isComparison() && m_eqn.comparisonType() == COMPARISON_EQUALS && m_eqn[0] == m_diff) { + dsolve(m_eqn, eo2, m_diff, vargs[1], vargs[2]); + } + if(m_eqn.contains(m_diff)) { + CALCULATOR->error(true, _("Unable to solve differential equation."), NULL); + return -1; + } + m_eqn.calculatesub(eo2, eo2, true); + MathStructure msolve(m_eqn); + if(solve_equation(msolve, m_eqn, m_diff[0], eo, true, m_diff[1], MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_C)), vargs[2], vargs[1]) <= 0) { + CALCULATOR->error(true, _("Unable to solve differential equation."), NULL); + return -1; + } + mstruct = msolve; + return 1; +} + diff -Nru libqalculate-3.6.0/libqalculate/BuiltinFunctions-calculus.cc libqalculate-3.7.0/libqalculate/BuiltinFunctions-calculus.cc --- libqalculate-3.6.0/libqalculate/BuiltinFunctions-calculus.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/BuiltinFunctions-calculus.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,471 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Number.h" +#include "Calculator.h" +#include "Variable.h" +#include "Unit.h" + +#include +#include +#include +#include + +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +#define FR_FUNCTION(FUNC) Number nr(vargs[0].number()); if(!nr.FUNC() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;} +#define FR_FUNCTION_2(FUNC) Number nr(vargs[0].number()); if(!nr.FUNC(vargs[1].number()) || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate() && !vargs[1].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex() && !vargs[1].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity() && !vargs[1].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;} +#define NON_COMPLEX_NUMBER_ARGUMENT(i) NumberArgument *arg_non_complex##i = new NumberArgument(); arg_non_complex##i->setComplexAllowed(false); setArgumentDefinition(i, arg_non_complex##i); + +liFunction::liFunction() : MathFunction("li", 1) { + names[0].case_sensitive = true; + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false)); +} +bool liFunction::representsReal(const MathStructure &vargs, bool) const { + return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative() && ((vargs[0].isNumber() && !COMPARISON_IS_NOT_EQUAL(vargs[0].number().compare(nr_one))) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && COMPARISON_IS_NOT_EQUAL(((KnownVariable*) vargs[0].variable())->get().number().compare(nr_one)))); +} +bool liFunction::representsNonComplex(const MathStructure &vargs, bool) const { + return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative(); +} +bool liFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber() && ((vargs[0].isNumber() && COMPARISON_IS_NOT_EQUAL(vargs[0].number().compare(nr_one))) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && COMPARISON_IS_NOT_EQUAL(((KnownVariable*) vargs[0].variable())->get().number().compare(nr_one))));} +int liFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION(logint) +} +EiFunction::EiFunction() : MathFunction("Ei", 1) { + names[0].case_sensitive = true; + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false)); +} +bool EiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonZero();} +bool EiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +bool EiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber() && vargs[0].representsNonZero();} +int EiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION(expint) +} +FresnelSFunction::FresnelSFunction() : MathFunction("fresnels", 1) { + NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + Number fr(-6, 1); + arg->setMin(&fr); + fr = 6; + arg->setMax(&fr); + setArgumentDefinition(1, arg); +} +bool FresnelSFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsPositive();} +bool FresnelSFunction::representsNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNegative();} +bool FresnelSFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative();} +bool FresnelSFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonPositive();} +bool FresnelSFunction::representsInteger(const MathStructure&, bool) const {return false;} +bool FresnelSFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} +bool FresnelSFunction::representsRational(const MathStructure&, bool) const {return false;} +bool FresnelSFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +bool FresnelSFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +bool FresnelSFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsComplex();} +bool FresnelSFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonZero();} +bool FresnelSFunction::representsEven(const MathStructure&, bool) const {return false;} +bool FresnelSFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool FresnelSFunction::representsUndefined(const MathStructure&) const {return false;} +int FresnelSFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct = vargs[0]; + mstruct.eval(eo); + if(contains_angle_unit(mstruct, eo.parse_options)) {mstruct /= CALCULATOR->getRadUnit(); mstruct.eval(eo);} + if(!mstruct.isNumber()) return -1; + Number nr(mstruct.number()); if(!nr.fresnels() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity())) { + return -1; + } + mstruct.set(nr); + return 1; +} +FresnelCFunction::FresnelCFunction() : MathFunction("fresnelc", 1) { + NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + Number fr(-6, 1); + arg->setMin(&fr); + fr = 6; + arg->setMax(&fr); + setArgumentDefinition(1, arg); +} +bool FresnelCFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsPositive();} +bool FresnelCFunction::representsNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNegative();} +bool FresnelCFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative();} +bool FresnelCFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonPositive();} +bool FresnelCFunction::representsInteger(const MathStructure&, bool) const {return false;} +bool FresnelCFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} +bool FresnelCFunction::representsRational(const MathStructure&, bool) const {return false;} +bool FresnelCFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +bool FresnelCFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +bool FresnelCFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsComplex();} +bool FresnelCFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonZero();} +bool FresnelCFunction::representsEven(const MathStructure&, bool) const {return false;} +bool FresnelCFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool FresnelCFunction::representsUndefined(const MathStructure&) const {return false;} +int FresnelCFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct = vargs[0]; + mstruct.eval(eo); + if(contains_angle_unit(mstruct, eo.parse_options)) {mstruct /= CALCULATOR->getRadUnit(); mstruct.eval(eo);} + if(!mstruct.isNumber()) return -1; + Number nr(mstruct.number()); if(!nr.fresnelc() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity())) { + return -1; + } + mstruct.set(nr); + return 1; +} +SiFunction::SiFunction() : MathFunction("Si", 1) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); +} +bool SiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} +bool SiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool SiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);} +int SiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(contains_angle_unit(mstruct, eo.parse_options)) {mstruct /= CALCULATOR->getRadUnit(); mstruct.eval(eo);} + if(mstruct.isNumber()) { + Number nr(mstruct.number()); + if(nr.isPlusInfinity()) { + mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI), true); + mstruct *= nr_half; + return 1; + } + if(nr.isMinusInfinity()) { + mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI), true); + mstruct *= nr_minus_half; + return 1; + } + if(nr.hasImaginaryPart() && !nr.hasRealPart()) { + mstruct.set(nr.imaginaryPart()); + mstruct.transformById(FUNCTION_ID_SINHINT); + mstruct *= nr_one_i; + return 1; + } + if(nr.sinint() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || mstruct.number().includesInfinity())) { + mstruct.set(nr); + return 1; + } + } + if(has_predominately_negative_sign(mstruct)) { + negate_struct(mstruct); + mstruct.transform(this); + mstruct.negate(); + return 1; + } + return -1; +} +CiFunction::CiFunction() : MathFunction("Ci", 1) { + names[0].case_sensitive = true; + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); +} +bool CiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsPositive();} +bool CiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} +bool CiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative(true);} +int CiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(contains_angle_unit(mstruct, eo.parse_options)) {mstruct /= CALCULATOR->getRadUnit(); mstruct.eval(eo);} + if(mstruct.isNumber()) { + if(mstruct.number().isNegative()) { + if(!eo.allow_complex) return -1; + mstruct.negate(); + mstruct.transform(this); + mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.last() *= nr_one_i; + return 1; + } + Number nr(mstruct.number()); + if(nr.isComplex() && nr.hasImaginaryPart() && !nr.hasRealPart()) { + mstruct.set(nr.imaginaryPart()); + if(nr.imaginaryPartIsNegative()) mstruct.negate(); + mstruct.transformById(FUNCTION_ID_COSHINT); + mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.last() *= nr_half; + if(nr.imaginaryPartIsPositive()) mstruct.last() *= nr_one_i; + else mstruct.last() *= nr_minus_i; + return 1; + } + if(nr.cosint() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || mstruct.number().includesInfinity())) { + mstruct.set(nr); + return 1; + } + } + return -1; +} +ShiFunction::ShiFunction() : MathFunction("Shi", 1) { + names[0].case_sensitive = true; + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); +} +bool ShiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool ShiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} +bool ShiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);} +int ShiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(mstruct.isNumber()) { + Number nr(mstruct.number()); + if(nr.hasImaginaryPart() && !nr.hasRealPart()) { + mstruct.set(nr.imaginaryPart()); + mstruct.transformById(FUNCTION_ID_SININT); + mstruct *= nr_one_i; + return 1; + } + if(nr.sinhint() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || mstruct.number().includesInfinity())) { + mstruct.set(nr); + return 1; + } + } + if(has_predominately_negative_sign(mstruct)) { + negate_struct(mstruct); + mstruct.transform(this); + mstruct.negate(); + return 1; + } + return -1; +} +ChiFunction::ChiFunction() : MathFunction("Chi", 1) { + names[0].case_sensitive = true; + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); +} +bool ChiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsPositive();} +bool ChiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative();} +bool ChiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} +int ChiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(mstruct.isNumber()) { + if(eo.allow_complex && mstruct.number().isNegative()) { + if(!eo.allow_complex) return -1; + mstruct.negate(); + mstruct.transform(this); + mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.last() *= nr_one_i; + return 1; + } + Number nr(mstruct.number()); + if(nr.isComplex() && nr.hasImaginaryPart() && !nr.hasRealPart()) { + mstruct.set(nr.imaginaryPart()); + if(nr.imaginaryPartIsNegative()) mstruct.negate(); + mstruct.transformById(FUNCTION_ID_COSINT); + mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.last() *= nr_half; + if(nr.imaginaryPartIsPositive()) mstruct.last() *= nr_one_i; + else mstruct.last() *= nr_minus_i; + return 1; + } + if(nr.coshint() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || mstruct.number().includesInfinity())) { + mstruct.set(nr); + return 1; + } + } + return -1; +} + +IGammaFunction::IGammaFunction() : MathFunction("igamma", 2) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false)); + setArgumentDefinition(2, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false)); +} +bool IGammaFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[1].representsPositive() || (vargs[0].representsInteger() && vargs[0].representsPositive()));} +bool IGammaFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[1].representsNonNegative() || (vargs[0].representsInteger() && vargs[0].representsNonNegative()));} +bool IGammaFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[1].representsNonZero() || vargs[0].representsPositive());} +int IGammaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION_2(igamma) +} + +LimitFunction::LimitFunction() : MathFunction("limit", 2, 4) { + NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + arg->setComplexAllowed(false); + arg->setHandleVector(true); + setArgumentDefinition(2, arg); + setArgumentDefinition(3, new SymbolicArgument()); + setDefaultValue(3, "x"); + IntegerArgument *iarg = new IntegerArgument(); + iarg->setMin(&nr_minus_one); + iarg->setMax(&nr_one); + setArgumentDefinition(4, iarg); + setDefaultValue(4, "0"); +} +int LimitFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[1].isVector()) return 0; + mstruct = vargs[0]; + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_EXACT; + if(mstruct.calculateLimit(vargs[2], vargs[1], eo2, vargs[3].number().intValue())) return 1; + CALCULATOR->error(true, _("Unable to find limit."), NULL); + return -1; +} +bool replace_diff_x(MathStructure &m, const MathStructure &mfrom, const MathStructure &mto) { + if(m.equals(mfrom, true, true)) { + m = mto; + return true; + } + if(m.type() == STRUCT_FUNCTION && m.function()->id() == FUNCTION_ID_DIFFERENTIATE) { + if(m.size() >= 4 && m[1] == mfrom && m[3].isUndefined()) { + m[3] = mto; + return true; + } + return false; + } + bool b = false; + for(size_t i = 0; i < m.size(); i++) { + if(replace_diff_x(m[i], mfrom, mto)) { + b = true; + m.childUpdated(i + 1); + } + } + return b; +} + +DeriveFunction::DeriveFunction() : MathFunction("diff", 1, 4) { + setArgumentDefinition(2, new SymbolicArgument()); + setDefaultValue(2, "undefined"); + Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SINT); + arg->setHandleVector(false); + setArgumentDefinition(3, arg); + setDefaultValue(3, "1"); + setDefaultValue(4, "undefined"); +} +int DeriveFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + int i = vargs[2].number().intValue(); + mstruct = vargs[0]; + bool b = false; + while(i) { + if(CALCULATOR->aborted()) return 0; + if(!mstruct.differentiate(vargs[1], eo) && !b) { + return 0; + } + b = true; + i--; + if(i > 0) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_EXACT; + eo2.calculate_functions = false; + mstruct.eval(eo2); + } + } + if(!vargs[3].isUndefined()) replace_diff_x(mstruct, vargs[1], vargs[3]); + return 1; +} + +RombergFunction::RombergFunction() : MathFunction("romberg", 3, 6) { + Argument *arg = new Argument("", false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); + NON_COMPLEX_NUMBER_ARGUMENT(2) + NON_COMPLEX_NUMBER_ARGUMENT(3) + setCondition("\\z > \\y"); + IntegerArgument *iarg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG); + Number nr(2, 1); + iarg->setMin(&nr); + setArgumentDefinition(4, iarg); + setDefaultValue(4, "6"); + setArgumentDefinition(5, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG)); + setDefaultValue(5, "20"); + setArgumentDefinition(6, new SymbolicArgument()); + setDefaultValue(6, "undefined"); +} +int RombergFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + MathStructure minteg(vargs[0]); + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + Number nr_interval; + nr_interval.setInterval(vargs[1].number(), vargs[2].number()); + UnknownVariable *var = new UnknownVariable("", format_and_print(vargs[5])); + var->setInterval(nr_interval); + MathStructure x_var(var); + minteg.replace(vargs[5], x_var); + var->destroy(); + minteg.eval(eo2); + Number nr; + eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; + eo2.warn_about_denominators_assumed_nonzero = false; + CALCULATOR->beginTemporaryStopMessages(); + if(romberg(minteg, nr, x_var, eo2, vargs[1].number(), vargs[2].number(), vargs[4].number().lintValue(), vargs[3].number().lintValue(), false)) { + CALCULATOR->endTemporaryStopMessages(); + mstruct = nr; + return 1; + } + CALCULATOR->endTemporaryStopMessages(); + CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); + return 0; +} +MonteCarloFunction::MonteCarloFunction() : MathFunction("montecarlo", 4, 5) { + Argument *arg = new Argument("", false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); + NON_COMPLEX_NUMBER_ARGUMENT(2) + NON_COMPLEX_NUMBER_ARGUMENT(3) + setCondition("\\z > \\y"); + setArgumentDefinition(4, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE)); + setArgumentDefinition(5, new SymbolicArgument()); + setDefaultValue(5, "undefined"); +} +int MonteCarloFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + MathStructure minteg(vargs[0]); + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + Number nr_interval; + nr_interval.setInterval(vargs[1].number(), vargs[2].number()); + UnknownVariable *var = new UnknownVariable("", format_and_print(vargs[4])); + var->setInterval(nr_interval); + MathStructure x_var(var); + minteg.replace(vargs[4], x_var); + var->destroy(); + minteg.eval(eo2); + Number nr; + eo2.interval_calculation = INTERVAL_CALCULATION_NONE; + if(montecarlo(minteg, nr, x_var, eo2, vargs[1].number(), vargs[2].number(), vargs[3].number())) { + mstruct = nr; + return 1; + } + CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); + return 0; +} + +IntegrateFunction::IntegrateFunction() : MathFunction("integrate", 1, 5) { + Argument *arg = new Argument("", false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); + setDefaultValue(2, "undefined"); + arg = new Argument("", false, false); + arg->setHandleVector(true); + setArgumentDefinition(2, arg); + setDefaultValue(3, "undefined"); + arg = new Argument("", false, false); + arg->setHandleVector(true); + setArgumentDefinition(3, arg); + setArgumentDefinition(4, new SymbolicArgument()); + setDefaultValue(4, "undefined"); + setArgumentDefinition(5, new BooleanArgument()); + setDefaultValue(5, "0"); +} +int IntegrateFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct = vargs[0]; + if(vargs.size() >= 2 && (vargs.size() == 2 || vargs[2].isUndefined()) && (vargs[1].isSymbolic() || (vargs[1].isVariable() && !vargs[1].variable()->isKnown()))) { + if(mstruct.integrate(vargs.size() < 3 ? m_undefined : vargs[2], vargs.size() < 4 ? m_undefined : vargs[3], vargs[1], eo, vargs.size() >= 4 && vargs[4].number().getBoolean(), true)) return 1; + } else { + if(mstruct.integrate(vargs.size() < 2 ? m_undefined : vargs[1], vargs.size() < 3 ? m_undefined : vargs[2], vargs.size() < 3 ? CALCULATOR->getVariableById(VARIABLE_ID_X) : vargs[3], eo, vargs.size() >= 4 && vargs[4].number().getBoolean(), true)) return 1; + } + return -1; +} + diff -Nru libqalculate-3.6.0/libqalculate/BuiltinFunctions.cc libqalculate-3.7.0/libqalculate/BuiltinFunctions.cc --- libqalculate-3.6.0/libqalculate/BuiltinFunctions.cc 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/BuiltinFunctions.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,9223 +0,0 @@ -/* - Qalculate (library) - - Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. -*/ - -#include "support.h" - -#include "BuiltinFunctions.h" -#include "util.h" -#include "MathStructure.h" -#include "Number.h" -#include "Calculator.h" -#include "Variable.h" -#include "Unit.h" - -#include -#include -#include -#include - -#if HAVE_UNORDERED_MAP -# include - using std::unordered_map; -#elif defined(__GNUC__) - -# ifndef __has_include -# define __has_include(x) 0 -# endif - -# if (defined(__clang__) && __has_include()) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 3) -# include - namespace Sgi = std; -# define unordered_map std::tr1::unordered_map -# else -# if __GNUC__ < 3 -# include - namespace Sgi { using ::hash_map; }; // inherit globals -# else -# include -# if __GNUC__ == 3 && __GNUC_MINOR__ == 0 - namespace Sgi = std; // GCC 3.0 -# else - namespace Sgi = ::__gnu_cxx; // GCC 3.1 and later -# endif -# endif -# define unordered_map Sgi::hash_map -# endif -#else // ... there are other compilers, right? - namespace Sgi = std; -# define unordered_map Sgi::hash_map -#endif - -using std::string; -using std::cout; -using std::vector; -using std::ostream; -using std::endl; - -#define FR_FUNCTION(FUNC) Number nr(vargs[0].number()); if(!nr.FUNC() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;} -#define FR_FUNCTION_2(FUNC) Number nr(vargs[0].number()); if(!nr.FUNC(vargs[1].number()) || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate() && !vargs[1].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex() && !vargs[1].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity() && !vargs[1].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;} -#define FR_FUNCTION_2R(FUNC) Number nr(vargs[1].number()); if(!nr.FUNC(vargs[0].number()) || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate() && !vargs[1].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex() && !vargs[1].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity() && !vargs[1].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;} - -#define REPRESENTS_FUNCTION(x, y) x::x() : MathFunction(#y, 1) {} int x::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {mstruct = vargs[0]; mstruct.eval(eo); if(mstruct.y()) {mstruct.clear(); mstruct.number().setTrue();} else {mstruct.clear(); mstruct.number().setFalse();} return 1;} - -#define IS_NUMBER_FUNCTION(x, y) x::x() : MathFunction(#y, 1) {} int x::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {mstruct = vargs[0]; if(!mstruct.isNumber()) mstruct.eval(eo); if(mstruct.isNumber() && mstruct.number().y()) {mstruct.number().setTrue();} else {mstruct.clear(); mstruct.number().setFalse();} return 1;} - -#define NON_COMPLEX_NUMBER_ARGUMENT(i) NumberArgument *arg_non_complex##i = new NumberArgument(); arg_non_complex##i->setComplexAllowed(false); setArgumentDefinition(i, arg_non_complex##i); -#define NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(i) NumberArgument *arg_non_complex##i = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false); arg_non_complex##i->setComplexAllowed(false); setArgumentDefinition(i, arg_non_complex##i); -#define NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR_NONZERO(i) NumberArgument *arg_non_complex##i = new NumberArgument("", ARGUMENT_MIN_MAX_NONZERO, true, false); arg_non_complex##i->setComplexAllowed(false); setArgumentDefinition(i, arg_non_complex##i); -#define RATIONAL_NUMBER_ARGUMENT_NO_ERROR(i) NumberArgument *arg_rational##i = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false); arg_rational##i->setRationalNumber(true); setArgumentDefinition(i, arg_rational##i); -#define RATIONAL_POLYNOMIAL_ARGUMENT(i) Argument *arg_poly##i = new Argument(); arg_poly##i->setRationalPolynomial(true); setArgumentDefinition(i, arg_poly##i); -#define RATIONAL_POLYNOMIAL_ARGUMENT_HV(i) Argument *arg_poly##i = new Argument(); arg_poly##i->setRationalPolynomial(true); arg_poly##i->setHandleVector(true); setArgumentDefinition(i, arg_poly##i); - -extern string format_and_print(const MathStructure &mstruct); -extern bool replace_f_interval(MathStructure &mstruct, const EvaluationOptions &eo); -extern bool replace_intervals_f(MathStructure &mstruct); - -bool calculate_arg(MathStructure &mstruct, const EvaluationOptions &eo); - -VectorFunction::VectorFunction() : MathFunction("vector", -1) { -} -int VectorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = vargs; - mstruct.setType(STRUCT_VECTOR); - return 1; -} -MatrixFunction::MatrixFunction() : MathFunction("matrix", 3) { - Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE); - arg->setHandleVector(false); - setArgumentDefinition(1, arg); - arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE); - arg->setHandleVector(false); - setArgumentDefinition(2, arg); - setArgumentDefinition(3, new VectorArgument()); -} -int MatrixFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - size_t rows = (size_t) vargs[0].number().uintValue(); - size_t columns = (size_t) vargs[1].number().uintValue(); - mstruct.clearMatrix(); mstruct.resizeMatrix(rows, columns, m_zero); - size_t r = 1, c = 1; - for(size_t i = 0; i < vargs[2].size(); i++) { - if(r > rows || c > columns) { - CALCULATOR->error(false, _("Too many elements (%s) for the dimensions (%sx%s) of the matrix."), i2s(vargs[2].size()).c_str(), i2s(rows).c_str(), i2s(columns).c_str(), NULL); - break; - } - mstruct[r - 1][c - 1] = vargs[2][i]; - if(c == columns) { - c = 1; - r++; - } else { - c++; - } - } - return 1; -} -RankFunction::RankFunction() : MathFunction("rank", 1, 2) { - setArgumentDefinition(1, new VectorArgument("")); - setArgumentDefinition(2, new BooleanArgument("")); - setDefaultValue(2, "1"); -} -int RankFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = vargs[0]; - return mstruct.rankVector(vargs[1].number().getBoolean()); -} -SortFunction::SortFunction() : MathFunction("sort", 1, 2) { - setArgumentDefinition(1, new VectorArgument("")); - setArgumentDefinition(2, new BooleanArgument("")); - setDefaultValue(2, "1"); -} -int SortFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = vargs[0]; - return mstruct.sortVector(vargs[1].number().getBoolean()); -} -MergeVectorsFunction::MergeVectorsFunction() : MathFunction("mergevectors", 1, -1) { - setArgumentDefinition(1, new VectorArgument("")); - setArgumentDefinition(2, new VectorArgument("")); -} -int MergeVectorsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct.clearVector(); - for(size_t i = 0; i < vargs.size(); i++) { - if(CALCULATOR->aborted()) return 0; - if(vargs[i].isVector()) { - for(size_t i2 = 0; i2 < vargs[i].size(); i2++) { - mstruct.addChild(vargs[i][i2]); - } - } else { - mstruct.addChild(vargs[i]); - } - } - return 1; -} -MatrixToVectorFunction::MatrixToVectorFunction() : MathFunction("matrix2vector", 1) { - setArgumentDefinition(1, new MatrixArgument()); -} -int MatrixToVectorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - vargs[0].matrixToVector(mstruct); - return 1; -} -RowFunction::RowFunction() : MathFunction("row", 2) { - setArgumentDefinition(1, new MatrixArgument()); - setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); -} -int RowFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - size_t row = (size_t) vargs[1].number().uintValue(); - if(row > vargs[0].rows()) { - CALCULATOR->error(true, _("Row %s does not exist in matrix."), format_and_print(vargs[1]).c_str(), NULL); - return 0; - } - vargs[0].rowToVector(row, mstruct); - return 1; -} -ColumnFunction::ColumnFunction() : MathFunction("column", 2) { - setArgumentDefinition(1, new MatrixArgument()); - setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); -} -int ColumnFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - size_t col = (size_t) vargs[1].number().uintValue(); - if(col > vargs[0].columns()) { - CALCULATOR->error(true, _("Column %s does not exist in matrix."), format_and_print(vargs[1]).c_str(), NULL); - return 0; - } - vargs[0].columnToVector(col, mstruct); - return 1; -} -RowsFunction::RowsFunction() : MathFunction("rows", 1) { - setArgumentDefinition(1, new VectorArgument("")); -} -int RowsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - if(!vargs[0].isMatrix()) mstruct = m_one; - else mstruct = (int) vargs[0].rows(); - return 1; -} -ColumnsFunction::ColumnsFunction() : MathFunction("columns", 1) { - setArgumentDefinition(1, new VectorArgument("")); -} -int ColumnsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - if(!vargs[0].isMatrix()) mstruct = (int) vargs[0].countChildren(); - else mstruct = (int) vargs[0].columns(); - return 1; -} -ElementsFunction::ElementsFunction() : MathFunction("elements", 1) { - setArgumentDefinition(1, new VectorArgument("")); -} -int ElementsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - if(vargs[0].isMatrix()) { - mstruct = (int) (vargs[0].rows() * vargs[0].columns()); - } else { - mstruct = (int) vargs[0].countChildren(); - } - return 1; -} -ElementFunction::ElementFunction() : MathFunction("element", 2, 3) { - setArgumentDefinition(1, new VectorArgument("")); - setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); - setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SIZE)); - setDefaultValue(3, "0"); -} -int ElementFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - if(vargs[2].number().isPositive() && vargs[0].isMatrix()) { - size_t row = (size_t) vargs[1].number().uintValue(); - size_t col = (size_t) vargs[2].number().uintValue(); - bool b = true; - if(col > vargs[0].columns()) { - CALCULATOR->error(true, _("Column %s does not exist in matrix."), format_and_print(vargs[2]).c_str(), NULL); - b = false; - } - if(row > vargs[0].rows()) { - CALCULATOR->error(true, _("Row %s does not exist in matrix."), format_and_print(vargs[1]).c_str(), NULL); - b = false; - } - if(b) { - const MathStructure *em = vargs[0].getElement(row, col); - if(em) mstruct = *em; - else b = false; - } - return b; - } else { - if(vargs[2].number().isGreaterThan(1)) { - CALCULATOR->error(false, _("Argument 3, %s, is ignored for vectors."), getArgumentDefinition(3)->name().c_str(), NULL); - } - size_t row = (size_t) vargs[1].number().uintValue(); - if(row > vargs[0].countChildren()) { - CALCULATOR->error(true, _("Element %s does not exist in vector."), format_and_print(vargs[1]).c_str(), NULL); - return 0; - } - mstruct = *vargs[0].getChild(row); - return 1; - } -} -DimensionFunction::DimensionFunction() : MathFunction("dimension", 1) { - setArgumentDefinition(1, new VectorArgument("")); -} -int DimensionFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = (int) vargs[0].countChildren(); - return 1; -} -ComponentFunction::ComponentFunction() : MathFunction("component", 2) { - setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); - setArgumentDefinition(2, new VectorArgument("")); -} -int ComponentFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - size_t i = (size_t) vargs[0].number().uintValue(); - if(i > vargs[1].countChildren()) { - CALCULATOR->error(true, _("Element %s does not exist in vector."), format_and_print(vargs[0]).c_str(), NULL); - return 0; - } - mstruct = *vargs[1].getChild(i); - return 1; -} -LimitsFunction::LimitsFunction() : MathFunction("limits", 3) { - setArgumentDefinition(1, new VectorArgument("")); - Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SINT); - arg->setHandleVector(false); - setArgumentDefinition(2, arg); - arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SINT); - arg->setHandleVector(false); - setArgumentDefinition(3, arg); -} -int LimitsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - vargs[0].getRange(vargs[1].number().intValue(), vargs[2].number().intValue(), mstruct); - return 1; -} -AreaFunction::AreaFunction() : MathFunction("area", 5) { - setArgumentDefinition(1, new MatrixArgument("")); - Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE); - arg->setHandleVector(false); - setArgumentDefinition(2, arg); - arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE); - arg->setHandleVector(false); - setArgumentDefinition(3, arg); - arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE); - arg->setHandleVector(false); - setArgumentDefinition(4, arg); - arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE); - arg->setHandleVector(false); - setArgumentDefinition(5, arg); -} -int AreaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - vargs[0].getArea(vargs[1].number().uintValue(), vargs[2].number().uintValue(), vargs[3].number().uintValue(), vargs[4].number().uintValue(), mstruct); - return 1; -} -TransposeFunction::TransposeFunction() : MathFunction("transpose", 1) { - setArgumentDefinition(1, new MatrixArgument()); -} -int TransposeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = vargs[0]; - return mstruct.transposeMatrix(); -} -IdentityFunction::IdentityFunction() : MathFunction("identity", 1) { - ArgumentSet *arg = new ArgumentSet(); - arg->addArgument(new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); - MatrixArgument *marg = new MatrixArgument(); - marg->setSquareDemanded(true); - arg->addArgument(marg); - setArgumentDefinition(1, arg); -} -int IdentityFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - if(vargs[0].isMatrix()) { - if(vargs[0].rows() != vargs[0].columns()) { - return 0; - } - mstruct.setToIdentityMatrix(vargs[0].size()); - } else { - mstruct.setToIdentityMatrix((size_t) vargs[0].number().uintValue()); - } - return 1; -} -DeterminantFunction::DeterminantFunction() : MathFunction("det", 1) { - MatrixArgument *marg = new MatrixArgument(); - marg->setSquareDemanded(true); - setArgumentDefinition(1, marg); -} -int DeterminantFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - vargs[0].determinant(mstruct, eo); - return !mstruct.isUndefined(); -} -PermanentFunction::PermanentFunction() : MathFunction("permanent", 1) { - MatrixArgument *marg = new MatrixArgument(); - marg->setSquareDemanded(true); - setArgumentDefinition(1, marg); -} -int PermanentFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - vargs[0].permanent(mstruct, eo); - return !mstruct.isUndefined(); -} -CofactorFunction::CofactorFunction() : MathFunction("cofactor", 3) { - setArgumentDefinition(1, new MatrixArgument()); - setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); - setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); -} -int CofactorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - vargs[0].cofactor((size_t) vargs[1].number().uintValue(), (size_t) vargs[2].number().uintValue(), mstruct, eo); - return !mstruct.isUndefined(); -} -AdjointFunction::AdjointFunction() : MathFunction("adj", 1) { - MatrixArgument *marg = new MatrixArgument(); - marg->setSquareDemanded(true); - setArgumentDefinition(1, marg); -} -int AdjointFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - mstruct = vargs[0]; - if(!mstruct.adjointMatrix(eo)) return 0; - return !mstruct.isUndefined(); -} -InverseFunction::InverseFunction() : MathFunction("inverse", 1) { - MatrixArgument *marg = new MatrixArgument(); - marg->setSquareDemanded(true); - setArgumentDefinition(1, marg); -} -int InverseFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - mstruct = vargs[0]; - return mstruct.invertMatrix(eo); -} -MagnitudeFunction::MagnitudeFunction() : MathFunction("magnitude", 1) { -} -int MagnitudeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - mstruct = vargs[0]; - if(mstruct.isVector()) { - mstruct ^= nr_two; - mstruct.raise(nr_half); - return 1; - } else if(mstruct.representsScalar()) { - mstruct.transform(CALCULATOR->f_abs); - return 1; - } - mstruct.eval(eo); - if(mstruct.isVector()) { - mstruct ^= nr_two; - mstruct.raise(nr_half); - return 1; - } - mstruct = vargs[0]; - mstruct.transform(CALCULATOR->f_abs); - return 1; -} -HadamardFunction::HadamardFunction() : MathFunction("hadamard", 1, -1) { - setArgumentDefinition(1, new VectorArgument()); - setArgumentDefinition(2, new VectorArgument()); -} -int HadamardFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - bool b_matrix = vargs[0].isMatrix(); - for(size_t i3 = 1; i3 < vargs.size(); i3++) { - if(b_matrix) { - if(!vargs[i3].isMatrix() || vargs[i3].columns() != vargs[0].columns() || vargs[i3].rows() != vargs[0].rows()) { - CALCULATOR->error(true, _("%s() requires that all matrices/vectors have the same dimensions."), preferredDisplayName().name.c_str(), NULL); - return 0; - } - } else if(vargs[i3].size() != vargs[0].size()) { - CALCULATOR->error(true, _("%s() requires that all matrices/vectors have the same dimensions."), preferredDisplayName().name.c_str(), NULL); - return 0; - } - } - mstruct = vargs[0]; - for(size_t i = 0; i < mstruct.size(); i++) { - if(b_matrix) { - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - for(size_t i3 = 1; i3 < vargs.size(); i3++) mstruct[i][i2] *= vargs[i3][i][i2]; - } - } else { - for(size_t i3 = 1; i3 < vargs.size(); i3++) mstruct[i] *= vargs[i3][i]; - } - } - return 1; -} -EntrywiseFunction::EntrywiseFunction() : MathFunction("entrywise", 2) { - VectorArgument *arg = new VectorArgument(); - arg->addArgument(new VectorArgument()); - arg->addArgument(new SymbolicArgument()); - arg->setReoccuringArguments(true); - setArgumentDefinition(2, arg); -} -int EntrywiseFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[1].size() == 0) { - mstruct = vargs[0]; - return 1; - } - bool b_matrix = vargs[1][0].isMatrix(); - for(size_t i3 = 2; i3 < vargs[1].size(); i3 += 2) { - if(b_matrix) { - if(!vargs[1][i3].isMatrix() || vargs[1][i3].columns() != vargs[1][0].columns() || vargs[1][i3].rows() != vargs[1][0].rows()) { - CALCULATOR->error(true, _("%s() requires that all matrices/vectors have the same dimensions."), preferredDisplayName().name.c_str(), NULL); - return 0; - } - } else if(vargs[1][i3].size() != vargs[1][0].size()) { - CALCULATOR->error(true, _("%s() requires that all matrices/vectors have the same dimensions."), preferredDisplayName().name.c_str(), NULL); - return 0; - } - } - MathStructure mexpr(vargs[0]); - EvaluationOptions eo2 = eo; - eo2.calculate_functions = false; - mexpr.eval(eo2); - mstruct = vargs[1][0]; - for(size_t i = 0; i < mstruct.size(); i++) { - if(b_matrix) { - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - mstruct[i][i2] = mexpr; - for(size_t i3 = 1; i3 < vargs[1].size(); i3 += 2) { - mstruct[i][i2].replace(vargs[1][i3], vargs[1][i3 - 1][i][i2]); - } - } - } else { - mstruct[i] = mexpr; - for(size_t i3 = 1; i3 < vargs[1].size(); i3 += 2) { - mstruct[i].replace(vargs[1][i3], vargs[1][i3 - 1][i]); - } - } - } - return 1; -} - -ZetaFunction::ZetaFunction() : MathFunction("zeta", 1, 1, SIGN_ZETA) { - IntegerArgument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG); - setArgumentDefinition(1, arg); -} -int ZetaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].number().isZero()) { - mstruct.set(1, 2, 0); - return 1; - } else if(vargs[0].number().isMinusOne()) { - mstruct.set(1, 12, 0); - return 1; - } else if(vargs[0].number().isNegative() && vargs[0].number().isEven()) { - mstruct.clear(); - return 1; - } else if(vargs[0].number() == 2) { - mstruct.set(CALCULATOR->v_pi); - mstruct.raise(2); - mstruct.divide(6); - mstruct.mergePrecision(vargs[0]); - return 1; - } else if(vargs[0].number() == 4) { - mstruct.set(CALCULATOR->v_pi); - mstruct.raise(4); - mstruct.divide(90); - mstruct.mergePrecision(vargs[0]); - return 1; - } else if(vargs[0].number() == 6) { - mstruct.set(CALCULATOR->v_pi); - mstruct.raise(6); - mstruct.divide(945); - mstruct.mergePrecision(vargs[0]); - return 1; - } else if(vargs[0].number() == 8) { - mstruct.set(CALCULATOR->v_pi); - mstruct.raise(8); - mstruct.divide(9450); - mstruct.mergePrecision(vargs[0]); - return 1; - } else if(vargs[0].number() == 10) { - mstruct.set(CALCULATOR->v_pi); - mstruct.raise(10); - mstruct.divide(93555); - mstruct.mergePrecision(vargs[0]); - return 1; - } - FR_FUNCTION(zeta) -} -GammaFunction::GammaFunction() : MathFunction("gamma", 1, 1, SIGN_CAPITAL_GAMMA) { - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1); -} -int GammaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].number().isRational() && (eo.approximation == APPROXIMATION_EXACT || (eo.approximation == APPROXIMATION_TRY_EXACT && vargs[0].number().isLessThan(1000)))) { - if(vargs[0].number().isInteger() && vargs[0].number().isPositive()) { - mstruct.set(CALCULATOR->f_factorial, &vargs[0], NULL); - mstruct[0] -= 1; - return 1; - } else if(vargs[0].number().denominatorIsTwo()) { - Number nr(vargs[0].number()); - nr.floor(); - if(nr.isZero()) { - MathStructure mtmp(CALCULATOR->v_pi); - mstruct.set(CALCULATOR->f_sqrt, &mtmp, NULL); - return 1; - } else if(nr.isPositive()) { - Number nr2(nr); - nr2 *= 2; - nr2 -= 1; - nr2.doubleFactorial(); - Number nr3(2, 1, 0); - nr3 ^= nr; - nr2 /= nr3; - mstruct = nr2; - MathStructure mtmp1(CALCULATOR->v_pi); - MathStructure mtmp2(CALCULATOR->f_sqrt, &mtmp1, NULL); - mstruct *= mtmp2; - return 1; - } else { - nr.negate(); - Number nr2(nr); - nr2 *= 2; - nr2 -= 1; - nr2.doubleFactorial(); - Number nr3(2, 1, 0); - nr3 ^= nr; - if(nr.isOdd()) nr3.negate(); - nr3 /= nr2; - mstruct = nr3; - MathStructure mtmp1(CALCULATOR->v_pi); - MathStructure mtmp2(CALCULATOR->f_sqrt, &mtmp1, NULL); - mstruct *= mtmp2; - return 1; - } - } - } - FR_FUNCTION(gamma) -} -DigammaFunction::DigammaFunction() : MathFunction("digamma", 1) { - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1); -} -int DigammaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].number().isOne()) { - mstruct.set(CALCULATOR->v_euler); - mstruct.negate(); - return 1; - } - FR_FUNCTION(digamma) -} -BetaFunction::BetaFunction() : MathFunction("beta", 2, 2, SIGN_CAPITAL_BETA) { - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false)); - setArgumentDefinition(2, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false)); -} -int BetaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = vargs[0]; - mstruct.set(CALCULATOR->f_gamma, &vargs[0], NULL); - MathStructure mstruct2(CALCULATOR->f_gamma, &vargs[1], NULL); - mstruct *= mstruct2; - mstruct2[0] += vargs[0]; - mstruct /= mstruct2; - return 1; -} -AiryFunction::AiryFunction() : MathFunction("airy", 1) { - NumberArgument *arg = new NumberArgument(); - Number fr(-500, 1, 0); - arg->setMin(&fr); - fr.set(500, 1, 0); - arg->setMax(&fr); - setArgumentDefinition(1, arg); -} -int AiryFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION(airy) -} -BesseljFunction::BesseljFunction() : MathFunction("besselj", 2) { - setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG)); - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(2); -} -int BesseljFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION_2R(besselj) -} -BesselyFunction::BesselyFunction() : MathFunction("bessely", 2) { - IntegerArgument *iarg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG); - Number nmax(1000); - iarg->setMax(&nmax); - setArgumentDefinition(1, iarg); - NON_COMPLEX_NUMBER_ARGUMENT(2); -} -int BesselyFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION_2R(bessely) -} -ErfFunction::ErfFunction() : MathFunction("erf", 1) { - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1); -} -int ErfFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION(erf) -} -ErfcFunction::ErfcFunction() : MathFunction("erfc", 1) { - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1); -} -int ErfcFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION(erfc) -} - -FactorialFunction::FactorialFunction() : MathFunction("factorial", 1) { - setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONNEGATIVE, true, false, INTEGER_TYPE_SLONG)); -} -int FactorialFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION(factorial) -} -bool FactorialFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool FactorialFunction::representsNegative(const MathStructure&, bool) const {return false;} -bool FactorialFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool FactorialFunction::representsNonPositive(const MathStructure&, bool) const {return false;} -bool FactorialFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool FactorialFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool FactorialFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool FactorialFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool FactorialFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} -bool FactorialFunction::representsComplex(const MathStructure&, bool) const {return false;} -bool FactorialFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool FactorialFunction::representsEven(const MathStructure&, bool) const {return false;} -bool FactorialFunction::representsOdd(const MathStructure&, bool) const {return false;} -bool FactorialFunction::representsUndefined(const MathStructure&) const {return false;} - -DoubleFactorialFunction::DoubleFactorialFunction() : MathFunction("factorial2", 1) { - IntegerArgument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG); - Number nr(-1, 1, 0); - arg->setMin(&nr); - setArgumentDefinition(1, arg); -} -int DoubleFactorialFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION(doubleFactorial) -} -bool DoubleFactorialFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool DoubleFactorialFunction::representsNegative(const MathStructure&, bool) const {return false;} -bool DoubleFactorialFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool DoubleFactorialFunction::representsNonPositive(const MathStructure&, bool) const {return false;} -bool DoubleFactorialFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool DoubleFactorialFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool DoubleFactorialFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool DoubleFactorialFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool DoubleFactorialFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} -bool DoubleFactorialFunction::representsComplex(const MathStructure&, bool) const {return false;} -bool DoubleFactorialFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool DoubleFactorialFunction::representsEven(const MathStructure&, bool) const {return false;} -bool DoubleFactorialFunction::representsOdd(const MathStructure&, bool) const {return false;} -bool DoubleFactorialFunction::representsUndefined(const MathStructure&) const {return false;} - -MultiFactorialFunction::MultiFactorialFunction() : MathFunction("multifactorial", 2) { - setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONNEGATIVE, true, true, INTEGER_TYPE_SLONG)); - setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SLONG)); -} -int MultiFactorialFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION_2(multiFactorial) -} -bool MultiFactorialFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool MultiFactorialFunction::representsNegative(const MathStructure&, bool) const {return false;} -bool MultiFactorialFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool MultiFactorialFunction::representsNonPositive(const MathStructure&, bool) const {return false;} -bool MultiFactorialFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool MultiFactorialFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool MultiFactorialFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} -bool MultiFactorialFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool MultiFactorialFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool MultiFactorialFunction::representsComplex(const MathStructure&, bool) const {return false;} -bool MultiFactorialFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();} -bool MultiFactorialFunction::representsEven(const MathStructure&, bool) const {return false;} -bool MultiFactorialFunction::representsOdd(const MathStructure&, bool) const {return false;} -bool MultiFactorialFunction::representsUndefined(const MathStructure&) const {return false;} - -BinomialFunction::BinomialFunction() : MathFunction("binomial", 2) { - setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true)); - setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_ULONG)); -} -int BinomialFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - Number nr; - if(!nr.binomial(vargs[0].number(), vargs[1].number())) return 0; - mstruct = nr; - return 1; -} - -BitXorFunction::BitXorFunction() : MathFunction("xor", 2) { - ArgumentSet *arg = new ArgumentSet(); - arg->addArgument(new IntegerArgument("", ARGUMENT_MIN_MAX_NONE)); - arg->addArgument(new VectorArgument); - setArgumentDefinition(1, arg); - arg = new ArgumentSet(); - arg->addArgument(new IntegerArgument("", ARGUMENT_MIN_MAX_NONE)); - arg->addArgument(new VectorArgument); - setArgumentDefinition(2, arg); -} -int BitXorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isNumber() && vargs[1].isNumber()) { - Number nr(vargs[0].number()); - if(nr.bitXor(vargs[1].number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || vargs[0].number().isApproximate() || vargs[1].number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || vargs[0].number().isComplex() || vargs[1].number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || vargs[0].number().includesInfinity() || vargs[1].number().includesInfinity())) { - mstruct.set(nr, true); - return 1; - } - } else if(vargs[0].isVector() && vargs[1].isVector()) { - int i1 = 0, i2 = 1; - if(vargs[0].size() < vargs[1].size()) { - i1 = 1; - i2 = 0; - } - mstruct.clearVector(); - mstruct.resizeVector(vargs[i1].size(), m_undefined); - size_t i = 0; - for(; i < vargs[i2].size(); i++) { - mstruct[i].set(CALCULATOR->f_xor, &vargs[i1][i], &vargs[i2][0], NULL); - } - for(; i < vargs[i1].size(); i++) { - mstruct[i] = vargs[i1][i]; - mstruct[i].add(m_zero, OPERATION_GREATER); - } - return 1; - } - mstruct = vargs[0]; - mstruct.add(vargs[1], OPERATION_BITWISE_XOR); - return 0; -} -XorFunction::XorFunction() : MathFunction("lxor", 2) { -} -int XorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - int b0, b1; - if(vargs[0].representsNonPositive(true)) { - b0 = 0; - } else if(vargs[0].representsPositive(true)) { - b0 = 1; - } else { - b0 = -1; - } - if(vargs[1].representsNonPositive(true)) { - b1 = 0; - } else if(vargs[1].representsPositive(true)) { - b1 = 1; - } else { - b1 = -1; - } - if((b0 == 1 && b1 == 0) || (b0 == 0 && b1 == 1)) { - mstruct = m_one; - return 1; - } else if(b0 >= 0 && b1 >= 0) { - return 1; - } else if(b0 == 0) { - mstruct = vargs[1]; - mstruct.add(m_zero, OPERATION_GREATER); - return 1; - } else if(b0 == 1) { - mstruct = vargs[1]; - mstruct.add(m_zero, OPERATION_EQUALS_LESS); - return 1; - } else if(b1 == 0) { - mstruct = vargs[0]; - mstruct.add(m_zero, OPERATION_GREATER); - return 1; - } else if(b1 == 1) { - mstruct = vargs[0]; - mstruct.add(m_zero, OPERATION_EQUALS_LESS); - return 1; - } - mstruct = vargs[1]; - mstruct.setLogicalNot(); - mstruct.add(vargs[0], OPERATION_LOGICAL_AND); - MathStructure mstruct2(vargs[0]); - mstruct2.setLogicalNot(); - mstruct2.add(vargs[1], OPERATION_LOGICAL_AND); - mstruct.add(mstruct2, OPERATION_LOGICAL_OR); - return 1; -} - -OddFunction::OddFunction() : MathFunction("odd", 1) { - Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -int OddFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - if(vargs[0].representsOdd()) { - mstruct.set(1, 1, 0); - return 1; - } else if(vargs[0].representsEven()) { - mstruct.clear(); - return 1; - } - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.representsOdd()) { - mstruct.set(1, 1, 0); - return 1; - } else if(mstruct.representsEven()) { - mstruct.clear(); - return 1; - } - return -1; -} -EvenFunction::EvenFunction() : MathFunction("even", 1) { - Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -int EvenFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - if(vargs[0].representsEven()) { - mstruct.set(1, 1, 0); - return 1; - } else if(vargs[0].representsOdd()) { - mstruct.clear(); - return 1; - } - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.representsEven()) { - mstruct.set(1, 1, 0); - return 1; - } else if(mstruct.representsOdd()) { - mstruct.clear(); - return 1; - } - return -1; -} -ShiftFunction::ShiftFunction() : MathFunction("shift", 2, 3) { - setArgumentDefinition(1, new IntegerArgument()); - setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG)); - setArgumentDefinition(3, new BooleanArgument()); - setDefaultValue(3, "1"); -} -int ShiftFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs.size() >= 3 && !vargs[2].number().getBoolean() && vargs[1].number().isNegative()) { - Number nr(vargs[0].number()); - Number nr_div(vargs[1].number()); - if(!nr_div.negate() || !nr_div.exp2() || !nr.divide(nr_div) || !nr.trunc()) return false; - mstruct.set(nr); - return 1; - } - FR_FUNCTION_2(shift) -} -CircularShiftFunction::CircularShiftFunction() : MathFunction("bitrot", 2, 4) { - setArgumentDefinition(1, new IntegerArgument()); - setArgumentDefinition(2, new IntegerArgument()); - setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_UINT)); - setArgumentDefinition(4, new BooleanArgument()); - setDefaultValue(3, "0"); - setDefaultValue(4, "1"); -} -int CircularShiftFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].number().isZero()) { - mstruct.clear(); - return 1; - } - Number nr(vargs[0].number()); - unsigned int bits = vargs[2].number().uintValue(); - if(bits == 0) { - bits = nr.integerLength(); - if(bits <= 8) bits = 8; - else if(bits <= 16) bits = 16; - else if(bits <= 32) bits = 32; - else if(bits <= 64) bits = 64; - else if(bits <= 128) bits = 128; - else { - bits = (unsigned int) ::ceil(::log2(bits)); - bits = ::pow(2, bits); - } - } - Number nr_n(vargs[1].number()); - nr_n.rem(bits); - if(nr_n.isZero()) { - mstruct = nr; - return 1; - } - PrintOptions po; - po.base = BASE_BINARY; - po.base_display = BASE_DISPLAY_NORMAL; - po.binary_bits = bits; - string str = nr.print(po); - remove_blanks(str); - if(str.length() < bits) return 0; - if(nr_n.isNegative()) { - nr_n.negate(); - std::rotate(str.rbegin(), str.rbegin() + nr_n.uintValue(), str.rend()); - } else { - std::rotate(str.begin(), str.begin() + nr_n.uintValue(), str.end()); - } - ParseOptions pao; - pao.base = BASE_BINARY; - pao.twos_complement = vargs[3].number().getBoolean(); - mstruct = Number(str, pao); - return 1; -} -BitCmpFunction::BitCmpFunction() : MathFunction("bitcmp", 1, 3) { - setArgumentDefinition(1, new IntegerArgument()); - setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_UINT)); - setDefaultValue(2, "0"); - setArgumentDefinition(3, new BooleanArgument()); - setDefaultValue(3, "0"); -} -int BitCmpFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - Number nr(vargs[0].number()); - if(vargs.size() >= 3 && vargs[2].number().getBoolean()) { - if(nr.bitNot()) { - mstruct = nr; - return 1; - } - return 0; - } - unsigned int bits = vargs[1].number().uintValue(); - if(bits == 0) { - bits = nr.integerLength(); - if(bits <= 8) bits = 8; - else if(bits <= 16) bits = 16; - else if(bits <= 32) bits = 32; - else if(bits <= 64) bits = 64; - else if(bits <= 128) bits = 128; - else { - bits = (unsigned int) ::ceil(::log2(bits)); - bits = ::pow(2, bits); - } - } - if(nr.bitCmp(bits)) { - mstruct = nr; - return 1; - } - return 0; -} - -bool test_eval(MathStructure &mtest, const EvaluationOptions &eo) { - EvaluationOptions eo2 = eo; - eo2.assume_denominators_nonzero = false; - eo2.approximation = APPROXIMATION_APPROXIMATE; - CALCULATOR->beginTemporaryEnableIntervalArithmetic(); - CALCULATOR->beginTemporaryStopMessages(); - mtest.calculateFunctions(eo2); - mtest.calculatesub(eo2, eo2, true); - CALCULATOR->endTemporaryEnableIntervalArithmetic(); - if(CALCULATOR->endTemporaryStopMessages()) return false; - return true; -} -bool has_interval_unknowns(MathStructure &m) { - if(m.isVariable() && !m.variable()->isKnown()) { - Assumptions *ass = ((UnknownVariable*) m.variable())->assumptions(); - return !((UnknownVariable*) m.variable())->interval().isUndefined() || (ass && ((ass->sign() != ASSUMPTION_SIGN_UNKNOWN && ass->sign() != ASSUMPTION_SIGN_NONZERO) || ass->min() || ass->max())); - } - for(size_t i = 0; i < m.size(); i++) { - if(has_interval_unknowns(m[i])) return true; - } - return false; -} - -AbsFunction::AbsFunction() : MathFunction("abs", 1) { - Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -bool AbsFunction::representsPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units) && vargs[0].representsNonZero(allow_units);} -bool AbsFunction::representsNegative(const MathStructure&, bool) const {return false;} -bool AbsFunction::representsNonNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} -bool AbsFunction::representsNonPositive(const MathStructure&, bool) const {return false;} -bool AbsFunction::representsInteger(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsInteger(allow_units);} -bool AbsFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} -bool AbsFunction::representsRational(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsRational(allow_units);} -bool AbsFunction::representsReal(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} -bool AbsFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} -bool AbsFunction::representsComplex(const MathStructure&, bool) const {return false;} -bool AbsFunction::representsNonZero(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units) && vargs[0].representsNonZero(allow_units);} -bool AbsFunction::representsEven(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsEven(allow_units);} -bool AbsFunction::representsOdd(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsOdd(allow_units);} -bool AbsFunction::representsUndefined(const MathStructure &vargs) const {return vargs.size() == 1 && vargs[0].representsUndefined();} -int AbsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.isNumber()) { - if(eo.approximation != APPROXIMATION_APPROXIMATE && mstruct.number().hasImaginaryPart() && mstruct.number().hasRealPart()) { - MathStructure m_i(mstruct.number().imaginaryPart()); - m_i ^= nr_two; - mstruct.number().clearImaginary(); - mstruct.numberUpdated(); - mstruct ^= nr_two; - mstruct += m_i; - mstruct ^= nr_half; - return 1; - } - Number nr(mstruct.number()); - if(!nr.abs() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate())) { - return -1; - } - mstruct = nr; - return 1; - } - if(mstruct.isPower() && mstruct[0].representsPositive()) { - if(mstruct[1].isNumber() && !mstruct[1].number().hasRealPart()) { - mstruct.set(1, 1, 0, true); - return 1; - } else if(mstruct[1].isMultiplication() && mstruct.size() > 0 && mstruct[1][0].isNumber() && !mstruct[1][0].number().hasRealPart()) { - bool b = true; - for(size_t i = 1; i < mstruct[1].size(); i++) { - if(!mstruct[1][i].representsNonComplex()) {b = false; break;} - } - if(b) { - mstruct.set(1, 1, 0, true); - return 1; - } - } - } - if(mstruct.representsNegative(true)) { - mstruct.negate(); - return 1; - } - if(mstruct.representsNonNegative(true)) { - return 1; - } - if(mstruct.isMultiplication()) { - for(size_t i = 0; i < mstruct.size(); i++) { - mstruct[i].transform(STRUCT_FUNCTION); - mstruct[i].setFunction(this); - } - mstruct.childrenUpdated(); - return 1; - } - if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_signum && mstruct.size() == 2) { - mstruct[0].transform(this); - mstruct.childUpdated(1); - return 1; - } - if(mstruct.isPower() && mstruct[1].representsReal()) { - mstruct[0].transform(this); - return 1; - } - if(eo.approximation == APPROXIMATION_EXACT || has_interval_unknowns(mstruct)) { - ComparisonResult cr = mstruct.compare(m_zero); - if(COMPARISON_IS_EQUAL_OR_LESS(cr)) { - return 1; - } else if(COMPARISON_IS_EQUAL_OR_GREATER(cr)) { - mstruct.negate(); - return 1; - } - } - return -1; -} -GcdFunction::GcdFunction() : MathFunction("gcd", 2) { - RATIONAL_POLYNOMIAL_ARGUMENT_HV(1) - RATIONAL_POLYNOMIAL_ARGUMENT_HV(2) -} -int GcdFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(MathStructure::gcd(vargs[0], vargs[1], mstruct, eo)) { - return 1; - } - return 0; -} -LcmFunction::LcmFunction() : MathFunction("lcm", 2) { - RATIONAL_POLYNOMIAL_ARGUMENT_HV(1) - RATIONAL_POLYNOMIAL_ARGUMENT_HV(2) -} -int LcmFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(MathStructure::lcm(vargs[0], vargs[1], mstruct, eo)) { - return 1; - } - return 0; -} - -HeavisideFunction::HeavisideFunction() : MathFunction("heaviside", 1) { - NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg->setHandleVector(true); - arg->setComplexAllowed(false); - setArgumentDefinition(1, arg); -} -bool HeavisideFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative(true);} -bool HeavisideFunction::representsNegative(const MathStructure&, bool) const {return false;} -bool HeavisideFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal(true);} -bool HeavisideFunction::representsNonPositive(const MathStructure&, bool) const {return false;} -bool HeavisideFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonZero() && vargs[0].representsReal(true);} -bool HeavisideFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal(true);} -bool HeavisideFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal(true);} -bool HeavisideFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);} -bool HeavisideFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal(true);} -bool HeavisideFunction::representsComplex(const MathStructure&, bool) const {return false;} -bool HeavisideFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative(true);} -bool HeavisideFunction::representsEven(const MathStructure&, bool) const {return false;} -bool HeavisideFunction::representsOdd(const MathStructure&, bool) const {return false;} -bool HeavisideFunction::representsUndefined(const MathStructure &vargs) const {return vargs.size() == 1 && vargs[0].representsUndefined();} -int HeavisideFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(!mstruct.representsNonComplex(true)) return false; - if(mstruct.representsPositive(true)) { - mstruct.set(1, 1, 0); - return 1; - } - if(mstruct.representsNegative(true)) { - mstruct.clear(); - return 1; - } - if(mstruct.isZero()) { - mstruct = nr_half; - return 1; - } - if(mstruct.isNumber() && mstruct.number().isInterval()) { - if(!mstruct.number().isNonNegative()) { - mstruct.number().setInterval(nr_half, nr_one); - } else if(!mstruct.number().isNonPositive()) { - mstruct.number().setInterval(nr_zero, nr_half); - } else { - mstruct.number().setInterval(nr_zero, nr_one); - } - return 1; - } - if(eo.approximation == APPROXIMATION_EXACT || has_interval_unknowns(mstruct)) { - ComparisonResult cr = mstruct.compare(m_zero); - if(cr == COMPARISON_RESULT_LESS) { - mstruct.set(1, 1, 0); - return 1; - } else if(cr == COMPARISON_RESULT_GREATER) { - mstruct.clear(); - return 1; - } - } - return -1; -} -DiracFunction::DiracFunction() : MathFunction("dirac", 1) { - NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg->setComplexAllowed(false); - setArgumentDefinition(1, arg); -} -bool DiracFunction::representsPositive(const MathStructure&, bool allow_units) const {return false;} -bool DiracFunction::representsNegative(const MathStructure&, bool) const {return false;} -bool DiracFunction::representsNonNegative(const MathStructure&, bool) const {return true;} -bool DiracFunction::representsNonPositive(const MathStructure&, bool) const {return false;} -bool DiracFunction::representsInteger(const MathStructure&, bool) const {return false;} -bool DiracFunction::representsNumber(const MathStructure&, bool) const {return false;} -bool DiracFunction::representsRational(const MathStructure&, bool) const {return false;} -bool DiracFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);} -bool DiracFunction::representsReal(const MathStructure&, bool) const {return false;} -bool DiracFunction::representsComplex(const MathStructure&, bool) const {return false;} -bool DiracFunction::representsNonZero(const MathStructure&, bool) const {return false;} -bool DiracFunction::representsEven(const MathStructure&, bool) const {return false;} -bool DiracFunction::representsOdd(const MathStructure&, bool) const {return false;} -bool DiracFunction::representsUndefined(const MathStructure &vargs) const {return vargs.size() == 1 && vargs[0].representsUndefined();} -int DiracFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - mstruct = vargs[0]; - mstruct.eval(eo); - if(!mstruct.representsNonComplex(true)) return false; - if(mstruct.representsNonZero(true)) { - mstruct.clear(); - return 1; - } - if(mstruct.isZero()) { - mstruct = nr_plus_inf; - return 1; - } - if(mstruct.isNumber() && mstruct.number().isInterval() && !mstruct.number().isNonZero()) { - mstruct.number().setInterval(nr_zero, nr_plus_inf); - return 1; - } - if(eo.approximation == APPROXIMATION_EXACT || has_interval_unknowns(mstruct)) { - ComparisonResult cr = mstruct.compare(m_zero); - if(COMPARISON_IS_NOT_EQUAL(cr)) { - mstruct.clear(); - return 1; - } - } - return -1; -} -SignumFunction::SignumFunction() : MathFunction("sgn", 1, 2) { - Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); - setDefaultValue(2, "0"); -} -bool SignumFunction::representsPositive(const MathStructure&, bool allow_units) const {return false;} -bool SignumFunction::representsNegative(const MathStructure&, bool) const {return false;} -bool SignumFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsNonNegative(true);} -bool SignumFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsNonPositive(true);} -bool SignumFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsReal(true);} -bool SignumFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsNumber(true);} -bool SignumFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsReal(true);} -bool SignumFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsNonComplex(true);} -bool SignumFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsReal(true);} -bool SignumFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsComplex(true);} -bool SignumFunction::representsNonZero(const MathStructure &vargs, bool) const {return (vargs.size() == 2 && !vargs[1].isZero()) || (vargs.size() >= 1 && vargs[0].representsNonZero(true));} -bool SignumFunction::representsEven(const MathStructure&, bool) const {return false;} -bool SignumFunction::representsOdd(const MathStructure &vargs, bool b) const {return representsNonZero(vargs, b);} -bool SignumFunction::representsUndefined(const MathStructure &vargs) const {return vargs.size() >= 1 && vargs[0].representsUndefined();} -int SignumFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.isNumber() && (vargs.size() == 1 || vargs[1].isZero())) { - Number nr(mstruct.number()); - if(!nr.signum() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate())) { - if(mstruct.number().isNonZero()) { - MathStructure *mabs = new MathStructure(mstruct); - mabs->transform(STRUCT_FUNCTION); - mabs->setFunction(CALCULATOR->f_abs); - mstruct.divide_nocopy(mabs); - return 1; - } - return -1; - } else { - mstruct = nr; - return 1; - } - } - if((vargs.size() > 1 && vargs[1].isOne() && mstruct.representsNonNegative(true)) || mstruct.representsPositive(true)) { - mstruct.set(1, 1, 0); - return 1; - } - if((vargs.size() > 1 && vargs[1].isMinusOne() && mstruct.representsNonPositive(true)) || mstruct.representsNegative(true)) { - mstruct.set(-1, 1, 0); - return 1; - } - if(mstruct.isMultiplication()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(vargs.size() > 1) mstruct[i].transform(STRUCT_FUNCTION, vargs[1]); - else mstruct[i].transform(STRUCT_FUNCTION); - mstruct[i].setFunction(this); - - } - mstruct.childrenUpdated(); - return 1; - } - if(vargs.size() > 1 && mstruct.isZero()) { - mstruct.set(vargs[1], true); - return 1; - } - if(eo.approximation == APPROXIMATION_EXACT || has_interval_unknowns(mstruct)) { - ComparisonResult cr = mstruct.compare(m_zero); - if(cr == COMPARISON_RESULT_LESS || (vargs.size() > 1 && vargs[1].isOne() && COMPARISON_IS_EQUAL_OR_LESS(cr))) { - mstruct.set(1, 1, 0); - return 1; - } else if(cr == COMPARISON_RESULT_GREATER || (vargs.size() > 1 && vargs[1].isMinusOne() && COMPARISON_IS_EQUAL_OR_GREATER(cr))) { - mstruct.set(-1, 1, 0); - return 1; - } - } - return -1; -} - -CeilFunction::CeilFunction() : MathFunction("ceil", 1) { - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) -} -int CeilFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION(ceil) -} -bool CeilFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsPositive();} -bool CeilFunction::representsNegative(const MathStructure&, bool) const {return false;} -bool CeilFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();} -bool CeilFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonPositive();} -bool CeilFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool CeilFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool CeilFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} -bool CeilFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool CeilFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool CeilFunction::representsComplex(const MathStructure&, bool) const {return false;} -bool CeilFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsPositive();} -bool CeilFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsEven();} -bool CeilFunction::representsOdd(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsOdd();} -bool CeilFunction::representsUndefined(const MathStructure&) const {return false;} - -FloorFunction::FloorFunction() : MathFunction("floor", 1) { - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) -} -int FloorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION(floor) -} -bool FloorFunction::representsPositive(const MathStructure&, bool) const {return false;} -bool FloorFunction::representsNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNegative();} -bool FloorFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();} -bool FloorFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonPositive();} -bool FloorFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool FloorFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool FloorFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool FloorFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} -bool FloorFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool FloorFunction::representsComplex(const MathStructure&, bool) const {return false;} -bool FloorFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNegative();} -bool FloorFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsEven();} -bool FloorFunction::representsOdd(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsOdd();} -bool FloorFunction::representsUndefined(const MathStructure&) const {return false;} - -TruncFunction::TruncFunction() : MathFunction("trunc", 1) { - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) -} -int TruncFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION(trunc) -} -bool TruncFunction::representsPositive(const MathStructure&, bool) const {return false;} -bool TruncFunction::representsNegative(const MathStructure&, bool) const {return false;} -bool TruncFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();} -bool TruncFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonPositive();} -bool TruncFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool TruncFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool TruncFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool TruncFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool TruncFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} -bool TruncFunction::representsComplex(const MathStructure&, bool) const {return false;} -bool TruncFunction::representsNonZero(const MathStructure&, bool) const {return false;} -bool TruncFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsEven();} -bool TruncFunction::representsOdd(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsOdd();} -bool TruncFunction::representsUndefined(const MathStructure&) const {return false;} - -RoundFunction::RoundFunction() : MathFunction("round", 1) { - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) -} -int RoundFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION(round) -} -bool RoundFunction::representsPositive(const MathStructure&, bool) const {return false;} -bool RoundFunction::representsNegative(const MathStructure&, bool) const {return false;} -bool RoundFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();} -bool RoundFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonPositive();} -bool RoundFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool RoundFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool RoundFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool RoundFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool RoundFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} -bool RoundFunction::representsComplex(const MathStructure&, bool) const {return false;} -bool RoundFunction::representsNonZero(const MathStructure&, bool) const {return false;} -bool RoundFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsEven();} -bool RoundFunction::representsOdd(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsOdd();} -bool RoundFunction::representsUndefined(const MathStructure&) const {return false;} - -FracFunction::FracFunction() : MathFunction("frac", 1) { - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) -} -int FracFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION(frac) -} -IntFunction::IntFunction() : MathFunction("int", 1) { - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) -} -int IntFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION(trunc) -} -NumeratorFunction::NumeratorFunction() : MathFunction("numerator", 1) { - NumberArgument *arg_rational_1 = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg_rational_1->setRationalNumber(true); - arg_rational_1->setHandleVector(true); - setArgumentDefinition(1, arg_rational_1); -} -int NumeratorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - if(vargs[0].isNumber()) { - if(vargs[0].number().isInteger()) { - mstruct = vargs[0]; - return 1; - } else if(vargs[0].number().isRational()) { - mstruct.set(vargs[0].number().numerator()); - return 1; - } - return 0; - } else if(vargs[0].representsInteger()) { - mstruct = vargs[0]; - return 1; - } - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.representsInteger()) { - return 1; - } else if(mstruct.isNumber() && mstruct.number().isRational()) { - Number nr(mstruct.number().numerator()); - mstruct.set(nr); - return 1; - } - return -1; -} -DenominatorFunction::DenominatorFunction() : MathFunction("denominator", 1) { - RATIONAL_NUMBER_ARGUMENT_NO_ERROR(1) -} -int DenominatorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct.set(vargs[0].number().denominator()); - return 1; -} -RemFunction::RemFunction() : MathFunction("rem", 2) { - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR_NONZERO(2) -} -int RemFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION_2(rem) -} -ModFunction::ModFunction() : MathFunction("mod", 2) { - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) - NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR_NONZERO(2) -} -int ModFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION_2(mod) -} - -PolynomialUnitFunction::PolynomialUnitFunction() : MathFunction("punit", 1, 2) { - RATIONAL_POLYNOMIAL_ARGUMENT(1) - setArgumentDefinition(2, new SymbolicArgument()); - setDefaultValue(2, "undefined"); -} -int PolynomialUnitFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct.set(vargs[0].polynomialUnit(vargs[1]), 0); - return 1; -} -PolynomialPrimpartFunction::PolynomialPrimpartFunction() : MathFunction("primpart", 1, 2) { - RATIONAL_POLYNOMIAL_ARGUMENT(1) - setArgumentDefinition(2, new SymbolicArgument()); - setDefaultValue(2, "undefined"); -} -int PolynomialPrimpartFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - vargs[0].polynomialPrimpart(vargs[1], mstruct, eo); - return 1; -} -PolynomialContentFunction::PolynomialContentFunction() : MathFunction("pcontent", 1, 2) { - RATIONAL_POLYNOMIAL_ARGUMENT(1) - setArgumentDefinition(2, new SymbolicArgument()); - setDefaultValue(2, "undefined"); -} -int PolynomialContentFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - vargs[0].polynomialContent(vargs[1], mstruct, eo); - return 1; -} -CoeffFunction::CoeffFunction() : MathFunction("coeff", 2, 3) { - RATIONAL_POLYNOMIAL_ARGUMENT(1) - setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_NONNEGATIVE)); - setArgumentDefinition(3, new SymbolicArgument()); - setDefaultValue(3, "undefined"); -} -int CoeffFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - vargs[0].coefficient(vargs[2], vargs[1].number(), mstruct); - return 1; -} -LCoeffFunction::LCoeffFunction() : MathFunction("lcoeff", 1, 2) { - RATIONAL_POLYNOMIAL_ARGUMENT(1) - setArgumentDefinition(2, new SymbolicArgument()); - setDefaultValue(2, "undefined"); -} -int LCoeffFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - vargs[0].lcoefficient(vargs[1], mstruct); - return 1; -} -TCoeffFunction::TCoeffFunction() : MathFunction("tcoeff", 1, 2) { - RATIONAL_POLYNOMIAL_ARGUMENT(1) - setArgumentDefinition(2, new SymbolicArgument()); - setDefaultValue(2, "undefined"); -} -int TCoeffFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - vargs[0].tcoefficient(vargs[1], mstruct); - return 1; -} -DegreeFunction::DegreeFunction() : MathFunction("degree", 1, 2) { - RATIONAL_POLYNOMIAL_ARGUMENT(1) - setArgumentDefinition(2, new SymbolicArgument()); - setDefaultValue(2, "undefined"); -} -int DegreeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = vargs[0].degree(vargs[1]); - return 1; -} -LDegreeFunction::LDegreeFunction() : MathFunction("ldegree", 1, 2) { - RATIONAL_POLYNOMIAL_ARGUMENT(1) - setArgumentDefinition(2, new SymbolicArgument()); - setDefaultValue(2, "undefined"); -} -int LDegreeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = vargs[0].ldegree(vargs[1]); - return 1; -} - -ImFunction::ImFunction() : MathFunction("im", 1) { - Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -int ImFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.isNumber()) { - mstruct = mstruct.number().imaginaryPart(); - return 1; - } else if(mstruct.representsReal(!eo.keep_zero_units)) { - mstruct.clear(true); - return 1; - } else if(mstruct.isUnit_exp()) { - mstruct *= m_zero; - mstruct.swapChildren(1, 2); - return 1; - } else if(mstruct.isPower() && mstruct[1].isNumber() && mstruct[1].number().denominatorIsTwo() && mstruct[0].representsNegative()) { - mstruct[0].negate(); - Number num = mstruct[1].number().numerator(); - num.rem(4); - if(num == 3 || num == -1) mstruct.negate(); - return 1; - } else if(mstruct.isMultiplication() && mstruct.size() > 0) { - if(mstruct[0].isNumber()) { - Number nr = mstruct[0].number(); - mstruct.delChild(1, true); - if(nr.hasImaginaryPart()) { - if(nr.hasRealPart()) { - MathStructure *madd = new MathStructure(mstruct); - mstruct.transform(CALCULATOR->f_re); - madd->transform(this); - madd->multiply(nr.realPart()); - mstruct.multiply(nr.imaginaryPart()); - mstruct.add_nocopy(madd); - return 1; - } - mstruct.transform(CALCULATOR->f_re); - mstruct.multiply(nr.imaginaryPart()); - return 1; - } - mstruct.transform(this); - mstruct.multiply(nr.realPart()); - return 1; - } - MathStructure *mreal = NULL; - for(size_t i = 0; i < mstruct.size();) { - if(mstruct[i].representsReal(true)) { - if(!mreal) { - mreal = new MathStructure(mstruct[i]); - } else { - mstruct[i].ref(); - if(!mreal->isMultiplication()) mreal->transform(STRUCT_MULTIPLICATION); - mreal->addChild_nocopy(&mstruct[i]); - } - mstruct.delChild(i + 1); - } else { - i++; - } - } - if(mreal) { - if(mstruct.size() == 0) mstruct.clear(true); - else if(mstruct.size() == 1) mstruct.setToChild(1, true); - mstruct.transform(this); - mstruct.multiply_nocopy(mreal); - return 1; - } - } - return -1; -} -bool ImFunction::representsPositive(const MathStructure&, bool) const {return false;} -bool ImFunction::representsNegative(const MathStructure&, bool) const {return false;} -bool ImFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool ImFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool ImFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool ImFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} -bool ImFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool ImFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} -bool ImFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} -bool ImFunction::representsComplex(const MathStructure&, bool) const {return false;} -bool ImFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsComplex();} -bool ImFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool ImFunction::representsOdd(const MathStructure&, bool) const {return false;} -bool ImFunction::representsUndefined(const MathStructure&) const {return false;} - -ReFunction::ReFunction() : MathFunction("re", 1) { - Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -int ReFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.isNumber()) { - mstruct = mstruct.number().realPart(); - return 1; - } else if(mstruct.representsReal(true)) { - return 1; - } else if(mstruct.isPower() && mstruct[1].isNumber() && mstruct[1].number().denominatorIsTwo() && mstruct[0].representsNegative()) { - mstruct.clear(true); - return 1; - } else if(mstruct.isMultiplication() && mstruct.size() > 0) { - if(mstruct[0].isNumber()) { - Number nr = mstruct[0].number(); - mstruct.delChild(1, true); - if(nr.hasImaginaryPart()) { - if(nr.hasRealPart()) { - MathStructure *madd = new MathStructure(mstruct); - mstruct.transform(CALCULATOR->f_im); - madd->transform(this); - madd->multiply(nr.realPart()); - mstruct.multiply(-nr.imaginaryPart()); - mstruct.add_nocopy(madd); - return 1; - } - mstruct.transform(CALCULATOR->f_im); - mstruct.multiply(-nr.imaginaryPart()); - return 1; - } - mstruct.transform(this); - mstruct.multiply(nr.realPart()); - return 1; - } - MathStructure *mreal = NULL; - for(size_t i = 0; i < mstruct.size();) { - if(mstruct[i].representsReal(true)) { - if(!mreal) { - mreal = new MathStructure(mstruct[i]); - } else { - mstruct[i].ref(); - if(!mreal->isMultiplication()) mreal->transform(STRUCT_MULTIPLICATION); - mreal->addChild_nocopy(&mstruct[i]); - } - mstruct.delChild(i + 1); - } else { - i++; - } - } - if(mreal) { - if(mstruct.size() == 0) mstruct.clear(true); - else if(mstruct.size() == 1) mstruct.setToChild(1, true); - mstruct.transform(this); - mstruct.multiply_nocopy(mreal); - return 1; - } - } - return -1; -} -bool ReFunction::representsPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsPositive(allow_units);} -bool ReFunction::representsNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNegative(allow_units);} -bool ReFunction::representsNonNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNonNegative(allow_units);} -bool ReFunction::representsNonPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNonPositive(allow_units);} -bool ReFunction::representsInteger(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsInteger(allow_units);} -bool ReFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} -bool ReFunction::representsRational(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsRational(allow_units);} -bool ReFunction::representsReal(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} -bool ReFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} -bool ReFunction::representsComplex(const MathStructure&, bool) const {return false;} -bool ReFunction::representsNonZero(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsReal(allow_units) && vargs[0].representsNonZero(true);} -bool ReFunction::representsEven(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsEven(allow_units);} -bool ReFunction::representsOdd(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsOdd(allow_units);} -bool ReFunction::representsUndefined(const MathStructure&) const {return false;} - -SqrtFunction::SqrtFunction() : MathFunction("sqrt", 1) { - Argument *arg = new Argument("", false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -int SqrtFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - if(!vargs[0].representsScalar()) { - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - } - mstruct.raise(nr_half); - return 1; -} -bool SqrtFunction::representsPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsPositive(allow_units);} -bool SqrtFunction::representsNegative(const MathStructure&, bool) const {return false;} -bool SqrtFunction::representsNonNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNonNegative(allow_units);} -bool SqrtFunction::representsNonPositive(const MathStructure&, bool) const {return false;} -bool SqrtFunction::representsInteger(const MathStructure&, bool) const {return false;} -bool SqrtFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} -bool SqrtFunction::representsRational(const MathStructure&, bool) const {return false;} -bool SqrtFunction::representsReal(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNonNegative(allow_units);} -bool SqrtFunction::representsNonComplex(const MathStructure &vargs, bool allow_units) const {return representsReal(vargs, allow_units);} -bool SqrtFunction::representsComplex(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNegative(allow_units);} -bool SqrtFunction::representsNonZero(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNonZero(allow_units);} -bool SqrtFunction::representsEven(const MathStructure&, bool) const {return false;} -bool SqrtFunction::representsOdd(const MathStructure&, bool) const {return false;} -bool SqrtFunction::representsUndefined(const MathStructure&) const {return false;} -CbrtFunction::CbrtFunction() : MathFunction("cbrt", 1) { - Argument *arg = new Argument("", false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -int CbrtFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - if(vargs[0].representsNegative(true)) { - mstruct = vargs[0]; - mstruct.negate(); - mstruct.raise(Number(1, 3, 0)); - mstruct.negate(); - } else if(vargs[0].representsNonNegative(true)) { - mstruct = vargs[0]; - mstruct.raise(Number(1, 3, 0)); - } else { - MathStructure mroot(3, 1, 0); - mstruct.set(CALCULATOR->f_root, &vargs[0], &mroot, NULL); - } - return 1; -} -RootFunction::RootFunction() : MathFunction("root", 2) { - NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg->setComplexAllowed(false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); - NumberArgument *arg2 = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, true); - arg2->setComplexAllowed(false); - arg2->setRationalNumber(true); - arg2->setHandleVector(true); - setArgumentDefinition(2, arg2); -} -int RootFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - if(vargs[1].number().isOne()) { - mstruct = vargs[0]; - return 1; - } - if(!vargs[1].number().isInteger() || !vargs[1].number().isPositive()) { - mstruct = vargs[0]; - if(!vargs[0].representsScalar()) { - mstruct.eval(eo); - } - if(mstruct.isVector()) return -1; - Number nr_root(vargs[1].number().numerator()); - nr_root.setPrecisionAndApproximateFrom(vargs[1].number()); - Number nr_pow(vargs[1].number().denominator()); - nr_pow.setPrecisionAndApproximateFrom(vargs[1].number()); - if(nr_root.isNegative()) { - nr_root.negate(); - nr_pow.negate(); - } - if(nr_root.isOne()) { - mstruct ^= nr_pow; - } else if(nr_root.isZero()) { - mstruct ^= nr_zero; - } else { - mstruct ^= nr_pow; - mstruct.transform(this); - mstruct.addChild(nr_root); - } - return 1; - } - if(vargs[0].representsNonNegative(true)) { - mstruct = vargs[0]; - Number nr_exp(vargs[1].number()); - nr_exp.recip(); - mstruct.raise(nr_exp); - return 1; - } else if(vargs[1].number().isOdd() && vargs[0].representsNegative(true)) { - mstruct = vargs[0]; - mstruct.negate(); - Number nr_exp(vargs[1].number()); - nr_exp.recip(); - mstruct.raise(nr_exp); - mstruct.negate(); - return 1; - } - bool eval_mstruct = !vargs[0].isNumber(); - Number nr; - if(eval_mstruct) { - mstruct = vargs[0]; - if(eo.approximation == APPROXIMATION_TRY_EXACT && mstruct.representsScalar()) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_EXACT; - mstruct.eval(eo2); - } else { - mstruct.eval(eo); - } - if(mstruct.isVector()) { - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - return -1; - } - if(mstruct.representsNonNegative(true)) { - Number nr_exp(vargs[1].number()); - nr_exp.recip(); - mstruct.raise(nr_exp); - return 1; - } else if(vargs[1].number().isOdd() && mstruct.representsNegative(true)) { - mstruct.negate(); - Number nr_exp(vargs[1].number()); - nr_exp.recip(); - mstruct.raise(nr_exp); - mstruct.negate(); - return 1; - } - if(!mstruct.isNumber()) { - if(mstruct.isPower() && mstruct[1].isNumber() && mstruct[1].number().isInteger()) { - if(mstruct[1] == vargs[1]) { - if(mstruct[1].number().isEven()) { - if(!mstruct[0].representsReal(true)) return -1; - mstruct.delChild(2); - mstruct.setType(STRUCT_FUNCTION); - mstruct.setFunction(CALCULATOR->f_abs); - } else { - mstruct.setToChild(1); - } - return 1; - } else if(mstruct[1].number().isIntegerDivisible(vargs[1].number())) { - if(mstruct[1].number().isEven()) { - if(!mstruct[0].representsReal(true)) return -1; - mstruct[0].transform(STRUCT_FUNCTION); - mstruct[0].setFunction(CALCULATOR->f_abs); - } - mstruct[1].divide(vargs[1].number()); - return 1; - } else if(!mstruct[1].number().isMinusOne() && vargs[1].number().isIntegerDivisible(mstruct[1].number())) { - if(mstruct[1].number().isEven()) { - if(!mstruct[0].representsReal(true)) return -1; - mstruct[0].transform(STRUCT_FUNCTION); - mstruct[0].setFunction(CALCULATOR->f_abs); - } - Number new_root(vargs[1].number()); - new_root.divide(mstruct[1].number()); - bool bdiv = new_root.isNegative(); - if(bdiv) new_root.negate(); - mstruct[1] = new_root; - mstruct.setType(STRUCT_FUNCTION); - mstruct.setFunction(this); - if(bdiv) mstruct.raise(nr_minus_one); - return 1; - } else if(mstruct[1].number().isMinusOne()) { - mstruct[0].transform(STRUCT_FUNCTION, vargs[1]); - mstruct[0].setFunction(this); - return 1; - } else if(mstruct[1].number().isNegative()) { - mstruct[1].number().negate(); - mstruct.transform(STRUCT_FUNCTION, vargs[1]); - mstruct.setFunction(this); - mstruct.raise(nr_minus_one); - return 1; - } - } else if(mstruct.isPower() && mstruct[1].isNumber() && mstruct[1].number().isRational() && mstruct[1].number().denominatorIsTwo()) { - Number new_root(vargs[1].number()); - new_root.multiply(Number(2, 1, 0)); - if(mstruct[1].number().numeratorIsOne()) { - mstruct[1].number().set(new_root, true); - mstruct.setType(STRUCT_FUNCTION); - mstruct.setFunction(this); - } else { - mstruct[1].number().set(mstruct[1].number().numerator(), true); - mstruct.transform(STRUCT_FUNCTION); - mstruct.addChild(new_root); - mstruct.setFunction(this); - } - return 1; - } else if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_sqrt && mstruct.size() == 1) { - Number new_root(vargs[1].number()); - new_root.multiply(Number(2, 1, 0)); - mstruct.addChild(new_root); - mstruct.setFunction(this); - return 1; - } else if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_root && mstruct.size() == 2 && mstruct[1].isNumber() && mstruct[1].number().isInteger() && mstruct[1].number().isPositive()) { - Number new_root(vargs[1].number()); - new_root.multiply(mstruct[1].number()); - mstruct[1] = new_root; - return 1; - } else if(mstruct.isMultiplication()) { - bool b = true; - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct[i].representsReal(true)) { - b = false; - break; - } - } - if(b) { - if(vargs[1].number().isOdd()) { - bool b_neg = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isNumber() && mstruct[i].number().isNegative() && !mstruct[i].isMinusOne()) { - mstruct[i].negate(); - b_neg = !b_neg; - } - mstruct[i].transform(STRUCT_FUNCTION, vargs[1]); - mstruct[i].setFunction(this); - } - if(b_neg) mstruct.insertChild_nocopy(new MathStructure(-1, 1, 0), 1); - return 1; - } else { - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isNumber() && mstruct[i].number().isNegative() && !mstruct[i].isMinusOne()) { - MathStructure *mmul = new MathStructure(this, &mstruct[i], &vargs[1], NULL); - (*mmul)[0].negate(); - mstruct[i] = nr_minus_one; - mstruct.transform(STRUCT_FUNCTION, vargs[1]); - mstruct.setFunction(this); - mstruct.multiply_nocopy(mmul); - return true; - } else if(mstruct[i].representsPositive()) { - mstruct[i].transform(STRUCT_FUNCTION, vargs[1]); - mstruct[i].setFunction(this); - mstruct[i].ref(); - MathStructure *mmul = &mstruct[i]; - mstruct.delChild(i + 1, true); - mstruct.transform(STRUCT_FUNCTION, vargs[1]); - mstruct.setFunction(this); - mstruct.multiply_nocopy(mmul); - return true; - } - } - } - } - } - return -1; - } - nr = mstruct.number(); - } else { - nr = vargs[0].number(); - } - if(!nr.root(vargs[1].number()) || (eo.approximation < APPROXIMATION_APPROXIMATE && nr.isApproximate() && !vargs[0].isApproximate() && !mstruct.isApproximate() && !vargs[1].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity())) { - if(!eval_mstruct) { - if(vargs[0].number().isNegative() && vargs[1].number().isOdd()) { - mstruct.set(this, &vargs[0], &vargs[1], NULL); - mstruct[0].number().negate(); - mstruct.negate(); - return 1; - } - return 0; - } else if(mstruct.number().isNegative() && vargs[1].number().isOdd()) { - mstruct.number().negate(); - mstruct.transform(STRUCT_FUNCTION, vargs[1]); - mstruct.setFunction(this); - mstruct.negate(); - return 1; - } - } else { - mstruct.set(nr); - return 1; - } - return -1; -} -bool RootFunction::representsPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsPositive(allow_units);} -bool RootFunction::representsNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsOdd() && vargs[1].representsPositive() && vargs[0].representsNegative(allow_units);} -bool RootFunction::representsNonNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsNonNegative(allow_units);} -bool RootFunction::representsNonPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsOdd() && vargs[1].representsPositive() && vargs[0].representsNonPositive(allow_units);} -bool RootFunction::representsInteger(const MathStructure&, bool) const {return false;} -bool RootFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsNumber(allow_units);} -bool RootFunction::representsRational(const MathStructure&, bool) const {return false;} -bool RootFunction::representsReal(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsReal(allow_units) && (vargs[0].representsNonNegative(allow_units) || vargs[1].representsOdd());} -bool RootFunction::representsNonComplex(const MathStructure &vargs, bool allow_units) const {return representsReal(vargs, allow_units);} -bool RootFunction::representsComplex(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && (vargs[0].representsComplex(allow_units) || (vargs[1].representsEven() && vargs[0].representsNegative(allow_units)));} -bool RootFunction::representsNonZero(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsNonZero(allow_units);} -bool RootFunction::representsEven(const MathStructure&, bool) const {return false;} -bool RootFunction::representsOdd(const MathStructure&, bool) const {return false;} -bool RootFunction::representsUndefined(const MathStructure&) const {return false;} - -SquareFunction::SquareFunction() : MathFunction("sq", 1) { - Argument *arg = new Argument("", false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -int SquareFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = vargs[0]; - mstruct ^= 2; - return 1; -} - -ExpFunction::ExpFunction() : MathFunction("exp", 1) { - Argument *arg = new Argument("", false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -int ExpFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = CALCULATOR->v_e; - mstruct ^= vargs[0]; - return 1; -} - -LogFunction::LogFunction() : MathFunction("ln", 1) { - Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONZERO, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -bool LogFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsPositive() && ((vargs[0].isNumber() && vargs[0].number().isGreaterThan(nr_one)) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && ((KnownVariable*) vargs[0].variable())->get().number().isGreaterThan(nr_one)));} -bool LogFunction::representsNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative() && ((vargs[0].isNumber() && vargs[0].number().isLessThan(nr_one)) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && ((KnownVariable*) vargs[0].variable())->get().number().isLessThan(nr_one)));} -bool LogFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsPositive() && ((vargs[0].isNumber() && vargs[0].number().isGreaterThanOrEqualTo(nr_one)) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && ((KnownVariable*) vargs[0].variable())->get().number().isGreaterThanOrEqualTo(nr_one)));} -bool LogFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative() && ((vargs[0].isNumber() && vargs[0].number().isLessThanOrEqualTo(nr_one)) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && ((KnownVariable*) vargs[0].variable())->get().number().isLessThanOrEqualTo(nr_one)));} -bool LogFunction::representsInteger(const MathStructure&, bool) const {return false;} -bool LogFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units) && vargs[0].representsNonZero(allow_units);} -bool LogFunction::representsRational(const MathStructure&, bool) const {return false;} -bool LogFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsPositive();} -bool LogFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();} -bool LogFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNegative();} -bool LogFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && (vargs[0].representsNonPositive() || (vargs[0].isNumber() && COMPARISON_IS_NOT_EQUAL(vargs[0].number().compare(nr_one))) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && COMPARISON_IS_NOT_EQUAL(((KnownVariable*) vargs[0].variable())->get().number().compare(nr_one))));} -bool LogFunction::representsEven(const MathStructure&, bool) const {return false;} -bool LogFunction::representsOdd(const MathStructure&, bool) const {return false;} -bool LogFunction::representsUndefined(const MathStructure&) const {return false;} -int LogFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - - mstruct = vargs[0]; - - if(mstruct.isVariable() && mstruct.variable() == CALCULATOR->v_e) { - mstruct.set(m_one); - return true; - } else if(mstruct.isPower()) { - if(mstruct[0].isVariable() && mstruct[0].variable() == CALCULATOR->v_e) { - if(mstruct[1].representsReal()) { - mstruct.setToChild(2, true); - return true; - } - } else if(eo.approximation != APPROXIMATION_APPROXIMATE && ((mstruct[0].representsPositive(true) && mstruct[1].representsReal()) || (mstruct[1].isNumber() && mstruct[1].number().isFraction()))) { - MathStructure mstruct2; - mstruct2.set(CALCULATOR->f_ln, &mstruct[0], NULL); - mstruct2 *= mstruct[1]; - mstruct = mstruct2; - return true; - } - } - - if(eo.approximation == APPROXIMATION_TRY_EXACT) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_EXACT; - CALCULATOR->beginTemporaryStopMessages(); - mstruct.eval(eo2); - if(mstruct.isVector()) {CALCULATOR->endTemporaryStopMessages(true); return -1;} - } else { - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - } - - bool b = false; - if(mstruct.isVariable() && mstruct.variable() == CALCULATOR->v_e) { - mstruct.set(m_one); - b = true; - } else if(mstruct.isPower()) { - if(mstruct[0].isVariable() && mstruct[0].variable() == CALCULATOR->v_e) { - if(mstruct[1].representsReal()) { - mstruct.setToChild(2, true); - b = true; - } - } else if((mstruct[0].representsPositive(true) && mstruct[1].representsReal()) || (mstruct[1].isNumber() && mstruct[1].number().isFraction())) { - MathStructure mstruct2; - mstruct2.set(CALCULATOR->f_ln, &mstruct[0], NULL); - mstruct2 *= mstruct[1]; - mstruct = mstruct2; - b = true; - } - } else if(mstruct.isMultiplication()) { - b = true; - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct[i].representsPositive()) { - b = false; - break; - } - } - if(b) { - MathStructure mstruct2; - mstruct2.set(CALCULATOR->f_ln, &mstruct[0], NULL); - for(size_t i = 1; i < mstruct.size(); i++) { - mstruct2.add(MathStructure(CALCULATOR->f_ln, &mstruct[i], NULL), i > 1); - } - mstruct = mstruct2; - } - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(b); - if(b) return 1; - if(eo.approximation == APPROXIMATION_TRY_EXACT && !mstruct.isNumber()) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - mstruct = vargs[0]; - mstruct.eval(eo2); - } - - if(mstruct.isNumber()) { - if(eo.allow_complex && mstruct.number().isMinusOne()) { - mstruct = CALCULATOR->v_i->get(); - mstruct *= CALCULATOR->v_pi; - return 1; - } else if(mstruct.number().isI()) { - mstruct.set(1, 2, 0); - mstruct *= CALCULATOR->v_pi; - mstruct *= CALCULATOR->v_i->get(); - return 1; - } else if(mstruct.number().isMinusI()) { - mstruct.set(-1, 2, 0); - mstruct *= CALCULATOR->v_pi; - mstruct *= CALCULATOR->v_i->get(); - return 1; - } else if(eo.allow_complex && eo.allow_infinite && mstruct.number().isMinusInfinity()) { - mstruct = CALCULATOR->v_pi; - mstruct *= CALCULATOR->v_i->get(); - Number nr; nr.setPlusInfinity(); - mstruct += nr; - return 1; - } - Number nr(mstruct.number()); - if(nr.ln() && !(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { - mstruct.set(nr, true); - return 1; - } - if(mstruct.number().isRational() && mstruct.number().isPositive()) { - if(mstruct.number().isInteger()) { - if(mstruct.number().isLessThanOrEqualTo(PRIMES[NR_OF_PRIMES - 1])) { - vector factors; - mstruct.number().factorize(factors); - if(factors.size() > 1) { - mstruct.clear(true); - mstruct.setType(STRUCT_ADDITION); - for(size_t i = 0; i < factors.size(); i++) { - if(i > 0 && factors[i] == factors[i - 1]) { - if(mstruct.last().isMultiplication()) mstruct.last().last().number()++; - else mstruct.last() *= nr_two; - } else { - mstruct.addChild(MathStructure(CALCULATOR->f_ln, NULL)); - mstruct.last().addChild(factors[i]); - } - } - if(mstruct.size() == 1) mstruct.setToChild(1, true); - return 1; - } - } - } else { - MathStructure mstruct2(CALCULATOR->f_ln, NULL); - mstruct2.addChild(mstruct.number().denominator()); - mstruct.number().set(mstruct.number().numerator()); - mstruct.transform(CALCULATOR->f_ln); - mstruct -= mstruct2; - return 1; - } - } else if(mstruct.number().hasImaginaryPart()) { - if(mstruct.number().hasRealPart()) { - MathStructure *marg = new MathStructure(mstruct); - if(calculate_arg(*marg, eo)) { - mstruct.transform(CALCULATOR->f_abs); - mstruct.transform(CALCULATOR->f_ln); - marg->multiply(CALCULATOR->v_i->get()); - mstruct.add_nocopy(marg); - return 1; - } - marg->unref(); - } else { - bool b_neg = mstruct.number().imaginaryPartIsNegative(); - if(mstruct.number().abs()) { - mstruct.transform(this); - mstruct += b_neg ? nr_minus_half : nr_half; - mstruct.last() *= CALCULATOR->v_pi; - mstruct.last().multiply(CALCULATOR->v_i->get(), true); - } - return 1; - } - } - } else if(mstruct.isPower()) { - if((mstruct[0].representsPositive(true) && mstruct[1].representsReal()) || (mstruct[1].isNumber() && mstruct[1].number().isFraction())) { - MathStructure mstruct2; - mstruct2.set(CALCULATOR->f_ln, &mstruct[0], NULL); - mstruct2 *= mstruct[1]; - mstruct = mstruct2; - return 1; - } - if(mstruct[1].isNumber() && mstruct[1].number().isTwo() && mstruct[0].representsPositive()) { - mstruct.setToChild(1, true); - mstruct.transform(this); - mstruct *= nr_two; - return 1; - } - if(eo.approximation == APPROXIMATION_EXACT && !mstruct[1].isNumber()) { - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mtest(mstruct[1]); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - mtest.eval(eo2); - if(!CALCULATOR->endTemporaryStopMessages() && mtest.isNumber() && mtest.number().isFraction()) { - MathStructure mstruct2; - mstruct2.set(CALCULATOR->f_ln, &mstruct[0], NULL); - mstruct2 *= mstruct[1]; - mstruct = mstruct2; - return 1; - } - } - } - if(eo.allow_complex && mstruct.representsNegative()) { - mstruct.negate(); - mstruct.transform(CALCULATOR->f_ln); - mstruct += CALCULATOR->v_pi; - mstruct.last() *= nr_one_i; - return 1; - } - if(!mstruct.representsReal()) { - MathStructure *marg = new MathStructure(mstruct); - if(calculate_arg(*marg, eo)) { - mstruct.transform(CALCULATOR->f_abs); - mstruct.transform(CALCULATOR->f_ln); - marg->multiply(CALCULATOR->v_i->get()); - mstruct.add_nocopy(marg); - return 1; - } - marg->unref(); - } - - return -1; - -} -LognFunction::LognFunction() : MathFunction("log", 1, 2) { - Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONZERO, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); - arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONZERO, false); - arg->setHandleVector(true); - setArgumentDefinition(2, arg); - setDefaultValue(2, "e"); -} -int LognFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector() || vargs[1].isVector()) return 0; - if(vargs[1].isVariable() && vargs[1].variable() == CALCULATOR->v_e) { - mstruct.set(CALCULATOR->f_ln, &vargs[0], NULL); - return 1; - } - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - MathStructure mstructv2 = vargs[1]; - mstructv2.eval(eo); - if(mstructv2.isVector()) return -2; - if(mstruct.isPower()) { - if((mstruct[0].representsPositive(true) && mstruct[1].representsReal()) || (mstruct[1].isNumber() && mstruct[1].number().isFraction())) { - MathStructure mstruct2; - mstruct2.set(CALCULATOR->f_logn, &mstruct[0], &mstructv2, NULL); - mstruct2 *= mstruct[1]; - mstruct = mstruct2; - return 1; - } - } else if(mstruct.isMultiplication()) { - bool b = true; - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct[i].representsPositive()) { - b = false; - break; - } - } - if(b) { - MathStructure mstruct2; - mstruct2.set(CALCULATOR->f_logn, &mstruct[0], &mstructv2, NULL); - for(size_t i = 1; i < mstruct.size(); i++) { - mstruct2.add(MathStructure(CALCULATOR->f_logn, &mstruct[i], &mstructv2, NULL), i > 1); - } - mstruct = mstruct2; - return 1; - } - } else if(mstruct.isNumber() && mstructv2.isNumber()) { - Number nr(mstruct.number()); - if(nr.log(mstructv2.number()) && !(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { - mstruct.set(nr, true); - return 1; - } - } - mstruct.set(CALCULATOR->f_ln, &vargs[0], NULL); - mstruct.divide_nocopy(new MathStructure(CALCULATOR->f_ln, &vargs[1], NULL)); - return 1; -} - -bool LambertWFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[0].representsNumber() && (vargs[1].isZero() || vargs[0].representsNonZero()));} -bool LambertWFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[1].isZero() && vargs[0].representsNonNegative());} -bool LambertWFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[0].isZero() || (vargs[1].isZero() && vargs[0].representsNonNegative()));} -bool LambertWFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[0].representsComplex() || (vargs[0].representsNonZero() && (vargs[1].isInteger() && (!vargs[1].isMinusOne() || vargs[0].representsPositive()) && !vargs[1].isZero())));} -bool LambertWFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[1].representsNonZero() || vargs[0].representsNonZero());} - -LambertWFunction::LambertWFunction() : MathFunction("lambertw", 1, 2) { - NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg->setComplexAllowed(false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); - setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, false)); - setDefaultValue(2, "0"); -} -int LambertWFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - - if(eo.approximation == APPROXIMATION_TRY_EXACT && vargs[1].isZero()) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_EXACT; - CALCULATOR->beginTemporaryStopMessages(); - mstruct.eval(eo2); - if(mstruct.isVector()) {CALCULATOR->endTemporaryStopMessages(true); return -1;} - } else { - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - } - - if(!vargs[1].isZero()) { - if(vargs[0].isZero()) { - mstruct.set(nr_minus_inf, true); - return 1; - } else if(vargs[1].isMinusOne()) { - if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0].isNumber() && vargs[0][1].isPower() && vargs[0][1][0].isVariable() && vargs[0][1][0].variable() == CALCULATOR->v_e && vargs[0][0].number() <= nr_minus_one && vargs[0][1][1] == vargs[0][0]) { - mstruct = vargs[0][0]; - return 1; - } - } - return 0; - } - - bool b = false; - if(mstruct.isZero()) { - b = true; - } else if(mstruct.isVariable() && mstruct.variable() == CALCULATOR->v_e) { - mstruct.set(1, 1, 0, true); - b = true; - } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isMinusOne() && mstruct[1].isPower() && mstruct[1][0].isVariable() && mstruct[1][0].variable() == CALCULATOR->v_e && mstruct[1][1].isMinusOne()) { - mstruct.set(-1, 1, 0, true); - b = true; - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(b); - if(b) return 1; - if(eo.approximation == APPROXIMATION_EXACT) return -1; - if(eo.approximation == APPROXIMATION_TRY_EXACT && !mstruct.isNumber()) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - mstruct = vargs[0]; - mstruct.eval(eo2); - } - if(mstruct.isNumber()) { - Number nr(mstruct.number()); - if(!nr.lambertW()) { - //if(!CALCULATOR->aborted()) CALCULATOR->error(false, _("Argument for %s() must be a real number greater than or equal to -1/e."), preferredDisplayName().name.c_str(), NULL); - } else if(!(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { - mstruct.set(nr, true); - return 1; - } - } - return -1; -} - -bool is_real_angle_value(const MathStructure &mstruct) { - if(mstruct.isUnit()) { - return mstruct.unit() == CALCULATOR->getRadUnit() || mstruct.unit() == CALCULATOR->getDegUnit() || mstruct.unit() == CALCULATOR->getGraUnit(); - } else if(mstruct.isMultiplication()) { - bool b = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(!b && mstruct[i].isUnit()) { - if(mstruct[i].unit() == CALCULATOR->getRadUnit() || mstruct[i].unit() == CALCULATOR->getDegUnit() || mstruct[i].unit() == CALCULATOR->getGraUnit()) { - b = true; - } else { - return false; - } - } else if(!mstruct[i].representsReal()) { - return false; - } - } - return b; - } else if(mstruct.isAddition()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(!is_real_angle_value(mstruct[i])) return false; - } - return true; - } - return false; -} -bool is_infinite_angle_value(const MathStructure &mstruct) { - if(mstruct.isMultiplication() && mstruct.size() == 2) { - bool b = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(!b && mstruct[i].isUnit()) { - if(mstruct[i].unit() == CALCULATOR->getRadUnit() || mstruct[i].unit() == CALCULATOR->getDegUnit() || mstruct[i].unit() == CALCULATOR->getGraUnit()) { - b = true; - } else { - return false; - } - } else if(!mstruct[i].isNumber() || !mstruct[i].number().isInfinite()) { - return false; - } - } - return b; - } - return false; -} -bool is_number_angle_value(const MathStructure &mstruct, bool allow_infinity = false) { - if(mstruct.isUnit()) { - return mstruct.unit() == CALCULATOR->getRadUnit() || mstruct.unit() == CALCULATOR->getDegUnit() || mstruct.unit() == CALCULATOR->getGraUnit(); - } else if(mstruct.isMultiplication()) { - bool b = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(!b && mstruct[i].isUnit()) { - if(mstruct[i].unit() == CALCULATOR->getRadUnit() || mstruct[i].unit() == CALCULATOR->getDegUnit() || mstruct[i].unit() == CALCULATOR->getGraUnit()) { - b = true; - } else { - return false; - } - } else if(!mstruct[i].representsNumber()) { - if(!allow_infinity || ((!mstruct[i].isNumber() || !mstruct[i].number().isInfinite()) && (!mstruct[i].isPower() || !mstruct[i][0].representsNumber() || !mstruct[i][1].representsNumber())) || mstruct[i].representsUndefined(true)) { - return false; - } - } - } - return b; - } else if(mstruct.isAddition()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(!is_number_angle_value(mstruct[i])) return false; - } - return true; - } - return false; -} - -bool has_predominately_negative_sign(const MathStructure &mstruct) { - if(mstruct.hasNegativeSign() && !mstruct.containsType(STRUCT_ADDITION, true)) return true; - if(mstruct.isAddition() && mstruct.size() > 0) { - size_t p_count = 0; - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].hasNegativeSign()) { - p_count++; - if(p_count > mstruct.size() / 2) return true; - } - } - if(mstruct.size() % 2 == 0 && p_count == mstruct.size() / 2) return mstruct[0].hasNegativeSign(); - } - return false; -} - -void negate_struct(MathStructure &mstruct) { - if(mstruct.isAddition()) { - for(size_t i = 0; i < mstruct.size(); i++) { - mstruct[i].negate(); - } - } else { - mstruct.negate(); - } -} - -bool trig_remove_i(MathStructure &mstruct) { - if(mstruct.isNumber() && mstruct.number().hasImaginaryPart() && !mstruct.number().hasRealPart()) { - mstruct.number() /= nr_one_i; - return true; - } else if(mstruct.isMultiplication() && mstruct.size() > 1 && mstruct[0].isNumber() && mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().hasRealPart()) { - mstruct[0].number() /= nr_one_i; - return true; - } else if(mstruct.isAddition() && mstruct.size() > 0) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(!(mstruct[i].isNumber() && mstruct[i].number().hasImaginaryPart() && !mstruct[i].number().hasRealPart()) && !(mstruct[i].isMultiplication() && mstruct[i].size() > 1 && mstruct[i][0].isNumber() && mstruct[i][0].number().hasImaginaryPart() && !mstruct[i][0].number().hasRealPart())) { - return false; - } - } - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isNumber()) mstruct[i].number() /= nr_one_i; - else mstruct[i][0].number() /= nr_one_i; - } - return true; - } - return false; -} - -SinFunction::SinFunction() : MathFunction("sin", 1) { - Argument *arg = new AngleArgument(); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -bool SinFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && ((allow_units && (vargs[0].representsNumber(true) || vargs[0].representsNonComplex(true))) || (!allow_units && is_number_angle_value(vargs[0], true)));} -bool SinFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && (is_real_angle_value(vargs[0]) || is_infinite_angle_value(vargs[0]));} -bool SinFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);} -int SinFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - - if(vargs[0].isVector()) return 0; - if(CALCULATOR->getRadUnit()) { - if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getRadUnit()) { - mstruct = vargs[0][0]; - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getRadUnit()) { - mstruct = vargs[0][1]; - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getDegUnit()) { - mstruct = vargs[0][0]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 180), true); - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getDegUnit()) { - mstruct = vargs[0][1]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 180), true); - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getGraUnit()) { - mstruct = vargs[0][0]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 200), true); - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getGraUnit()) { - mstruct = vargs[0][1]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 200), true); - } else { - mstruct = vargs[0]; - mstruct.convert(CALCULATOR->getRadUnit()); - mstruct /= CALCULATOR->getRadUnit(); - } - } else { - mstruct = vargs[0]; - } - - MathFunction *f = NULL; - if(eo.approximation == APPROXIMATION_APPROXIMATE && (eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS)) { - if(mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[0].isFunction() && mstruct[0].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable() == CALCULATOR->v_pi && mstruct[2].isNumber() && mstruct[2].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) { - f = mstruct[0].function(); - } - } - - if(eo.approximation == APPROXIMATION_TRY_EXACT) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_EXACT; - CALCULATOR->beginTemporaryStopMessages(); - mstruct.eval(eo2); - } else if(!f) { - mstruct.eval(eo); - } - - if(mstruct.isVector()) { - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - if(CALCULATOR->getRadUnit()) { - for(size_t i = 0; i < mstruct.size(); i++) { - mstruct[i] *= CALCULATOR->getRadUnit(); - } - } - return -1; - } - - bool b = false, b_recalc = true; - - if(eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS) { - if(!f && mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[2].isFunction() && mstruct[2].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable() == CALCULATOR->v_pi && mstruct[0].isNumber() && mstruct[0].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) { - f = mstruct[2].function(); - } - } else if(mstruct.isFunction() && mstruct.size() == 1) { - f = mstruct.function(); - } - - if(mstruct.isVariable() && mstruct.variable() == CALCULATOR->v_pi) { - mstruct.clear(); - b = true; - } else if(f) { - if(f == CALCULATOR->f_asin) { - if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); - mstruct.setToChild(1, true); - b = true; - } else if(f == CALCULATOR->f_acos) { - if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); - mstruct.setToChild(1); - mstruct ^= nr_two; - mstruct.negate(); - mstruct += nr_one; - mstruct ^= nr_half; - b = true; - } else if(f == CALCULATOR->f_atan && (mstruct.isFunction() ? !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : (mstruct[0][0].isFunction() ? mstruct[2][0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)))) { - if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); - mstruct.setToChild(1); - MathStructure *mmul = new MathStructure(mstruct); - mstruct ^= nr_two; - mstruct += nr_one; - mstruct ^= nr_minus_half; - mstruct.multiply_nocopy(mmul); - b = true; - } - } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[1].isVariable() && mstruct[1].variable() == CALCULATOR->v_pi) { - if(mstruct[0].number().isInteger()) { - mstruct.clear(); - b = true; - } else if(!mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().includesInfinity() && !mstruct[0].number().isInterval()) { - Number nr(mstruct[0].number()); - nr.frac(); - Number nr_int(mstruct[0].number()); - nr_int.floor(); - bool b_even = nr_int.isEven(); - nr.setNegative(false); - if(nr.equals(Number(1, 2, 0))) { - if(b_even) mstruct.set(1, 1, 0); - else mstruct.set(-1, 1, 0); - b = true; - } else if(nr.equals(Number(1, 4, 0)) || nr.equals(Number(3, 4, 0))) { - mstruct.set(2, 1, 0); - mstruct.raise_nocopy(new MathStructure(1, 2, 0)); - mstruct.divide_nocopy(new MathStructure(2, 1, 0)); - if(!b_even) mstruct.negate(); - b = true; - } else if(nr.equals(Number(1, 3, 0)) || nr.equals(Number(2, 3, 0))) { - mstruct.set(3, 1, 0); - mstruct.raise_nocopy(new MathStructure(1, 2, 0)); - mstruct.divide_nocopy(new MathStructure(2, 1, 0)); - if(!b_even) mstruct.negate(); - b = true; - } else if(nr.equals(Number(1, 6, 0)) || nr.equals(Number(5, 6, 0))) { - if(b_even) mstruct.set(1, 2, 0); - else mstruct.set(-1, 2, 0); - b = true; - } else if(eo.approximation == APPROXIMATION_EXACT && (mstruct[0].number().isNegative() || !mstruct[0].number().isFraction() || mstruct[0].number().isGreaterThan(nr_half))) { - nr_int = mstruct[0].number(); - nr_int.floor(); - Number nr_frac = mstruct[0].number(); - nr_frac -= nr_int; - if(nr_frac.isGreaterThan(nr_half)) { - nr_frac -= nr_half; - mstruct[0].number() = nr_half; - mstruct[0].number() -= nr_frac; - } else { - mstruct[0].number() = nr_frac; - } - if(nr_int.isOdd()) { - if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); - mstruct.transform(this); - mstruct.negate(); - b = true; - } - } - } - } else if(mstruct.isAddition()) { - size_t i = 0; - bool b_negate = false; - for(; i < mstruct.size(); i++) { - if((mstruct[i].isVariable() && mstruct[i].variable() == CALCULATOR->v_pi) || (mstruct[i].isMultiplication() && mstruct[i].size() == 2 && mstruct[i][1] == CALCULATOR->v_pi && mstruct[i][0].isNumber())) { - if(mstruct[i].isVariable() || mstruct[i][0].number().isInteger()) { - b_negate = mstruct[i].isVariable() || mstruct[i][0].number().isOdd(); - mstruct.delChild(i + 1); - b_recalc = false; - break; - } else if(mstruct[i][0].number().isReal() && (mstruct[i][0].number().isNegative() || !mstruct[i][0].number().isFraction())) { - Number nr_int = mstruct[i][0].number(); - nr_int.floor(); - mstruct[i][0].number() -= nr_int; - b_negate = nr_int.isOdd(); - b_recalc = false; - break; - } - } - } - b = b_negate; - if(b_negate) { - if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); - mstruct.transform(this); - mstruct.negate(); - } - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(b); - if(b) return 1; - if(eo.approximation == APPROXIMATION_TRY_EXACT && !mstruct.isNumber()) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - if(b_recalc) { - mstruct = vargs[0]; - if(CALCULATOR->getRadUnit()) { - mstruct.convert(CALCULATOR->getRadUnit()); - mstruct /= CALCULATOR->getRadUnit(); - } - } - mstruct.eval(eo2); - } - - if(mstruct.isNumber()) { - Number nr(mstruct.number()); - if(nr.sin() && !(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { - mstruct.set(nr, true); - return 1; - } - } - - if(trig_remove_i(mstruct)) { - mstruct.transform(CALCULATOR->f_sinh); - mstruct *= nr_one_i; - return 1; - } - - if(has_predominately_negative_sign(mstruct)) { - negate_struct(mstruct); - if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); - mstruct.transform(this); - mstruct.negate(); - return 1; - } - - - if(CALCULATOR->getRadUnit()) { - if(mstruct.isVector()) { - for(size_t i = 0; i < mstruct.size(); i++) { - mstruct[i] *= CALCULATOR->getRadUnit(); - } - } else { - mstruct *= CALCULATOR->getRadUnit(); - } - } - return -1; -} - -CosFunction::CosFunction() : MathFunction("cos", 1) { - Argument *arg = new AngleArgument(); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -bool CosFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && ((allow_units && (vargs[0].representsNumber(true) || vargs[0].representsNonComplex(true))) || (!allow_units && is_number_angle_value(vargs[0], true)));} -bool CosFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && (is_real_angle_value(vargs[0]) || is_infinite_angle_value(vargs[0]));} -bool CosFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);} -int CosFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - - if(vargs[0].isVector()) return 0; - if(CALCULATOR->getRadUnit()) { - if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getRadUnit()) { - mstruct = vargs[0][0]; - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getRadUnit()) { - mstruct = vargs[0][1]; - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getDegUnit()) { - mstruct = vargs[0][0]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 180), true); - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getDegUnit()) { - mstruct = vargs[0][1]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 180), true); - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getGraUnit()) { - mstruct = vargs[0][0]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 200), true); - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getGraUnit()) { - mstruct = vargs[0][1]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 200), true); - } else { - mstruct = vargs[0]; - mstruct.convert(CALCULATOR->getRadUnit()); - mstruct /= CALCULATOR->getRadUnit(); - } - } else { - mstruct = vargs[0]; - } - - MathFunction *f = NULL; - if(eo.approximation == APPROXIMATION_APPROXIMATE && (eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS)) { - if(mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[0].isFunction() && mstruct[0].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable() == CALCULATOR->v_pi && mstruct[2].isNumber() && mstruct[2].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) { - f = mstruct[0].function(); - } - } - - if(eo.approximation == APPROXIMATION_TRY_EXACT) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_EXACT; - CALCULATOR->beginTemporaryStopMessages(); - mstruct.eval(eo2); - } else if(!f) { - mstruct.eval(eo); - } - - if(mstruct.isVector()) { - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - if(CALCULATOR->getRadUnit()) { - for(size_t i = 0; i < mstruct.size(); i++) { - mstruct[i] *= CALCULATOR->getRadUnit(); - } - } - return -1; - } - - bool b = false, b_recalc = true; - - if(eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS) { - if(!f && mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[2].isFunction() && mstruct[2].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable() == CALCULATOR->v_pi && mstruct[0].isNumber() && mstruct[0].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) { - f = mstruct[2].function(); - } - } else if(mstruct.isFunction() && mstruct.size() == 1) { - f = mstruct.function(); - } - - if(mstruct.isVariable() && mstruct.variable() == CALCULATOR->v_pi) { - mstruct = -1; - b = true; - } else if(f) { - if(f == CALCULATOR->f_acos) { - if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); - mstruct.setToChild(1, true); - b = true; - } else if(f == CALCULATOR->f_asin) { - if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); - mstruct.setToChild(1); - mstruct ^= nr_two; - mstruct.negate(); - mstruct += nr_one; - mstruct ^= nr_half; - b = true; - } else if(f == CALCULATOR->f_atan) { - if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); - mstruct.setToChild(1); - mstruct ^= nr_two; - mstruct += nr_one; - mstruct ^= nr_minus_half; - b = true; - } - } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[1].isVariable() && mstruct[1].variable() == CALCULATOR->v_pi) { - if(mstruct[0].number().isInteger()) { - if(mstruct[0].number().isEven()) { - mstruct = 1; - } else { - mstruct = -1; - } - b = true; - } else if(!mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().includesInfinity() && !mstruct[0].number().isInterval()) { - Number nr(mstruct[0].number()); - nr.frac(); - Number nr_int(mstruct[0].number()); - nr_int.trunc(); - bool b_even = nr_int.isEven(); - nr.setNegative(false); - if(nr.equals(Number(1, 2, 0))) { - mstruct.clear(); - b = true; - } else if(nr.equals(Number(1, 4, 0))) { - mstruct.set(2, 1, 0); - mstruct.raise_nocopy(new MathStructure(1, 2, 0)); - mstruct.divide_nocopy(new MathStructure(2, 1, 0)); - if(!b_even) mstruct.negate(); - b = true; - } else if(nr.equals(Number(3, 4, 0))) { - mstruct.set(2, 1, 0); - mstruct.raise_nocopy(new MathStructure(1, 2, 0)); - mstruct.divide_nocopy(new MathStructure(2, 1, 0)); - if(b_even) mstruct.negate(); - b = true; - } else if(nr.equals(Number(1, 3, 0))) { - if(b_even) mstruct.set(1, 2, 0); - else mstruct.set(-1, 2, 0); - b = true; - } else if(nr.equals(Number(2, 3, 0))) { - if(b_even) mstruct.set(-1, 2, 0); - else mstruct.set(1, 2, 0); - b = true; - } else if(nr.equals(Number(1, 6, 0))) { - mstruct.set(3, 1, 0); - mstruct.raise_nocopy(new MathStructure(1, 2, 0)); - mstruct.divide_nocopy(new MathStructure(2, 1, 0)); - if(!b_even) mstruct.negate(); - b = true; - } else if(nr.equals(Number(5, 6, 0))) { - mstruct.set(3, 1, 0); - mstruct.raise_nocopy(new MathStructure(1, 2, 0)); - mstruct.divide_nocopy(new MathStructure(2, 1, 0)); - if(b_even) mstruct.negate(); - b = true; - } else if(eo.approximation == APPROXIMATION_EXACT && (mstruct[0].number().isNegative() || !mstruct[0].number().isFraction() || mstruct[0].number().isGreaterThan(nr_half))) { - nr_int = mstruct[0].number(); - nr_int.floor(); - Number nr_frac = mstruct[0].number(); - nr_frac -= nr_int; - if(nr_frac.isGreaterThan(nr_half)) { - nr_frac -= nr_half; - mstruct[0].number() = nr_half; - mstruct[0].number() -= nr_frac; - nr_int++; - } else { - mstruct[0].number() = nr_frac; - } - if(nr_int.isOdd()) { - if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); - mstruct.transform(this); - mstruct.negate(); - b = true; - } - } - } - } else if(mstruct.isAddition()) { - size_t i = 0; - bool b_negate = false; - for(; i < mstruct.size(); i++) { - if((mstruct[i].isVariable() && mstruct[i].variable() == CALCULATOR->v_pi) || (mstruct[i].isMultiplication() && mstruct[i].size() == 2 && mstruct[i][1] == CALCULATOR->v_pi && mstruct[i][0].isNumber())) { - if(mstruct[i].isVariable() || mstruct[i][0].number().isInteger()) { - b_negate = mstruct[i].isVariable() || mstruct[i][0].number().isOdd(); - mstruct.delChild(i + 1); - b_recalc = false; - break; - } else if(mstruct[i][0].number().isReal() && (mstruct[i][0].number().isNegative() || !mstruct[i][0].number().isFraction())) { - Number nr_int = mstruct[i][0].number(); - nr_int.floor(); - mstruct[i][0].number() -= nr_int; - b_negate = nr_int.isOdd(); - b_recalc = false; - break; - } - } - } - b = b_negate; - if(b_negate) { - if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); - mstruct.transform(this); - mstruct.negate(); - } - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(b); - if(b) return 1; - if(eo.approximation == APPROXIMATION_TRY_EXACT && !mstruct.isNumber()) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - if(b_recalc) { - mstruct = vargs[0]; - if(CALCULATOR->getRadUnit()) { - mstruct.convert(CALCULATOR->getRadUnit()); - mstruct /= CALCULATOR->getRadUnit(); - } - } - mstruct.eval(eo2); - } - if(mstruct.isNumber()) { - Number nr(mstruct.number()); - if(nr.cos() && !(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { - mstruct.set(nr, true); - return 1; - } - } - if(trig_remove_i(mstruct)) { - mstruct.transform(CALCULATOR->f_cosh); - return 1; - } - if(has_predominately_negative_sign(mstruct)) { - negate_struct(mstruct); - } - if(CALCULATOR->getRadUnit()) { - if(mstruct.isVector()) { - for(size_t i = 0; i < mstruct.size(); i++) { - mstruct[i] *= CALCULATOR->getRadUnit(); - } - } else { - mstruct *= CALCULATOR->getRadUnit(); - } - } - return -1; -} - -TanFunction::TanFunction() : MathFunction("tan", 1) { - Argument *arg = new AngleArgument(); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -bool TanFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && ((allow_units && vargs[0].representsNumber(true)) || (!allow_units && is_number_angle_value(vargs[0], true)));} -bool TanFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && is_real_angle_value(vargs[0]);} -bool TanFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);} -int TanFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - - if(vargs[0].isVector()) return 0; - if(CALCULATOR->getRadUnit()) { - if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getRadUnit()) { - mstruct = vargs[0][0]; - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getRadUnit()) { - mstruct = vargs[0][1]; - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getDegUnit()) { - mstruct = vargs[0][0]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 180), true); - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getDegUnit()) { - mstruct = vargs[0][1]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 180), true); - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getGraUnit()) { - mstruct = vargs[0][0]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 200), true); - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getGraUnit()) { - mstruct = vargs[0][1]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 200), true); - } else { - mstruct = vargs[0]; - mstruct.convert(CALCULATOR->getRadUnit()); - mstruct /= CALCULATOR->getRadUnit(); - } - } else { - mstruct = vargs[0]; - } - - MathFunction *f = NULL; - if(eo.approximation == APPROXIMATION_APPROXIMATE && (eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS)) { - if(mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[0].isFunction() && mstruct[0].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable() == CALCULATOR->v_pi && mstruct[2].isNumber() && mstruct[2].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) { - f = mstruct[0].function(); - } - } - - if(eo.approximation == APPROXIMATION_TRY_EXACT) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_EXACT; - CALCULATOR->beginTemporaryStopMessages(); - mstruct.eval(eo2); - } else if(!f) { - mstruct.eval(eo); - } - - if(mstruct.isVector()) { - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - if(CALCULATOR->getRadUnit()) { - for(size_t i = 0; i < mstruct.size(); i++) { - mstruct[i] *= CALCULATOR->getRadUnit(); - } - } - return -1; - } - - bool b = false, b_recalc = true; - - if(eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS) { - if(!f && mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[2].isFunction() && mstruct[2].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable() == CALCULATOR->v_pi && mstruct[0].isNumber() && mstruct[0].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) { - f = mstruct[2].function(); - } - } else if(mstruct.isFunction() && mstruct.size() == 1) { - f = mstruct.function(); - } - - if(mstruct.isVariable() && mstruct.variable() == CALCULATOR->v_pi) { - mstruct.clear(); - b = true; - } else if(f) { - if(f == CALCULATOR->f_atan) { - if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); - mstruct.setToChild(1, true); - b = true; - } else if(f == CALCULATOR->f_asin && (mstruct.isFunction() ? !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : (mstruct[0][0].isFunction() ? mstruct[2][0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)))) { - if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); - mstruct.setToChild(1); - MathStructure *mmul = new MathStructure(mstruct); - mstruct ^= nr_two; - mstruct.negate(); - mstruct += nr_one; - mstruct ^= nr_minus_half; - mstruct.multiply_nocopy(mmul); - b = true; - } else if(f == CALCULATOR->f_acos && (mstruct.isFunction() ? !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : (mstruct[0][0].isFunction() ? mstruct[2][0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)))) { - if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); - mstruct.setToChild(1); - MathStructure *mmul = new MathStructure(mstruct); - mstruct ^= nr_two; - mstruct.negate(); - mstruct += nr_one; - mstruct ^= nr_half; - mstruct.divide_nocopy(mmul); - b = true; - } - } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[1].isVariable() && mstruct[1].variable() == CALCULATOR->v_pi) { - if(mstruct[0].number().isInteger()) { - mstruct.clear(); - b = true; - } else if(!mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().includesInfinity() && !mstruct[0].number().isInterval()) { - Number nr(mstruct[0].number()); - nr.frac(); - bool b_neg = nr.isNegative(); - nr.setNegative(false); - if(nr.equals(nr_half)) { - Number nr_int(mstruct[0].number()); - nr_int.floor(); - bool b_even = nr_int.isEven(); - if(b_even) nr.setPlusInfinity(); - else nr.setMinusInfinity(); - mstruct.set(nr); - b = true; - } else if(nr.equals(Number(1, 4, 0))) { - if(b_neg) mstruct.set(-1, 1, 0); - else mstruct.set(1, 1, 0); - b = true; - } else if(nr.equals(Number(3, 4, 0))) { - if(!b_neg) mstruct.set(-1, 1, 0); - else mstruct.set(1, 1, 0); - b = true; - } else if(nr.equals(Number(1, 3, 0))) { - mstruct.set(3, 1, 0); - mstruct.raise_nocopy(new MathStructure(1, 2, 0)); - if(b_neg) mstruct.negate(); - b = true; - } else if(nr.equals(Number(2, 3, 0))) { - mstruct.set(3, 1, 0); - mstruct.raise_nocopy(new MathStructure(1, 2, 0)); - if(!b_neg) mstruct.negate(); - b = true; - } else if(nr.equals(Number(1, 6, 0))) { - mstruct.set(3, 1, 0); - mstruct.raise_nocopy(new MathStructure(-1, 2, 0)); - if(b_neg) mstruct.negate(); - b = true; - } else if(nr.equals(Number(5, 6, 0))) { - mstruct.set(3, 1, 0); - mstruct.raise_nocopy(new MathStructure(-1, 2, 0)); - if(!b_neg) mstruct.negate(); - b = true; - } else if(eo.approximation == APPROXIMATION_EXACT && (mstruct[0].number().isNegative() || !mstruct[0].number().isFraction() || mstruct[0].number().isGreaterThan(nr_half))) { - Number nr_int(mstruct[0].number()); - nr_int.floor(); - Number nr_frac = mstruct[0].number(); - nr_frac -= nr_int; - if(nr_frac.isGreaterThan(nr_half)) { - nr_frac -= nr_half; - mstruct[0].number() = nr_half; - mstruct[0].number() -= nr_frac; - if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); - mstruct.transform(this); - mstruct.negate(); - b = true; - } else { - mstruct[0].number() = nr_frac; - } - } - } - } else if(mstruct.isAddition()) { - size_t i = 0; - for(; i < mstruct.size(); i++) { - if((mstruct[i].isVariable() && mstruct[i].variable() == CALCULATOR->v_pi) || (mstruct[i].isMultiplication() && mstruct[i].size() == 2 && mstruct[i][1] == CALCULATOR->v_pi && mstruct[i][0].isNumber())) { - if(mstruct[i].isVariable() || mstruct[i][0].number().isInteger()) { - mstruct.delChild(i + 1); - b_recalc = false; - break; - } else if(mstruct[i][0].number().isReal() && (mstruct[i][0].number().isNegative() || !mstruct[i][0].number().isFraction())) { - Number nr_int = mstruct[i][0].number(); - nr_int.floor(); - mstruct[i][0].number() -= nr_int; - b_recalc = false; - break; - } - } - } - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(b); - if(b) return 1; - if(eo.approximation == APPROXIMATION_TRY_EXACT && !mstruct.isNumber()) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - if(b_recalc) { - mstruct = vargs[0]; - if(CALCULATOR->getRadUnit()) { - mstruct.convert(CALCULATOR->getRadUnit()); - mstruct /= CALCULATOR->getRadUnit(); - } - mstruct.eval(eo2); - } - } - - if(mstruct.isNumber()) { - Number nr(mstruct.number()); - if(nr.tan() && !(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { - mstruct.set(nr, true); - return 1; - } - } - - if(trig_remove_i(mstruct)) { - mstruct.transform(CALCULATOR->f_tanh); - mstruct *= nr_one_i; - return 1; - } - - if(has_predominately_negative_sign(mstruct)) { - negate_struct(mstruct); - if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); - mstruct.transform(this); - mstruct.negate(); - return 1; - } - - if(CALCULATOR->getRadUnit()) { - if(mstruct.isVector()) { - for(size_t i = 0; i < mstruct.size(); i++) { - mstruct[i] *= CALCULATOR->getRadUnit(); - } - } else { - mstruct *= CALCULATOR->getRadUnit(); - } - } - - return -1; -} - -AsinFunction::AsinFunction() : MathFunction("asin", 1) { - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); -} -bool AsinFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} -int AsinFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - if(eo.approximation == APPROXIMATION_TRY_EXACT) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_EXACT; - CALCULATOR->beginTemporaryStopMessages(); - mstruct.eval(eo2); - } else { - mstruct.eval(eo); - } - if(mstruct.isVector()) { - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - return -1; - } - if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0] == nr_half && mstruct[1].isPower() && mstruct[1][1] == nr_half) { - if(mstruct[1][0] == nr_two) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.set(45, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.set(50, 1, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - default: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - return 1; - } else if(mstruct[1][0] == nr_three) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.set(60, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 3, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct.set(1, 3, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - default: {mstruct.set(1, 3, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - return 1; - } - } else if(mstruct.isPower() && mstruct[1] == nr_minus_half && mstruct[0] == nr_two) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.set(45, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.set(50, 1, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - default: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - return 1; - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) { - if(!mstruct.isNumber()) { - CALCULATOR->endTemporaryStopMessages(false); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - mstruct = vargs[0]; - mstruct.eval(eo2); - } else { - CALCULATOR->endTemporaryStopMessages(true); - } - } - if(!mstruct.isNumber()) { - if(trig_remove_i(mstruct)) { - mstruct.transform(CALCULATOR->f_asinh); - mstruct *= nr_one_i; - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_RADIANS: {break;} - default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} - } - return 1; - } - if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;} - return -1; - } - if(mstruct.number().isZero()) { - mstruct.clear(); - } else if(mstruct.number().isOne()) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - mstruct.set(90, 1, 0); - break; - } - case ANGLE_UNIT_GRADIANS: { - mstruct.set(100, 1, 0); - break; - } - case ANGLE_UNIT_RADIANS: { - mstruct.set(1, 2, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - break; - } - default: { - mstruct.set(1, 2, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - if(CALCULATOR->getRadUnit()) { - mstruct *= CALCULATOR->getRadUnit(); - } - } - } - } else if(mstruct.number().isMinusOne()) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - mstruct.set(-90, 1, 0); - break; - } - case ANGLE_UNIT_GRADIANS: { - mstruct.set(-100, 1, 0); - break; - } - case ANGLE_UNIT_RADIANS: { - mstruct.set(-1, 2, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - break; - } - default: { - mstruct.set(-1, 2, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - if(CALCULATOR->getRadUnit()) { - mstruct *= CALCULATOR->getRadUnit(); - } - } - } - } else if(mstruct.number().equals(nr_half)) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - mstruct.set(30, 1, 0); - break; - } - case ANGLE_UNIT_GRADIANS: { - mstruct.set(100, 3, 0); - break; - } - case ANGLE_UNIT_RADIANS: { - mstruct.set(1, 6, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - break; - } - default: { - mstruct.set(1, 6, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - if(CALCULATOR->getRadUnit()) { - mstruct *= CALCULATOR->getRadUnit(); - } - } - } - } else { - Number nr = mstruct.number(); - if(!nr.asin() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { - if(trig_remove_i(mstruct)) { - mstruct.transform(CALCULATOR->f_asinh); - mstruct *= nr_one_i; - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_RADIANS: {break;} - default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} - } - return 1; - } - if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;} - return -1; - } - mstruct = nr; - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_RADIANS: {break;} - default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} - } - } - return 1; - -} - -AcosFunction::AcosFunction() : MathFunction("acos", 1) { - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); -} -bool AcosFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} -int AcosFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - if(eo.approximation == APPROXIMATION_TRY_EXACT) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_EXACT; - CALCULATOR->beginTemporaryStopMessages(); - mstruct.eval(eo2); - } else { - mstruct.eval(eo); - } - if(mstruct.isVector()) { - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - return -1; - } - if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0] == nr_half && mstruct[1].isPower() && mstruct[1][1] == nr_half) { - if(mstruct[1][0] == nr_two) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.set(45, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.set(50, 1, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - default: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - return 1; - } else if(mstruct[1][0] == nr_three) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.set(30, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.set(100, 3, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct.set(1, 6, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - default: {mstruct.set(1, 6, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - return 1; - } - } else if(mstruct.isPower() && mstruct[1] == nr_minus_half && mstruct[0] == nr_two) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.set(45, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.set(50, 1, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - default: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - return 1; - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) { - if(!mstruct.isNumber()) { - CALCULATOR->endTemporaryStopMessages(false); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - mstruct = vargs[0]; - mstruct.eval(eo2); - } else { - CALCULATOR->endTemporaryStopMessages(true); - } - } - if(!mstruct.isNumber()) { - if(has_predominately_negative_sign(mstruct)) { - negate_struct(mstruct); mstruct.transform(CALCULATOR->f_asin); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct += Number(90, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct += Number(100, 1, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct += CALCULATOR->v_pi; mstruct.last() *= nr_half; break;} - default: {mstruct += CALCULATOR->v_pi; mstruct.last() *= nr_half; if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} - } - return 1; - } - return -1; - } - if(mstruct.number().isZero()) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - mstruct.set(90, 1, 0); - break; - } - case ANGLE_UNIT_GRADIANS: { - mstruct.set(100, 1, 0); - break; - } - case ANGLE_UNIT_RADIANS: { - mstruct.set(1, 2, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - break; - } - default: { - mstruct.set(1, 2, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - if(CALCULATOR->getRadUnit()) { - mstruct *= CALCULATOR->getRadUnit(); - } - } - } - } else if(mstruct.number().isOne()) { - mstruct.clear(); - } else if(mstruct.number().isMinusOne()) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - mstruct.set(180, 1, 0); - break; - } - case ANGLE_UNIT_GRADIANS: { - mstruct.set(200, 1, 0); - break; - } - case ANGLE_UNIT_RADIANS: { - mstruct.set(CALCULATOR->v_pi); - break; - } - default: { - mstruct.set(CALCULATOR->v_pi); - if(CALCULATOR->getRadUnit()) { - mstruct *= CALCULATOR->getRadUnit(); - } - } - } - } else if(mstruct.number().equals(nr_half)) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - mstruct.set(60, 1, 0); - break; - } - case ANGLE_UNIT_GRADIANS: { - mstruct.set(200, 3, 0); - break; - } - case ANGLE_UNIT_RADIANS: { - mstruct.set(1, 3, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - break; - } - default: { - mstruct.set(1, 3, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - if(CALCULATOR->getRadUnit()) { - mstruct *= CALCULATOR->getRadUnit(); - } - } - } - } else { - Number nr = mstruct.number(); - if(!nr.acos() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { - if(has_predominately_negative_sign(mstruct)) { - mstruct.number().negate(); - mstruct.transform(CALCULATOR->f_asin); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct += Number(90, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct += Number(100, 1, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct += CALCULATOR->v_pi; mstruct.last() *= nr_half; break;} - default: {mstruct += CALCULATOR->v_pi; mstruct.last() *= nr_half; if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} - } - return 1; - } - return -1; - } - mstruct = nr; - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_RADIANS: {break;} - default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} - } - } - return 1; - -} - -AtanFunction::AtanFunction() : MathFunction("atan", 1) { - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); -} -bool AtanFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && (vargs[0].representsReal(allow_units) || (vargs[0].isNumber() && !vargs[0].number().isI() && !vargs[0].number().isMinusI()));} -bool AtanFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool AtanFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} -int AtanFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - if(eo.approximation == APPROXIMATION_TRY_EXACT) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_EXACT; - CALCULATOR->beginTemporaryStopMessages(); - mstruct.eval(eo2); - } else { - mstruct.eval(eo); - } - if(mstruct.isVector()) { - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - return -1; - } - if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[1].isPower() && mstruct[1][1] == nr_half && mstruct[1][0] == nr_three && mstruct[0].number() == Number(1, 3)) { - if(mstruct[1][0] == nr_three) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.set(30, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.set(100, 3, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct.set(1, 6, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - default: {mstruct.set(1, 6, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - return 1; - } - } else if(mstruct.isPower() && mstruct[1] == nr_half && mstruct[0] == nr_three) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.set(60, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 3, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct.set(1, 3, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - default: {mstruct.set(1, 3, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); - return 1; - } - if(eo.approximation == APPROXIMATION_TRY_EXACT) { - if(!mstruct.isNumber()) { - CALCULATOR->endTemporaryStopMessages(false); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - mstruct = vargs[0]; - mstruct.eval(eo2); - } else { - CALCULATOR->endTemporaryStopMessages(true); - } - } - if(!mstruct.isNumber()) { - if(trig_remove_i(mstruct)) { - mstruct.transform(CALCULATOR->f_atanh); - mstruct *= nr_one_i; - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_RADIANS: {break;} - default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} - } - return 1; - } - if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;} - return -1; - } - if(mstruct.number().isZero()) { - mstruct.clear(); - } else if(eo.allow_infinite && mstruct.number().isI()) { - Number nr; nr.setImaginaryPart(nr_plus_inf); - mstruct = nr; - } else if(eo.allow_infinite && mstruct.number().isMinusI()) { - Number nr; nr.setImaginaryPart(nr_minus_inf); - mstruct = nr; - } else if(mstruct.number().isPlusInfinity()) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - mstruct.set(90, 1, 0); - break; - } - case ANGLE_UNIT_GRADIANS: { - mstruct.set(100, 1, 0); - break; - } - case ANGLE_UNIT_RADIANS: { - mstruct.set(1, 2, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - break; - } - default: { - mstruct.set(1, 2, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - if(CALCULATOR->getRadUnit()) { - mstruct *= CALCULATOR->getRadUnit(); - } - } - } - } else if(mstruct.number().isMinusInfinity()) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - mstruct.set(-90, 1, 0); - break; - } - case ANGLE_UNIT_GRADIANS: { - mstruct.set(-100, 1, 0); - break; - } - case ANGLE_UNIT_RADIANS: { - mstruct.set(-1, 2, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - break; - } - default: { - mstruct.set(-1, 2, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - if(CALCULATOR->getRadUnit()) { - mstruct *= CALCULATOR->getRadUnit(); - } - } - } - } else if(mstruct.number().isOne()) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - mstruct.set(45, 1, 0); - break; - } - case ANGLE_UNIT_GRADIANS: { - mstruct.set(50, 1, 0); - break; - } - case ANGLE_UNIT_RADIANS: { - mstruct.set(1, 4, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - break; - } - default: { - mstruct.set(1, 4, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - if(CALCULATOR->getRadUnit()) { - mstruct *= CALCULATOR->getRadUnit(); - } - } - } - } else if(mstruct.number().isMinusOne()) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - mstruct.set(-45, 1, 0); - break; - } - case ANGLE_UNIT_GRADIANS: { - mstruct.set(-50, 1, 0); - break; - } - case ANGLE_UNIT_RADIANS: { - mstruct.set(-1, 4, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - break; - } - default: { - mstruct.set(-1, 4, 0); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); - if(CALCULATOR->getRadUnit()) { - mstruct *= CALCULATOR->getRadUnit(); - } - } - } - } else { - Number nr = mstruct.number(); - if(!nr.atan() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { - if(trig_remove_i(mstruct)) { - mstruct.transform(CALCULATOR->f_atanh); - mstruct *= nr_one_i; - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_RADIANS: {break;} - default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} - } - return 1; - } - if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;} - return -1; - } - mstruct = nr; - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_RADIANS: {break;} - default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} - } - } - return 1; - -} - -SinhFunction::SinhFunction() : MathFunction("sinh", 1) { - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); -} -bool SinhFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} -bool SinhFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool SinhFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} -int SinhFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.isFunction() && mstruct.size() == 1) { - if(mstruct.function() == CALCULATOR->f_asinh) { - mstruct.setToChild(1, true); - return 1; - } else if(mstruct.function() == CALCULATOR->f_acosh && !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, false, false, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)) { - mstruct.setToChild(1); - MathStructure *mmul = new MathStructure(mstruct); - mstruct += nr_minus_one; - mstruct ^= nr_half; - *mmul += nr_one; - *mmul ^= nr_half; - mstruct.multiply_nocopy(mmul); - return 1; - } else if(mstruct.function() == CALCULATOR->f_atanh && !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, false, false, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)) { - mstruct.setToChild(1); - MathStructure *mmul = new MathStructure(mstruct); - mstruct ^= nr_two; - mstruct.negate(); - mstruct += nr_one; - mstruct ^= nr_minus_half; - mstruct.multiply_nocopy(mmul); - return 1; - } - } - if(!mstruct.isNumber()) { - if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transform(CALCULATOR->f_sin); mstruct *= nr_one_i; return 1;} - if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;} - return -1; - } - Number nr = mstruct.number(); - if(!nr.sinh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { - if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transform(CALCULATOR->f_sin); mstruct *= nr_one_i; return 1;} - if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;} - return -1; - } - mstruct = nr; - return 1; -} -CoshFunction::CoshFunction() : MathFunction("cosh", 1) { - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); -} -bool CoshFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} -bool CoshFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool CoshFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} -int CoshFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.isFunction() && mstruct.size() == 1) { - if(mstruct.function() == CALCULATOR->f_acosh) { - mstruct.setToChild(1, true); - return 1; - } else if(mstruct.function() == CALCULATOR->f_asinh) { - mstruct.setToChild(1); - mstruct ^= nr_two; - mstruct += nr_one; - mstruct ^= nr_half; - return 1; - } else if(mstruct.function() == CALCULATOR->f_atanh) { - mstruct.setToChild(1); - mstruct ^= nr_two; - mstruct.negate(); - mstruct += nr_one; - mstruct ^= nr_minus_half; - return 1; - } - } - if(!mstruct.isNumber()) { - if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transform(CALCULATOR->f_cos); return 1;} - if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); return -1;} - return -1; - } - Number nr = mstruct.number(); - if(!nr.cosh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { - if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transform(CALCULATOR->f_cos); return 1;} - if(has_predominately_negative_sign(mstruct)) mstruct.number().negate(); - return -1; - } - mstruct = nr; - return 1; -} -TanhFunction::TanhFunction() : MathFunction("tanh", 1) { - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); -} -bool TanhFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} -bool TanhFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool TanhFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} -int TanhFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.isFunction() && mstruct.size() == 1) { - if(mstruct.function() == CALCULATOR->f_atanh) { - mstruct.setToChild(1, true); - return 1; - } else if(mstruct.function() == CALCULATOR->f_asinh && !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, false, false, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)) { - mstruct.setToChild(1); - MathStructure *mmul = new MathStructure(mstruct); - mstruct ^= nr_two; - mstruct += nr_one; - mstruct ^= nr_minus_half; - mstruct.multiply_nocopy(mmul); - return 1; - } else if(mstruct.function() == CALCULATOR->f_acosh && !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, false, false, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)) { - mstruct.setToChild(1); - MathStructure *mmul = new MathStructure(mstruct); - MathStructure *mmul2 = new MathStructure(mstruct); - *mmul2 ^= nr_minus_one; - mstruct += nr_minus_one; - mstruct ^= nr_half; - *mmul += nr_one; - *mmul ^= nr_half; - mstruct.multiply_nocopy(mmul); - mstruct.multiply_nocopy(mmul2); - return 1; - } - } - if(!mstruct.isNumber()) { - if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transform(CALCULATOR->f_tan); mstruct *= nr_one_i; return 1;} - if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;} - return -1; - } - Number nr = mstruct.number(); - if(!nr.tanh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { - if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;} - if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transform(CALCULATOR->f_tan); mstruct *= nr_one_i; return 1;} - return -1; - } - mstruct = nr; - return 1; -} -AsinhFunction::AsinhFunction() : MathFunction("asinh", 1) { - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); -} -bool AsinhFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} -bool AsinhFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool AsinhFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} -int AsinhFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(!mstruct.isNumber()) { - if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;} - return -1; - } - Number nr = mstruct.number(); - if(!nr.asinh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { - if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;} - return -1; - } - mstruct = nr; - return 1; -} -AcoshFunction::AcoshFunction() : MathFunction("acosh", 1) { - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false)); -} -bool AcoshFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} -int AcoshFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(eo.allow_complex && vargs[0].isZero()) { - mstruct.set(1, 2, 0); - mstruct.number() *= nr_one_i; - mstruct *= CALCULATOR->v_pi; - return 1; - } else if(vargs[0].isOne()) { - mstruct.clear(); - return 1; - } else if(eo.approximation != APPROXIMATION_APPROXIMATE && eo.allow_complex && vargs[0].number() <= -1) { - mstruct = nr_one_i; - mstruct *= CALCULATOR->v_pi; - mstruct.add_nocopy(new MathStructure(this, &vargs[0], NULL)); - mstruct.last()[0].negate(); - return 1; - } - FR_FUNCTION(acosh) -} -AtanhFunction::AtanhFunction() : MathFunction("atanh", 1) { - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); -} -int AtanhFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(!mstruct.isNumber()) { - if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;} - return -1; - } - if(eo.allow_complex && mstruct.number().includesInfinity()) { - if(mstruct.number().isPlusInfinity() || (!mstruct.number().hasRealPart() && mstruct.number().hasImaginaryPart() && mstruct.number().internalImaginary()->isMinusInfinity())) { - mstruct = nr_minus_half; - mstruct *= nr_one_i; - mstruct *= CALCULATOR->v_pi; - return true; - } else if(mstruct.number().isMinusInfinity() || (!mstruct.number().hasRealPart() && mstruct.number().hasImaginaryPart() && mstruct.number().internalImaginary()->isPlusInfinity())) { - mstruct = nr_half; - mstruct *= nr_one_i; - mstruct *= CALCULATOR->v_pi; - return true; - } - } else if(eo.approximation != APPROXIMATION_APPROXIMATE && eo.allow_complex && mstruct.number() > 1) { - mstruct.set(-1, 2, 0); - mstruct.number() *= nr_one_i; - mstruct *= CALCULATOR->v_pi; - mstruct.add_nocopy(new MathStructure(this, &vargs[0], NULL)); - mstruct.last()[0].inverse(); - return 1; - } else if(eo.approximation != APPROXIMATION_APPROXIMATE && eo.allow_complex && mstruct.number() < -1) { - mstruct.set(1, 2, 0); - mstruct.number() *= nr_one_i; - mstruct *= CALCULATOR->v_pi; - mstruct.add_nocopy(new MathStructure(this, &vargs[0], NULL)); - mstruct.last()[0].inverse(); - mstruct.last()[0].negate(); - mstruct.last().negate(); - return 1; - } - Number nr = mstruct.number(); - if(!nr.atanh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { - if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;} - return -1; - } - mstruct = nr; - return 1; -} -Atan2Function::Atan2Function() : MathFunction("atan2", 2) { - NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, true); - arg->setComplexAllowed(false); - setArgumentDefinition(1, arg); - arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, true); - arg->setComplexAllowed(false); - setArgumentDefinition(2, arg); -} -bool Atan2Function::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[0].representsNumber() && vargs[1].representsNumber();} -int Atan2Function::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].number().isZero()) { - if(!vargs[1].number().isNonZero()) return 0; - if(vargs[1].number().isNegative()) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.set(180, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 1, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->v_pi); break;} - default: {mstruct.set(CALCULATOR->v_pi); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();} - } - } else { - mstruct.clear(); - } - } else if(vargs[1].number().isZero() && vargs[0].number().isNonZero()) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.set(90, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.set(100, 1, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->v_pi); mstruct.multiply(nr_half); break;} - default: {mstruct.set(CALCULATOR->v_pi); mstruct.multiply(nr_half); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();} - } - if(vargs[0].number().hasNegativeSign()) mstruct.negate(); - } else if(!vargs[1].number().isNonZero()) { - FR_FUNCTION_2(atan2) - } else { - MathStructure new_nr(vargs[0]); - if(!new_nr.number().divide(vargs[1].number())) return -1; - if(vargs[1].number().isNegative() && vargs[0].number().isNonZero()) { - if(vargs[0].number().isNegative()) { - mstruct.set(CALCULATOR->f_atan, &new_nr, NULL); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.add(-180); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.add(-200); break;} - case ANGLE_UNIT_RADIANS: {mstruct.subtract(CALCULATOR->v_pi); break;} - default: {MathStructure msub(CALCULATOR->v_pi); if(CALCULATOR->getRadUnit()) msub *= CALCULATOR->getRadUnit(); mstruct.subtract(msub);} - } - } else { - mstruct.set(CALCULATOR->f_atan, &new_nr, NULL); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.add(180); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.add(200); break;} - case ANGLE_UNIT_RADIANS: {mstruct.add(CALCULATOR->v_pi); break;} - default: {MathStructure madd(CALCULATOR->v_pi); if(CALCULATOR->getRadUnit()) madd *= CALCULATOR->getRadUnit(); mstruct.add(madd);} - } - } - } else { - mstruct.set(CALCULATOR->f_atan, &new_nr, NULL); - } - } - return 1; -} - -bool calculate_arg(MathStructure &mstruct, const EvaluationOptions &eo) { - - MathStructure msave; - - if(!mstruct.isNumber()) { - if(mstruct.isPower() && mstruct[0] == CALCULATOR->v_e && mstruct[1].isNumber() && mstruct[1].number().hasImaginaryPart() && !mstruct[1].number().hasRealPart()) { - CALCULATOR->beginTemporaryStopMessages(); - CALCULATOR->beginTemporaryEnableIntervalArithmetic(); - Number nr(*mstruct[1].number().internalImaginary()); - nr.add(CALCULATOR->v_pi->get().number()); - nr.divide(CALCULATOR->v_pi->get().number() * 2); - Number nr_u(nr.upperEndPoint()); - nr = nr.lowerEndPoint(); - CALCULATOR->endTemporaryEnableIntervalArithmetic(); - nr_u.floor(); - nr.floor(); - if(!CALCULATOR->endTemporaryStopMessages() && nr == nr_u) { - nr.setApproximate(false); - nr *= 2; - nr.negate(); - mstruct = mstruct[1].number().imaginaryPart(); - if(!nr.isZero()) { - mstruct += nr; - mstruct.last() *= CALCULATOR->v_pi; - } - return true; - } - } - if(eo.approximation == APPROXIMATION_EXACT) { - msave = mstruct; - if(!test_eval(mstruct, eo)) { - mstruct = msave; - return false; - } - } - } - if(mstruct.isNumber()) { - if(!mstruct.number().hasImaginaryPart()) { - return false; - } else if(!mstruct.number().hasRealPart() && mstruct.number().imaginaryPartIsNonZero()) { - bool b_neg = mstruct.number().imaginaryPartIsNegative(); - mstruct.set(CALCULATOR->v_pi); mstruct.multiply(nr_half); - if(b_neg) mstruct.negate(); - } else if(!msave.isZero()) { - mstruct = msave; - return false; - } else if(!mstruct.number().realPartIsNonZero()) { - return false; - } else { - MathStructure new_nr(mstruct.number().imaginaryPart()); - if(!new_nr.number().divide(mstruct.number().realPart())) return false; - if(mstruct.number().realPartIsNegative()) { - if(mstruct.number().imaginaryPartIsNegative()) { - mstruct.set(CALCULATOR->f_atan, &new_nr, NULL); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.divide_nocopy(new MathStructure(180, 1, 0)); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.divide_nocopy(new MathStructure(200, 1, 0)); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_RADIANS: {break;} - default: {if(CALCULATOR->getRadUnit()) {mstruct /= CALCULATOR->getRadUnit();} break;} - } - mstruct.subtract(CALCULATOR->v_pi); - } else if(mstruct.number().imaginaryPartIsNonNegative()) { - mstruct.set(CALCULATOR->f_atan, &new_nr, NULL); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.divide_nocopy(new MathStructure(180, 1, 0)); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.divide_nocopy(new MathStructure(200, 1, 0)); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_RADIANS: {break;} - default: {if(CALCULATOR->getRadUnit()) {mstruct /= CALCULATOR->getRadUnit();} break;} - } - mstruct.add(CALCULATOR->v_pi); - } else { - return false; - } - } else { - mstruct.set(CALCULATOR->f_atan, &new_nr, NULL); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.divide_nocopy(new MathStructure(180, 1, 0)); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.divide_nocopy(new MathStructure(200, 1, 0)); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->v_pi)); break;} - case ANGLE_UNIT_RADIANS: {break;} - default: {if(CALCULATOR->getRadUnit()) {mstruct /= CALCULATOR->getRadUnit();} break;} - } - } - } - return true; - } - if(!msave.isZero()) { - mstruct = msave; - } - return false; - -} - -ArgFunction::ArgFunction() : MathFunction("arg", 1) { - Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -bool ArgFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber(true);} -bool ArgFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber(true);} -bool ArgFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} -int ArgFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - - MathStructure msave; - - arg_test_non_number: - if(!mstruct.isNumber()) { - if(mstruct.representsPositive(true)) { - mstruct.clear(); - return 1; - } - if(mstruct.representsNegative(true)) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.set(180, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 1, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->v_pi); break;} - default: {mstruct.set(CALCULATOR->v_pi); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();} - } - return 1; - } - if(!msave.isZero()) { - mstruct = msave; - return -1; - } - if(mstruct.isMultiplication()) { - bool b = false; - for(size_t i = 0; i < mstruct.size();) { - if(mstruct[i].representsPositive()) { - mstruct.delChild(i + 1); - b = true; - } else { - if(!mstruct[i].isMinusOne() && mstruct[i].representsNegative()) { - mstruct[i].set(-1, 1, 0, true); - b = true; - } - i++; - } - } - if(b) { - if(mstruct.size() == 1) { - mstruct.setToChild(1); - } else if(mstruct.size() == 0) { - mstruct.clear(true); - } - mstruct.transform(STRUCT_FUNCTION); - mstruct.setFunction(this); - return 1; - } - } - if(mstruct.isPower() && mstruct[0].representsComplex() && mstruct[1].representsInteger()) { - mstruct.setType(STRUCT_MULTIPLICATION); - mstruct[0].transform(STRUCT_FUNCTION); - mstruct[0].setFunction(this); - return 1; - } - if(mstruct.isPower() && mstruct[0] == CALCULATOR->v_e && mstruct[1].isNumber() && mstruct[1].number().hasImaginaryPart() && !mstruct[1].number().hasRealPart()) { - CALCULATOR->beginTemporaryStopMessages(); - CALCULATOR->beginTemporaryEnableIntervalArithmetic(); - Number nr(*mstruct[1].number().internalImaginary()); - nr.add(CALCULATOR->v_pi->get().number()); - nr.divide(CALCULATOR->v_pi->get().number() * 2); - Number nr_u(nr.upperEndPoint()); - nr = nr.lowerEndPoint(); - CALCULATOR->endTemporaryEnableIntervalArithmetic(); - nr_u.floor(); - nr.floor(); - if(!CALCULATOR->endTemporaryStopMessages() && nr == nr_u) { - nr.setApproximate(false); - nr *= 2; - nr.negate(); - mstruct = mstruct[1].number().imaginaryPart(); - if(!nr.isZero()) { - mstruct += nr; - mstruct.last() *= CALCULATOR->v_pi; - } - return true; - } - } - if(eo.approximation == APPROXIMATION_EXACT) { - msave = mstruct; - if(!test_eval(mstruct, eo)) { - mstruct = msave; - return -1; - } - } - } - if(mstruct.isNumber()) { - if(!mstruct.number().hasImaginaryPart()) { - if(!mstruct.number().isNonZero()) { - if(!msave.isZero()) mstruct = msave; - return -1; - } - if(mstruct.number().isNegative()) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.set(180, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 1, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->v_pi); break;} - default: {mstruct.set(CALCULATOR->v_pi); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();} - } - } else { - mstruct.clear(); - } - } else if(!mstruct.number().hasRealPart() && mstruct.number().imaginaryPartIsNonZero()) { - bool b_neg = mstruct.number().imaginaryPartIsNegative(); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.set(90, 1, 0); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.set(100, 1, 0); break;} - case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->v_pi); mstruct.multiply(nr_half); break;} - default: {mstruct.set(CALCULATOR->v_pi); mstruct.multiply(nr_half); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();} - } - if(b_neg) mstruct.negate(); - } else if(!msave.isZero()) { - mstruct = msave; - return -1; - } else if(!mstruct.number().realPartIsNonZero()) { - FR_FUNCTION(arg) - } else { - MathStructure new_nr(mstruct.number().imaginaryPart()); - if(!new_nr.number().divide(mstruct.number().realPart())) return -1; - if(mstruct.number().realPartIsNegative()) { - if(mstruct.number().imaginaryPartIsNegative()) { - mstruct.set(CALCULATOR->f_atan, &new_nr, NULL); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.add(-180); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.add(-200); break;} - case ANGLE_UNIT_RADIANS: {mstruct.subtract(CALCULATOR->v_pi); break;} - default: {MathStructure msub(CALCULATOR->v_pi); if(CALCULATOR->getRadUnit()) msub *= CALCULATOR->getRadUnit(); mstruct.subtract(msub);} - } - } else if(mstruct.number().imaginaryPartIsNonNegative()) { - mstruct.set(CALCULATOR->f_atan, &new_nr, NULL); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct.add(180); break;} - case ANGLE_UNIT_GRADIANS: {mstruct.add(200); break;} - case ANGLE_UNIT_RADIANS: {mstruct.add(CALCULATOR->v_pi); break;} - default: {MathStructure madd(CALCULATOR->v_pi); if(CALCULATOR->getRadUnit()) madd *= CALCULATOR->getRadUnit(); mstruct.add(madd);} - } - } else { - FR_FUNCTION(arg) - } - } else { - mstruct.set(CALCULATOR->f_atan, &new_nr, NULL); - } - } - return 1; - } - if(!msave.isZero()) { - goto arg_test_non_number; - } - return -1; -} - -SincFunction::SincFunction() : MathFunction("sinc", 1) { - Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -bool SincFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && (vargs[0].representsNumber() || is_number_angle_value(vargs[0]));} -bool SincFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && (vargs[0].representsReal() || is_real_angle_value(vargs[0]));} -bool SincFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} -int SincFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.containsType(STRUCT_UNIT) && CALCULATOR->getRadUnit()) { - mstruct.convert(CALCULATOR->getRadUnit()); - mstruct /= CALCULATOR->getRadUnit(); - } - if(mstruct.isZero()) { - mstruct.set(1, 1, 0, true); - return 1; - } else if(mstruct.representsNonZero(true)) { - bool b = replace_f_interval(mstruct, eo); - b = replace_intervals_f(mstruct) || b; - MathStructure *m_sin = new MathStructure(CALCULATOR->f_sin, &mstruct, NULL); - if(CALCULATOR->getRadUnit()) (*m_sin)[0].multiply(CALCULATOR->getRadUnit()); - mstruct.inverse(); - mstruct.multiply_nocopy(m_sin); - if(b) mstruct.eval(eo); - return 1; - } - return -1; -} -CisFunction::CisFunction() : MathFunction("cis", 1) { - Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); -} -int CisFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - - if(vargs[0].isVector()) return 0; - if(vargs[0].contains(CALCULATOR->getRadUnit(), false, true, true) > 0 || vargs[0].contains(CALCULATOR->getDegUnit(), false, true, true) > 0 || vargs[0].contains(CALCULATOR->getGraUnit(), false, true, true) > 0) { - if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getRadUnit()) { - mstruct = vargs[0][0]; - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getRadUnit()) { - mstruct = vargs[0][1]; - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getDegUnit()) { - mstruct = vargs[0][0]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 180), true); - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getDegUnit()) { - mstruct = vargs[0][1]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 180), true); - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getGraUnit()) { - mstruct = vargs[0][0]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 200), true); - } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getGraUnit()) { - mstruct = vargs[0][1]; - mstruct *= CALCULATOR->v_pi; - mstruct.multiply(Number(1, 200), true); - } else { - mstruct = vargs[0]; - mstruct.convert(CALCULATOR->getRadUnit()); - mstruct /= CALCULATOR->getRadUnit(); - } - } else { - mstruct = vargs[0]; - } - - if(mstruct.isVariable() && mstruct.variable() == CALCULATOR->v_pi) { - mstruct.set(-1, 1, 0, true); - return 1; - } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isInteger() && mstruct[1].isVariable() && mstruct[1].variable() == CALCULATOR->v_pi) { - if(mstruct[0].number().isEven()) { - mstruct.set(1, 1, 0, true); - return 1; - } else if(mstruct[0].number().isOdd()) { - mstruct.set(-1, 1, 0, true); - return 1; - } - } - - mstruct *= CALCULATOR->v_i; - mstruct ^= CALCULATOR->v_e; - mstruct.swapChildren(1, 2); - - return 1; - -} - - -bool create_interval(MathStructure &mstruct, const MathStructure &m1, const MathStructure &m2) { - if(m1.contains(CALCULATOR->v_pinf, true) || m2.contains(CALCULATOR->v_pinf, true) || m1.contains(CALCULATOR->v_minf, true) || m2.contains(CALCULATOR->v_minf, true)) { - MathStructure m1b(m1), m2b(m2); - m1b.replace(CALCULATOR->v_pinf, nr_plus_inf); - m2b.replace(CALCULATOR->v_pinf, nr_plus_inf); - m1b.replace(CALCULATOR->v_minf, nr_minus_inf); - m2b.replace(CALCULATOR->v_minf, nr_minus_inf); - return create_interval(mstruct, m1b, m2b); - } - if(m1 == m2) { - mstruct.set(m1, true); - return 1; - } else if(m1.isNumber() && m2.isNumber()) { - Number nr; - if(!nr.setInterval(m1.number(), m2.number())) return false; - mstruct.set(nr, true); - return true; - } else if(m1.isMultiplication() && m2.isMultiplication() && m1.size() > 1 && m2.size() > 1) { - size_t i0 = 0, i1 = 0; - if(m1[0].isNumber()) i0++; - if(m2[0].isNumber()) i1++; - if(i0 == 0 && i1 == 0) return false; - if(m1.size() - i0 != m2.size() - i1) return false; - for(size_t i = 0; i < m1.size() - i0; i++) { - if(!m1[i + i0].equals(m2[i + i1], true)) { - return false; - } - } - Number nr; - if(!nr.setInterval(i0 == 1 ? m1[0].number() : nr_one, i1 == 1 ? m2[0].number() : nr_one)) return 0; - mstruct.set(m1, true); - if(i0 == 1) mstruct.delChild(1, true); - mstruct *= nr; - mstruct.evalSort(false); - return 1; - } else if(m1.isAddition() && m2.isAddition() && m1.size() > 1 && m2.size() > 1) { - size_t i0 = 0, i1 = 0; - if(m1.last().isNumber()) i0++; - if(m2.last().isNumber()) i1++; - if(i0 == 0 && i1 == 0) return false; - if(m1.size() - i0 != m2.size() - i1) return false; - for(size_t i = 0; i < m1.size() - i0; i++) { - if(!m1[i].equals(m2[i], true)) { - return false; - } - } - Number nr; - if(!nr.setInterval(i0 == 1 ? m1.last().number() : nr_one, i1 == 1 ? m2.last().number() : nr_one)) return false; - mstruct.set(m1, true); - if(i0 == 1) mstruct.delChild(mstruct.size(), true); - mstruct += nr; - mstruct.evalSort(false); - return true; - } else if(m1.isMultiplication() && m1.size() == 2 && m1[0].isNumber() && m2.equals(m1[1], true)) { - Number nr; - if(!nr.setInterval(m1[0].number(), nr_one)) return false; - mstruct.set(nr, true); - mstruct *= m2; - return true; - } else if(m2.isMultiplication() && m2.size() == 2 && m2[0].isNumber() && m1.equals(m2[1], true)) { - Number nr; - if(!nr.setInterval(nr_one, m2[0].number())) return false; - mstruct.set(nr, true); - mstruct *= m1; - return true; - } - return false; -} - -IntervalFunction::IntervalFunction() : MathFunction("interval", 2) { - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false)); - setArgumentDefinition(2, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false)); -} -int IntervalFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(create_interval(mstruct, vargs[0], vargs[1])) return 1; - MathStructure marg1(vargs[0]); - marg1.eval(eo); - MathStructure marg2(vargs[1]); - marg2.eval(eo); - if(create_interval(mstruct, marg1, marg2)) return 1; - return 0; -} -bool IntervalFunction::representsPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsPositive(allow_units) && vargs[0].representsPositive(allow_units);} -bool IntervalFunction::representsNegative(const MathStructure&vargs, bool allow_units) const {return vargs.size() == 2 && vargs[0].representsNegative(allow_units) && vargs[1].representsNegative(allow_units);} -bool IntervalFunction::representsNonNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[0].representsNonNegative(allow_units) && vargs[1].representsNonNegative(allow_units);} -bool IntervalFunction::representsNonPositive(const MathStructure&vargs, bool allow_units) const {return vargs.size() == 2 && vargs[0].representsNonPositive(allow_units) && vargs[1].representsNonPositive(allow_units);} -bool IntervalFunction::representsInteger(const MathStructure &, bool) const {return false;} -bool IntervalFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[0].representsNumber(allow_units) && vargs[1].representsNumber(allow_units);} -bool IntervalFunction::representsRational(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[0].representsRational(allow_units) && vargs[1].representsRational(allow_units);} -bool IntervalFunction::representsReal(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[0].representsReal(allow_units) && vargs[1].representsReal(allow_units);} -bool IntervalFunction::representsNonComplex(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[0].representsNonComplex(allow_units) && vargs[1].representsNonComplex(allow_units);} -bool IntervalFunction::representsComplex(const MathStructure&, bool) const {return false;} -bool IntervalFunction::representsNonZero(const MathStructure &vargs, bool allow_units) const {return representsPositive(vargs, allow_units) || representsNegative(vargs, allow_units);} -bool IntervalFunction::representsEven(const MathStructure&, bool) const {return false;} -bool IntervalFunction::representsOdd(const MathStructure&, bool) const {return false;} -bool IntervalFunction::representsUndefined(const MathStructure &vargs) const {return vargs.size() == 2 && (vargs[0].representsUndefined() || vargs[1].representsUndefined());} - - -bool set_uncertainty(MathStructure &mstruct, MathStructure &munc, const EvaluationOptions &eo = default_evaluation_options, bool do_eval = false) { - if(munc.isFunction() && munc.function() == CALCULATOR->f_abs && munc.size() == 1) { - munc.setToChild(1, true); - } - test_munc: - if(munc.isNumber()) { - if(munc.isZero()) { - return 1; - } else if(mstruct.isNumber()) { - mstruct.number().setUncertainty(munc.number(), eo.interval_calculation == INTERVAL_CALCULATION_NONE); - mstruct.numberUpdated(); - return 1; - } else if(mstruct.isAddition()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isNumber()) { - mstruct[i].number().setUncertainty(munc.number(), eo.interval_calculation == INTERVAL_CALCULATION_NONE); - mstruct[i].numberUpdated(); - mstruct.childUpdated(i + 1); - return 1; - } - } - } - mstruct.add(m_zero, true); - mstruct.last().number().setUncertainty(munc.number(), eo.interval_calculation == INTERVAL_CALCULATION_NONE); - mstruct.last().numberUpdated(); - mstruct.childUpdated(mstruct.size()); - return 1; - } else { - if(munc.isMultiplication()) { - if(!munc[0].isNumber()) { - munc.insertChild(m_one, 1); - } - } else { - munc.transform(STRUCT_MULTIPLICATION); - munc.insertChild(m_one, 1); - } - if(munc.isMultiplication()) { - if(munc.size() == 2) { - if(mstruct.isMultiplication() && mstruct[0].isNumber() && (munc[1] == mstruct[1] || (munc[1].isFunction() && munc[1].function() == CALCULATOR->f_abs && munc[1].size() == 1 && mstruct[1] == munc[1][0]))) { - mstruct[0].number().setUncertainty(munc[0].number(), eo.interval_calculation == INTERVAL_CALCULATION_NONE); - mstruct[0].numberUpdated(); - mstruct.childUpdated(1); - return 1; - } else if(mstruct.equals(munc[1]) || (munc[1].isFunction() && munc[1].function() == CALCULATOR->f_abs && munc[1].size() == 1 && mstruct.equals(munc[1][0]))) { - mstruct.transform(STRUCT_MULTIPLICATION); - mstruct.insertChild(m_one, 1); - mstruct[0].number().setUncertainty(munc[0].number(), eo.interval_calculation == INTERVAL_CALCULATION_NONE); - mstruct[0].numberUpdated(); - mstruct.childUpdated(1); - return 1; - } - } else if(mstruct.isMultiplication()) { - size_t i2 = 0; - if(mstruct[0].isNumber()) i2++; - if(mstruct.size() + 1 - i2 == munc.size()) { - bool b = true; - for(size_t i = 1; i < munc.size(); i++, i2++) { - if(!munc[i].equals(mstruct[i2]) && !(munc[i].isFunction() && munc[i].function() == CALCULATOR->f_abs && munc[i].size() == 1 && mstruct[i2] == munc[i][0])) { - b = false; - break; - } - } - if(b) { - if(!mstruct[0].isNumber()) { - mstruct.insertChild(m_one, 1); - } - mstruct[0].number().setUncertainty(munc[0].number(), eo.interval_calculation == INTERVAL_CALCULATION_NONE); - mstruct[0].numberUpdated(); - mstruct.childUpdated(1); - return 1; - } - } - } - if(do_eval) { - bool b = false; - for(size_t i = 0; i < munc.size(); i++) { - if(munc[i].isFunction() && munc[i].function() == CALCULATOR->f_abs && munc[i].size() == 1) { - munc[i].setToChild(1); - b = true; - } - } - if(b) { - munc.eval(eo); - goto test_munc; - } - } - } - } - return false; -} - -UncertaintyFunction::UncertaintyFunction() : MathFunction("uncertainty", 2, 3) { - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false)); - setArgumentDefinition(2, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false)); - setArgumentDefinition(3, new BooleanArgument()); - setDefaultValue(3, "1"); -} -int UncertaintyFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - mstruct = vargs[0]; - MathStructure munc(vargs[1]); - mstruct.eval(eo); - munc.eval(eo); - if(vargs[2].number().getBoolean()) { - if(munc.isNumber() && mstruct.isNumber()) { - mstruct.number().setRelativeUncertainty(munc.number(), eo.interval_calculation == INTERVAL_CALCULATION_NONE); - mstruct.numberUpdated(); - return 1; - } - mstruct = vargs[0]; - mstruct *= m_one; - mstruct.last() -= vargs[1]; - mstruct.transform(CALCULATOR->f_interval); - MathStructure *m2 = new MathStructure(vargs[0]); - m2->multiply(m_one); - m2->last() += vargs[1]; - mstruct.addChild_nocopy(m2); - return 1; - } else { - if(set_uncertainty(mstruct, munc, eo, true)) return 1; - mstruct = vargs[0]; - mstruct -= vargs[1]; - mstruct.transform(CALCULATOR->f_interval); - MathStructure *m2 = new MathStructure(vargs[0]); - m2->add(vargs[1]); - mstruct.addChild_nocopy(m2); - return 1; - } - return 0; -} - -RadiansToDefaultAngleUnitFunction::RadiansToDefaultAngleUnitFunction() : MathFunction("radtodef", 1) { -} -int RadiansToDefaultAngleUnitFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - mstruct = vargs[0]; - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - mstruct *= 180; - mstruct /= CALCULATOR->v_pi; - break; - } - case ANGLE_UNIT_GRADIANS: { - mstruct *= 200; - mstruct /= CALCULATOR->v_pi; - break; - } - case ANGLE_UNIT_RADIANS: { - break; - } - default: { - if(CALCULATOR->getRadUnit()) { - mstruct *= CALCULATOR->getRadUnit(); - } - } - } - return 1; -} - -TotalFunction::TotalFunction() : MathFunction("total", 1) { - setArgumentDefinition(1, new VectorArgument("")); -} -int TotalFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - mstruct.clear(); - for(size_t index = 0; index < vargs[0].size(); index++) { - if(CALCULATOR->aborted()) return 0; - mstruct.calculateAdd(vargs[0][index], eo); - } - return 1; -} -PercentileFunction::PercentileFunction() : MathFunction("percentile", 2, 3) { - setArgumentDefinition(1, new VectorArgument("")); - NumberArgument *arg = new NumberArgument(); - Number fr; - arg->setMin(&fr); - fr.set(100, 1, 0); - arg->setMax(&fr); - arg->setIncludeEqualsMin(true); - arg->setIncludeEqualsMax(true); - setArgumentDefinition(2, arg); - IntegerArgument *iarg = new IntegerArgument(); - fr.set(1, 1, 0); - iarg->setMin(&fr); - fr.set(9, 1, 0); - iarg->setMax(&fr); - setArgumentDefinition(3, iarg); - setDefaultValue(3, "8"); -} -int PercentileFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - MathStructure v(vargs[0]); - if(v.size() == 0) {mstruct.clear(); return 1;} - MathStructure *mp; - Number fr100(100, 1, 0); - int i_variant = vargs[2].number().intValue(); - if(!v.sortVector()) { - return 0; - } else { - Number pfr(vargs[1].number()); - if(pfr == fr100) { - // Max value - mstruct = v[v.size() - 1]; - return 1; - } else if(pfr.isZero()) { - // Min value - mstruct = v[0]; - return 1; - } - pfr /= 100; - if(pfr == nr_half) { - // Median - if(v.size() % 2 == 1) { - mstruct = v[v.size() / 2]; - } else { - mstruct = v[v.size() / 2 - 1]; - mstruct += v[v.size() / 2]; - mstruct *= nr_half; - } - return 1; - } - // Method numbers as in R - switch(i_variant) { - case 2: { - Number ufr(pfr); - ufr *= (long int) v.countChildren(); - if(ufr.isInteger()) { - pfr = ufr; - ufr++; - mstruct = v[pfr.uintValue() - 1]; - if(ufr.uintValue() > v.size()) return 1; - mstruct += v[ufr.uintValue() - 1]; - mstruct *= nr_half; - return 1; - } - } - case 1: { - pfr *= (long int) v.countChildren(); - pfr.ceil(); - size_t index = pfr.uintValue(); - if(index > v.size()) index = v.size(); - if(index == 0) index = 1; - mstruct = v[index - 1]; - return 1; - } - case 3: { - pfr *= (long int) v.countChildren(); - pfr.round(); - size_t index = pfr.uintValue(); - if(index > v.size()) index = v.size(); - if(index == 0) index = 1; - mstruct = v[index - 1]; - return 1; - } - case 4: {pfr *= (long int) v.countChildren(); break;} - case 5: {pfr *= (long int) v.countChildren(); pfr += nr_half; break;} - case 6: {pfr *= (long int) v.countChildren() + 1; break;} - case 7: {pfr *= (long int) v.countChildren() - 1; pfr += 1; break;} - case 9: {pfr *= Number(v.countChildren() * 4 + 1, 4); pfr += Number(3, 8); break;} - case 8: {} - default: {pfr *= Number(v.countChildren() * 3 + 1, 3); pfr += Number(1, 3); break;} - } - Number ufr(pfr); - ufr.ceil(); - Number lfr(pfr); - lfr.floor(); - pfr -= lfr; - size_t u_index = ufr.uintValue(); - size_t l_index = lfr.uintValue(); - if(u_index > v.size()) { - mstruct = v[v.size() - 1]; - return 1; - } - if(l_index == 0) { - mstruct = v[0]; - return 1; - } - mp = v.getChild(u_index); - if(!mp) return 0; - MathStructure gap(*mp); - mp = v.getChild(l_index); - if(!mp) return 0; - gap -= *mp; - gap *= pfr; - mp = v.getChild(l_index); - if(!mp) return 0; - mstruct = *mp; - mstruct += gap; - } - return 1; -} -MinFunction::MinFunction() : MathFunction("min", 1) { - setArgumentDefinition(1, new VectorArgument("")); -} -int MinFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - ComparisonResult cmp; - const MathStructure *min = NULL; - vector unsolveds; - bool b = false; - for(size_t index = 0; index < vargs[0].size(); index++) { - if(min == NULL) { - min = &vargs[0][index]; - } else { - cmp = min->compare(vargs[0][index]); - if(cmp == COMPARISON_RESULT_LESS) { - min = &vargs[0][index]; - b = true; - } else if(COMPARISON_NOT_FULLY_KNOWN(cmp)) { - if(CALCULATOR->showArgumentErrors()) { - CALCULATOR->error(true, _("Unsolvable comparison in %s()."), name().c_str(), NULL); - } - unsolveds.push_back(&vargs[0][index]); - } else { - b = true; - } - } - } - if(min) { - if(unsolveds.size() > 0) { - if(!b) return 0; - MathStructure margs; margs.clearVector(); - margs.addChild(*min); - for(size_t i = 0; i < unsolveds.size(); i++) { - margs.addChild(*unsolveds[i]); - } - mstruct.set(this, &margs, NULL); - return 1; - } else { - mstruct = *min; - return 1; - } - } - return 0; -} -MaxFunction::MaxFunction() : MathFunction("max", 1) { - setArgumentDefinition(1, new VectorArgument("")); -} -int MaxFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - ComparisonResult cmp; - const MathStructure *max = NULL; - vector unsolveds; - bool b = false; - for(size_t index = 0; index < vargs[0].size(); index++) { - if(max == NULL) { - max = &vargs[0][index]; - } else { - cmp = max->compare(vargs[0][index]); - if(cmp == COMPARISON_RESULT_GREATER) { - max = &vargs[0][index]; - b = true; - } else if(COMPARISON_NOT_FULLY_KNOWN(cmp)) { - if(CALCULATOR->showArgumentErrors()) { - CALCULATOR->error(true, _("Unsolvable comparison in %s()."), name().c_str(), NULL); - } - unsolveds.push_back(&vargs[0][index]); - } else { - b = true; - } - } - } - if(max) { - if(unsolveds.size() > 0) { - if(!b) return 0; - MathStructure margs; margs.clearVector(); - margs.addChild(*max); - for(size_t i = 0; i < unsolveds.size(); i++) { - margs.addChild(*unsolveds[i]); - } - mstruct.set(this, &margs, NULL); - return 1; - } else { - mstruct = *max; - return 1; - } - } - return 0; -} -ModeFunction::ModeFunction() : MathFunction("mode", 1) { - setArgumentDefinition(1, new VectorArgument("")); -} -int ModeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - if(vargs[0].size() <= 0) { - return 0; - } - size_t n = 0; - bool b; - vector vargs_nodup; - vector is; - const MathStructure *value = NULL; - for(size_t index_c = 0; index_c < vargs[0].size(); index_c++) { - b = true; - for(size_t index = 0; index < vargs_nodup.size(); index++) { - if(vargs_nodup[index]->equals(vargs[0][index_c])) { - is[index]++; - b = false; - break; - } - } - if(b) { - vargs_nodup.push_back(&vargs[0][index_c]); - is.push_back(1); - } - } - for(size_t index = 0; index < is.size(); index++) { - if(is[index] > n) { - n = is[index]; - value = vargs_nodup[index]; - } - } - if(value) { - mstruct = *value; - return 1; - } - return 0; -} - -RandFunction::RandFunction() : MathFunction("rand", 0, 2) { - setArgumentDefinition(1, new IntegerArgument()); - setDefaultValue(1, "0"); - setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); - setDefaultValue(2, "1"); -} -int RandFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - size_t n = (size_t) vargs[1].number().uintValue(); - if(n > 1) {mstruct.clearVector(); mstruct.resizeVector(n, m_zero);} - Number nr; - for(size_t i = 0; i < n; i++) { - if(vargs[0].number().isZero() || vargs[0].number().isNegative()) { - nr.rand(); - } else { - nr.intRand(vargs[0].number()); - nr++; - } - if(n > 1) mstruct[i] = nr; - else mstruct = nr; - } - return 1; -} -bool RandFunction::representsReal(const MathStructure&, bool) const {return true;} -bool RandFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() > 0 && vargs[0].isNumber() && vargs[0].number().isPositive();} -bool RandFunction::representsNonNegative(const MathStructure&, bool) const {return true;} - -RandnFunction::RandnFunction() : MathFunction("randnorm", 0, 3) { - setDefaultValue(1, "0"); - setDefaultValue(2, "1"); - setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); - setDefaultValue(3, "1"); -} -int RandnFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - size_t n = (size_t) vargs[2].number().uintValue(); - if(n > 1) {mstruct.clearVector(); mstruct.resizeVector(n, m_zero);} -#if MPFR_VERSION_MAJOR < 4 - Number nr_u, nr_v, nr_r2; - for(size_t i = 0; i < n; i++) { - do { - nr_u.rand(); nr_u *= 2; nr_u -= 1; - nr_v.rand(); nr_v *= 2; nr_v -= 1; - nr_r2 = (nr_u ^ 2) + (nr_v ^ 2); - } while(nr_r2 > 1 || nr_r2.isZero()); - Number nr_rsq(nr_r2); - nr_rsq.ln(); - nr_rsq /= nr_r2; - nr_rsq *= -2; - nr_rsq.sqrt(); - nr_u *= nr_rsq; - if(n > 1) { - mstruct[i] = nr_u; - i++; - if(i < n) { - nr_v *= nr_rsq; - mstruct[i] = nr_v; - } - } else { - mstruct = nr_u; - } - } -#else - Number nr; - for(size_t i = 0; i < n; i++) { - nr.randn(); - if(n > 1) mstruct[i] = nr; - else mstruct = nr; - } -#endif - if(!vargs[1].isOne()) mstruct *= vargs[1]; - if(!vargs[0].isZero()) mstruct += vargs[0]; - return 1; -} -bool RandnFunction::representsReal(const MathStructure&, bool) const {return true;} -bool RandnFunction::representsNonComplex(const MathStructure&, bool) const {return true;} -bool RandnFunction::representsNumber(const MathStructure&, bool) const {return true;} - -RandPoissonFunction::RandPoissonFunction() : MathFunction("randpoisson", 1, 2) { - setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONNEGATIVE)); - setDefaultValue(1, "0"); - setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); - setDefaultValue(2, "1"); -} -int RandPoissonFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - size_t n = (size_t) vargs[2].number().uintValue(); - if(n > 1) {mstruct.clearVector(); mstruct.resizeVector(n, m_zero);} - Number nr_L(vargs[1].number()); - nr_L.exp(); - Number nr_k, nr_p, nr_u; - for(size_t i = 0; i < n; i++) { - nr_k.clear(); nr_p = 1; - do { - nr_k++; - nr_u.rand(); - nr_p *= nr_u; - } while(nr_p > nr_L); - nr_k--; - if(n > 1) mstruct[i] = nr_k; - else mstruct = nr_k; - } - return 1; -} -bool RandPoissonFunction::representsReal(const MathStructure&, bool) const {return true;} -bool RandPoissonFunction::representsInteger(const MathStructure &vargs, bool) const {return true;} -bool RandPoissonFunction::representsNonNegative(const MathStructure&, bool) const {return true;} - -int calender_to_id(const string &str) { - if(str == "1" || equalsIgnoreCase(str, "gregorian") || equalsIgnoreCase(str, _("gregorian"))) return CALENDAR_GREGORIAN; - if(str == "8" || equalsIgnoreCase(str, "milankovic") || equalsIgnoreCase(str, "milanković") || equalsIgnoreCase(str, _("milankovic"))) return CALENDAR_MILANKOVIC; - if(str == "7" || equalsIgnoreCase(str, "julian") || equalsIgnoreCase(str, _("julian"))) return CALENDAR_JULIAN; - if(str == "3" || equalsIgnoreCase(str, "islamic") || equalsIgnoreCase(str, _("islamic"))) return CALENDAR_ISLAMIC; - if(str == "2" || equalsIgnoreCase(str, "hebrew") || equalsIgnoreCase(str, _("hebrew"))) return CALENDAR_HEBREW; - if(str == "11" || equalsIgnoreCase(str, "egyptian") || equalsIgnoreCase(str, _("egyptian"))) return CALENDAR_EGYPTIAN; - if(str == "4" || equalsIgnoreCase(str, "persian") || equalsIgnoreCase(str, _("persian"))) return CALENDAR_PERSIAN; - if(str == "9" || equalsIgnoreCase(str, "coptic") || equalsIgnoreCase(str, _("coptic"))) return CALENDAR_COPTIC; - if(str == "10" || equalsIgnoreCase(str, "ethiopian") || equalsIgnoreCase(str, _("ethiopian"))) return CALENDAR_ETHIOPIAN; - if(str == "5" || equalsIgnoreCase(str, "indian") || equalsIgnoreCase(str, _("indian"))) return CALENDAR_INDIAN; - if(str == "6" || equalsIgnoreCase(str, "chinese") || equalsIgnoreCase(str, _("chinese"))) return CALENDAR_CHINESE; - return -1; -} - -DateFunction::DateFunction() : MathFunction("date", 1, 4) { - setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG)); - IntegerArgument *iarg = new IntegerArgument(); - iarg->setHandleVector(false); - Number fr(1, 1, 0); - iarg->setMin(&fr); - fr.set(24, 1, 0); - iarg->setMax(&fr); - setArgumentDefinition(2, iarg); - setDefaultValue(2, "1"); - iarg = new IntegerArgument(); - iarg->setHandleVector(false); - fr.set(1, 1, 0); - iarg->setMin(&fr); - fr.set(31, 1, 0); - iarg->setMax(&fr); - setDefaultValue(3, "1"); - setArgumentDefinition(3, iarg); - TextArgument *targ = new TextArgument(); - setArgumentDefinition(4, targ); - setDefaultValue(4, _("gregorian")); -} -int DateFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - int ct = calender_to_id(vargs[3].symbol()); - if(ct < 0) { - CALCULATOR->error(true, "Unrecognized calendar.", NULL); - return 0; - } - QalculateDateTime dt; - if(!calendarToDate(dt, vargs[0].number().lintValue(), vargs[1].number().lintValue(), vargs[2].number().lintValue(), (CalendarSystem) ct)) return 0; - mstruct.set(dt); - return 1; -} -DateTimeFunction::DateTimeFunction() : MathFunction("datetime", 1, 6) { - setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG)); - IntegerArgument *iarg = new IntegerArgument(); - iarg->setHandleVector(false); - Number fr(1, 1, 0); - iarg->setMin(&fr); - fr.set(12, 1, 0); - iarg->setMax(&fr); - setArgumentDefinition(2, iarg); - setDefaultValue(2, "1"); - iarg = new IntegerArgument(); - iarg->setHandleVector(false); - fr.set(1, 1, 0); - iarg->setMin(&fr); - fr.set(31, 1, 0); - iarg->setMax(&fr); - setDefaultValue(3, "1"); - setArgumentDefinition(3, iarg); - iarg = new IntegerArgument(); - iarg->setHandleVector(false); - iarg->setMin(&nr_zero); - fr.set(23, 1, 0); - iarg->setMax(&fr); - setArgumentDefinition(4, iarg); - setDefaultValue(4, "0"); - iarg = new IntegerArgument(); - iarg->setHandleVector(false); - iarg->setMin(&nr_zero); - fr.set(59, 1, 0); - iarg->setMax(&fr); - setArgumentDefinition(5, iarg); - setDefaultValue(5, "0"); - NumberArgument *narg = new NumberArgument(); - narg->setHandleVector(false); - narg->setMin(&nr_zero); - fr.set(61, 1, 0); - narg->setMax(&fr); - narg->setIncludeEqualsMax(false); - setArgumentDefinition(6, narg); - setDefaultValue(6, "0"); -} -int DateTimeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - QalculateDateTime dt; - if(!dt.set(vargs[0].number().lintValue(), vargs[1].number().lintValue(), vargs[2].number().lintValue())) return 0; - if(!vargs[3].isZero() || !vargs[4].isZero() || !vargs[5].isZero()) { - if(!dt.setTime(vargs[3].number().lintValue(), vargs[4].number().lintValue(), vargs[5].number())) return 0; - } - mstruct.set(dt); - return 1; -} -TimeValueFunction::TimeValueFunction() : MathFunction("timevalue", 0, 1) { - setArgumentDefinition(1, new DateArgument()); - setDefaultValue(1, "now"); -} -int TimeValueFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - Number nr(vargs[0].datetime()->second()); - nr /= 60; - nr += vargs[0].datetime()->minute(); - nr /= 60; - nr += vargs[0].datetime()->hour(); - mstruct.set(nr); - return 1; -} -TimestampFunction::TimestampFunction() : MathFunction("timestamp", 0, 1) { - setArgumentDefinition(1, new DateArgument()); - setDefaultValue(1, "now"); -} -int TimestampFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - QalculateDateTime date(*vargs[0].datetime()); - Number nr(date.timestamp()); - if(nr.isInfinite()) return 0; - mstruct.set(nr); - return 1; -} -TimestampToDateFunction::TimestampToDateFunction() : MathFunction("stamptodate", 1) { - //setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG)); -} -int TimestampToDateFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - mstruct = vargs[0]; - mstruct.eval(eo); - if((mstruct.isUnit() && mstruct.unit()->baseUnit() == CALCULATOR->u_second) || (mstruct.isMultiplication() && mstruct.size() >= 2 && mstruct.last().isUnit() && mstruct.last().unit()->baseUnit() == CALCULATOR->u_second)) { - Unit *u = NULL; - if(mstruct.isUnit()) { - u = mstruct.unit(); - mstruct.set(1, 1, 0, true); - } else { - u = mstruct.last().unit(); - mstruct.delChild(mstruct.size(), true); - } - if(u != CALCULATOR->u_second) { - u->convertToBaseUnit(mstruct); - mstruct.eval(eo); - } - } - if(!mstruct.isNumber() || !mstruct.number().isReal() || mstruct.number().isInterval()) return -1; - QalculateDateTime date; - if(!date.set(mstruct.number())) return -1; - mstruct.set(date, true); - return 1; -} - -AddDaysFunction::AddDaysFunction() : MathFunction("addDays", 2) { - setArgumentDefinition(1, new DateArgument()); - setArgumentDefinition(2, new NumberArgument()); -} -int AddDaysFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = vargs[0]; - if(!mstruct.datetime()->addDays(vargs[1].number())) return 0; - return 1; -} -AddMonthsFunction::AddMonthsFunction() : MathFunction("addMonths", 2) { - setArgumentDefinition(1, new DateArgument()); - setArgumentDefinition(2, new NumberArgument()); -} -int AddMonthsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = vargs[0]; - if(!mstruct.datetime()->addMonths(vargs[1].number())) return 0; - return 1; -} -AddYearsFunction::AddYearsFunction() : MathFunction("addYears", 2) { - setArgumentDefinition(1, new DateArgument()); - setArgumentDefinition(2, new NumberArgument()); -} -int AddYearsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = vargs[0]; - if(!mstruct.datetime()->addYears(vargs[1].number())) return 0; - return 1; -} - -DaysFunction::DaysFunction() : MathFunction("days", 2, 4) { - setArgumentDefinition(1, new DateArgument()); - setArgumentDefinition(2, new DateArgument()); - IntegerArgument *arg = new IntegerArgument(); - Number integ; - arg->setMin(&integ); - integ.set(4, 1, 0); - arg->setMax(&integ); - setArgumentDefinition(3, arg); - setArgumentDefinition(4, new BooleanArgument()); - setDefaultValue(3, "1"); -} -int DaysFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - QalculateDateTime date1(*vargs[0].datetime()), date2(*vargs[1].datetime()); - Number days(date1.daysTo(date2, vargs[2].number().intValue(), vargs[3].number().isZero())); - if(days.isInfinite()) return 0; - days.abs(); - mstruct.set(days); - return 1; -} -YearFracFunction::YearFracFunction() : MathFunction("yearfrac", 2, 4) { - setArgumentDefinition(1, new DateArgument()); - setArgumentDefinition(2, new DateArgument()); - IntegerArgument *arg = new IntegerArgument(); - Number integ; - arg->setMin(&integ); - integ.set(4, 1, 0); - arg->setMax(&integ); - setArgumentDefinition(3, arg); - setArgumentDefinition(4, new BooleanArgument()); - setDefaultValue(3, "1"); -} -int YearFracFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - QalculateDateTime date1(*vargs[0].datetime()), date2(*vargs[1].datetime()); - Number years(date1.yearsTo(date2, vargs[2].number().intValue(), vargs[3].number().isZero())); - if(years.isInfinite()) return 0; - years.abs(); - mstruct.set(years); - return 1; -} -WeekFunction::WeekFunction() : MathFunction("week", 0, 2) { - setArgumentDefinition(1, new DateArgument()); - setArgumentDefinition(2, new BooleanArgument()); - setDefaultValue(1, "today"); -} -int WeekFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - QalculateDateTime date(*vargs[0].datetime()); - int w = date.week(vargs[1].number().getBoolean()); - if(w < 0) return 0; - mstruct.set(w, 1, 0); - return 1; -} -WeekdayFunction::WeekdayFunction() : MathFunction("weekday", 0, 2) { - setArgumentDefinition(1, new DateArgument()); - setArgumentDefinition(2, new BooleanArgument()); - setDefaultValue(1, "today"); -} -int WeekdayFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - QalculateDateTime date(*vargs[0].datetime()); - int w = date.weekday(); - if(w < 0) return 0; - if(vargs[1].number().getBoolean()) { - if(w == 7) w = 1; - else w++; - } - mstruct.set(w, 1, 0); - return 1; -} -YeardayFunction::YeardayFunction() : MathFunction("yearday", 0, 1) { - setArgumentDefinition(1, new DateArgument()); - setDefaultValue(1, "today"); -} -int YeardayFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - QalculateDateTime date(*vargs[0].datetime()); - int yd = date.yearday(); - if(yd < 0) return 0; - mstruct.set(yd, 1, 0); - return 1; -} -MonthFunction::MonthFunction() : MathFunction("month", 0, 1) { - setArgumentDefinition(1, new DateArgument()); - setDefaultValue(1, "today"); -} -int MonthFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - QalculateDateTime date(*vargs[0].datetime()); - mstruct.set(date.month(), 1L, 0L); - return 1; -} -DayFunction::DayFunction() : MathFunction("day", 0, 1) { - setArgumentDefinition(1, new DateArgument()); - setDefaultValue(1, "today"); -} -int DayFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - QalculateDateTime date(*vargs[0].datetime()); - mstruct.set(date.day(), 1L, 0L); - return 1; -} -YearFunction::YearFunction() : MathFunction("year", 0, 1) { - setArgumentDefinition(1, new DateArgument()); - setDefaultValue(1, "today"); -} -int YearFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - QalculateDateTime date(*vargs[0].datetime()); - mstruct.set(date.year(), 1L, 0L); - return 1; -} -TimeFunction::TimeFunction() : MathFunction("time", 0) { -} -int TimeFunction::calculate(MathStructure &mstruct, const MathStructure&, const EvaluationOptions&) { - int hour, min, sec; - now(hour, min, sec); - Number tnr(sec, 1, 0); - tnr /= 60; - tnr += min; - tnr /= 60; - tnr += hour; - mstruct = tnr; - return 1; -} -LunarPhaseFunction::LunarPhaseFunction() : MathFunction("lunarphase", 0, 1) { - setArgumentDefinition(1, new DateArgument()); - setDefaultValue(1, "now"); -} -int LunarPhaseFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = lunarPhase(*vargs[0].datetime()); - if(CALCULATOR->aborted()) return 0; - return 1; -} -NextLunarPhaseFunction::NextLunarPhaseFunction() : MathFunction("nextlunarphase", 1, 2) { - NumberArgument *arg = new NumberArgument(); - Number fr; - arg->setMin(&fr); - fr.set(1, 1, 0); - arg->setMax(&fr); - arg->setIncludeEqualsMin(true); - arg->setIncludeEqualsMax(false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); - setArgumentDefinition(2, new DateArgument()); - setDefaultValue(2, "now"); -} -int NextLunarPhaseFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = findNextLunarPhase(*vargs[1].datetime(), vargs[0].number()); - if(CALCULATOR->aborted()) return 0; - return 1; -} - -BinFunction::BinFunction() : MathFunction("bin", 1, 2) { - setArgumentDefinition(1, new TextArgument()); - setArgumentDefinition(2, new BooleanArgument()); - setDefaultValue(2, "0"); -} -int BinFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - ParseOptions po = eo.parse_options; - po.base = BASE_BINARY; - po.twos_complement = vargs[1].number().getBoolean(); - CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); - return 1; -} -OctFunction::OctFunction() : MathFunction("oct", 1) { - setArgumentDefinition(1, new TextArgument()); -} -int OctFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - ParseOptions po = eo.parse_options; - po.base = BASE_OCTAL; - CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); - return 1; -} -DecFunction::DecFunction() : MathFunction("dec", 1) { - setArgumentDefinition(1, new TextArgument()); -} -int DecFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - ParseOptions po = eo.parse_options; - po.base = BASE_DECIMAL; - CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); - return 1; -} -HexFunction::HexFunction() : MathFunction("hex", 1, 2) { - setArgumentDefinition(1, new TextArgument()); - setArgumentDefinition(2, new BooleanArgument()); - setDefaultValue(2, "0"); -} -int HexFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - ParseOptions po = eo.parse_options; - po.base = BASE_HEXADECIMAL; - po.hexadecimal_twos_complement = vargs[1].number().getBoolean(); - CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); - return 1; -} - -BaseFunction::BaseFunction() : MathFunction("base", 2, 3) { - setArgumentDefinition(1, new TextArgument()); - Argument *arg = new Argument(); - arg->setHandleVector(true); - setArgumentDefinition(2, arg); - IntegerArgument *arg2 = new IntegerArgument(); - arg2->setMin(&nr_zero); - arg2->setMax(&nr_three); - setArgumentDefinition(3, arg2); - setArgumentDefinition(3, new TextArgument()); - setDefaultValue(3, "0"); -} -int BaseFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[1].isVector()) return 0; - Number nbase; - int idigits = 0; - string sdigits; - if(vargs.size() > 2) sdigits = vargs[2].symbol(); - if(sdigits.empty() || sdigits == "0" || sdigits == "auto") idigits = 0; - else if(sdigits == "1") idigits = 1; - else if(sdigits == "2") idigits = 2; - else if(sdigits == "3" || sdigits == "Unicode" || sdigits == "unicode" || sdigits == "escaped") idigits = 3; - else idigits = -1; - if(vargs[1].isNumber() && idigits == 0) { - nbase = vargs[1].number(); - } else { - mstruct = vargs[1]; - mstruct.eval(eo); - if(mstruct.isVector()) return -2; - if(idigits == 0 && !mstruct.isNumber() && eo.approximation == APPROXIMATION_EXACT) { - MathStructure mstruct2(mstruct); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_TRY_EXACT; - CALCULATOR->beginTemporaryStopMessages(); - mstruct2.eval(eo2); - if(mstruct2.isVector() || mstruct2.isNumber()) { - mstruct = mstruct2; - CALCULATOR->endTemporaryStopMessages(true); - if(mstruct.isVector()) return -2; - } else { - CALCULATOR->endTemporaryStopMessages(); - } - } - if(mstruct.isNumber() && idigits == 0) { - nbase = mstruct.number(); - } else { - string number = vargs[0].symbol(); - size_t i_dot = number.length(); - vector digits; - bool b_minus = false; - if(idigits < 0) { - unordered_map vdigits; - string schar; - long int v = 0; - for(size_t i = 0; i < sdigits.length(); v++) { - size_t l = 1; - while(i + l < sdigits.length() && sdigits[i + l] <= 0 && (unsigned char) sdigits[i + l] < 0xC0) l++; - vdigits[sdigits.substr(i, l)] = v; - i += l; - } - remove_blanks(number); - i_dot = number.length(); - for(size_t i = 0; i < number.length();) { - size_t l = 1; - while(i + l < number.length() && number[i + l] <= 0 && (unsigned char) number[i + l] < 0xC0) l++; - unordered_map::iterator it = vdigits.find(number.substr(i, l)); - if(it == vdigits.end()) { - if(l == 1 && (number[i] == CALCULATOR->getDecimalPoint()[0] || (!eo.parse_options.dot_as_separator && number[i] == '.'))) { - if(i_dot == number.length()) i_dot = digits.size(); - } else { - CALCULATOR->error(true, _("Character \'%s\' was ignored in the number \"%s\" with base %s."), number.substr(i, l).c_str(), number.c_str(), format_and_print(mstruct).c_str(), NULL); - } - } else { - digits.push_back(it->second); - } - i += l; - } - } else if(idigits <= 2) { - remove_blanks(number); - bool b_case = (idigits == 2); - i_dot = number.length(); - for(size_t i = 0; i < number.length(); i++) { - long int c = -1; - if(number[i] >= '0' && number[i] <= '9') { - c = number[i] - '0'; - } else if(number[i] >= 'a' && number[i] <= 'z') { - if(b_case) c = number[i] - 'a' + 36; - else c = number[i] - 'a' + 10; - } else if(number[i] >= 'A' && number[i] <= 'Z') { - c = number[i] - 'A' + 10; - } else if(number[i] == CALCULATOR->getDecimalPoint()[0] || (!eo.parse_options.dot_as_separator && number[i] == '.')) { - if(i_dot == number.length()) i_dot = digits.size(); - } else if(number[i] == '-' && digits.empty()) { - b_minus = !b_minus; - } else { - string str_char = number.substr(i, 1); - while(i + 1 < number.length() && number[i + 1] < 0 && number[i + 1] && (unsigned char) number[i + 1] < 0xC0) { - i++; - str_char += number[i]; - } - CALCULATOR->error(true, _("Character \'%s\' was ignored in the number \"%s\" with base %s."), str_char.c_str(), number.c_str(), format_and_print(mstruct).c_str(), NULL); - } - if(c >= 0) { - digits.push_back(c); - } - } - } else { - for(size_t i = 0; i < number.length(); i++) { - long int c = (unsigned char) number[i]; - bool b_esc = false; - if(number[i] == '\\' && i < number.length() - 1) { - i++; - Number nrd; - if(is_in(NUMBERS, number[i])) { - size_t i2 = number.find_first_not_of(NUMBERS, i); - if(i2 == string::npos) i2 = number.length(); - nrd.set(number.substr(i, i2 - i)); - i = i2 - 1; - b_esc = true; - } else if(number[i] == 'x' && i < number.length() - 1 && is_in(NUMBERS "ABCDEFabcdef", number[i + 1])) { - i++; - size_t i2 = number.find_first_not_of(NUMBERS "ABCDEFabcdef", i); - if(i2 == string::npos) i2 = number.length(); - ParseOptions po; - po.base = BASE_HEXADECIMAL; - nrd.set(number.substr(i, i2 - i), po); - i = i2 - 1; - b_esc = true; - } - if(digits.empty() && number[i] == (char) -30 && i + 3 < number.length() && number[i + 1] == (char) -120 && number[i + 2] == (char) -110) { - i += 2; - b_minus = !b_minus; - b_esc = true; - } else if(digits.empty() && number[i] == '-') { - b_minus = !b_minus; - b_esc = true; - } else if(i_dot == number.size() && (number[i] == CALCULATOR->getDecimalPoint()[0] || (!eo.parse_options.dot_as_separator && number[i] == '.'))) { - i_dot = digits.size(); - b_esc = true; - } else if(b_esc) { - digits.push_back(nrd); - - } else if(number[i] != '\\') { - i--; - } - } - if(!b_esc) { - if((c & 0x80) != 0) { - if(c<0xe0) { - i++; - if(i >= number.length()) return -2; - c = ((c & 0x1f) << 6) | (((unsigned char) number[i]) & 0x3f); - } else if(c<0xf0) { - i++; - if(i + 1 >= number.length()) return -2; - c = (((c & 0xf) << 12) | ((((unsigned char) number[i]) & 0x3f) << 6)|(((unsigned char) number[i + 1]) & 0x3f)); - i++; - } else { - i++; - if(i + 2 >= number.length()) return -2; - c = ((c & 7) << 18) | ((((unsigned char) number[i]) & 0x3f) << 12) | ((((unsigned char) number[i + 1]) & 0x3f) << 6) | (((unsigned char) number[i + 2]) & 0x3f); - i += 2; - } - } - digits.push_back(c); - } - } - } - MathStructure mbase = mstruct; - mstruct.clear(); - if(i_dot > digits.size()) i_dot = digits.size(); - for(size_t i = 0; i < digits.size(); i++) { - long int exp = i_dot - 1 - i; - MathStructure m; - if(exp != 0) { - m = mbase; - m.raise(Number(exp, 1)); - m.multiply(digits[i]); - } else { - m.set(digits[i]); - } - if(mstruct.isZero()) mstruct = m; - else mstruct.add(m, true); - } - if(b_minus) mstruct.negate(); - return 1; - } - } - ParseOptions po = eo.parse_options; - if(nbase.isInteger() && nbase >= 2 && nbase <= 36) { - po.base = nbase.intValue(); - CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); - } else { - po.base = BASE_CUSTOM; - Number cb_save = CALCULATOR->customInputBase(); - CALCULATOR->setCustomInputBase(nbase); - CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); - CALCULATOR->setCustomInputBase(cb_save); - } - return 1; -} -RomanFunction::RomanFunction() : MathFunction("roman", 1) { - setArgumentDefinition(1, new TextArgument()); -} -int RomanFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].symbol().find_first_not_of("0123456789.:" SIGNS) == string::npos && vargs[0].symbol().find_first_not_of("0" SIGNS) != string::npos) { - CALCULATOR->parse(&mstruct, vargs[0].symbol(), eo.parse_options); - PrintOptions po; po.base = BASE_ROMAN_NUMERALS; - mstruct.eval(eo); - mstruct.set(mstruct.print(po), true, true); - return 1; - } - ParseOptions po = eo.parse_options; - po.base = BASE_ROMAN_NUMERALS; - CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); - return 1; -} -BijectiveFunction::BijectiveFunction() : MathFunction("bijective", 1) { - setArgumentDefinition(1, new TextArgument()); -} -int BijectiveFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].symbol().find_first_not_of("0123456789.:" SIGNS) == string::npos && vargs[0].symbol().find_first_not_of(SIGNS) != string::npos) { - CALCULATOR->parse(&mstruct, vargs[0].symbol(), eo.parse_options); - PrintOptions po; po.base = BASE_BIJECTIVE_26; - mstruct.eval(eo); - mstruct.set(mstruct.print(po), true, true); - return 1; - } - ParseOptions po = eo.parse_options; - po.base = BASE_BIJECTIVE_26; - CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); - return 1; -} - -AsciiFunction::AsciiFunction() : MathFunction("code", 1) { - setArgumentDefinition(1, new TextArgument()); -} -int AsciiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - if(vargs[0].symbol().empty()) { - return false; - } - const string &str = vargs[0].symbol(); - mstruct.clear(); - for(size_t i = 0; i < str.length(); i++) { - long int c = (unsigned char) str[i]; - if((c & 0x80) != 0) { - if(c<0xe0) { - i++; - if(i >= str.length()) return false; - c = ((c & 0x1f) << 6) | (((unsigned char) str[i]) & 0x3f); - } else if(c<0xf0) { - i++; - if(i + 1 >= str.length()) return false; - c = (((c & 0xf) << 12) | ((((unsigned char) str[i]) & 0x3f) << 6)|(((unsigned char) str[i + 1]) & 0x3f)); - i++; - } else { - i++; - if(i + 2 >= str.length()) return false; - c = ((c & 7) << 18) | ((((unsigned char) str[i]) & 0x3f) << 12) | ((((unsigned char) str[i + 1]) & 0x3f) << 6) | (((unsigned char) str[i + 2]) & 0x3f); - i += 2; - } - } - if(mstruct.isZero()) { - mstruct.set(c, 1L, 0L); - } else if(mstruct.isVector()) { - mstruct.addChild(MathStructure(c, 1L, 0L)); - } else { - mstruct.transform(STRUCT_VECTOR, MathStructure(c, 1L, 0L)); - } - } - return 1; -} -CharFunction::CharFunction() : MathFunction("char", 1) { - IntegerArgument *arg = new IntegerArgument(); - Number fr(32, 1, 0); - arg->setMin(&fr); - fr.set(0x10ffff, 1, 0); - arg->setMax(&fr); - setArgumentDefinition(1, arg); -} -int CharFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - - long int v = vargs[0].number().lintValue(); - string str; - if(v <= 0x7f) { - str = (char) v; - } else if(v <= 0x7ff) { - str = (char) ((v >> 6) | 0xc0); - str += (char) ((v & 0x3f) | 0x80); - } else if((v <= 0xd7ff || (0xe000 <= v && v <= 0xffff))) { - str = (char) ((v >> 12) | 0xe0); - str += (char) (((v >> 6) & 0x3f) | 0x80); - str += (char) ((v & 0x3f) | 0x80); - } else if(0xffff < v && v <= 0x10ffff) { - str = (char) ((v >> 18) | 0xf0); - str += (char) (((v >> 12) & 0x3f) | 0x80); - str += (char) (((v >> 6) & 0x3f) | 0x80); - str += (char) ((v & 0x3f) | 0x80); - } else { - return 0; - } - mstruct = str; - return 1; - -} - -ConcatenateFunction::ConcatenateFunction() : MathFunction("concatenate", 1, -1) { - setArgumentDefinition(1, new TextArgument()); - setArgumentDefinition(2, new TextArgument()); -} -int ConcatenateFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - string str; - for(size_t i = 0; i < vargs.size(); i++) { - str += vargs[i].symbol(); - } - mstruct = str; - return 1; -} -LengthFunction::LengthFunction() : MathFunction("len", 1) { - setArgumentDefinition(1, new TextArgument()); -} -int LengthFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - mstruct = (int) vargs[0].symbol().length(); - return 1; -} - -bool replace_function(MathStructure &m, MathFunction *f1, MathFunction *f2, const EvaluationOptions &eo) { - bool ret = false; - if(m.isFunction() && m.function() == f1) { - m.setFunction(f2); - while(f2->maxargs() >= 0 && m.size() > (size_t) f2->maxargs()) { - m.delChild(m.countChildren()); - } - if(m.size() >= 1) { - if((f1->getArgumentDefinition(1) && f1->getArgumentDefinition(1)->type() == ARGUMENT_TYPE_ANGLE) && (!f2->getArgumentDefinition(1) || f2->getArgumentDefinition(1)->type() != ARGUMENT_TYPE_ANGLE)) { - if(m[0].contains(CALCULATOR->getRadUnit(), false, true, true) > 0) m[0] /= CALCULATOR->getRadUnit(); - else if(m[0].contains(CALCULATOR->getDegUnit(), false, true, true) > 0) m[0] /= CALCULATOR->getDegUnit(); - else if(m[0].contains(CALCULATOR->getGraUnit(), false, true, true) > 0) m[0] /= CALCULATOR->getGraUnit(); - } else if((f2->getArgumentDefinition(1) && f2->getArgumentDefinition(1)->type() == ARGUMENT_TYPE_ANGLE) && (!f1->getArgumentDefinition(1) || f1->getArgumentDefinition(1)->type() != ARGUMENT_TYPE_ANGLE)) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {m[0] *= CALCULATOR->getDegUnit(); break;} - case ANGLE_UNIT_GRADIANS: {m[0] *= CALCULATOR->getGraUnit(); break;} - case ANGLE_UNIT_RADIANS: {m[0] *= CALCULATOR->getRadUnit(); break;} - default: {} - } - } - } - ret = true; - } - for(size_t i = 0; i < m.size(); i++) { - if(replace_function(m[i], f1, f2, eo)) ret = true; - } - return ret; -} -ReplaceFunction::ReplaceFunction() : MathFunction("replace", 3, 4) { - setArgumentDefinition(4, new BooleanArgument()); - setDefaultValue(4, "0"); -} -int ReplaceFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - mstruct = vargs[0]; - bool b_evaled = false; - if(vargs[3].number().getBoolean()) {mstruct.eval(eo); b_evaled = true;} - if(vargs[1].isVector() && vargs[2].isVector() && vargs[1].size() == vargs[2].size()) { - for(size_t i = 0; i < vargs[1].size(); i++) { - if(vargs[1][i].isFunction() && vargs[2][i].isFunction() && vargs[1][i].size() == 0 && vargs[2][i].size() == 0) { - if(!replace_function(mstruct, vargs[1][i].function(), vargs[2][i].function(), eo)) CALCULATOR->error(false, _("Original value (%s) was not found."), (vargs[1][i].function()->name() + "()").c_str(), NULL); - } else if(vargs[2][i].containsInterval(true) || vargs[2][i].containsFunction(CALCULATOR->f_interval, true)) { - MathStructure mv(vargs[2][i]); - replace_f_interval(mv, eo); - replace_intervals_f(mv); - if(!mstruct.replace(vargs[1][i], mv)) CALCULATOR->error(false, _("Original value (%s) was not found."), format_and_print(vargs[1][i]).c_str(), NULL); - } else { - if(!mstruct.replace(vargs[1][i], vargs[2][i])) CALCULATOR->error(false, _("Original value (%s) was not found."), format_and_print(vargs[1][i]).c_str(), NULL); - } - } - } else { - while(true) { - if(vargs[1].isFunction() && vargs[2].isFunction() && vargs[1].size() == 0 && vargs[2].size() == 0) { - if(replace_function(mstruct, vargs[1].function(), vargs[2].function(), eo)) break; - } else if(vargs[2].containsInterval(true) || vargs[2].containsFunction(CALCULATOR->f_interval, true)) { - MathStructure mv(vargs[2]); - replace_f_interval(mv, eo); - replace_intervals_f(mv); - if(mstruct.replace(vargs[1], mv)) break; - } else { - if(mstruct.replace(vargs[1], vargs[2])) break; - } - if(b_evaled) { - CALCULATOR->error(false, _("Original value (%s) was not found."), format_and_print(vargs[1]).c_str(), NULL); - break; - } else { - mstruct.eval(); - b_evaled = true; - } - } - } - return 1; -} -void remove_nounit(MathStructure &mstruct) { - if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_stripunits && mstruct.size() == 1) { - mstruct.setToChild(1, true); - } - if(mstruct.isMultiplication() || mstruct.isAddition()) { - for(size_t i = 0; i < mstruct.size(); i++) { - remove_nounit(mstruct[i]); - } - } -} -StripUnitsFunction::StripUnitsFunction() : MathFunction("nounit", 1) {} -int StripUnitsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - mstruct = vargs[0]; - remove_nounit(mstruct); - mstruct.removeType(STRUCT_UNIT); - if(mstruct.containsType(STRUCT_UNIT, false, true, true) == 0) return 1; - if(mstruct.isMultiplication() || mstruct.isAddition()) { - MathStructure *mleft = NULL; - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].containsType(STRUCT_UNIT, false, true, true) == 0) { - mstruct[i].ref(); - if(mleft) { - if(mstruct.isMultiplication()) mleft->multiply_nocopy(&mstruct[i], true); - else mleft->add_nocopy(&mstruct[i], true); - } else { - mleft = &mstruct[i]; - } - mstruct.delChild(i + 1); - } - } - if(mleft) { - if(mstruct.size() == 0) { - mstruct.set_nocopy(*mleft); - mleft->unref(); - } else { - bool b_multi = mstruct.isMultiplication(); - if(mstruct.size() == 1) { - mstruct.setType(STRUCT_FUNCTION); - mstruct.setFunction(this); - } else { - mstruct.transform(this); - } - if(b_multi) mstruct.multiply_nocopy(mleft, true); - else mstruct.add_nocopy(mleft, true); - } - return 1; - } - } - EvaluationOptions eo2 = eo; - eo2.sync_units = false; - eo2.keep_prefixes = true; - mstruct.eval(eo2); - remove_nounit(mstruct); - mstruct.removeType(STRUCT_UNIT); - if(mstruct.containsType(STRUCT_UNIT, false, true, true) == 0) return 1; - if(mstruct.isMultiplication() || mstruct.isAddition()) { - MathStructure *mleft = NULL; - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].containsType(STRUCT_UNIT, false, true, true) == 0) { - mstruct[i].ref(); - if(mleft) { - if(mstruct.isMultiplication()) mleft->multiply_nocopy(&mstruct[i], true); - else mleft->add_nocopy(&mstruct[i], true); - } else { - mleft = &mstruct[i]; - } - mstruct.delChild(i + 1); - } - } - if(mleft) { - if(mstruct.size() == 0) { - mstruct.set_nocopy(*mleft); - mleft->unref(); - } else { - bool b_multi = mstruct.isMultiplication(); - if(mstruct.size() == 1) { - mstruct.setType(STRUCT_FUNCTION); - mstruct.setFunction(this); - } else { - mstruct.transform(this); - } - if(b_multi) mstruct.multiply_nocopy(mleft, true); - else mstruct.add_nocopy(mleft, true); - } - return 1; - } - } - return -1; -} - -ErrorFunction::ErrorFunction() : MathFunction("error", 1) { - setArgumentDefinition(1, new TextArgument()); -} -int ErrorFunction::calculate(MathStructure&, const MathStructure &vargs, const EvaluationOptions&) { - CALCULATOR->error(true, vargs[0].symbol().c_str(), NULL); - return 1; -} -WarningFunction::WarningFunction() : MathFunction("warning", 1) { - setArgumentDefinition(1, new TextArgument()); -} -int WarningFunction::calculate(MathStructure&, const MathStructure &vargs, const EvaluationOptions&) { - CALCULATOR->error(false, vargs[0].symbol().c_str(), NULL); - return 1; -} -MessageFunction::MessageFunction() : MathFunction("message", 1) { - setArgumentDefinition(1, new TextArgument()); -} -int MessageFunction::calculate(MathStructure&, const MathStructure &vargs, const EvaluationOptions&) { - CALCULATOR->message(MESSAGE_INFORMATION, vargs[0].symbol().c_str(), NULL); - return 1; -} - -GenerateVectorFunction::GenerateVectorFunction() : MathFunction("genvector", 4, 6) { - setArgumentDefinition(5, new SymbolicArgument()); - setDefaultValue(5, "undefined"); - setArgumentDefinition(6, new BooleanArgument()); - setDefaultValue(6, "0"); -} -int GenerateVectorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(CALCULATOR->aborted()) return 0; - if(vargs[5].number().getBoolean()) { - mstruct = vargs[0].generateVector(vargs[4], vargs[1], vargs[2], vargs[3], NULL, eo); - } else { - bool overflow = false; - int steps = vargs[3].number().intValue(&overflow); - if(!vargs[3].isNumber() || overflow || steps < 1) { - CALCULATOR->error(true, _("The number of requested elements in generate vector function must be a positive integer."), NULL); - return 0; - } - mstruct = vargs[0].generateVector(vargs[4], vargs[1], vargs[2], steps, NULL, eo); - } - if(CALCULATOR->aborted()) return 0; - return 1; -} -ForFunction::ForFunction() : MathFunction("for", 7) { - setArgumentDefinition(2, new SymbolicArgument()); - setArgumentDefinition(7, new SymbolicArgument()); -} -int ForFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - - mstruct = vargs[4]; - MathStructure mcounter = vargs[0]; - MathStructure mtest; - MathStructure mcount; - MathStructure mupdate; - while(true) { - mtest = vargs[2]; - mtest.replace(vargs[1], mcounter); - mtest.eval(eo); - if(!mtest.isNumber() || CALCULATOR->aborted()) return 0; - if(!mtest.number().getBoolean()) { - break; - } - if(vargs[5].isComparison() && vargs[5].comparisonType() == COMPARISON_EQUALS && vargs[5][0] == vargs[6]) mupdate = vargs[5][1]; - else mupdate = vargs[5]; - mupdate.replace(vargs[1], mcounter, vargs[6], mstruct); - mstruct = mupdate; - mstruct.calculatesub(eo, eo, false); - - if(vargs[3].isComparison() && vargs[3].comparisonType() == COMPARISON_EQUALS && vargs[3][0] == vargs[1]) mcount = vargs[3][1]; - else mcount = vargs[3]; - mcount.replace(vargs[1], mcounter); - mcounter = mcount; - mcounter.calculatesub(eo, eo, false); - } - return 1; - -} -SumFunction::SumFunction() : MathFunction("sum", 3, 4) { - Argument *arg = new IntegerArgument(); - arg->setHandleVector(false); - setArgumentDefinition(2, arg); - arg = new IntegerArgument(); - arg->setHandleVector(false); - setArgumentDefinition(3, arg); - setArgumentDefinition(4, new SymbolicArgument()); - setDefaultValue(4, "undefined"); - setCondition("\\z >= \\y"); -} -int SumFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - - MathStructure m1(vargs[0]); - EvaluationOptions eo2 = eo; - eo2.calculate_functions = false; - eo2.expand = false; - Number i_nr(vargs[1].number()); - if(eo2.approximation == APPROXIMATION_TRY_EXACT) { - Number nr(vargs[2].number()); - nr.subtract(i_nr); - if(nr.isGreaterThan(100)) eo2.approximation = APPROXIMATION_APPROXIMATE; - } - CALCULATOR->beginTemporaryStopMessages(); - m1.eval(eo2); - int im = 0; - if(CALCULATOR->endTemporaryStopMessages(NULL, &im) > 0 || im > 0) m1 = vargs[0]; - eo2.calculate_functions = eo.calculate_functions; - eo2.expand = eo.expand; - mstruct.clear(); - MathStructure mstruct_calc; - bool started = false; - while(i_nr.isLessThanOrEqualTo(vargs[2].number())) { - if(CALCULATOR->aborted()) { - if(!started) { - return 0; - } else if(i_nr != vargs[2].number()) { - MathStructure mmin(i_nr); - mstruct.add(MathStructure(this, &vargs[0], &mmin, &vargs[2], &vargs[3], NULL), true); - return 1; - } - } - mstruct_calc.set(m1); - mstruct_calc.replace(vargs[3], i_nr); - mstruct_calc.eval(eo2); - if(started) { - mstruct.calculateAdd(mstruct_calc, eo2); - } else { - mstruct = mstruct_calc; - mstruct.calculatesub(eo2, eo2); - started = true; - } - i_nr += 1; - } - return 1; - -} -ProductFunction::ProductFunction() : MathFunction("product", 3, 4) { - Argument *arg = new IntegerArgument(); - arg->setHandleVector(false); - setArgumentDefinition(2, arg); - arg = new IntegerArgument(); - arg->setHandleVector(false); - setArgumentDefinition(3, arg); - setArgumentDefinition(4, new SymbolicArgument()); - setDefaultValue(4, "undefined"); - setCondition("\\z >= \\y"); -} -int ProductFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - - MathStructure m1(vargs[0]); - EvaluationOptions eo2 = eo; - eo2.calculate_functions = false; - eo2.expand = false; - Number i_nr(vargs[1].number()); - if(eo2.approximation == APPROXIMATION_TRY_EXACT) { - Number nr(vargs[2].number()); - nr.subtract(i_nr); - if(nr.isGreaterThan(100)) eo2.approximation = APPROXIMATION_APPROXIMATE; - } - CALCULATOR->beginTemporaryStopMessages(); - m1.eval(eo2); - int im = 0; - if(CALCULATOR->endTemporaryStopMessages(NULL, &im) || im > 0) m1 = vargs[0]; - eo2.calculate_functions = eo.calculate_functions; - eo2.expand = eo.expand; - mstruct.clear(); - MathStructure mstruct_calc; - bool started = false; - while(i_nr.isLessThanOrEqualTo(vargs[2].number())) { - if(CALCULATOR->aborted()) { - if(!started) { - return 0; - } else if(i_nr != vargs[2].number()) { - MathStructure mmin(i_nr); - mstruct.multiply(MathStructure(this, &vargs[0], &mmin, &vargs[2], &vargs[3], NULL), true); - return 1; - } - } - mstruct_calc.set(m1); - mstruct_calc.replace(vargs[3], i_nr); - mstruct_calc.eval(eo2); - if(started) { - mstruct.calculateMultiply(mstruct_calc, eo2); - } else { - mstruct = mstruct_calc; - mstruct.calculatesub(eo2, eo2); - started = true; - } - i_nr += 1; - } - return 1; - -} - -bool process_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t index); -bool process_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t index) { - if(mprocess == vargs[1]) { - mprocess = mstruct[index]; - return true; - } - if(!vargs[3].isEmptySymbol() && mprocess == vargs[3]) { - mprocess = (int) index + 1; - return true; - } - if(!vargs[4].isEmptySymbol() && mprocess == vargs[4]) { - mprocess = vargs[2]; - return true; - } - bool b = false; - for(size_t i = 0; i < mprocess.size(); i++) { - if(process_replace(mprocess[i], mstruct, vargs, index)) { - mprocess.childUpdated(i + 1); - b = true; - } - } - return b; -} - -ProcessFunction::ProcessFunction() : MathFunction("process", 3, 5) { - setArgumentDefinition(2, new SymbolicArgument()); - setArgumentDefinition(3, new VectorArgument()); - setArgumentDefinition(4, new SymbolicArgument()); - setDefaultValue(4, "\"\""); - setArgumentDefinition(5, new SymbolicArgument()); - setDefaultValue(5, "\"\""); -} -int ProcessFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - - mstruct = vargs[2]; - MathStructure mprocess; - for(size_t index = 0; index < mstruct.size(); index++) { - mprocess = vargs[0]; - process_replace(mprocess, mstruct, vargs, index); - mstruct[index] = mprocess; - } - return 1; - -} - - -bool process_matrix_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t rindex, size_t cindex); -bool process_matrix_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t rindex, size_t cindex) { - if(mprocess == vargs[1]) { - mprocess = mstruct[rindex][cindex]; - return true; - } - if(!vargs[3].isEmptySymbol() && mprocess == vargs[3]) { - mprocess = (int) rindex + 1; - return true; - } - if(!vargs[4].isEmptySymbol() && mprocess == vargs[4]) { - mprocess = (int) cindex + 1; - return true; - } - if(!vargs[5].isEmptySymbol() && mprocess == vargs[5]) { - mprocess = vargs[2]; - return true; - } - bool b = false; - for(size_t i = 0; i < mprocess.size(); i++) { - if(process_matrix_replace(mprocess[i], mstruct, vargs, rindex, cindex)) { - mprocess.childUpdated(i + 1); - b = true; - } - } - return b; -} - -ProcessMatrixFunction::ProcessMatrixFunction() : MathFunction("processm", 3, 6) { - setArgumentDefinition(2, new SymbolicArgument()); - setArgumentDefinition(3, new MatrixArgument()); - setArgumentDefinition(4, new SymbolicArgument()); - setDefaultValue(4, "\"\""); - setArgumentDefinition(5, new SymbolicArgument()); - setDefaultValue(5, "\"\""); - setArgumentDefinition(6, new SymbolicArgument()); - setDefaultValue(6, "\"\""); -} -int ProcessMatrixFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - - mstruct = vargs[2]; - MathStructure mprocess; - for(size_t rindex = 0; rindex < mstruct.size(); rindex++) { - for(size_t cindex = 0; cindex < mstruct[rindex].size(); cindex++) { - if(CALCULATOR->aborted()) return 0; - mprocess = vargs[0]; - process_matrix_replace(mprocess, mstruct, vargs, rindex, cindex); - mstruct[rindex][cindex] = mprocess; - } - } - return 1; - -} - -bool csum_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t index, const EvaluationOptions &eo2); -bool csum_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t index, const EvaluationOptions &eo2) { - if(mprocess == vargs[4]) { - mprocess = vargs[6][index]; - return true; - } - if(mprocess == vargs[5]) { - mprocess = mstruct; - return true; - } - if(!vargs[7].isEmptySymbol() && mprocess == vargs[7]) { - mprocess = (int) index + 1; - return true; - } - if(!vargs[8].isEmptySymbol()) { - if(mprocess.isFunction() && mprocess.function() == CALCULATOR->f_component && mprocess.size() == 2 && mprocess[1] == vargs[8]) { - bool b = csum_replace(mprocess[0], mstruct, vargs, index, eo2); - mprocess[0].eval(eo2); - if(mprocess[0].isNumber() && mprocess[0].number().isInteger() && mprocess[0].number().isPositive() && mprocess[0].number().isLessThanOrEqualTo(vargs[6].size())) { - mprocess = vargs[6][mprocess[0].number().intValue() - 1]; - return true; - } - return csum_replace(mprocess[1], mstruct, vargs, index, eo2) || b; - } else if(mprocess == vargs[8]) { - mprocess = vargs[6]; - return true; - } - } - bool b = false; - for(size_t i = 0; i < mprocess.size(); i++) { - if(csum_replace(mprocess[i], mstruct, vargs, index, eo2)) { - mprocess.childUpdated(i + 1); - b = true; - } - } - return b; -} -CustomSumFunction::CustomSumFunction() : MathFunction("csum", 7, 9) { - Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SINT); - setArgumentDefinition(1, arg); //begin - arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SINT); - arg->setHandleVector(false); - setArgumentDefinition(2, arg); //end - //3. initial - //4. function - setArgumentDefinition(5, new SymbolicArgument()); //x var - setArgumentDefinition(6, new SymbolicArgument()); //y var - setArgumentDefinition(7, new VectorArgument()); - setArgumentDefinition(8, new SymbolicArgument()); //i var - setDefaultValue(8, "\"\""); - setArgumentDefinition(9, new SymbolicArgument()); //v var - setDefaultValue(9, "\"\""); -} -int CustomSumFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - - int start = vargs[0].number().intValue(); - if(start < 1) start = 1; - int end = vargs[1].number().intValue(); - int n = vargs[6].countChildren(); - if(start > n) { - CALCULATOR->error(true, _("Too few elements (%s) in vector (%s required)"), i2s(n).c_str(), i2s(start).c_str(), NULL); - start = n; - } - if(end < 1 || end > n) { - if(end > n) CALCULATOR->error(true, _("Too few elements (%s) in vector (%s required)"), i2s(n).c_str(), i2s(end).c_str(), NULL); - end = n; - } else if(end < start) { - end = start; - } - - mstruct = vargs[2]; - MathStructure mexpr(vargs[3]); - MathStructure mprocess; - EvaluationOptions eo2 = eo; - eo2.calculate_functions = false; - mstruct.eval(eo2); - for(size_t index = (size_t) start - 1; index < (size_t) end; index++) { - if(CALCULATOR->aborted()) return 0; - mprocess = mexpr; - csum_replace(mprocess, mstruct, vargs, index, eo2); - mprocess.eval(eo2); - mstruct = mprocess; - } - return 1; - -} - -FunctionFunction::FunctionFunction() : MathFunction("function", 2) { - setArgumentDefinition(1, new TextArgument()); - setArgumentDefinition(2, new VectorArgument()); -} -int FunctionFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - UserFunction f = new UserFunction("", "Generated MathFunction", vargs[0].symbol()); - MathStructure args = vargs[1]; - mstruct = f.MathFunction::calculate(args, eo); - if(mstruct.isFunction() && mstruct.function() == &f) mstruct.setUndefined(); - return 1; -} -SelectFunction::SelectFunction() : MathFunction("select", 2, 4) { - setArgumentDefinition(3, new SymbolicArgument()); - setDefaultValue(3, "undefined"); - setArgumentDefinition(4, new BooleanArgument()); - setDefaultValue(4, "0"); -} -int SelectFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - MathStructure mtest; - mstruct = vargs[0]; - mstruct.eval(eo); - if(!mstruct.isVector()) { - mtest = vargs[1]; - mtest.replace(vargs[2], mstruct); - mtest.eval(eo); - if(!mtest.isNumber() || mtest.number().getBoolean() < 0) { - CALCULATOR->error(true, _("Comparison failed."), NULL); - return -1; - } - if(mtest.number().getBoolean() == 0) { - if(vargs[3].number().getBoolean() > 0) { - CALCULATOR->error(true, _("No matching item found."), NULL); - return -1; - } - mstruct.clearVector(); - } - return 1; - } - for(size_t i = 0; i < mstruct.size();) { - mtest = vargs[1]; - mtest.replace(vargs[2], mstruct[i]); - mtest.eval(eo); - if(!mtest.isNumber() || mtest.number().getBoolean() < 0) { - CALCULATOR->error(true, _("Comparison failed."), NULL); - return -1; - } - if(mtest.number().getBoolean() == 0) { - if(vargs[3].number().getBoolean() == 0) { - mstruct.delChild(i + 1); - } else { - i++; - } - } else if(vargs[3].number().getBoolean() > 0) { - MathStructure msave(mstruct[i]); - mstruct = msave; - return 1; - } else { - i++; - } - } - if(vargs[3].number().getBoolean() > 0) { - CALCULATOR->error(true, _("No matching item found."), NULL); - return -1; - } - return 1; -} -IFFunction::IFFunction() : MathFunction("if", 3, 4) { - setArgumentDefinition(4, new BooleanArgument()); - setDefaultValue(4, "0"); -} -int IFFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isNumber()) { - int result = vargs[0].number().getBoolean(); - if(result > 0) { - mstruct = vargs[1]; - } else if(result == 0 || vargs[3].isOne()) { - mstruct = vargs[2]; - } else { - return 0; - } - return 1; - } - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct[i].isNumber() && vargs[3].isZero()) { - return -1; - } - int result = mstruct[i].number().getBoolean(); - if(result > 0) { - if(vargs[1].isVector() && vargs[1].size() == vargs[0].size()) { - mstruct = vargs[1][i]; - } else { - mstruct = vargs[1]; - } - return 1; - } else if(result < 0 && vargs[3].isZero()) { - return -1; - } - } - mstruct = vargs[2]; - return 1; - } - if(mstruct.isNumber()) { - int result = mstruct.number().getBoolean(); - if(result > 0) { - mstruct = vargs[1]; - } else if(result == 0 || vargs[3].isOne()) { - mstruct = vargs[2]; - } else { - return -1; - } - return 1; - } - if(vargs[3].isOne()) { - mstruct = vargs[2]; - return 1; - } - return -1; -} - -IsNumberFunction::IsNumberFunction() : MathFunction("isNumber", 1) { -} -int IsNumberFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - mstruct = vargs[0]; - if(!mstruct.isNumber()) mstruct.eval(eo); - if(mstruct.isNumber()) { - mstruct.number().setTrue(); - } else { - mstruct.clear(); - mstruct.number().setFalse(); - } - return 1; -} -IS_NUMBER_FUNCTION(IsIntegerFunction, isInteger) -IS_NUMBER_FUNCTION(IsRealFunction, isReal) -IS_NUMBER_FUNCTION(IsRationalFunction, isRational) -REPRESENTS_FUNCTION(RepresentsIntegerFunction, representsInteger) -REPRESENTS_FUNCTION(RepresentsRealFunction, representsReal) -REPRESENTS_FUNCTION(RepresentsRationalFunction, representsRational) -REPRESENTS_FUNCTION(RepresentsNumberFunction, representsNumber) - -LoadFunction::LoadFunction() : MathFunction("load", 1, 3) { - setArgumentDefinition(1, new FileArgument()); - Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SINT); - arg->setHandleVector(false); - setArgumentDefinition(2, arg); - setDefaultValue(2, "1"); - setArgumentDefinition(3, new TextArgument()); - setDefaultValue(3, ","); -} -int LoadFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - string delim = vargs[2].symbol(); - if(delim == "tab") { - delim = "\t"; - } - if(!CALCULATOR->importCSV(mstruct, vargs[0].symbol().c_str(), vargs[1].number().intValue(), delim)) { - CALCULATOR->error(true, "Failed to load %s.", vargs[0].symbol().c_str(), NULL); - return 0; - } - return 1; -} -ExportFunction::ExportFunction() : MathFunction("export", 2, 3) { - setArgumentDefinition(1, new VectorArgument()); - setArgumentDefinition(2, new FileArgument()); - setArgumentDefinition(3, new TextArgument()); - setDefaultValue(3, ","); -} -int ExportFunction::calculate(MathStructure&, const MathStructure &vargs, const EvaluationOptions&) { - string delim = vargs[2].symbol(); - if(delim == "tab") { - delim = "\t"; - } - if(!CALCULATOR->exportCSV(vargs[0], vargs[1].symbol().c_str(), delim)) { - CALCULATOR->error(true, "Failed to export to %s.", vargs[1].symbol().c_str(), NULL); - return 0; - } - return 1; -} -TitleFunction::TitleFunction() : MathFunction("title", 1) { - setArgumentDefinition(1, new ExpressionItemArgument()); -} -int TitleFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - ExpressionItem *item = CALCULATOR->getExpressionItem(vargs[0].symbol()); - if(!item) { - CALCULATOR->error(true, _("Object %s does not exist."), vargs[0].symbol().c_str(), NULL); - return 0; - } else { - mstruct = item->title(); - } - return 1; -} -SaveFunction::SaveFunction() : MathFunction("save", 2, 4) { - setArgumentDefinition(2, new TextArgument()); - setArgumentDefinition(3, new TextArgument()); - setArgumentDefinition(4, new TextArgument()); - setDefaultValue(3, CALCULATOR->temporaryCategory()); - setDefaultValue(4, ""); -} -int SaveFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - mstruct = vargs[0]; - mstruct.eval(eo); - if(!CALCULATOR->variableNameIsValid(vargs[1].symbol())) { - CALCULATOR->error(true, _("Invalid variable name (%s)."), vargs[1].symbol().c_str(), NULL); - return -1; - } - if(CALCULATOR->variableNameTaken(vargs[1].symbol())) { - Variable *v = CALCULATOR->getActiveVariable(vargs[1].symbol()); - if(v && v->isLocal() && v->isKnown()) { - if(!vargs[2].symbol().empty()) v->setCategory(vargs[2].symbol()); - if(!vargs[3].symbol().empty()) v->setTitle(vargs[3].symbol()); - ((KnownVariable*) v)->set(mstruct); - if(v->countNames() == 0) { - ExpressionName ename(vargs[1].symbol()); - ename.reference = true; - v->setName(ename, 1); - } else { - v->setName(vargs[1].symbol(), 1); - } - } else { - CALCULATOR->error(false, _("A global unit or variable was deactivated. It will be restored after the new variable has been removed."), NULL); - CALCULATOR->addVariable(new KnownVariable(vargs[2].symbol(), vargs[1].symbol(), mstruct, vargs[3].symbol())); - } - } else { - CALCULATOR->addVariable(new KnownVariable(vargs[2].symbol(), vargs[1].symbol(), mstruct, vargs[3].symbol())); - } - CALCULATOR->saveFunctionCalled(); - return 1; -} - -RegisterFunction::RegisterFunction() : MathFunction("register", 1) { - setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); -} -int RegisterFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { - if(vargs[0].number().isGreaterThan(CALCULATOR->RPNStackSize())) { - CALCULATOR->error(false, _("Register %s does not exist. Returning zero."), format_and_print(vargs[0]).c_str(), NULL); - mstruct.clear(); - return 1; - } - mstruct.set(*CALCULATOR->getRPNRegister((size_t) vargs[0].number().uintValue())); - return 1; -} -StackFunction::StackFunction() : MathFunction("stack", 0) { -} -int StackFunction::calculate(MathStructure &mstruct, const MathStructure&, const EvaluationOptions&) { - mstruct.clearVector(); - for(size_t i = 1; i <= CALCULATOR->RPNStackSize(); i++) { - mstruct.addChild(*CALCULATOR->getRPNRegister(i)); - } - return 1; -} - -bool replace_diff_x(MathStructure &m, const MathStructure &mfrom, const MathStructure &mto) { - if(m.equals(mfrom, true, true)) { - m = mto; - return true; - } - if(m.type() == STRUCT_FUNCTION && m.function() == CALCULATOR->f_diff) { - if(m.size() >= 4 && m[1] == mfrom && m[3].isUndefined()) { - m[3] = mto; - return true; - } - return false; - } - bool b = false; - for(size_t i = 0; i < m.size(); i++) { - if(replace_diff_x(m[i], mfrom, mto)) { - b = true; - m.childUpdated(i + 1); - } - } - return b; -} - -DeriveFunction::DeriveFunction() : MathFunction("diff", 1, 4) { - setArgumentDefinition(2, new SymbolicArgument()); - setDefaultValue(2, "undefined"); - Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SINT); - arg->setHandleVector(false); - setArgumentDefinition(3, arg); - setDefaultValue(3, "1"); - setDefaultValue(4, "undefined"); -} -int DeriveFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - int i = vargs[2].number().intValue(); - mstruct = vargs[0]; - bool b = false; - while(i) { - if(CALCULATOR->aborted()) return 0; - if(!mstruct.differentiate(vargs[1], eo) && !b) { - return 0; - } - b = true; - i--; - if(i > 0) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_EXACT; - eo2.calculate_functions = false; - mstruct.eval(eo2); - } - } - if(!vargs[3].isUndefined()) replace_diff_x(mstruct, vargs[1], vargs[3]); - return 1; -} - -liFunction::liFunction() : MathFunction("li", 1) { - names[0].case_sensitive = true; - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false)); -} -bool liFunction::representsReal(const MathStructure &vargs, bool) const { - return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative() && ((vargs[0].isNumber() && !COMPARISON_IS_NOT_EQUAL(vargs[0].number().compare(nr_one))) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && COMPARISON_IS_NOT_EQUAL(((KnownVariable*) vargs[0].variable())->get().number().compare(nr_one)))); -} -bool liFunction::representsNonComplex(const MathStructure &vargs, bool) const { - return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative(); -} -bool liFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber() && ((vargs[0].isNumber() && COMPARISON_IS_NOT_EQUAL(vargs[0].number().compare(nr_one))) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && COMPARISON_IS_NOT_EQUAL(((KnownVariable*) vargs[0].variable())->get().number().compare(nr_one))));} -int liFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION(logint) -} -LiFunction::LiFunction() : MathFunction("Li", 2) { - names[0].case_sensitive = true; - setArgumentDefinition(1, new IntegerArgument()); - Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false); - arg->setHandleVector(true); - setArgumentDefinition(2, arg); -} -bool LiFunction::representsReal(const MathStructure &vargs, bool) const { - return vargs.size() == 2 && vargs[0].representsInteger() && vargs[1].representsReal() && (vargs[1].representsNonPositive() || ((vargs[1].isNumber() && vargs[1].number().isLessThanOrEqualTo(1)) || (vargs[1].isVariable() && vargs[1].variable()->isKnown() && ((KnownVariable*) vargs[1].variable())->get().isNumber() && ((KnownVariable*) vargs[1].variable())->get().number().isLessThanOrEqualTo(1)))) && ((vargs[0].representsPositive() || ((vargs[1].isNumber() && COMPARISON_IS_NOT_EQUAL(vargs[1].number().compare(nr_one))) || (vargs[1].isVariable() && vargs[1].variable()->isKnown() && ((KnownVariable*) vargs[1].variable())->get().isNumber() && COMPARISON_IS_NOT_EQUAL(((KnownVariable*) vargs[1].variable())->get().number().compare(nr_one)))))); -} -bool LiFunction::representsNonComplex(const MathStructure &vargs, bool) const { - return vargs.size() == 2 && vargs[0].representsInteger() && vargs[1].representsNonComplex() && (vargs[1].representsNonPositive() || ((vargs[1].isNumber() && vargs[1].number().isLessThanOrEqualTo(1)) || (vargs[1].isVariable() && vargs[1].variable()->isKnown() && ((KnownVariable*) vargs[1].variable())->get().isNumber() && ((KnownVariable*) vargs[1].variable())->get().number().isLessThanOrEqualTo(1)))); -} -bool LiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[0].representsInteger() && (vargs[0].representsPositive() || (vargs[1].representsNumber() && ((vargs[1].isNumber() && COMPARISON_IS_NOT_EQUAL(vargs[1].number().compare(nr_one))) || (vargs[1].isVariable() && vargs[1].variable()->isKnown() && ((KnownVariable*) vargs[1].variable())->get().isNumber() && COMPARISON_IS_NOT_EQUAL(((KnownVariable*) vargs[1].variable())->get().number().compare(nr_one))))));} -int LiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[1].isVector()) return 0; - if(vargs[0].isOne()) { - mstruct.set(1, 1, 0); - mstruct -= vargs[1]; - mstruct.transform(CALCULATOR->f_ln); - mstruct.negate(); - return true; - } else if(vargs[0].isZero()) { - mstruct.set(1, 1, 0); - mstruct -= vargs[1]; - mstruct.inverse(); - mstruct *= vargs[1]; - return true; - } else if(vargs[0].isMinusOne()) { - mstruct.set(1, 1, 0); - mstruct -= vargs[1]; - mstruct.raise(Number(-2, 1)); - mstruct *= vargs[1]; - return true; - } - mstruct = vargs[1]; - mstruct.eval(eo); - if(mstruct.isVector()) return -2; - if(vargs[0].number().isPositive() && mstruct.isOne()) { - mstruct = vargs[0]; - mstruct.transform(CALCULATOR->f_zeta); - return true; - } - if(mstruct.isNumber()) { - Number nr(mstruct.number()); - if(nr.polylog(vargs[0].number()) && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || vargs[0].isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || vargs[0].number().isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || vargs[0].number().includesInfinity() || mstruct.number().includesInfinity())) { - mstruct.set(nr); return 1; - } - } - return -2; -} -EiFunction::EiFunction() : MathFunction("Ei", 1) { - names[0].case_sensitive = true; - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONZERO, true, false)); -} -bool EiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonZero();} -bool EiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} -bool EiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber() && vargs[0].representsNonZero();} -int EiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION(expint) -} - -SiFunction::SiFunction() : MathFunction("Si", 1) { - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); -} -bool SiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} -bool SiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool SiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);} -int SiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.isNumber()) { - Number nr(mstruct.number()); - if(nr.isPlusInfinity()) { - mstruct.set(CALCULATOR->v_pi, true); - mstruct *= nr_half; - return 1; - } - if(nr.isMinusInfinity()) { - mstruct.set(CALCULATOR->v_pi, true); - mstruct *= nr_minus_half; - return 1; - } - if(nr.hasImaginaryPart() && !nr.hasRealPart()) { - mstruct.set(nr.imaginaryPart()); - mstruct.transform(CALCULATOR->f_Shi); - mstruct *= nr_one_i; - return 1; - } - if(nr.sinint() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || mstruct.number().includesInfinity())) { - mstruct.set(nr); - return 1; - } - } - if(has_predominately_negative_sign(mstruct)) { - negate_struct(mstruct); - mstruct.transform(this); - mstruct.negate(); - return 1; - } - return -1; -} -CiFunction::CiFunction() : MathFunction("Ci", 1) { - names[0].case_sensitive = true; - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); -} -bool CiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsPositive();} -bool CiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} -bool CiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative(true);} -int CiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.isNumber()) { - if(mstruct.number().isNegative()) { - if(!eo.allow_complex) return -1; - mstruct.negate(); - mstruct.transform(this); - mstruct += CALCULATOR->v_pi; - mstruct.last() *= nr_one_i; - return 1; - } - Number nr(mstruct.number()); - if(nr.isComplex() && nr.hasImaginaryPart() && !nr.hasRealPart()) { - mstruct.set(nr.imaginaryPart()); - if(nr.imaginaryPartIsNegative()) mstruct.negate(); - mstruct.transform(CALCULATOR->f_Chi); - mstruct += CALCULATOR->v_pi; - mstruct.last() *= nr_half; - if(nr.imaginaryPartIsPositive()) mstruct.last() *= nr_one_i; - else mstruct.last() *= nr_minus_i; - return 1; - } - if(nr.cosint() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || mstruct.number().includesInfinity())) { - mstruct.set(nr); - return 1; - } - } - return -1; -} -ShiFunction::ShiFunction() : MathFunction("Shi", 1) { - names[0].case_sensitive = true; - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); -} -bool ShiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} -bool ShiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} -bool ShiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);} -int ShiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.isNumber()) { - Number nr(mstruct.number()); - if(nr.hasImaginaryPart() && !nr.hasRealPart()) { - mstruct.set(nr.imaginaryPart()); - mstruct.transform(CALCULATOR->f_Si); - mstruct *= nr_one_i; - return 1; - } - if(nr.sinhint() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || mstruct.number().includesInfinity())) { - mstruct.set(nr); - return 1; - } - } - if(has_predominately_negative_sign(mstruct)) { - negate_struct(mstruct); - mstruct.transform(this); - mstruct.negate(); - return 1; - } - return -1; -} -ChiFunction::ChiFunction() : MathFunction("Chi", 1) { - names[0].case_sensitive = true; - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); -} -bool ChiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsPositive();} -bool ChiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative();} -bool ChiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} -int ChiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[0].isVector()) return 0; - mstruct = vargs[0]; - mstruct.eval(eo); - if(mstruct.isVector()) return -1; - if(mstruct.isNumber()) { - if(eo.allow_complex && mstruct.number().isNegative()) { - if(!eo.allow_complex) return -1; - mstruct.negate(); - mstruct.transform(this); - mstruct += CALCULATOR->v_pi; - mstruct.last() *= nr_one_i; - return 1; - } - Number nr(mstruct.number()); - if(nr.isComplex() && nr.hasImaginaryPart() && !nr.hasRealPart()) { - mstruct.set(nr.imaginaryPart()); - if(nr.imaginaryPartIsNegative()) mstruct.negate(); - mstruct.transform(CALCULATOR->f_Ci); - mstruct += CALCULATOR->v_pi; - mstruct.last() *= nr_half; - if(nr.imaginaryPartIsPositive()) mstruct.last() *= nr_one_i; - else mstruct.last() *= nr_minus_i; - return 1; - } - if(nr.coshint() && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || mstruct.number().includesInfinity())) { - mstruct.set(nr); - return 1; - } - } - return -1; -} - -IGammaFunction::IGammaFunction() : MathFunction("igamma", 2) { - setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false)); - setArgumentDefinition(2, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false)); -} -bool IGammaFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[1].representsPositive() || (vargs[0].representsInteger() && vargs[0].representsPositive()));} -bool IGammaFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[1].representsNonNegative() || (vargs[0].representsInteger() && vargs[0].representsNonNegative()));} -bool IGammaFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[1].representsNonZero() || vargs[0].representsPositive());} -int IGammaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - FR_FUNCTION_2(igamma) -} - -IntegrateFunction::IntegrateFunction() : MathFunction("integrate", 1, 5) { - Argument *arg = new Argument("", false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); - setDefaultValue(2, "undefined"); - arg = new Argument("", false, false); - arg->setHandleVector(true); - setArgumentDefinition(2, arg); - setDefaultValue(3, "undefined"); - arg = new Argument("", false, false); - arg->setHandleVector(true); - setArgumentDefinition(3, arg); - setArgumentDefinition(4, new SymbolicArgument()); - setDefaultValue(4, "undefined"); - setArgumentDefinition(5, new BooleanArgument()); - setDefaultValue(5, "0"); -} - -// Type 0: Simpson's rule, 1: trapezoid, 2: Simpson's 3/8, 3: Boole's - -bool numerical_integration(const MathStructure &mstruct, Number &nvalue, const MathStructure &x_var, const EvaluationOptions &eo2, const Number &nr_begin, const Number &nr_end, int i_samples, int type = 0) { - if((type == 0 && i_samples % 2 == 1) || (type == 2 && i_samples % 3 == 2) || (type == 3 && i_samples % 4 == 3)) { - i_samples++; - } else if((type == 2 && i_samples % 3 == 1) || (type == 3 && i_samples % 4 == 2)) { - i_samples += 2; - } else if(type == 3 && i_samples % 4 == 1) { - i_samples += 3; - } - Number nr_step(nr_end); - nr_step -= nr_begin; - nr_step /= i_samples; - MathStructure m_a = mstruct; - m_a.replace(x_var, nr_begin); - m_a.eval(eo2); - if(!m_a.isNumber()) return false; - nvalue = m_a.number(); - m_a = mstruct; - m_a.replace(x_var, nr_end); - m_a.eval(eo2); - if(!m_a.isNumber()) return false; - if(!nvalue.add(m_a.number())) return false; - if(type == 1 && !nvalue.multiply(nr_half)) return false; - if(type == 3 && !nvalue.multiply(7)) return false; - for(int i = 1; i < i_samples; i++) { - if(CALCULATOR->aborted()) { - return false; - } - Number nr(nr_step); - nr *= i; - nr += nr_begin; - MathStructure m_a(mstruct); - m_a.replace(x_var, nr); - m_a.eval(eo2); - if(!m_a.isNumber()) return false; - if((type == 0 && i % 2 == 0) || (type == 2 && i % 3 == 0)) { - if(!m_a.number().multiply(nr_two)) return false; - } else if(type == 0) { - if(!m_a.number().multiply(4)) return false; - } else if(type == 2) { - if(!m_a.number().multiply(nr_three)) return false; - } else if(type == 3 && i % 4 == 0) { - if(!m_a.number().multiply(14)) return false; - } else if(type == 3 && i % 2 == 0) { - if(!m_a.number().multiply(12)) return false; - } else if(type == 3) { - if(!m_a.number().multiply(32)) return false; - } - if(!nvalue.add(m_a.number())) return false; - } - if(!nvalue.multiply(nr_step)) return false; - if(type == 0 && !nvalue.multiply(Number(1, 3))) return false; - if(type == 2 && !nvalue.multiply(Number(3, 8))) return false; - if(type == 3 && !nvalue.multiply(Number(2, 45))) return false; - return true; -} -bool montecarlo(const MathStructure &minteg, Number &nvalue, const MathStructure &x_var, const EvaluationOptions &eo, Number a, Number b, Number n) { - Number range(b); range -= a; - MathStructure m; - Number u; - nvalue.clear(); - vector v; - Number i(1, 1); - while(i <= n) { - if(CALCULATOR->aborted()) { - n = i; - break; - } - u.rand(); - u *= range; - u += a; - m = minteg; - m.replace(x_var, u); - m.eval(eo); - if(!m.isNumber() || m.number().includesInfinity()) return false; - if(!m.number().multiply(range)) return false; - if(!nvalue.add(m.number())) return false; - v.push_back(m.number()); - i++; - } - if(!nvalue.divide(n)) return false; - Number var; - for(size_t i = 0; i < v.size(); i++) { - if(!v[i].subtract(nvalue) || !v[i].square() || !var.add(v[i])) return false; - } - if(!var.divide(n) || !var.sqrt()) return false; - Number nsqrt(n); if(!nsqrt.sqrt() || !var.divide(nsqrt)) return false; - nvalue.setUncertainty(var); - return true; -} -bool has_wide_trig_interval(const MathStructure &m, const MathStructure &x_var, const EvaluationOptions &eo, Number a, Number b) { - for(size_t i = 0; i < m.size(); i++) { - if(has_wide_trig_interval(m[i], x_var, eo, a, b)) return true; - } - if(m.isFunction() && m.size() == 1 && (m.function() == CALCULATOR->f_sin || m.function() == CALCULATOR->f_cos)) { - Number nr_interval; - nr_interval.setInterval(a, b); - MathStructure mtest(m[0]); - mtest.replace(x_var, nr_interval); - CALCULATOR->beginTemporaryStopMessages(); - mtest.eval(eo); - CALCULATOR->endTemporaryStopMessages(); - return mtest.isMultiplication() && mtest.size() >= 1 && mtest[0].isNumber() && (mtest[0].number().uncertainty().realPart() > 100 || mtest[0].number().uncertainty().imaginaryPart() > 100); - } - return false; -} -bool romberg(const MathStructure &minteg, Number &nvalue, const MathStructure &x_var, const EvaluationOptions &eo, Number a, Number b, long int max_steps = -1, long int min_steps = 6, bool safety_measures = true) { - - bool auto_max = max_steps <= 0; - if(auto_max) max_steps = 22; - if(min_steps > max_steps) max_steps = min_steps; - - Number R1[max_steps], R2[max_steps]; - Number *Rp = &R1[0], *Rc = &R2[0]; - Number h(b); h -= a; - Number acc, acc_i, c, ntmp, prevunc, prevunc_i, nunc, nunc_i; - - nvalue.clear(); - - MathStructure mf(minteg); - mf.replace(x_var, a); - mf.eval(eo); - if(!mf.isNumber() || mf.number().includesInfinity()) { - if(!a.setToFloatingPoint()) return false; - mpfr_nextabove(a.internalLowerFloat()); - mpfr_nextabove(a.internalUpperFloat()); - mf = minteg; - mf.replace(x_var, a); - mf.eval(eo); - } - if(!mf.isNumber()) return false; - Rp[0] = mf.number(); - - mf = minteg; - mf.replace(x_var, b); - mf.eval(eo); - if(!mf.isNumber() || mf.number().includesInfinity()) { - if(!b.setToFloatingPoint()) return false; - mpfr_nextbelow(b.internalLowerFloat()); - mpfr_nextbelow(b.internalUpperFloat()); - mf = minteg; - mf.replace(x_var, a); - mf.eval(eo); - } - if(!mf.isNumber()) return false; - - if(!Rp[0].add(mf.number()) || !Rp[0].multiply(nr_half) || !Rp[0].multiply(h)) return false; - - if(safety_measures && min_steps < 15 && has_wide_trig_interval(minteg, x_var, eo, a, b)) min_steps = (max_steps < 15 ? max_steps : 15); - - for(long int i = 1; i < max_steps; i++) { - - if(CALCULATOR->aborted()) break; - - if(!h.multiply(nr_half)) return false; - - c.clear(); - - long int ep = 1 << (i - 1); - ntmp = a; ntmp += h; - for(long int j = 1; j <= ep; j++){ - if(CALCULATOR->aborted()) break; - mf = minteg; - mf.replace(x_var, ntmp); - mf.eval(eo); - if(CALCULATOR->aborted()) break; - if(!mf.isNumber() || mf.number().includesInfinity()) { - Number ntmp2(ntmp); - if(ntmp2.setToFloatingPoint()) return false; - if(j % 2 == 0) {mpfr_nextabove(ntmp2.internalLowerFloat()); mpfr_nextabove(ntmp2.internalUpperFloat());} - else {mpfr_nextbelow(ntmp2.internalLowerFloat()); mpfr_nextbelow(ntmp2.internalUpperFloat());} - mf = minteg; - mf.replace(x_var, ntmp2); - mf.eval(eo); - if(CALCULATOR->aborted()) break; - } - if(!mf.isNumber() || !c.add(mf.number())) return false; - ntmp += h; ntmp += h; - } - if(CALCULATOR->aborted()) break; - - Rc[0] = h; - ntmp = Rp[0]; - if(!ntmp.multiply(nr_half) || !Rc[0].multiply(c) || !Rc[0].add(ntmp)) return false; - - for(long int j = 1; j <= i; ++j){ - if(CALCULATOR->aborted()) break; - ntmp = 4; - ntmp ^= j; - Rc[j] = ntmp; - ntmp--; ntmp.recip(); - if(!Rc[j].multiply(Rc[j - 1]) || !Rc[j].subtract(Rp[j - 1]) || !Rc[j].multiply(ntmp)) return false; - } - if(CALCULATOR->aborted()) break; - - if(i >= min_steps - 1 && !Rp[i - 1].includesInfinity() && !Rc[i].includesInfinity()) { - if(Rp[i - 1].hasImaginaryPart()) nunc = Rp[i - 1].realPart(); - else nunc = Rp[i - 1]; - if(Rc[i].hasImaginaryPart()) nunc -= Rc[i].realPart(); - else nunc -= Rc[i]; - nunc.abs(); - if(safety_measures) nunc *= 10; - nunc.intervalToMidValue(); - if(Rp[i - 1].hasImaginaryPart() || Rc[i].hasImaginaryPart()) { - nunc_i = Rp[i - 1].imaginaryPart(); - nunc_i -= Rc[i].imaginaryPart(); - nunc_i.abs(); - } else { - nunc_i.clear(); - } - if(safety_measures) nunc_i *= 10; - nunc_i.intervalToMidValue(); - long int prec = PRECISION + (auto_max ? 3 : 1); - if(auto_max) { - if(i > 10) prec += 10 - ((!prevunc.isZero() || !prevunc_i.isZero()) ? i - 1 : i); - if(prec < 4) prec = 4; - } - acc.set(1, 1, -prec); - ntmp = Rc[i - 1]; - ntmp.intervalToMidValue(); - if(ntmp.hasImaginaryPart()) { - if(ntmp.hasRealPart()) acc *= ntmp.realPart(); - } else { - if(!ntmp.isZero()) acc *= ntmp; - } - acc.abs(); - acc.intervalToMidValue(); - nvalue = Rc[i - 1]; - if(nunc <= acc) { - if(!nunc_i.isZero()) { - acc_i.set(1, 1, -prec); - if(ntmp.hasImaginaryPart()) acc_i *= ntmp.imaginaryPart(); - acc_i.abs(); - acc_i.intervalToMidValue(); - if(nunc_i <= acc_i) { - if(!safety_measures) { - nunc.setImaginaryPart(nunc_i); - nvalue.setUncertainty(nunc); - return true; - } - if(!prevunc.isZero() || !prevunc_i.isZero() || (nunc.isZero() && nunc_i.isZero())) { - if(nunc <= prevunc && nunc_i <= prevunc_i) { - if(!ntmp.hasRealPart()) prevunc = acc; - if(!ntmp.hasImaginaryPart()) prevunc.setImaginaryPart(acc_i); - else prevunc.setImaginaryPart(prevunc_i); - nvalue.setUncertainty(prevunc); - } else { - acc.setImaginaryPart(acc_i); - nvalue.setUncertainty(acc); - } - return true; - } - prevunc = nunc; - prevunc_i = nunc_i; - } else { - prevunc.clear(); - prevunc_i.clear(); - } - } else { - if(!safety_measures) { - nvalue.setUncertainty(nunc); - return true; - } - if(!prevunc.isZero() || nunc.isZero()) { - if(!prevunc_i.isZero()) nunc.setImaginaryPart(prevunc_i); - if(!ntmp.isZero() && nunc <= prevunc) nvalue.setUncertainty(prevunc); - else nvalue.setUncertainty(acc); - return true; - } - prevunc = nunc; - prevunc_i = nunc_i; - } - } else { - prevunc.clear(); - prevunc_i.clear(); - } - } - - Number *rt = Rp; - Rp = Rc; - Rc = rt; - } - if(!nunc.isZero() || !nunc_i.isZero()) { - acc.set(1, 1, auto_max ? -3 : -2); - ntmp = nvalue; - ntmp.intervalToMidValue(); - if(ntmp.hasImaginaryPart()) { - if(ntmp.hasRealPart()) acc *= ntmp.realPart(); - } else { - if(!ntmp.isZero()) acc *= ntmp; - } - acc.abs(); - acc.intervalToMidValue(); - if(nunc > acc) return false; - if(!ntmp.hasRealPart()) nunc = acc; - if(!nunc_i.isZero()) { - acc.set(1, 1, -3); - if(ntmp.hasImaginaryPart()) acc *= ntmp.imaginaryPart(); - acc.abs(); - acc.intervalToMidValue(); - if(nunc_i > acc) return false; - if(ntmp.hasImaginaryPart()) nunc.setImaginaryPart(nunc_i); - else nunc.setImaginaryPart(acc); - } - if(safety_measures) nunc *= 10; - nvalue.setUncertainty(nunc); - return true; - } - return false; -} -int numerical_integration_part(const MathStructure &minteg, const MathStructure &x_var, const MathStructure &merr_pre, const MathStructure &merr_diff, KnownVariable *v, Number &nvalue, EvaluationOptions &eo, const Number &nr, int type = 0, int depth = 0, bool nzerodiff = false) { - if(CALCULATOR->aborted()) return 0; - eo.interval_calculation = INTERVAL_CALCULATION_NONE; - MathStructure merr(merr_pre); - int i_ret = 1; - v->set(nr); - bool do_parts = true; - /*if(nzerodiff) { - v->set(nr.lowerEndPoint()); - MathStructure mlow(merr); - mlow.eval(eo); - v->set(nr.upperEndPoint()); - merr.eval(eo); - if(!merr.isNumber() || !mlow.isNumber() || merr.number().includesInfinity() || mlow.number().includesInfinity()) return 0; - merr.number().setInterval(mlow.number(), merr.number()); - do_parts = false; - } else if(depth > 1 && !merr_diff.isUndefined()) { - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mzero(merr_diff); - mzero.eval(eo); - if(CALCULATOR->endTemporaryStopMessages() == 0 && mzero.isNumber() && mzero.number().isNonZero() && (!mzero.number().hasImaginaryPart() || mzero.number().internalImaginary()->isNonZero())) { - v->set(nr.lowerEndPoint()); - MathStructure mlow(merr); - mlow.eval(eo); - v->set(nr.upperEndPoint()); - merr.eval(eo); - if(!merr.isNumber() || !mlow.isNumber() || merr.number().includesInfinity() || mlow.number().includesInfinity()) return 0; - merr.number().setInterval(mlow.number(), merr.number()); - do_parts = false; - nzerodiff = true; - } - }*/ - if(depth > 0 && do_parts) { - CALCULATOR->beginTemporaryStopMessages(); - merr.eval(eo); - do_parts = (CALCULATOR->endTemporaryStopMessages() > 0 || !merr.isNumber() || merr.number().includesInfinity()); - } - if(do_parts) { - integrate_parts: - if(depth > 4) { - if(numerical_integration(minteg, nvalue, x_var, eo, nr.lowerEndPoint(), nr.upperEndPoint(), 1002, type)) {nvalue.setApproximate(); return -1;} - return 0; - } - vector parts; - nr.splitInterval(depth == 0 ? 5 : 5, parts); - nvalue.clear(); - Number n_i; - for(size_t i = 0; i < parts.size(); i++) { - int i_reti = numerical_integration_part(minteg, x_var, merr_pre, merr_diff, v, n_i, eo, parts[i], type, depth + 1, nzerodiff); - if(i_reti != 0) { - if(i_reti < i_ret) i_ret = i_reti; - if(!nvalue.add(n_i)) return false; - } else { - return 0; - } - } - return i_ret; - } else { - CALCULATOR->beginTemporaryStopIntervalArithmetic(); - eo.interval_calculation = INTERVAL_CALCULATION_NONE; - Number nr_interval(merr.number()); - Number nr_interval_abs; - Number nr1(nr_interval.upperEndPoint(true)); - Number nr2(nr_interval.lowerEndPoint(true)); - nr1.abs(); - nr2.abs(); - if(nr1.isGreaterThan(nr2)) nr_interval_abs = nr1; - else nr_interval_abs = nr2; - if(merr.number().hasImaginaryPart()) { - if(merr.number().hasRealPart()) { - nr1 = merr.number().realPart().upperEndPoint(); - nr2 = merr.number().realPart().lowerEndPoint(); - nr1.abs(); - nr2.abs(); - if(nr1.isGreaterThan(nr2)) nr_interval = nr1; - else nr_interval = nr2; - nr1 = merr.number().imaginaryPart().upperEndPoint(); - nr2 = merr.number().imaginaryPart().lowerEndPoint(); - nr1.abs(); - nr2.abs(); - if(nr1.isGreaterThan(nr2)) nr_interval.setImaginaryPart(nr1); - else nr_interval.setImaginaryPart(nr2); - } else { - nr_interval.setImaginaryPart(nr_interval_abs); - } - } else { - nr_interval = nr_interval_abs; - } - Number nr_samples(6, 1); - Number nr_range(nr.upperEndPoint()); - nr_range -= nr.lowerEndPoint(); - int i_run = 0; - while(true) { - if(CALCULATOR->aborted()) {CALCULATOR->endTemporaryStopIntervalArithmetic(); return 0;} - if(numerical_integration(minteg, nvalue, x_var, eo, nr.lowerEndPoint(), nr.upperEndPoint(), nr_samples.intValue(), type)) { - if(nr.includesInfinity()) { - CALCULATOR->endTemporaryStopIntervalArithmetic(); - return 0; - } - Number nr_prec(nr_range); - if(type == 0 || type == 2) { - nr_prec /= nr_samples; - nr_prec ^= 4; - nr_prec *= nr_range; - nr_prec /= (type == 2 ? 80 : 180); - } else if(type == 1) { - nr_prec /= nr_samples; - nr_prec ^= 2; - nr_prec *= nr_range; - nr_prec /= 12; - } else if(type == 3) { - nr_prec ^= 7; - //nr_prec *= Number(8, 945); ? - nr_prec /= (nr_samples ^ 6); - } - nr_prec *= nr_interval; - Number nr_prec_abs(nr_prec); - nr_prec_abs.abs(); - Number mabs(nvalue); - mabs.abs(); - Number max_error(1, 1, -(PRECISION + 1 - (i_run * 2))); - max_error *= mabs; - if(nr_prec_abs >= max_error) { - for(int i = 0; ; i++) { - if(type == 0 || type == 2) { - nr_samples = nr_range; - nr_samples ^= 5; - nr_samples /= (type == 2 ? 80 : 180); - nr_samples *= nr_interval_abs; - nr_samples /= max_error; - nr_samples.root(4); - } else if(type == 3) { - nr_samples = nr_range; - nr_samples ^= 7; - //nr_samples *= Number(8, 945); ? - nr_samples *= nr_interval_abs; - nr_samples /= max_error; - nr_samples.root(6); - } else { - nr_samples = nr_range; - nr_samples ^= 3; - nr_samples /= 12; - nr_samples *= nr_interval_abs; - nr_samples /= max_error; - nr_samples.sqrt(); - } - nr_samples.ceil(); - if(type == 0 && nr_samples.isOdd()) { - nr_samples++; - } else if(type == 2 && !nr_samples.isIntegerDivisible(3)) { - Number nmod(nr_samples); - nmod.mod(3); - if(nmod == 1) nr_samples += 2; - else nr_samples += 1; - } else if(type == 3 && !nr_samples.isIntegerDivisible(4)) { - Number nmod(nr_samples); - nmod.mod(4); - if(nmod == 1) nr_samples += 3; - if(nmod == 2) nr_samples += 2; - else nr_samples += 1; - } - if(nr_samples < 10000) break; - i_run++; - if(depth <= 3 && PRECISION + 1 - (i_run * 2) < (PRECISION > 10 ? 10 : PRECISION) - depth) goto integrate_parts; - if(PRECISION + 1 - (i_run * 2) < 5) { - if(nr_samples < 50000) break; - if(PRECISION + 1 - (i_run * 2) < 2 - depth) { - if(numerical_integration(minteg, nvalue, x_var, eo, nr.lowerEndPoint(), nr.upperEndPoint(), 1002, type)) {nvalue.setApproximate(); return -1;} - return 0; - } - } - max_error *= Number(1, 1, (PRECISION + 1 - ((i_run - 1) * 2))); - max_error *= Number(1, 1, -(PRECISION + 1 - (i_run * 2))); - } - } else { - CALCULATOR->endTemporaryStopIntervalArithmetic(); - nvalue.setUncertainty(nr_prec); - return 1; - } - } else { - CALCULATOR->endTemporaryStopIntervalArithmetic(); - return 0; - } - i_run++; - } - } - return 0; -} -bool contains_complex(const MathStructure &mstruct) { - if(mstruct.isNumber()) return mstruct.number().isComplex(); - if(mstruct.isVariable() && mstruct.variable()->isKnown()) return contains_complex(((KnownVariable*) mstruct.variable())->get()); - for(size_t i = 0; i < mstruct.size(); i++) { - if(contains_complex(mstruct[i])) return true; - } - return false; -} - -bool check_denominators(const MathStructure &m, const MathStructure &mi, const MathStructure &mx, const EvaluationOptions &eo) { - if(m.contains(mx, false, true, true) == 0) return true; - for(size_t i = 0; i < m.size(); i++) { - if(!check_denominators(m[i], mi, mx, eo)) return false; - } - if(m.isPower()) { - bool b_neg = m[1].representsNegative(); - if(!m[1].representsNonNegative()) { - if(!m[0].representsNonZero()) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - eo2.interval_calculation = INTERVAL_CALCULATION_INTERVAL_ARITHMETIC; - CALCULATOR->beginTemporaryStopMessages(); - KnownVariable *v = new KnownVariable("", "v", mi); - MathStructure mpow(m[1]); - mpow.replace(mx, v, true); - mpow.eval(eo2); - b_neg = mpow.representsNegative(); - CALCULATOR->endTemporaryStopMessages(); - v->destroy(); - } - } - if(b_neg && !m[0].representsNonZero()) { - if(m[0].isZero()) return false; - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mbase(m[0]); - KnownVariable *v = new KnownVariable("", "v", mi); - mbase.replace(mx, v, true); - bool b_multiple = mbase.contains(mx, true) > 0; - if(b_multiple) mbase.replace(mx, v); - mbase.eval(eo2); - CALCULATOR->endTemporaryStopMessages(); - /*if(mbase.isZero()) { - v->destroy(); return false; - } else if(!b_multiple && mbase.isNumber()) { - if(!mbase.number().isNonZero()) {v->destroy(); return false;} - } else if(!mbase.isNumber() || !mbase.number().isNonZero()) { - CALCULATOR->beginTemporaryStopMessages(); - eo2.interval_calculation = INTERVAL_CALCULATION_INTERVAL_ARITHMETIC; - mbase = m[0]; - mbase.replace(mx, v); - mbase.eval(eo2); - CALCULATOR->endTemporaryStopMessages(); - }*/ - if(mbase.isZero()) { - v->destroy(); return false; - } else if(!b_multiple && mbase.isNumber()) { - if(!mbase.number().isNonZero()) {v->destroy(); return false;} - } else if(!mbase.isNumber() || !mbase.number().isNonZero()) { - CALCULATOR->beginTemporaryStopMessages(); - mbase = m[0]; - eo2.isolate_x = true; - eo2.isolate_var = &mx; - eo2.test_comparisons = true; - eo2.approximation = APPROXIMATION_EXACT; - mbase.transform(COMPARISON_NOT_EQUALS, m_zero); - mbase.eval(eo2); - eo2.approximation = APPROXIMATION_APPROXIMATE; - eo2.isolate_x = false; - eo2.isolate_var = NULL; - if(!mbase.isNumber()) { - MathStructure mtest(mbase); - mtest.replace(mx, v); - mtest.eval(eo2); - if(mtest.isNumber()) mbase = mtest; - } - CALCULATOR->endTemporaryStopMessages(); - if(!mbase.isOne()) { - if(mbase.isZero()) {v->destroy(); return false;} - bool b = false; - if(mbase.isComparison()) { - CALCULATOR->beginTemporaryStopMessages(); - mbase[0].eval(eo2); mbase[1].eval(eo2); - CALCULATOR->endTemporaryStopMessages(); - } - if(mbase.isComparison() && mbase.comparisonType() == COMPARISON_NOT_EQUALS && (mbase[0] == mx || mbase[0].isFunction()) && mbase[1].isNumber() && mi.isNumber()) { - ComparisonResult cr = COMPARISON_RESULT_UNKNOWN; - if(mbase[0].isFunction()) { - MathStructure mfunc(mbase[0]); - mfunc.replace(mx, v); - mfunc.eval(eo2); - if(mfunc.isNumber()) cr = mbase[1].number().compare(mfunc.number()); - } else { - cr = mbase[1].number().compare(mi.number()); - } - b = COMPARISON_IS_NOT_EQUAL(cr); - if(!b && cr != COMPARISON_RESULT_UNKNOWN) {v->destroy(); return false;} - } else if(mbase.isLogicalAnd()) { - for(size_t i = 0; i < mbase.size(); i++) { - if(mbase[i].isComparison()) {mbase[i][0].eval(eo2); mbase[i][1].eval(eo2);} - if(mbase[i].isComparison() && mbase[i].comparisonType() == COMPARISON_NOT_EQUALS && (mbase[i][0] == mx || mbase[i][0].isFunction()) && mbase[i][1].isNumber() && mi.isNumber()) { - ComparisonResult cr = COMPARISON_RESULT_UNKNOWN; - if(mbase[i][0].isFunction()) { - MathStructure mfunc(mbase[i][0]); - mfunc.replace(mx, v); - mfunc.eval(eo2); - if(mfunc.isNumber()) cr = mbase[i][1].number().compare(mfunc.number()); - } else { - cr = mbase[i][1].number().compare(mi.number()); - } - b = COMPARISON_IS_NOT_EQUAL(cr); - if(!b && cr != COMPARISON_RESULT_UNKNOWN) {v->destroy(); return false;} - } - } - } - if(!b) { - CALCULATOR->endTemporaryStopMessages(); - CALCULATOR->endTemporaryStopMessages(); - CALCULATOR->error(false, _("To avoid division by zero, the following must be true: %s."), format_and_print(mbase).c_str(), NULL); - CALCULATOR->beginTemporaryStopMessages(); - CALCULATOR->beginTemporaryStopMessages(); - } - } - } - v->destroy(); - } - } else if(m.isVariable()) { - if(m.variable()->isKnown() && !check_denominators(((KnownVariable*) m.variable())->get(), mi, mx, eo)) return false; - } else if(m.isFunction() && (m.function() == CALCULATOR->f_tan || m.function() == CALCULATOR->f_tanh || !m.representsNumber(true))) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - eo2.assume_denominators_nonzero = false; - MathStructure mfunc(m); - bool b = mfunc.calculateFunctions(eo2); - if(b && !check_denominators(mfunc, mi, mx, eo)) return false; - if(mfunc.function() == CALCULATOR->f_tan || mfunc.function() == CALCULATOR->f_tanh) { - mfunc.replace(mx, mi); - eo2.interval_calculation = INTERVAL_CALCULATION_INTERVAL_ARITHMETIC; - CALCULATOR->beginTemporaryStopMessages(); - b = mfunc.calculateFunctions(eo2); - CALCULATOR->endTemporaryStopMessages(); - if(!b) return false; - } - } - return true; -} -bool replace_atanh(MathStructure &m, const MathStructure &x_var, const MathStructure &m1, const MathStructure &m2, const EvaluationOptions &eo) { - bool b = false; - if(m.isFunction() && m.function() == CALCULATOR->f_atanh && m.size() == 1 && m[0].contains(x_var, true)) { - /*MathStructure mtest(m[0]); - mtest.replace(x_var, m1); - b = (mtest.compare(m_one) == COMPARISON_RESULT_EQUAL) || (mtest.compare(m_minus_one) == COMPARISON_RESULT_EQUAL); - if(!b) { - mtest = m[0]; - mtest.replace(x_var, m2); - b = (mtest.compare(m_one) == COMPARISON_RESULT_EQUAL) || (mtest.compare(m_minus_one) == COMPARISON_RESULT_EQUAL); - }*/ - b = true; - if(b) { - MathStructure marg(m[0]); - m = marg; - m += m_one; - m.transform(CALCULATOR->f_ln); - m *= nr_half; - m += marg; - m.last().negate(); - m.last() += m_one; - m.last().transform(CALCULATOR->f_ln); - m.last() *= Number(-1, 2); - return true; - } - } - for(size_t i = 0; i < m.size(); i++) { - if(replace_atanh(m[i], x_var, m1, m2, eo)) b = true; - } - if(b) { - m.childrenUpdated(); - m.calculatesub(eo, eo, false); - } - return b; -} -MathStructure *find_abs_x(MathStructure &mstruct, const MathStructure &x_var) { - if(mstruct.isFunction() && ((mstruct.function() == CALCULATOR->f_abs && mstruct.size() == 1) || (mstruct.function() == CALCULATOR->f_root && mstruct.size() == 2 && mstruct[1].isInteger() && mstruct[1].number().isOdd()))) { - return &mstruct; - } - for(size_t i = 0; i < mstruct.size(); i++) { - MathStructure *m = find_abs_x(mstruct[i], x_var); - if(m) return m; - } - return NULL; -} -bool replace_abs(MathStructure &mstruct, const MathStructure &mabs, bool neg) { - if(mstruct.equals(mabs, true, true)) { - if(mabs.function() == CALCULATOR->f_root) { - mstruct[1].inverse(); - mstruct.setType(STRUCT_POWER); - if(neg) { - mstruct[0].negate(); - mstruct.negate(); - } - } else { - mstruct.setToChild(1, true); - if(neg) mstruct.negate(); - } - return true; - } - bool b_ret = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(replace_abs(mstruct[i], mabs, neg)) b_ret = true; - } - return b_ret; -} -bool contains_incalc_function(const MathStructure &mstruct, const EvaluationOptions &eo) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(contains_incalc_function(mstruct[i], eo)) return true; - } - if(mstruct.isFunction()) { - if((mstruct.function() == CALCULATOR->f_erf || mstruct.function() == CALCULATOR->f_Ei) && mstruct.size() == 1 && !mstruct[0].representsNonComplex()) { - if(mstruct[0].representsComplex()) return true; - MathStructure mtest(mstruct[0]); - mtest.eval(eo); - return !mtest.representsNonComplex(); - } else if((mstruct.function() == CALCULATOR->f_Ci || mstruct.function() == CALCULATOR->f_Si) && mstruct.size() == 1 && !mstruct[0].representsNonComplex()) { - MathStructure mtest(mstruct[0]); - mtest.eval(eo); - return mtest.isNumber() && mtest.number().hasImaginaryPart() && mtest.number().hasRealPart(); - } else if(mstruct.function() == CALCULATOR->f_Li) { - MathStructure mtest(mstruct); - return !mtest.calculateFunctions(eo); - } else if(mstruct.function() == CALCULATOR->f_igamma && mstruct.size() == 2) { -#if MPFR_VERSION_MAJOR < 4 - return true; -#else - return !COMPARISON_IS_EQUAL_OR_LESS(mstruct[1].compare(m_zero)); -#endif - } - } - return false; -} - -bool test_definite_ln(const MathStructure &m, const MathStructure &mi, const MathStructure &mx, const EvaluationOptions &eo) { - for(size_t i = 0; i < m.size(); i++) { - if(!test_definite_ln(m[i], mi, mx, eo)) return false; - } - if(m.function() == CALCULATOR->f_ln && m.size() == 1 && m[0].contains(mx, true) > 0 && !m[0].representsNonComplex(true)) { - MathStructure mtest(m[0]); - mtest.replace(mx, mi); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - CALCULATOR->beginTemporaryStopMessages(); - mtest.eval(eo2); - CALCULATOR->endTemporaryStopMessages(); - if(mtest.isNumber() && mtest.number().hasImaginaryPart() && !mtest.number().imaginaryPartIsNonZero() && !mtest.number().realPart().isNonNegative()) return false; - } - return true; -} - -extern bool do_simplification(MathStructure &mstruct, const EvaluationOptions &eo, bool combine_divisions = true, bool only_gcd = false, bool combine_only = false, bool recursive = true, bool limit_size = false, int i_run = 1); - -void replace_intervals(MathStructure &m, vector vars) { - if(m.isNumber() && m.number().isInterval()) { - KnownVariable *v = new KnownVariable("", format_and_print(m), m); - m.set(v, true); - vars.push_back(v); - return; - } - for(size_t i = 0; i < m.size(); i++) { - replace_intervals(m[i], vars); - } -} -void restore_intervals(MathStructure &m, MathStructure &m2, vector vars, const EvaluationOptions &eo) { - for(size_t i = 0; i < vars.size(); i++) { - if(eo.approximation == APPROXIMATION_EXACT) { - m.replace(vars[i], vars[i]->get()); - m2.replace(vars[i], vars[i]->get()); - } - vars[i]->destroy(); - } -} - -int IntegrateFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - - MathStructure m1, m2; - if(vargs.size() >= 2) m1 = vargs[1]; - else m1.setUndefined(); - if(vargs.size() >= 3) m2 = vargs[2]; - else m2.setUndefined(); - MathStructure x_var = vargs[3]; - if(m2.isUndefined() && (m1.isSymbolic() || (m1.isVariable() && !m1.variable()->isKnown()))) {x_var = m1; m1.setUndefined();} - if(m1.isUndefined() != m2.isUndefined()) { - if(m1.isUndefined()) m1.set(nr_minus_inf); - else m2.set(nr_plus_inf); - } - m1.eval(eo); - m2.eval(eo); - int definite_integral = 0; - if(!m1.isUndefined() && !m2.isUndefined()) definite_integral = -1; - if(definite_integral < 0 && (!m1.isNumber() || !m1.number().isMinusInfinity()) && (!m2.isNumber() || !m2.number().isPlusInfinity())) definite_integral = 1; - if(definite_integral > 0 && m1 == m2) { - mstruct.clear(); - return 1; - } - CALCULATOR->beginTemporaryStopMessages(); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_EXACT; - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mstruct_pre = vargs[0]; - MathStructure m_interval; - if(!m1.isUndefined()) { - m_interval.set(CALCULATOR->f_interval, &m1, &m2, NULL); - CALCULATOR->beginTemporaryStopMessages(); - EvaluationOptions eo3 = eo; - eo3.approximation = APPROXIMATION_APPROXIMATE; - m_interval.calculateFunctions(eo3); - CALCULATOR->endTemporaryStopMessages(); - UnknownVariable *var = new UnknownVariable("", format_and_print(vargs[3])); - var->setInterval(m_interval); - x_var.set(var); - mstruct_pre.replace(vargs[3], x_var); - var->destroy(); - if(definite_integral && !check_denominators(mstruct_pre, m_interval, x_var, eo)) { - if(definite_integral < 0) { - definite_integral = 0; - } else { - CALCULATOR->endTemporaryStopMessages(); - CALCULATOR->endTemporaryStopMessages(true); - CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); - return false; - } - } - } - mstruct = mstruct_pre; - vector vars; - replace_intervals(mstruct, vars); - eo2.do_polynomial_division = false; - mstruct.eval(eo2); - if(definite_integral > 0 && mstruct.isAddition() && m1.isNumber() && m1.number().isReal() && m2.isNumber() && m2.number().isReal()) { - mstruct.replace(x_var, vargs[3]); - Number nr; - for(size_t i = 0; i < mstruct.size();) { - mstruct[i].transform(this); - for(size_t i2 = 1; i2 < vargs.size(); i2++) mstruct[i].addChild(vargs[i2]); - if(!mstruct[i].calculateFunctions(eo, false)) { - CALCULATOR->endTemporaryStopMessages(); - CALCULATOR->endTemporaryStopMessages(); - CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); - return false; - } - if(mstruct[i].isNumber()) { - if(nr.add(mstruct[i].number())) mstruct.delChild(i + 1); - else i++; - } else i++; - } - mstruct.childrenUpdated(); - if(mstruct.size() == 0) mstruct.set(nr, true); - else if(!nr.isZero() || nr.isApproximate()) mstruct.addChild(nr); - CALCULATOR->endTemporaryStopMessages(true); - CALCULATOR->endTemporaryStopMessages(true); - return 1; - } - do_simplification(mstruct, eo2, true, false, false, true, true); - eo2.do_polynomial_division = eo.do_polynomial_division; - MathStructure mbak(mstruct); - - if(vargs.size() < 5 || !vargs[4].number().getBoolean() || definite_integral == 0) { - - int use_abs = -1; - /*if(m1.isUndefined() && x_var.representsReal() && !contains_complex(mstruct)) { - use_abs = 1; - }*/ - if(definite_integral) replace_atanh(mstruct, x_var, vargs[1], vargs[2], eo2); - int b = mstruct.integrate(x_var, eo2, true, use_abs, definite_integral, true, (definite_integral && eo.approximation != APPROXIMATION_EXACT && PRECISION < 20) ? 2 : 4); - if(b < 0) { - restore_intervals(mstruct, mbak, vars, eo); - mstruct = mbak; - if(definite_integral) mstruct.replace(x_var, vargs[3]); - CALCULATOR->endTemporaryStopMessages(true); - CALCULATOR->endTemporaryStopMessages(true); - CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); - return -1; - } - if(eo.approximation != APPROXIMATION_EXACT && (!b || mstruct.containsFunction(this, true) > 0)) { - vector blocked_messages; - CALCULATOR->endTemporaryStopMessages(false, &blocked_messages); - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mbak_integ(mstruct); - eo2.approximation = eo.approximation; - eo2.do_polynomial_division = false; - mstruct = mstruct_pre; - if(definite_integral) replace_atanh(mstruct, x_var, vargs[1], vargs[2], eo2); - mstruct.eval(eo2); - do_simplification(mstruct, eo2, true, false, false, true, true); - eo2.do_polynomial_division = eo.do_polynomial_division; - int b2 = mstruct.integrate(x_var, eo2, true, use_abs, definite_integral, true, (definite_integral && eo.approximation != APPROXIMATION_EXACT && PRECISION < 20) ? 2 : 4); - if(b2 < 0) { - restore_intervals(mstruct, mbak, vars, eo); - mstruct = mbak; - if(definite_integral) mstruct.replace(x_var, vargs[3]); - CALCULATOR->endTemporaryStopMessages(true); - CALCULATOR->endTemporaryStopMessages(true); - CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); - return -1; - } - if(b2 && (!b || mstruct.containsFunction(this, true) <= 0)) { - CALCULATOR->endTemporaryStopMessages(true); - b = true; - } else { - CALCULATOR->endTemporaryStopMessages(false); - if(b) { - CALCULATOR->addMessages(&blocked_messages); - mstruct = mbak_integ; - } - } - } else { - restore_intervals(mstruct, mbak, vars, eo); - CALCULATOR->endTemporaryStopMessages(true); - } - - eo2.approximation = eo.approximation; - if(b) { - if(definite_integral && mstruct.containsFunction(this, true) <= 0 && test_definite_ln(mstruct, m_interval, x_var, eo)) { - CALCULATOR->endTemporaryStopMessages(true); - MathStructure mstruct_lower(mstruct); - if(m1.isInfinite() || m2.isInfinite()) { - CALCULATOR->beginTemporaryStopMessages(); - EvaluationOptions eo3 = eo; - eo3.approximation = APPROXIMATION_EXACT; - if(m1.isInfinite()) { - b = mstruct_lower.calculateLimit(x_var, m1, eo3) && !mstruct_lower.isInfinite(); - } else { - mstruct_lower.replace(x_var, vargs[1]); - b = eo.approximation == APPROXIMATION_EXACT || !contains_incalc_function(mstruct_lower, eo); - } - MathStructure mstruct_upper(mstruct); - if(m2.isInfinite()) { - b = mstruct_upper.calculateLimit(x_var, m2, eo3) && !mstruct_upper.isInfinite(); - } else { - mstruct_upper.replace(x_var, vargs[2]); - b = eo.approximation == APPROXIMATION_EXACT || !contains_incalc_function(mstruct_upper, eo); - } - if(b) { - mstruct = mstruct_upper; - mstruct -= mstruct_lower; - return 1; - } else { - if(definite_integral > 0) { - CALCULATOR->endTemporaryStopMessages(true); - mstruct = mbak; - mstruct.replace(x_var, vargs[3]); - CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); - return -1; - } else { - definite_integral = 0; - } - } - } else { - mstruct_lower.replace(x_var, vargs[1]); - if(eo.approximation == APPROXIMATION_EXACT || !contains_incalc_function(mstruct_lower, eo)) { - mstruct.replace(x_var, vargs[2]); - if(eo.approximation != APPROXIMATION_EXACT && contains_incalc_function(mstruct, eo)) { - mstruct = mbak; - } else { - mstruct -= mstruct_lower; - return 1; - } - } - } - } else if(definite_integral < 0) { - definite_integral = 0; - } else if(definite_integral > 0) { - mstruct = mbak; - } - if(!definite_integral) { - if(!m1.isUndefined()) mstruct.replace(x_var, vargs[3]); - CALCULATOR->endTemporaryStopMessages(true); - mstruct += CALCULATOR->v_C; - return 1; - } - } - if(!b) { - mstruct = mbak; - if(definite_integral <= 0) { - if(!m1.isUndefined()) mstruct.replace(x_var, vargs[3]); - CALCULATOR->endTemporaryStopMessages(true); - CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); - return -1; - } - } - MathStructure *mabs = find_abs_x(mbak, x_var); - if(mabs && !(*mabs)[0].representsNonComplex(true)) { - MathStructure mtest((*mabs)[0]); - mtest.transform(CALCULATOR->f_im); - if(mtest.compare(m_zero) != COMPARISON_RESULT_EQUAL) mabs = NULL; - } - if(mabs) { - bool b_reversed = COMPARISON_IS_EQUAL_OR_GREATER(m2.compare(m1)); - MathStructure m0((*mabs)[0]); - m0.transform(COMPARISON_EQUALS, m_zero); - EvaluationOptions eo3 = eo; - eo3.approximation = APPROXIMATION_EXACT; - eo3.isolate_x = true; - eo3.isolate_var = &x_var; - m0.eval(eo3); - bool b_exit = true; - if(m0.isZero()) { - m0 = (*mabs)[0]; - m0.replace(x_var, vargs[1]); - ComparisonResult cr1 = m0.compare(m_zero); - if(COMPARISON_IS_EQUAL_OR_LESS(cr1)) { - if(replace_abs(mbak, *mabs, false)) { - mbak.replace(x_var, vargs[3]); - mstruct.set(this, &mbak, &vargs[1], &vargs[2], &vargs[3], &m_zero, NULL); - CALCULATOR->endTemporaryStopMessages(true); - return 1; - } - } else if(COMPARISON_IS_EQUAL_OR_GREATER(cr1)) { - if(replace_abs(mbak, *mabs, true)) { - mbak.replace(x_var, vargs[3]); - mstruct.set(this, &mbak, &vargs[1], &vargs[2], &vargs[3], &m_zero, NULL); - CALCULATOR->endTemporaryStopMessages(true); - return 1; - } - } - } else if(m0.isComparison() && m0.comparisonType() == COMPARISON_EQUALS && m0[0] == x_var && m0[1].contains(x_var, true) == 0) { - CALCULATOR->endTemporaryStopMessages(); - CALCULATOR->beginTemporaryStopMessages(); - m0.setToChild(2, true); - ComparisonResult cr1 = m0.compare(b_reversed ? m2 : m1); - ComparisonResult cr2 = m0.compare(b_reversed ? m1 : m2); - if(COMPARISON_IS_EQUAL_OR_GREATER(cr1) || COMPARISON_IS_EQUAL_OR_LESS(cr2)) { - MathStructure mtest((*mabs)[0]); - if(b_reversed) mtest.replace(x_var, COMPARISON_IS_EQUAL_OR_GREATER(cr1) ? vargs[1] : vargs[2]); - else mtest.replace(x_var, COMPARISON_IS_EQUAL_OR_GREATER(cr1) ? vargs[2] : vargs[1]); - ComparisonResult cr = mtest.compare(m_zero); - if(COMPARISON_IS_EQUAL_OR_LESS(cr)) { - if(replace_abs(mbak, *mabs, false)) { - mbak.replace(x_var, vargs[3]); - mstruct.set(this, &mbak, &vargs[1], &vargs[2], &vargs[3], &m_zero, NULL); - CALCULATOR->endTemporaryStopMessages(true); - return 1; - } - } else if(COMPARISON_IS_EQUAL_OR_GREATER(cr)) { - if(replace_abs(mbak, *mabs, true)) { - mbak.replace(x_var, vargs[3]); - mstruct.set(this, &mbak, &vargs[1], &vargs[2], &vargs[3], &m_zero, NULL); - CALCULATOR->endTemporaryStopMessages(true); - return 1; - } - } - } else if(cr1 == COMPARISON_RESULT_LESS && cr2 == COMPARISON_RESULT_GREATER) { - MathStructure mtest((*mabs)[0]); - mtest.replace(x_var, vargs[1]); - ComparisonResult cr = mtest.compare(m_zero); - MathStructure m1(mbak), m2, minteg1, minteg2; - b = false; - if(COMPARISON_IS_EQUAL_OR_LESS(cr)) { - if(replace_abs(m1, *mabs, false)) b = true; - } else if(COMPARISON_IS_EQUAL_OR_GREATER(cr)) { - if(replace_abs(m1, *mabs, true)) b = true; - } - if(b) { - m1.replace(x_var, vargs[3]); - minteg1.set(this, &m1, &vargs[1], &m0, &vargs[3], &m_zero, NULL); - CALCULATOR->beginTemporaryStopMessages(); - minteg1.eval(eo); - b_exit = CALCULATOR->endTemporaryStopMessages(NULL, NULL, MESSAGE_ERROR) == 0; - b = b_exit && minteg1.containsFunction(this, true) <= 0; - } - if(b) { - mtest = (*mabs)[0]; - mtest.replace(x_var, vargs[2]); - cr = mtest.compare(m_zero); - m2 = mbak; - b = false; - if(COMPARISON_IS_EQUAL_OR_LESS(cr)) { - if(replace_abs(m2, *mabs, false)) b = true; - } else if(COMPARISON_IS_EQUAL_OR_GREATER(cr)) { - if(replace_abs(m2, *mabs, true)) b = true; - } - } - if(b) { - m2.replace(x_var, vargs[3]); - minteg2.set(this, &m2, &m0, &vargs[2], &vargs[3], &m_zero, NULL); - CALCULATOR->beginTemporaryStopMessages(); - minteg2.eval(eo); - b_exit = CALCULATOR->endTemporaryStopMessages(NULL, NULL, MESSAGE_ERROR) == 0; - b = b_exit && minteg2.containsFunction(this, true) <= 0; - } - if(b) { - CALCULATOR->endTemporaryStopMessages(true); - mstruct = minteg1; - mstruct += minteg2; - return 1; - } - } - if(b_exit) { - CALCULATOR->endTemporaryStopMessages(); - mstruct = mbak; - mstruct.replace(x_var, vargs[3]); - CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); - return -1; - } - } - } - CALCULATOR->endTemporaryStopMessages(); - if(mstruct.containsInterval() && eo.approximation == APPROXIMATION_EXACT) { - CALCULATOR->error(false, _("Unable to integrate the expression exact."), NULL); - mstruct.replace(x_var, vargs[3]); - return -1; - } - } else { - CALCULATOR->endTemporaryStopMessages(); - CALCULATOR->endTemporaryStopMessages(); - restore_intervals(mstruct, mbak, vars, eo); - } - - if(m1.isNumber() && m1.number().isReal() && m2.isNumber() && m2.number().isReal()) { - - if(eo.approximation != APPROXIMATION_EXACT) eo2.approximation = APPROXIMATION_APPROXIMATE; - - mstruct = mstruct_pre; - mstruct.eval(eo2); - - eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; - eo2.warn_about_denominators_assumed_nonzero = false; - - Number nr_begin, nr_end; - bool b_reversed = false; - if(m1.number().isGreaterThan(m2.number())) { - nr_begin = m2.number(); - nr_end = m1.number(); - b_reversed = true; - } else { - nr_begin = m1.number(); - nr_end = m2.number(); - } - if(eo.approximation != APPROXIMATION_EXACT) { - Number nr; - CALCULATOR->beginTemporaryStopMessages(); - if(romberg(mstruct, nr, x_var, eo2, nr_begin, nr_end)) { - CALCULATOR->endTemporaryStopMessages(); - if(b_reversed) nr.negate(); - mstruct = nr; - if(vargs.size() < 5 || !vargs[4].number().getBoolean()) CALCULATOR->error(false, _("Definite integral was approximated."), NULL); - return 1; - } - CALCULATOR->endTemporaryStopMessages(); - mstruct = mbak; - mstruct.replace(x_var, vargs[3]); - CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); - return -1; - } - Number nr_range(nr_end); - nr_range -= nr_begin; - MathStructure merr(mstruct); - CALCULATOR->beginTemporaryStopMessages(); - eo2.expand = false; - for(size_t i = 0; i < 4; i++) { - if(merr.containsFunction(CALCULATOR->f_diff, true) > 0 || !merr.differentiate(x_var, eo2)) { - break; - } - merr.calculatesub(eo2, eo2, true); - if(CALCULATOR->aborted() || merr.countTotalChildren() > 200) { - break; - } - } - eo2.expand = eo.expand; - CALCULATOR->endTemporaryStopMessages(); - if(merr.isZero()) { - Number nr; - if(numerical_integration(mstruct, nr, x_var, eo2, nr_begin, nr_end, 12, 0)) { - if(b_reversed) nr.negate(); - mstruct = nr; - return 1; - } - } - CALCULATOR->error(false, _("Unable to integrate the expression exact."), NULL); - mstruct = mbak; - mstruct.replace(x_var, vargs[3]); - return -1; - } - mstruct = mbak; - mstruct.replace(x_var, vargs[3]); - CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); - return -1; -} - -RombergFunction::RombergFunction() : MathFunction("romberg", 3, 6) { - Argument *arg = new Argument("", false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); - NON_COMPLEX_NUMBER_ARGUMENT(2) - NON_COMPLEX_NUMBER_ARGUMENT(3) - setCondition("\\z > \\y"); - IntegerArgument *iarg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG); - Number nr(2, 1); - iarg->setMin(&nr); - setArgumentDefinition(4, iarg); - setDefaultValue(4, "6"); - setArgumentDefinition(5, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG)); - setDefaultValue(5, "20"); - setArgumentDefinition(6, new SymbolicArgument()); - setDefaultValue(6, "undefined"); -} -int RombergFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - MathStructure minteg(vargs[0]); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - Number nr_interval; - nr_interval.setInterval(vargs[1].number(), vargs[2].number()); - UnknownVariable *var = new UnknownVariable("", format_and_print(vargs[5])); - var->setInterval(nr_interval); - MathStructure x_var(var); - minteg.replace(vargs[5], x_var); - var->destroy(); - minteg.eval(eo2); - Number nr; - eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; - eo2.warn_about_denominators_assumed_nonzero = false; - CALCULATOR->beginTemporaryStopMessages(); - if(romberg(minteg, nr, x_var, eo2, vargs[1].number(), vargs[2].number(), vargs[4].number().lintValue(), vargs[3].number().lintValue(), false)) { - CALCULATOR->endTemporaryStopMessages(); - mstruct = nr; - return 1; - } - CALCULATOR->endTemporaryStopMessages(); - CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); - return 0; -} -MonteCarloFunction::MonteCarloFunction() : MathFunction("montecarlo", 4, 5) { - Argument *arg = new Argument("", false, false); - arg->setHandleVector(true); - setArgumentDefinition(1, arg); - NON_COMPLEX_NUMBER_ARGUMENT(2) - NON_COMPLEX_NUMBER_ARGUMENT(3) - setCondition("\\z > \\y"); - setArgumentDefinition(4, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE)); - setArgumentDefinition(5, new SymbolicArgument()); - setDefaultValue(5, "undefined"); -} -int MonteCarloFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - MathStructure minteg(vargs[0]); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - Number nr_interval; - nr_interval.setInterval(vargs[1].number(), vargs[2].number()); - UnknownVariable *var = new UnknownVariable("", format_and_print(vargs[4])); - var->setInterval(nr_interval); - MathStructure x_var(var); - minteg.replace(vargs[4], x_var); - var->destroy(); - minteg.eval(eo2); - Number nr; - eo2.interval_calculation = INTERVAL_CALCULATION_NONE; - if(montecarlo(minteg, nr, x_var, eo2, vargs[1].number(), vargs[2].number(), vargs[3].number())) { - mstruct = nr; - return 1; - } - CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); - return 0; -} - -SolveFunction::SolveFunction() : MathFunction("solve", 1, 2) { - setArgumentDefinition(2, new SymbolicArgument()); - setDefaultValue(2, "undefined"); -} -bool is_comparison_structure(const MathStructure &mstruct, const MathStructure &xvar, bool *bce = NULL, bool do_bce_or = false); -bool is_comparison_structure(const MathStructure &mstruct, const MathStructure &xvar, bool *bce, bool do_bce_or) { - if(mstruct.isComparison()) { - if(bce) *bce = mstruct.comparisonType() == COMPARISON_EQUALS && mstruct[0] == xvar; - return true; - } - if(bce && do_bce_or && mstruct.isLogicalOr()) { - *bce = true; - for(size_t i = 0; i < mstruct.size(); i++) { - bool bcei = false; - if(!is_comparison_structure(mstruct[i], xvar, &bcei, false)) return false; - if(!bcei) *bce = false; - } - return true; - } - if(bce) *bce = false; - if(mstruct.isLogicalAnd()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(is_comparison_structure(mstruct[i], xvar)) return true; - } - return true; - } else if(mstruct.isLogicalOr()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(!is_comparison_structure(mstruct[i], xvar)) return false; - } - return true; - } - return false; -} - -MathStructure *solve_handle_logical_and(MathStructure &mstruct, MathStructure **mtruefor, ComparisonType ct, bool &b_partial, const MathStructure &x_var) { - MathStructure *mcondition = NULL; - for(size_t i2 = 0; i2 < mstruct.size(); ) { - if(ct == COMPARISON_EQUALS) { - if(mstruct[i2].isComparison() && ct == mstruct[i2].comparisonType() && mstruct[i2][0].contains(x_var)) { - if(mstruct[i2][0] == x_var) { - if(mstruct.size() == 2) { - if(i2 == 0) { - mstruct[1].ref(); - mcondition = &mstruct[1]; - } else { - mstruct[0].ref(); - mcondition = &mstruct[0]; - } - } else { - mcondition = new MathStructure(); - mcondition->set_nocopy(mstruct); - mcondition->delChild(i2 + 1); - } - mstruct.setToChild(i2 + 1, true); - break; - } else { - b_partial = true; - i2++; - } - } else { - i2++; - } - } else { - if(mstruct[i2].isComparison() && mstruct[i2][0].contains(x_var)) { - i2++; - } else { - mstruct[i2].ref(); - if(mcondition) { - mcondition->add_nocopy(&mstruct[i2], OPERATION_LOGICAL_AND, true); - } else { - mcondition = &mstruct[i2]; - } - mstruct.delChild(i2 + 1); - } - } - } - if(ct == COMPARISON_EQUALS) { - if(mstruct.isLogicalAnd()) { - MathStructure *mtmp = new MathStructure(); - mtmp->set_nocopy(mstruct); - if(!(*mtruefor)) { - *mtruefor = mtmp; - } else { - (*mtruefor)->add_nocopy(mtmp, OPERATION_LOGICAL_OR, true); - } - mstruct.clear(true); - } - } else { - if(mstruct.size() == 1) { - mstruct.setToChild(1, true); - if(ct != COMPARISON_EQUALS) mstruct.setProtected(); - } else if(mstruct.size() == 0) { - mstruct.clear(true); - if(!(*mtruefor)) { - *mtruefor = mcondition; - } else { - (*mtruefor)->add_nocopy(mcondition, OPERATION_LOGICAL_OR, true); - } - mcondition = NULL; - } else if(ct != COMPARISON_EQUALS) { - for(size_t i = 0; i < mstruct.size(); i++) { - mstruct[i].setProtected(); - } - } - } - return mcondition; -} - -void simplify_constant(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &y_var, const MathStructure &c_var, bool in_comparison = false, bool in_or = false, bool in_and = false); -void simplify_constant(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &y_var, const MathStructure &c_var, bool in_comparison, bool in_or, bool in_and) { - if(!in_comparison && mstruct.isComparison()) { - if(mstruct[0] == c_var) { - if(in_or) mstruct.clear(true); - else mstruct.set(1, 1, 0); - } else if(mstruct[0] == y_var) { - if(mstruct[1].contains(y_var, true) <= 0) simplify_constant(mstruct[1], x_var, y_var, c_var, true); - } else if(mstruct[0].contains(y_var, true) <= 0 && mstruct.contains(c_var, true) > 0) { - if(in_or) mstruct.clear(true); - else mstruct.set(1, 1, 0); - } - } - if(in_comparison) { - if(mstruct.contains(y_var, true) <= 0 && mstruct.contains(x_var, true) <= 0 && mstruct.contains(c_var, true) > 0) { - mstruct = c_var; - return; - } - } - if(in_comparison) { - int n_c = 0, b_cx = false; - size_t i_c = 0; - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].contains(c_var, true) > 0) { - n_c++; - i_c = i; - if(!b_cx && mstruct[i].contains(x_var, true) > 0) { - b_cx = true; - } - } - } - if(!b_cx && n_c >= 1 && (mstruct.isAddition() || mstruct.isMultiplication())) { - bool b_c = false; - for(size_t i = 0; i < mstruct.size();) { - if(mstruct[i].contains(c_var, true) > 0) { - if(b_c) { - mstruct.delChild(i + 1); - } else { - b_c = true; - mstruct[i] = c_var; - i++; - } - } else if(mstruct[i].contains(x_var, true) <= 0) { - mstruct.delChild(i + 1); - } else { - i++; - } - } - if(mstruct.size() == 1) mstruct.setToChild(1, true); - } else if(n_c == 1) { - if(b_cx) simplify_constant(mstruct[i_c], x_var, y_var, c_var, true); - else mstruct[i_c] = c_var; - } - } else { - for(size_t i = 0; i < mstruct.size(); i++) { - simplify_constant(mstruct[i], x_var, y_var, c_var, false, mstruct.isLogicalOr(), mstruct.isLogicalAnd()); - } - } -} - -extern int test_comparisons(const MathStructure &msave, MathStructure &mthis, const MathStructure &x_var, const EvaluationOptions &eo, bool sub = false, int alt = 0); -int test_equation(MathStructure &mstruct, const EvaluationOptions &eo, const MathStructure &x_var, const MathStructure &y_var, const MathStructure &x_value, const MathStructure &y_value) { - if(mstruct.isComparison() && mstruct.comparisonType() == COMPARISON_EQUALS && mstruct[0] == y_var) { - MathStructure mtest(mstruct); - mtest.replace(x_var, x_value); - MathStructure mtest2(y_var); - mtest2.transform(COMPARISON_EQUALS, y_value); - CALCULATOR->beginTemporaryStopMessages(); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - mtest.calculateFunctions(eo2); - mtest2.calculateFunctions(eo2); - int b = test_comparisons(mtest, mtest2, y_var, eo); - CALCULATOR->endTemporaryStopMessages(); - if(!b) mstruct.clear(true); - return b; - } - bool b_ret = 0; - for(size_t i = 0; i < mstruct.size(); i++) { - int b = test_equation(mstruct[i], eo, x_var, y_var, x_value, y_value); - if(b < 0) return b; - else if(b > 0) b_ret = 1; - } - return b_ret; -} - -int solve_equation(MathStructure &mstruct, const MathStructure &m_eqn, const MathStructure &y_var, const EvaluationOptions &eo, bool dsolve = false, const MathStructure &x_var = m_undefined, const MathStructure &c_var = m_undefined, const MathStructure &x_value = m_undefined, const MathStructure &y_value = m_undefined) { - - int itry = 0; - int ierror = 0; - int first_error = 0; - - Assumptions *assumptions = NULL; - bool assumptions_added = false; - AssumptionSign as = ASSUMPTION_SIGN_UNKNOWN; - AssumptionType at = ASSUMPTION_TYPE_NUMBER; - MathStructure msave; - string strueforall; - - while(true) { - - if(itry == 1) { - if(ierror == 1) { - if(!dsolve) CALCULATOR->error(true, _("No equality or inequality to solve. The entered expression to solve is not correct (ex. \"x + 5 = 3\" is correct)"), NULL); - return -1; - } else { - first_error = ierror; - msave = mstruct; - } - } - - itry++; - - if(itry == 2) { - if(y_var.isVariable() && y_var.variable()->subtype() == SUBTYPE_UNKNOWN_VARIABLE) { - assumptions = ((UnknownVariable*) y_var.variable())->assumptions(); - if(!assumptions) { - assumptions = new Assumptions(); - assumptions->setSign(CALCULATOR->defaultAssumptions()->sign()); - assumptions->setType(CALCULATOR->defaultAssumptions()->type()); - ((UnknownVariable*) y_var.variable())->setAssumptions(assumptions); - assumptions_added = true; - } - } else { - assumptions = CALCULATOR->defaultAssumptions(); - } - if(assumptions->sign() != ASSUMPTION_SIGN_UNKNOWN) { - as = assumptions->sign(); - assumptions->setSign(ASSUMPTION_SIGN_UNKNOWN); - } else { - itry++; - } - } - if(itry == 3) { - if(assumptions->type() > ASSUMPTION_TYPE_NUMBER) { - at = assumptions->type(); - assumptions->setType(ASSUMPTION_TYPE_NUMBER); - as = assumptions->sign(); - assumptions->setSign(ASSUMPTION_SIGN_UNKNOWN); - } else { - itry++; - } - } - - if(itry > 3) { - if(as != ASSUMPTION_SIGN_UNKNOWN) assumptions->setSign(as); - if(at > ASSUMPTION_TYPE_NUMBER) assumptions->setType(at); - if(assumptions_added) ((UnknownVariable*) y_var.variable())->setAssumptions(NULL); - switch(first_error) { - case 2: { - CALCULATOR->error(true, _("The comparison is true for all %s (with current assumptions)."), format_and_print(y_var).c_str(), NULL); - break; - } - case 3: { - CALCULATOR->error(true, _("No possible solution was found (with current assumptions)."), NULL); - break; - } - case 4: { - CALCULATOR->error(true, _("Was unable to completely isolate %s."), format_and_print(y_var).c_str(), NULL); - break; - } - case 7: { - CALCULATOR->error(false, _("The comparison is true for all %s if %s."), format_and_print(y_var).c_str(), strueforall.c_str(), NULL); - break; - } - default: { - CALCULATOR->error(true, _("Was unable to isolate %s."), format_and_print(y_var).c_str(), NULL); - break; - } - } - mstruct = msave; - return -1; - } - - ComparisonType ct = COMPARISON_EQUALS; - - bool b = false; - bool b_partial = false; - - if(m_eqn.isComparison()) { - ct = m_eqn.comparisonType(); - mstruct = m_eqn; - b = true; - } else if(m_eqn.isLogicalAnd() && m_eqn.size() > 0 && m_eqn[0].isComparison()) { - ct = m_eqn[0].comparisonType(); - for(size_t i = 0; i < m_eqn.size(); i++) { - if(m_eqn[i].isComparison() && m_eqn[i].contains(y_var, true) > 0) { - ct = m_eqn[i].comparisonType(); - break; - } - } - mstruct = m_eqn; - b = true; - } else if(m_eqn.isLogicalOr() && m_eqn.size() > 0 && m_eqn[0].isComparison()) { - ct = m_eqn[0].comparisonType(); - mstruct = m_eqn; - b = true; - } else if(m_eqn.isLogicalOr() && m_eqn.size() > 0 && m_eqn[0].isLogicalAnd() && m_eqn[0].size() > 0 && m_eqn[0][0].isComparison()) { - ct = m_eqn[0][0].comparisonType(); - for(size_t i = 0; i < m_eqn[0].size(); i++) { - if(m_eqn[0][i].isComparison() && m_eqn[0][i].contains(y_var, true) > 0) { - ct = m_eqn[0][i].comparisonType(); - break; - } - } - mstruct = m_eqn; - b = true; - } else if(m_eqn.isVariable() && m_eqn.variable()->isKnown() && (eo.approximation != APPROXIMATION_EXACT || !m_eqn.variable()->isApproximate()) && ((KnownVariable*) m_eqn.variable())->get().isComparison()) { - mstruct = ((KnownVariable*) m_eqn.variable())->get(); - mstruct.unformat(); - ct = m_eqn.comparisonType(); - b = true; - } else { - EvaluationOptions eo2 = eo; - eo2.test_comparisons = false; - eo2.assume_denominators_nonzero = false; - eo2.isolate_x = false; - mstruct = m_eqn; - mstruct.eval(eo2); - if(mstruct.isComparison()) { - ct = mstruct.comparisonType(); - b = true; - } else if(mstruct.isLogicalAnd() && mstruct.size() > 0 && mstruct[0].isComparison()) { - ct = mstruct[0].comparisonType(); - b = true; - } else if(mstruct.isLogicalOr() && mstruct.size() > 0 && mstruct[0].isComparison()) { - ct = mstruct[0].comparisonType(); - b = true; - } else if(mstruct.isLogicalOr() && mstruct.size() > 0 && mstruct[0].isLogicalAnd() && mstruct[0].size() > 0 && mstruct[0][0].isComparison()) { - ct = mstruct[0][0].comparisonType(); - b = true; - } - } - - if(!b) { - ierror = 1; - continue; - } - - EvaluationOptions eo2 = eo; - eo2.isolate_var = &y_var; - eo2.isolate_x = true; - eo2.test_comparisons = true; - mstruct.eval(eo2); - if(dsolve) { - if(x_value.isUndefined() || y_value.isUndefined()) { - simplify_constant(mstruct, x_var, y_var, c_var); - mstruct.eval(eo2); - } else { - int test_r = test_equation(mstruct, eo2, x_var, y_var, x_value, y_value); - if(test_r < 0) { - ierror = 8; - continue; - } else if(test_r > 0) { - mstruct.eval(eo2); - } - } - } - - if(mstruct.isOne()) { - ierror = 2; - continue; - } else if(mstruct.isZero()) { - ierror = 3; - continue; - } - - if(mstruct.isComparison()) { - if((ct == COMPARISON_EQUALS && mstruct.comparisonType() != COMPARISON_EQUALS) || !mstruct.contains(y_var)) { - if(itry == 1) { - strueforall = format_and_print(mstruct); - } - ierror = 7; - continue; - } else if(ct == COMPARISON_EQUALS && mstruct[0] != y_var) { - ierror = 4; - continue; - } - if(ct == COMPARISON_EQUALS) { - mstruct.setToChild(2, true); - } else { - mstruct.setProtected(); - } - if(itry > 1) { - assumptions->setSign(as); - if(itry == 2) { - CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL); - } else if(itry == 3) { - assumptions->setType(at); - CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed type and sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL); - } - if(assumptions_added) ((UnknownVariable*) y_var.variable())->setAssumptions(NULL); - } - return 1; - } else if(mstruct.isLogicalAnd()) { - MathStructure *mtruefor = NULL; - bool b_partial; - MathStructure mcopy(mstruct); - MathStructure *mcondition = solve_handle_logical_and(mstruct, &mtruefor, ct, b_partial, y_var); - if((!mstruct.isComparison() && !mstruct.isLogicalAnd()) || (ct == COMPARISON_EQUALS && (!mstruct.isComparison() || mstruct.comparisonType() != COMPARISON_EQUALS || mstruct[0] != y_var)) || !mstruct.contains(y_var)) { - if(mtruefor) delete mtruefor; - if(mcondition) delete mcondition; - if(b_partial) { - ierror = 4; - } else { - ierror = 5; - } - mstruct = mcopy; - continue; - } - if(itry > 1) { - assumptions->setSign(as); - if(itry == 2) { - CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL); - } else if(itry == 3) { - assumptions->setType(at); - CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed type and sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL); - } - if(assumptions_added) ((UnknownVariable*) y_var.variable())->setAssumptions(NULL); - } - if(mcondition) { - CALCULATOR->error(false, _("The solution requires that %s."), format_and_print(*mcondition).c_str(), NULL); - delete mcondition; - } - if(mtruefor) { - CALCULATOR->error(false, _("The comparison is true for all %s if %s."), format_and_print(y_var).c_str(), format_and_print(*mtruefor).c_str(), NULL); - delete mtruefor; - } - if(ct == COMPARISON_EQUALS) mstruct.setToChild(2, true); - return 1; - } else if(mstruct.isLogicalOr()) { - MathStructure mcopy(mstruct); - MathStructure *mtruefor = NULL; - vector mconditions; - for(size_t i = 0; i < mstruct.size(); ) { - MathStructure *mcondition = NULL; - bool b_and = false; - if(mstruct[i].isLogicalAnd()) { - mcondition = solve_handle_logical_and(mstruct[i], &mtruefor, ct, b_partial, y_var); - b_and = true; - } - if(!mstruct[i].isZero()) { - for(size_t i2 = 0; i2 < i; i2++) { - if(mstruct[i2] == mstruct[i]) { - mstruct[i].clear(); - if(mcondition && mconditions[i2]) { - mconditions[i2]->add_nocopy(mcondition, OPERATION_LOGICAL_OR, true); - } - break; - } - } - } - bool b_del = false; - if((!mstruct[i].isComparison() && !mstruct[i].isLogicalAnd()) || (ct == COMPARISON_EQUALS && (!mstruct[i].isComparison() || mstruct[i].comparisonType() != COMPARISON_EQUALS)) || !mstruct[i].contains(y_var)) { - b_del = true; - } else if(ct == COMPARISON_EQUALS && mstruct[i][0] != y_var) { - b_partial = true; - b_del = true; - } - if(b_del) { - if(!mstruct[i].isZero()) { - mstruct[i].ref(); - if(!mtruefor) { - mtruefor = &mstruct[i]; - } else { - mtruefor->add_nocopy(&mstruct[i], OPERATION_LOGICAL_OR, true); - } - } - mstruct.delChild(i + 1); - } else { - mconditions.push_back(mcondition); - if(!b_and && ct != COMPARISON_EQUALS) mstruct[i].setProtected(); - i++; - } - } - if(ct == COMPARISON_EQUALS) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isComparison() && mstruct[i].comparisonType() == ct) mstruct[i].setToChild(2, true); - } - } - if(mstruct.size() == 1) { - mstruct.setToChild(1, true); - } else if(mstruct.size() == 0) { - if(mtruefor) delete mtruefor; - if(b_partial) ierror = 4; - else ierror = 5; - mstruct = mcopy; - continue; - } else { - mstruct.setType(STRUCT_VECTOR); - } - if(itry > 1) { - assumptions->setSign(as); - if(itry == 2) { - CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL); - } else if(itry == 3) { - assumptions->setType(at); - CALCULATOR->error(false, _("Was unable to isolate %s with the current assumptions. The assumed type and sign was therefore temporarily set as unknown."), format_and_print(y_var).c_str(), NULL); - } - if(assumptions_added) ((UnknownVariable*) y_var.variable())->setAssumptions(NULL); - } - - if(mconditions.size() == 1) { - if(mconditions[0]) { - CALCULATOR->error(false, _("The solution requires that %s."), format_and_print(mconditions[0]).c_str(), NULL); - delete mconditions[0]; - } - } else { - string sconditions; - for(size_t i = 0; i < mconditions.size(); i++) { - if(mconditions[i]) { - CALCULATOR->error(false, _("Solution %s requires that %s."), i2s(i + 1).c_str(), format_and_print(mconditions[i]).c_str(), NULL); - delete mconditions[i]; - } - } - } - if(mtruefor) { - CALCULATOR->error(false, _("The comparison is true for all %s if %s."), format_and_print(y_var).c_str(), format_and_print(*mtruefor).c_str(), NULL); - delete mtruefor; - } - return 1; - } else { - ierror = 6; - } - } - return -1; - -} - -int SolveFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - return solve_equation(mstruct, vargs[0], vargs[1], eo); -} - -SolveMultipleFunction::SolveMultipleFunction() : MathFunction("multisolve", 2) { - setArgumentDefinition(1, new VectorArgument()); - VectorArgument *arg = new VectorArgument(); - arg->addArgument(new SymbolicArgument()); - arg->setReoccuringArguments(true); - setArgumentDefinition(2, arg); - setCondition("dimension(\\x) = dimension(\\y)"); -} -int SolveMultipleFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - - mstruct.clearVector(); - - if(vargs[1].size() < 1) return 1; - - vector eleft; - eleft.resize(vargs[0].size(), true); - vector eorder; - bool b = false; - for(size_t i = 0; i < vargs[1].size(); i++) { - b = false; - for(size_t i2 = 0; i2 < vargs[0].size(); i2++) { - if(eleft[i2] && vargs[0][i2].contains(vargs[1][i], true)) { - eorder.push_back(i2); - eleft[i2] = false; - b = true; - break; - } - } - if(!b) { - eorder.clear(); - for(size_t i2 = 0; i2 < vargs[0].size(); i2++) { - eorder.push_back(i2); - } - break; - } - } - - for(size_t i = 0; i < eorder.size(); i++) { - MathStructure msolve(vargs[0][eorder[i]]); - EvaluationOptions eo2 = eo; - eo2.isolate_var = &vargs[1][i]; - for(size_t i2 = 0; i2 < i; i2++) { - msolve.replace(vargs[1][i2], mstruct[i2]); - } - msolve.eval(eo2); - - if(msolve.isComparison()) { - if(msolve[0] != vargs[1][i]) { - if(!b) { - CALCULATOR->error(true, _("Unable to isolate %s.\n\nYou might need to place the equations and variables in an appropriate order so that each equation at least contains the corresponding variable (if automatic reordering failed)."), format_and_print(vargs[1][i]).c_str(), NULL); - } else { - CALCULATOR->error(true, _("Unable to isolate %s."), format_and_print(vargs[1][i]).c_str(), NULL); - } - return 0; - } else { - if(msolve.comparisonType() == COMPARISON_EQUALS) { - mstruct.addChild(msolve[1]); - } else { - CALCULATOR->error(true, _("Inequalities is not allowed in %s()."), preferredName().name.c_str(), NULL); - return 0; - } - } - } else if(msolve.isLogicalOr()) { - for(size_t i2 = 0; i2 < msolve.size(); i2++) { - if(!msolve[i2].isComparison() || msolve[i2].comparisonType() != COMPARISON_EQUALS || msolve[i2][0] != vargs[1][i]) { - CALCULATOR->error(true, _("Unable to isolate %s."), format_and_print(vargs[1][i]).c_str(), NULL); - return 0; - } else { - msolve[i2].setToChild(2, true); - } - } - msolve.setType(STRUCT_VECTOR); - mstruct.addChild(msolve); - } else { - CALCULATOR->error(true, _("Unable to isolate %s."), format_and_print(vargs[1][i]).c_str(), NULL); - return 0; - } - for(size_t i2 = 0; i2 < i; i2++) { - for(size_t i3 = 0; i3 <= i; i3++) { - if(i2 != i3) { - mstruct[i2].replace(vargs[1][i3], mstruct[i3]); - } - } - } - } - - return 1; - -} - -MathStructure *find_deqn(MathStructure &mstruct); -MathStructure *find_deqn(MathStructure &mstruct) { - if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_diff) return &mstruct; - for(size_t i = 0; i < mstruct.size(); i++) { - MathStructure *m = find_deqn(mstruct[i]); - if(m) return m; - } - return NULL; -} - -bool contains_ignore_diff(const MathStructure &m, const MathStructure &mstruct, const MathStructure &mdiff); -bool contains_ignore_diff(const MathStructure &m, const MathStructure &mstruct, const MathStructure &mdiff) { - if(m.equals(mstruct)) return true; - if(m.equals(mdiff)) return false; - for(size_t i = 0; i < m.size(); i++) { - if(contains_ignore_diff(m[i], mstruct, mdiff)) return true; - } - if(m.isVariable() && m.variable()->isKnown()) { - return contains_ignore_diff(((KnownVariable*) m.variable())->get(), mstruct, mdiff); - } else if(m.isVariable()) { - if(mstruct.isNumber() || !m.representsNumber()) return true; - } else if(m.isAborted()) { - return true; - } - return false; -} - -void add_C(MathStructure &m_eqn, const MathStructure &m_x, const MathStructure &m_y, const MathStructure &x_value, const MathStructure &y_value) { - if(!y_value.isUndefined() && !x_value.isUndefined()) { - MathStructure m_c(m_eqn); - m_c.replace(m_x, x_value); - m_c.replace(m_y, y_value); - m_c.setType(STRUCT_ADDITION); - m_c[1].negate(); - m_c.childUpdated(2); - m_eqn[1] += m_c; - } else { - m_eqn[1] += CALCULATOR->v_C; - } - m_eqn.childrenUpdated(); -} - -bool dsolve(MathStructure &m_eqn, const EvaluationOptions &eo, const MathStructure &m_diff, const MathStructure &y_value, const MathStructure &x_value) { - MathStructure m_y(m_diff[0]), m_x(m_diff[1]); - bool b = false; - if(m_eqn[0] == m_diff) { - if(m_eqn[1].containsRepresentativeOf(m_y, true, true) == 0) { - // y'=f(x) - MathStructure m_fx(m_eqn[1]); - if(m_fx.integrate(m_x, eo, true, false) > 0) { - m_eqn[0] = m_y; - m_eqn[1] = m_fx; - b = true; - } - } else if(m_eqn[1].containsRepresentativeOf(m_x, true, true) == 0) { - MathStructure m_fy(m_eqn[1]); - m_fy.inverse(); - if(m_fy.integrate(m_y, eo, true, false) > 0) { - m_eqn[0] = m_fy; - m_eqn[1] = m_x; - b = true; - } - } else if(m_eqn[1].isMultiplication() && m_eqn[1].size() >= 2) { - b = true; - MathStructure m_fx(1, 1, 0), m_fy(1, 1, 0); - for(size_t i = 0; i < m_eqn[1].size(); i++) { - if(m_eqn[1][i].containsRepresentativeOf(m_y, true, true) != 0) { - if(m_eqn[1][i].containsRepresentativeOf(m_x, true, true) != 0) { - b = false; - break; - } - if(m_fy.isOne()) m_fy = m_eqn[1][i]; - else m_fy.multiply(m_eqn[1][i], true); - } else { - if(m_fx.isOne()) m_fx = m_eqn[1][i]; - else m_fx.multiply(m_eqn[1][i], true); - } - } - if(b) { - // y'=f(x)*f(y) - m_fy.inverse(); - if(m_fy.integrate(m_y, eo, true, false) > 0 && m_fx.integrate(m_x, eo, true, false) > 0) { - m_eqn[0] = m_fy; - m_eqn[1] = m_fx; - } else { - b = false; - } - } - } else { - MathStructure mfactor(m_eqn); - mfactor[1].factorize(eo, false, 0, 0, false, false, NULL, m_x); - if(mfactor[1].isMultiplication() && mfactor[1].size() >= 2) { - mfactor.childUpdated(2); - if(dsolve(mfactor, eo, m_diff, y_value, x_value)) { - m_eqn = mfactor; - return 1; - } - } - if(m_eqn[1].isAddition()) { - MathStructure m_left; - MathStructure m_muly; - MathStructure m_mul_exp; - MathStructure m_exp; - b = true; - for(size_t i = 0; i < m_eqn[1].size(); i++) { - if(m_eqn[1][i] == m_y) { - if(m_muly.isZero()) m_muly = m_one; - else m_muly.add(m_one, true); - } else if(m_eqn[1][i].containsRepresentativeOf(m_y, true, true) != 0) { - if(m_left.isZero() && m_eqn[1][i].isPower() && m_eqn[1][i][0] == m_y && (m_mul_exp.isZero() || m_eqn[1][i][1] == m_exp)) { - if(m_mul_exp.isZero()) { - m_exp = m_eqn[1][i][1]; - m_mul_exp = m_one; - } else { - m_mul_exp.add(m_one, true); - } - } else if(m_eqn[1][i].isMultiplication()) { - size_t i_my = 0; - bool b2 = false, b2_exp = false; - for(size_t i2 = 0; i2 < m_eqn[1][i].size(); i2++) { - if(!b2 && m_eqn[1][i][i2] == m_y) { - i_my = i2; - b2 = true; - } else if(!b2 && m_left.isZero() && m_eqn[1][i][i2].isPower() && m_eqn[1][i][i2][0] == m_y && (m_mul_exp.isZero() || m_eqn[1][i][i2][1] == m_exp)) { - i_my = i2; - b2 = true; - b2_exp = true; - } else if(m_eqn[1][i][i2].containsRepresentativeOf(m_y, true, true) != 0) { - b2 = false; - break; - } - } - if(b2) { - MathStructure m_a(m_eqn[1][i]); - m_a.delChild(i_my + 1, true); - if(b2_exp) { - if(m_mul_exp.isZero()) { - m_exp = m_eqn[1][i][i_my][1]; - m_mul_exp = m_a; - } else { - m_mul_exp.add(m_a, true); - } - } else { - if(m_muly.isZero()) m_muly = m_a; - else m_muly.add(m_a, true); - } - } else { - b = false; - break; - } - } else { - b = false; - break; - } - } else { - if(!m_mul_exp.isZero()) { - b = false; - break; - } - if(m_left.isZero()) m_left = m_eqn[1][i]; - else m_left.add(m_eqn[1][i], true); - } - } - if(b && !m_muly.isZero()) { - if(!m_mul_exp.isZero()) { - if(m_exp.isOne() || !m_left.isZero()) return false; - // y' = f(x)*y+g(x)*y^c - b = false; - m_muly.calculateNegate(eo); - MathStructure m_y1_integ(m_muly); - if(m_y1_integ.integrate(m_x, eo, true, false) > 0) { - m_exp.negate(); - m_exp += m_one; - MathStructure m_y1_exp(m_exp); - m_y1_exp *= m_y1_integ; - m_y1_exp.transform(STRUCT_POWER, CALCULATOR->v_e); - m_y1_exp.swapChildren(1, 2); - MathStructure m_y1_exp_integ(m_y1_exp); - m_y1_exp_integ *= m_mul_exp; - if(m_y1_exp_integ.integrate(m_x, eo, true, false) > 0) { - m_eqn[1] = m_exp; - m_eqn[1] *= m_y1_exp_integ; - m_eqn[0] = m_y; - m_eqn[0] ^= m_exp; - m_eqn[0] *= m_y1_exp; - add_C(m_eqn, m_x, m_y, x_value, y_value); - m_eqn[0].delChild(m_eqn[0].size()); - m_eqn[1] /= m_y1_exp; - m_eqn.childrenUpdated(); - return 1; - } - } - } else if(m_left.isZero()) { - // y'=f(x)*y+g(x)*y - MathStructure mtest(m_eqn); - MathStructure m_fy(m_y); - m_fy.inverse(); - MathStructure m_fx(m_muly); - if(m_fy.integrate(m_y, eo, true, false) > 0 && m_fx.integrate(m_x, eo, true, false) > 0) { - m_eqn[0] = m_fy; - m_eqn[1] = m_fx; - b = true; - } - } else { - // y'=f(x)*y+g(x) - MathStructure integ_fac(m_muly); - integ_fac.negate(); - if(integ_fac.integrate(m_x, eo, true, false) > 0) { - UnknownVariable *var = new UnknownVariable("", "u"); - Assumptions *ass = new Assumptions(); - if(false) { - ass->setType(ASSUMPTION_TYPE_REAL); - } - var->setAssumptions(ass); - MathStructure m_u(var); - m_u.inverse(); - if(m_u.integrate(var, eo, false, false) > 0) { - MathStructure m_eqn2(integ_fac); - m_eqn2.transform(COMPARISON_EQUALS, m_u); - m_eqn2.isolate_x(eo, var); - if(m_eqn2.isComparison() && m_eqn2.comparisonType() == COMPARISON_EQUALS && m_eqn2[0] == var) { - integ_fac = m_eqn2[1]; - MathStructure m_fx(m_left); - m_fx *= integ_fac; - if(m_fx.integrate(m_x, eo, true, false) > 0) { - m_eqn[0] = m_y; - m_eqn[0] *= integ_fac; - m_eqn[1] = m_fx; - add_C(m_eqn, m_x, m_y, x_value, y_value); - m_eqn[0] = m_y; - m_eqn[1] /= integ_fac; - m_eqn.childrenUpdated(); - return 1; - } - } else if(m_eqn2.isLogicalOr() && m_eqn2.size() >= 2) { - b = true; - for(size_t i = 0; i < m_eqn2.size(); i++) { - if(!m_eqn2[i].isComparison() || m_eqn2[i].comparisonType() != COMPARISON_EQUALS || m_eqn2[i][0] != var) { - b = false; - break; - } - } - if(b) { - MathStructure m_eqn_new; - m_eqn_new.setType(STRUCT_LOGICAL_OR); - for(size_t i = 0; i < m_eqn2.size(); i++) { - integ_fac = m_eqn2[i][1]; - MathStructure m_fx(m_left); - m_fx *= integ_fac; - if(m_fx.integrate(m_x, eo, true, false) > 0) { - MathStructure m_fy(m_y); - m_fy *= integ_fac; - m_eqn_new.addChild(m_fy); - m_eqn_new.last().transform(COMPARISON_EQUALS, m_fx); - add_C(m_eqn_new.last(), m_x, m_y, x_value, y_value); - m_eqn_new.last()[0] = m_y; - m_eqn_new.last()[1] /= integ_fac; - m_eqn_new.last().childrenUpdated(); - m_eqn_new.childUpdated(m_eqn_new.size()); - } else { - b = false; - break; - } - } - if(b) { - m_eqn_new.childrenUpdated(); - m_eqn = m_eqn_new; - return 1; - } - } - } - } - var->destroy(); - } - } - } else { - b = false; - } - } - } - if(b) { - add_C(m_eqn, m_x, m_y, x_value, y_value); - return 1; - } - } - return false; -} - -DSolveFunction::DSolveFunction() : MathFunction("dsolve", 1, 3) { - setDefaultValue(2, "undefined"); - setDefaultValue(3, "0"); -} -int DSolveFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - MathStructure m_eqn(vargs[0]); - EvaluationOptions eo2 = eo; - eo2.isolate_x = false; - eo2.protected_function = CALCULATOR->f_diff; - m_eqn.eval(eo2); - MathStructure *m_diff_p = NULL; - if(m_eqn.isLogicalAnd()) { - for(size_t i = 0; i < m_eqn.size(); i++) { - if(m_eqn[i].isComparison() && m_eqn.comparisonType() == COMPARISON_EQUALS) { - m_diff_p = find_deqn(m_eqn[i]); - if(m_diff_p) break; - } - } - } else if(m_eqn.isComparison() && m_eqn.comparisonType() == COMPARISON_EQUALS) { - m_diff_p = find_deqn(m_eqn); - } - if(!m_diff_p) { - CALCULATOR->error(true, _("No differential equation found."), NULL); - mstruct = m_eqn; return -1; - } - MathStructure m_diff(*m_diff_p); - if(m_diff.size() < 3 || (!m_diff[0].isSymbolic() && !m_diff[0].isVariable()) || (!m_diff[1].isSymbolic() && !m_diff[1].isVariable()) || !m_diff[2].isInteger() || !m_diff[2].number().isPositive() || !m_diff[2].number().isLessThanOrEqualTo(10)) { - CALCULATOR->error(true, _("No differential equation found."), NULL); - mstruct = m_eqn; return -1; - } - if(m_diff[2].number().intValue() != 1) { - CALCULATOR->error(true, _("Unable to solve differential equation."), NULL); - mstruct = m_eqn; - return -1; - } - m_eqn.isolate_x(eo2, m_diff); - mstruct = m_eqn; - if(eo.approximation == APPROXIMATION_TRY_EXACT) eo2.approximation = APPROXIMATION_EXACT; - if(m_eqn.isLogicalAnd()) { - for(size_t i = 0; i < m_eqn.size(); i++) { - if(m_eqn[i].isComparison() && m_eqn[i].comparisonType() == COMPARISON_EQUALS && m_eqn[i][0] == m_diff) { - dsolve(m_eqn[i], eo2, m_diff, vargs[1], vargs[2]); - } - } - } else if(m_eqn.isLogicalOr()) { - for(size_t i = 0; i < m_eqn.size(); i++) { - if(m_eqn[i].isComparison() && m_eqn[i].comparisonType() == COMPARISON_EQUALS && m_eqn[i][0] == m_diff) { - dsolve(m_eqn[i], eo2, m_diff, vargs[1], vargs[2]); - } else if(m_eqn[i].isLogicalAnd()) { - for(size_t i2 = 0; i2 < m_eqn[i].size(); i2++) { - if(m_eqn[i][i2].isComparison() && m_eqn[i][i2].comparisonType() == COMPARISON_EQUALS && m_eqn[i][i2][0] == m_diff) { - dsolve(m_eqn[i][i2], eo2, m_diff, vargs[1], vargs[2]); - } - } - } - } - } else if(m_eqn.isComparison() && m_eqn.comparisonType() == COMPARISON_EQUALS && m_eqn[0] == m_diff) { - dsolve(m_eqn, eo2, m_diff, vargs[1], vargs[2]); - } - if(m_eqn.contains(m_diff)) { - CALCULATOR->error(true, _("Unable to solve differential equation."), NULL); - return -1; - } - m_eqn.calculatesub(eo2, eo2, true); - MathStructure msolve(m_eqn); - if(solve_equation(msolve, m_eqn, m_diff[0], eo, true, m_diff[1], MathStructure(CALCULATOR->v_C), vargs[2], vargs[1]) <= 0) { - CALCULATOR->error(true, _("Unable to solve differential equation."), NULL); - return -1; - } - mstruct = msolve; - return 1; -} - -LimitFunction::LimitFunction() : MathFunction("limit", 2, 4) { - NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); - arg->setComplexAllowed(false); - arg->setHandleVector(true); - setArgumentDefinition(2, arg); - setArgumentDefinition(3, new SymbolicArgument()); - setDefaultValue(3, "x"); - IntegerArgument *iarg = new IntegerArgument(); - iarg->setMin(&nr_minus_one); - iarg->setMax(&nr_one); - setArgumentDefinition(4, iarg); - setDefaultValue(4, "0"); -} -int LimitFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - if(vargs[1].isVector()) return 0; - mstruct = vargs[0]; - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_EXACT; - if(mstruct.calculateLimit(vargs[2], vargs[1], eo2, vargs[3].number().intValue())) return 1; - CALCULATOR->error(true, _("Unable to find limit."), NULL); - return -1; -} - -PlotFunction::PlotFunction() : MathFunction("plot", 1, 6) { - NumberArgument *arg = new NumberArgument(); - arg->setComplexAllowed(false); - arg->setHandleVector(false); - setArgumentDefinition(2, arg); - setDefaultValue(2, "0"); - arg = new NumberArgument(); - arg->setHandleVector(false); - arg->setComplexAllowed(false); - setArgumentDefinition(3, arg); - setDefaultValue(3, "10"); - setDefaultValue(4, "1001"); - setArgumentDefinition(5, new SymbolicArgument()); - setDefaultValue(5, "x"); - setArgumentDefinition(6, new BooleanArgument()); - setDefaultValue(6, "0"); - setCondition("\\y < \\z"); -} -int PlotFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { - - EvaluationOptions eo2; - eo2.parse_options = eo.parse_options; - eo2.approximation = APPROXIMATION_APPROXIMATE; - eo2.parse_options.read_precision = DONT_READ_PRECISION; - eo2.interval_calculation = INTERVAL_CALCULATION_NONE; - bool use_step_size = vargs[5].number().getBoolean(); - mstruct = vargs[0]; - CALCULATOR->beginTemporaryStopIntervalArithmetic(); - if(!mstruct.contains(vargs[4], true)) { - mstruct.eval(eo2); - } else { - eo2.calculate_functions = false; - eo2.expand = false; - CALCULATOR->beginTemporaryStopMessages(); - mstruct.eval(eo2); - int im = 0; - if(CALCULATOR->endTemporaryStopMessages(NULL, &im) > 0 || im > 0) mstruct = vargs[0]; - eo2.calculate_functions = eo.calculate_functions; - eo2.expand = eo.expand; - } - CALCULATOR->endTemporaryStopIntervalArithmetic(); - vector x_vectors, y_vectors; - vector dpds; - if(mstruct.isMatrix() && mstruct.columns() == 2) { - MathStructure x_vector, y_vector; - mstruct.columnToVector(1, x_vector); - mstruct.columnToVector(2, y_vector); - y_vectors.push_back(y_vector); - x_vectors.push_back(x_vector); - PlotDataParameters *dpd = new PlotDataParameters; - dpd->title = _("Matrix"); - dpds.push_back(dpd); - } else if(mstruct.isVector()) { - int matrix_index = 1, vector_index = 1; - if(mstruct.size() > 0 && (mstruct[0].isVector() || mstruct[0].contains(vargs[4], false, true, true))) { - for(size_t i = 0; i < mstruct.size() && !CALCULATOR->aborted(); i++) { - MathStructure x_vector; - if(mstruct[i].isMatrix() && mstruct[i].columns() == 2) { - MathStructure y_vector; - mstruct[i].columnToVector(1, x_vector); - mstruct[i].columnToVector(2, y_vector); - y_vectors.push_back(y_vector); - x_vectors.push_back(x_vector); - PlotDataParameters *dpd = new PlotDataParameters; - dpd->title = _("Matrix"); - if(matrix_index > 1) { - dpd->title += " "; - dpd->title += i2s(matrix_index); - } - matrix_index++; - dpds.push_back(dpd); - } else if(mstruct[i].isVector()) { - y_vectors.push_back(mstruct[i]); - x_vectors.push_back(x_vector); - PlotDataParameters *dpd = new PlotDataParameters; - dpd->title = _("Vector"); - if(vector_index > 1) { - dpd->title += " "; - dpd->title += i2s(vector_index); - } - vector_index++; - dpds.push_back(dpd); - } else { - MathStructure y_vector; - if(use_step_size) { - CALCULATOR->beginTemporaryStopMessages(); - CALCULATOR->beginTemporaryStopIntervalArithmetic(); - y_vector.set(mstruct[i].generateVector(vargs[4], vargs[1], vargs[2], vargs[3], &x_vector, eo2)); - CALCULATOR->endTemporaryStopIntervalArithmetic(); - CALCULATOR->endTemporaryStopMessages(); - if(y_vector.size() == 0) CALCULATOR->error(true, _("Unable to generate plot data with current min, max and step size."), NULL); - } else if(!vargs[3].isInteger() || !vargs[3].representsPositive()) { - CALCULATOR->error(true, _("Sampling rate must be a positive integer."), NULL); - } else { - bool overflow = false; - int steps = vargs[3].number().intValue(&overflow); - CALCULATOR->beginTemporaryStopMessages(); - CALCULATOR->beginTemporaryStopIntervalArithmetic(); - if(steps <= 1000000 && !overflow) y_vector.set(mstruct[i].generateVector(vargs[4], vargs[1], vargs[2], steps, &x_vector, eo2)); - CALCULATOR->endTemporaryStopIntervalArithmetic(); - CALCULATOR->endTemporaryStopMessages(); - if(y_vector.size() == 0) CALCULATOR->error(true, _("Unable to generate plot data with current min, max and sampling rate."), NULL); - } - if(CALCULATOR->aborted()) { - mstruct.clear(); - return 1; - } - if(y_vector.size() > 0) { - x_vectors.push_back(x_vector); - y_vectors.push_back(y_vector); - PlotDataParameters *dpd = new PlotDataParameters; - MathStructure mprint; - if(vargs[0].isVector() && vargs[0].size() == mstruct.size()) mprint = vargs[0][i]; - else mprint = mstruct[i]; - dpd->title = format_and_print(mprint); - dpd->test_continuous = true; - dpds.push_back(dpd); - } - } - } - } else { - MathStructure x_vector; - y_vectors.push_back(mstruct); - x_vectors.push_back(x_vector); - PlotDataParameters *dpd = new PlotDataParameters; - dpd->title = _("Vector"); - dpds.push_back(dpd); - } - } else { - MathStructure x_vector, y_vector; - if(use_step_size) { - CALCULATOR->beginTemporaryStopMessages(); - CALCULATOR->beginTemporaryStopIntervalArithmetic(); - y_vector.set(mstruct.generateVector(vargs[4], vargs[1], vargs[2], vargs[3], &x_vector, eo2)); - CALCULATOR->endTemporaryStopIntervalArithmetic(); - CALCULATOR->endTemporaryStopMessages(); - if(y_vector.size() == 0) CALCULATOR->error(true, _("Unable to generate plot data with current min, max and step size."), NULL); - } else if(!vargs[3].isInteger() || !vargs[3].representsPositive()) { - CALCULATOR->error(true, _("Sampling rate must be a positive integer."), NULL); - } else { - bool overflow = false; - int steps = vargs[3].number().intValue(&overflow); - CALCULATOR->beginTemporaryStopMessages(); - CALCULATOR->beginTemporaryStopIntervalArithmetic(); - if(steps <= 1000000 && !overflow) y_vector.set(mstruct.generateVector(vargs[4], vargs[1], vargs[2], steps, &x_vector, eo2)); - CALCULATOR->endTemporaryStopIntervalArithmetic(); - CALCULATOR->endTemporaryStopMessages(); - if(y_vector.size() == 0) CALCULATOR->error(true, _("Unable to generate plot data with current min, max and sampling rate."), NULL); - } - if(CALCULATOR->aborted()) { - mstruct.clear(); - return 1; - } - if(y_vector.size() > 0) { - x_vectors.push_back(x_vector); - y_vectors.push_back(y_vector); - PlotDataParameters *dpd = new PlotDataParameters; - MathStructure mprint(vargs[0]); - dpd->title = format_and_print(mprint); - dpd->test_continuous = true; - dpds.push_back(dpd); - } - } - if(x_vectors.size() > 0 && !CALCULATOR->aborted()) { - PlotParameters param; - CALCULATOR->plotVectors(¶m, y_vectors, x_vectors, dpds, false, 0); - for(size_t i = 0; i < dpds.size(); i++) { - if(dpds[i]) delete dpds[i]; - } - } - mstruct.clear(); - return 1; - -} - diff -Nru libqalculate-3.6.0/libqalculate/BuiltinFunctions-combinatorics.cc libqalculate-3.7.0/libqalculate/BuiltinFunctions-combinatorics.cc --- libqalculate-3.6.0/libqalculate/BuiltinFunctions-combinatorics.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/BuiltinFunctions-combinatorics.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,114 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Number.h" +#include "Calculator.h" +#include "Variable.h" +#include "Unit.h" + +#include +#include +#include +#include + +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +#define FR_FUNCTION(FUNC) Number nr(vargs[0].number()); if(!nr.FUNC() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;} +#define FR_FUNCTION_2(FUNC) Number nr(vargs[0].number()); if(!nr.FUNC(vargs[1].number()) || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate() && !vargs[1].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex() && !vargs[1].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity() && !vargs[1].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;} + +FactorialFunction::FactorialFunction() : MathFunction("factorial", 1) { + setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONNEGATIVE, true, false, INTEGER_TYPE_SLONG)); +} +int FactorialFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION(factorial) +} +bool FactorialFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool FactorialFunction::representsNegative(const MathStructure&, bool) const {return false;} +bool FactorialFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool FactorialFunction::representsNonPositive(const MathStructure&, bool) const {return false;} +bool FactorialFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool FactorialFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool FactorialFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool FactorialFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool FactorialFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} +bool FactorialFunction::representsComplex(const MathStructure&, bool) const {return false;} +bool FactorialFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool FactorialFunction::representsEven(const MathStructure&, bool) const {return false;} +bool FactorialFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool FactorialFunction::representsUndefined(const MathStructure&) const {return false;} + +DoubleFactorialFunction::DoubleFactorialFunction() : MathFunction("factorial2", 1) { + IntegerArgument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG); + Number nr(-1, 1, 0); + arg->setMin(&nr); + setArgumentDefinition(1, arg); +} +int DoubleFactorialFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION(doubleFactorial) +} +bool DoubleFactorialFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool DoubleFactorialFunction::representsNegative(const MathStructure&, bool) const {return false;} +bool DoubleFactorialFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool DoubleFactorialFunction::representsNonPositive(const MathStructure&, bool) const {return false;} +bool DoubleFactorialFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool DoubleFactorialFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool DoubleFactorialFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool DoubleFactorialFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool DoubleFactorialFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} +bool DoubleFactorialFunction::representsComplex(const MathStructure&, bool) const {return false;} +bool DoubleFactorialFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool DoubleFactorialFunction::representsEven(const MathStructure&, bool) const {return false;} +bool DoubleFactorialFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool DoubleFactorialFunction::representsUndefined(const MathStructure&) const {return false;} + +MultiFactorialFunction::MultiFactorialFunction() : MathFunction("multifactorial", 2) { + setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONNEGATIVE, true, true, INTEGER_TYPE_SLONG)); + setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SLONG)); +} +int MultiFactorialFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION_2(multiFactorial) +} +bool MultiFactorialFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool MultiFactorialFunction::representsNegative(const MathStructure&, bool) const {return false;} +bool MultiFactorialFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool MultiFactorialFunction::representsNonPositive(const MathStructure&, bool) const {return false;} +bool MultiFactorialFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool MultiFactorialFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool MultiFactorialFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} +bool MultiFactorialFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool MultiFactorialFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool MultiFactorialFunction::representsComplex(const MathStructure&, bool) const {return false;} +bool MultiFactorialFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsInteger() && vargs[0].representsNonNegative();} +bool MultiFactorialFunction::representsEven(const MathStructure&, bool) const {return false;} +bool MultiFactorialFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool MultiFactorialFunction::representsUndefined(const MathStructure&) const {return false;} + +BinomialFunction::BinomialFunction() : MathFunction("binomial", 2) { + setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true)); + setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_ULONG)); +} +int BinomialFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + Number nr; + if(!nr.binomial(vargs[0].number(), vargs[1].number())) return 0; + mstruct = nr; + return 1; +} + diff -Nru libqalculate-3.6.0/libqalculate/BuiltinFunctions-datetime.cc libqalculate-3.7.0/libqalculate/BuiltinFunctions-datetime.cc --- libqalculate-3.6.0/libqalculate/BuiltinFunctions-datetime.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/BuiltinFunctions-datetime.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,355 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Number.h" +#include "Calculator.h" +#include "Unit.h" +#include "QalculateDateTime.h" + +#include +#include +#include +#include + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +int calender_to_id(const string &str) { + if(str == "1" || equalsIgnoreCase(str, "gregorian") || equalsIgnoreCase(str, _("gregorian"))) return CALENDAR_GREGORIAN; + if(str == "8" || equalsIgnoreCase(str, "milankovic") || equalsIgnoreCase(str, "milanković") || equalsIgnoreCase(str, _("milankovic"))) return CALENDAR_MILANKOVIC; + if(str == "7" || equalsIgnoreCase(str, "julian") || equalsIgnoreCase(str, _("julian"))) return CALENDAR_JULIAN; + if(str == "3" || equalsIgnoreCase(str, "islamic") || equalsIgnoreCase(str, _("islamic"))) return CALENDAR_ISLAMIC; + if(str == "2" || equalsIgnoreCase(str, "hebrew") || equalsIgnoreCase(str, _("hebrew"))) return CALENDAR_HEBREW; + if(str == "11" || equalsIgnoreCase(str, "egyptian") || equalsIgnoreCase(str, _("egyptian"))) return CALENDAR_EGYPTIAN; + if(str == "4" || equalsIgnoreCase(str, "persian") || equalsIgnoreCase(str, _("persian"))) return CALENDAR_PERSIAN; + if(str == "9" || equalsIgnoreCase(str, "coptic") || equalsIgnoreCase(str, _("coptic"))) return CALENDAR_COPTIC; + if(str == "10" || equalsIgnoreCase(str, "ethiopian") || equalsIgnoreCase(str, _("ethiopian"))) return CALENDAR_ETHIOPIAN; + if(str == "5" || equalsIgnoreCase(str, "indian") || equalsIgnoreCase(str, _("indian"))) return CALENDAR_INDIAN; + if(str == "6" || equalsIgnoreCase(str, "chinese") || equalsIgnoreCase(str, _("chinese"))) return CALENDAR_CHINESE; + return -1; +} + +DateFunction::DateFunction() : MathFunction("date", 1, 4) { + setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG)); + IntegerArgument *iarg = new IntegerArgument(); + iarg->setHandleVector(false); + Number fr(1, 1, 0); + iarg->setMin(&fr); + fr.set(24, 1, 0); + iarg->setMax(&fr); + setArgumentDefinition(2, iarg); + setDefaultValue(2, "1"); + iarg = new IntegerArgument(); + iarg->setHandleVector(false); + fr.set(1, 1, 0); + iarg->setMin(&fr); + fr.set(31, 1, 0); + iarg->setMax(&fr); + setDefaultValue(3, "1"); + setArgumentDefinition(3, iarg); + TextArgument *targ = new TextArgument(); + setArgumentDefinition(4, targ); + setDefaultValue(4, _("gregorian")); +} +int DateFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + int ct = calender_to_id(vargs[3].symbol()); + if(ct < 0) { + CALCULATOR->error(true, "Unrecognized calendar.", NULL); + return 0; + } + QalculateDateTime dt; + if(!calendarToDate(dt, vargs[0].number().lintValue(), vargs[1].number().lintValue(), vargs[2].number().lintValue(), (CalendarSystem) ct)) return 0; + mstruct.set(dt); + return 1; +} +DateTimeFunction::DateTimeFunction() : MathFunction("datetime", 1, 6) { + setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG)); + IntegerArgument *iarg = new IntegerArgument(); + iarg->setHandleVector(false); + Number fr(1, 1, 0); + iarg->setMin(&fr); + fr.set(12, 1, 0); + iarg->setMax(&fr); + setArgumentDefinition(2, iarg); + setDefaultValue(2, "1"); + iarg = new IntegerArgument(); + iarg->setHandleVector(false); + fr.set(1, 1, 0); + iarg->setMin(&fr); + fr.set(31, 1, 0); + iarg->setMax(&fr); + setDefaultValue(3, "1"); + setArgumentDefinition(3, iarg); + iarg = new IntegerArgument(); + iarg->setHandleVector(false); + iarg->setMin(&nr_zero); + fr.set(23, 1, 0); + iarg->setMax(&fr); + setArgumentDefinition(4, iarg); + setDefaultValue(4, "0"); + iarg = new IntegerArgument(); + iarg->setHandleVector(false); + iarg->setMin(&nr_zero); + fr.set(59, 1, 0); + iarg->setMax(&fr); + setArgumentDefinition(5, iarg); + setDefaultValue(5, "0"); + NumberArgument *narg = new NumberArgument(); + narg->setHandleVector(false); + narg->setMin(&nr_zero); + fr.set(61, 1, 0); + narg->setMax(&fr); + narg->setIncludeEqualsMax(false); + setArgumentDefinition(6, narg); + setDefaultValue(6, "0"); +} +int DateTimeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + QalculateDateTime dt; + if(!dt.set(vargs[0].number().lintValue(), vargs[1].number().lintValue(), vargs[2].number().lintValue())) return 0; + if(!vargs[3].isZero() || !vargs[4].isZero() || !vargs[5].isZero()) { + if(!dt.setTime(vargs[3].number().lintValue(), vargs[4].number().lintValue(), vargs[5].number())) return 0; + } + mstruct.set(dt); + return 1; +} +TimeValueFunction::TimeValueFunction() : MathFunction("timevalue", 0, 1) { + setArgumentDefinition(1, new DateArgument()); + setDefaultValue(1, "now"); +} +int TimeValueFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + Number nr(vargs[0].datetime()->second()); + nr /= 60; + nr += vargs[0].datetime()->minute(); + nr /= 60; + nr += vargs[0].datetime()->hour(); + mstruct.set(nr); + return 1; +} +TimestampFunction::TimestampFunction() : MathFunction("timestamp", 0, 1) { + setArgumentDefinition(1, new DateArgument()); + setDefaultValue(1, "now"); +} +int TimestampFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + QalculateDateTime date(*vargs[0].datetime()); + Number nr(date.timestamp()); + if(nr.isInfinite()) return 0; + mstruct.set(nr); + return 1; +} +TimestampToDateFunction::TimestampToDateFunction() : MathFunction("stamptodate", 1) { + //setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG)); +} +int TimestampToDateFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct = vargs[0]; + mstruct.eval(eo); + if((mstruct.isUnit() && mstruct.unit()->baseUnit() == CALCULATOR->getUnitById(UNIT_ID_SECOND)) || (mstruct.isMultiplication() && mstruct.size() >= 2 && mstruct.last().isUnit() && mstruct.last().unit()->baseUnit() == CALCULATOR->getUnitById(UNIT_ID_SECOND))) { + Unit *u = NULL; + if(mstruct.isUnit()) { + u = mstruct.unit(); + mstruct.set(1, 1, 0, true); + } else { + u = mstruct.last().unit(); + mstruct.delChild(mstruct.size(), true); + } + if(u != CALCULATOR->getUnitById(UNIT_ID_SECOND)) { + u->convertToBaseUnit(mstruct); + mstruct.eval(eo); + } + } + if(!mstruct.isNumber() || !mstruct.number().isReal() || mstruct.number().isInterval()) return -1; + QalculateDateTime date; + if(!date.set(mstruct.number())) return -1; + mstruct.set(date, true); + return 1; +} + +AddDaysFunction::AddDaysFunction() : MathFunction("addDays", 2) { + setArgumentDefinition(1, new DateArgument()); + setArgumentDefinition(2, new NumberArgument()); +} +int AddDaysFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = vargs[0]; + if(!mstruct.datetime()->addDays(vargs[1].number())) return 0; + return 1; +} +AddMonthsFunction::AddMonthsFunction() : MathFunction("addMonths", 2) { + setArgumentDefinition(1, new DateArgument()); + setArgumentDefinition(2, new NumberArgument()); +} +int AddMonthsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = vargs[0]; + if(!mstruct.datetime()->addMonths(vargs[1].number())) return 0; + return 1; +} +AddYearsFunction::AddYearsFunction() : MathFunction("addYears", 2) { + setArgumentDefinition(1, new DateArgument()); + setArgumentDefinition(2, new NumberArgument()); +} +int AddYearsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = vargs[0]; + if(!mstruct.datetime()->addYears(vargs[1].number())) return 0; + return 1; +} + +DaysFunction::DaysFunction() : MathFunction("days", 2, 4) { + setArgumentDefinition(1, new DateArgument()); + setArgumentDefinition(2, new DateArgument()); + IntegerArgument *arg = new IntegerArgument(); + Number integ; + arg->setMin(&integ); + integ.set(4, 1, 0); + arg->setMax(&integ); + setArgumentDefinition(3, arg); + setArgumentDefinition(4, new BooleanArgument()); + setDefaultValue(3, "1"); +} +int DaysFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + QalculateDateTime date1(*vargs[0].datetime()), date2(*vargs[1].datetime()); + Number days(date1.daysTo(date2, vargs[2].number().intValue(), vargs[3].number().isZero())); + if(days.isInfinite()) return 0; + days.abs(); + mstruct.set(days); + return 1; +} +YearFracFunction::YearFracFunction() : MathFunction("yearfrac", 2, 4) { + setArgumentDefinition(1, new DateArgument()); + setArgumentDefinition(2, new DateArgument()); + IntegerArgument *arg = new IntegerArgument(); + Number integ; + arg->setMin(&integ); + integ.set(4, 1, 0); + arg->setMax(&integ); + setArgumentDefinition(3, arg); + setArgumentDefinition(4, new BooleanArgument()); + setDefaultValue(3, "1"); +} +int YearFracFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + QalculateDateTime date1(*vargs[0].datetime()), date2(*vargs[1].datetime()); + Number years(date1.yearsTo(date2, vargs[2].number().intValue(), vargs[3].number().isZero())); + if(years.isInfinite()) return 0; + years.abs(); + mstruct.set(years); + return 1; +} +WeekFunction::WeekFunction() : MathFunction("week", 0, 2) { + setArgumentDefinition(1, new DateArgument()); + setArgumentDefinition(2, new BooleanArgument()); + setDefaultValue(1, "today"); +} +int WeekFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + QalculateDateTime date(*vargs[0].datetime()); + int w = date.week(vargs[1].number().getBoolean()); + if(w < 0) return 0; + mstruct.set(w, 1, 0); + return 1; +} +WeekdayFunction::WeekdayFunction() : MathFunction("weekday", 0, 2) { + setArgumentDefinition(1, new DateArgument()); + setArgumentDefinition(2, new BooleanArgument()); + setDefaultValue(1, "today"); +} +int WeekdayFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + QalculateDateTime date(*vargs[0].datetime()); + int w = date.weekday(); + if(w < 0) return 0; + if(vargs[1].number().getBoolean()) { + if(w == 7) w = 1; + else w++; + } + mstruct.set(w, 1, 0); + return 1; +} +YeardayFunction::YeardayFunction() : MathFunction("yearday", 0, 1) { + setArgumentDefinition(1, new DateArgument()); + setDefaultValue(1, "today"); +} +int YeardayFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + QalculateDateTime date(*vargs[0].datetime()); + int yd = date.yearday(); + if(yd < 0) return 0; + mstruct.set(yd, 1, 0); + return 1; +} +MonthFunction::MonthFunction() : MathFunction("month", 0, 1) { + setArgumentDefinition(1, new DateArgument()); + setDefaultValue(1, "today"); +} +int MonthFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + QalculateDateTime date(*vargs[0].datetime()); + mstruct.set(date.month(), 1L, 0L); + return 1; +} +DayFunction::DayFunction() : MathFunction("day", 0, 1) { + setArgumentDefinition(1, new DateArgument()); + setDefaultValue(1, "today"); +} +int DayFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + QalculateDateTime date(*vargs[0].datetime()); + mstruct.set(date.day(), 1L, 0L); + return 1; +} +YearFunction::YearFunction() : MathFunction("year", 0, 1) { + setArgumentDefinition(1, new DateArgument()); + setDefaultValue(1, "today"); +} +int YearFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + QalculateDateTime date(*vargs[0].datetime()); + mstruct.set(date.year(), 1L, 0L); + return 1; +} +TimeFunction::TimeFunction() : MathFunction("time", 0) { +} +int TimeFunction::calculate(MathStructure &mstruct, const MathStructure&, const EvaluationOptions&) { + int hour, min, sec; + now(hour, min, sec); + Number tnr(sec, 1, 0); + tnr /= 60; + tnr += min; + tnr /= 60; + tnr += hour; + mstruct = tnr; + return 1; +} +LunarPhaseFunction::LunarPhaseFunction() : MathFunction("lunarphase", 0, 1) { + setArgumentDefinition(1, new DateArgument()); + setDefaultValue(1, "now"); +} +int LunarPhaseFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = lunarPhase(*vargs[0].datetime()); + if(CALCULATOR->aborted()) return 0; + return 1; +} +NextLunarPhaseFunction::NextLunarPhaseFunction() : MathFunction("nextlunarphase", 1, 2) { + NumberArgument *arg = new NumberArgument(); + Number fr; + arg->setMin(&fr); + fr.set(1, 1, 0); + arg->setMax(&fr); + arg->setIncludeEqualsMin(true); + arg->setIncludeEqualsMax(false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); + setArgumentDefinition(2, new DateArgument()); + setDefaultValue(2, "now"); +} +int NextLunarPhaseFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = findNextLunarPhase(*vargs[1].datetime(), vargs[0].number()); + if(CALCULATOR->aborted()) return 0; + return 1; +} + diff -Nru libqalculate-3.6.0/libqalculate/BuiltinFunctions-explog.cc libqalculate-3.7.0/libqalculate/BuiltinFunctions-explog.cc --- libqalculate-3.6.0/libqalculate/BuiltinFunctions-explog.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/BuiltinFunctions-explog.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,872 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Number.h" +#include "Calculator.h" +#include "Variable.h" +#include "Unit.h" + +#include +#include +#include +#include + +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +bool test_eval(MathStructure &mtest, const EvaluationOptions &eo) { + EvaluationOptions eo2 = eo; + eo2.assume_denominators_nonzero = false; + eo2.approximation = APPROXIMATION_APPROXIMATE; + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(!CALCULATOR->usesIntervalArithmetic()) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + CALCULATOR->beginTemporaryStopMessages(); + mtest.calculateFunctions(eo2); + mtest.calculatesub(eo2, eo2, true); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + if(CALCULATOR->endTemporaryStopMessages()) return false; + return true; +} + +bool calculate_arg(MathStructure &mstruct, const EvaluationOptions &eo) { + + MathStructure msave; + + if(!mstruct.isNumber()) { + if(mstruct.isPower() && mstruct[0] == CALCULATOR->getVariableById(VARIABLE_ID_E) && mstruct[1].isNumber() && mstruct[1].number().hasImaginaryPart() && !mstruct[1].number().hasRealPart()) { + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(CALCULATOR->usesIntervalArithmetic()) { + CALCULATOR->beginTemporaryStopMessages(); + Number nr(*mstruct[1].number().internalImaginary()); + Number nrpi; nrpi.pi(); + nr.add(nrpi); + nr.divide(nrpi); + nr.divide(2); + Number nr_u(nr.upperEndPoint()); + nr = nr.lowerEndPoint(); + nr_u.floor(); + nr.floor(); + if(!CALCULATOR->endTemporaryStopMessages() && nr == nr_u) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + nr.setApproximate(false); + nr *= 2; + nr.negate(); + mstruct = mstruct[1].number().imaginaryPart(); + if(!nr.isZero()) { + mstruct += nr; + mstruct.last() *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + } + return true; + } + } + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + } + if(eo.approximation == APPROXIMATION_EXACT) { + msave = mstruct; + if(!test_eval(mstruct, eo)) { + mstruct = msave; + return false; + } + } + } + if(mstruct.isNumber()) { + if(!mstruct.number().hasImaginaryPart()) { + return false; + } else if(!mstruct.number().hasRealPart() && mstruct.number().imaginaryPartIsNonZero()) { + bool b_neg = mstruct.number().imaginaryPartIsNegative(); + mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); mstruct.multiply(nr_half); + if(b_neg) mstruct.negate(); + } else if(!msave.isZero()) { + mstruct = msave; + return false; + } else if(!mstruct.number().realPartIsNonZero()) { + return false; + } else { + MathStructure new_nr(mstruct.number().imaginaryPart()); + if(!new_nr.number().divide(mstruct.number().realPart())) return false; + if(mstruct.number().realPartIsNegative()) { + if(mstruct.number().imaginaryPartIsNegative()) { + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.divide_nocopy(new MathStructure(180, 1, 0)); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.divide_nocopy(new MathStructure(200, 1, 0)); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_RADIANS: {break;} + default: {if(CALCULATOR->getRadUnit()) {mstruct /= CALCULATOR->getRadUnit();} break;} + } + mstruct.subtract(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + } else if(mstruct.number().imaginaryPartIsNonNegative()) { + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.divide_nocopy(new MathStructure(180, 1, 0)); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.divide_nocopy(new MathStructure(200, 1, 0)); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_RADIANS: {break;} + default: {if(CALCULATOR->getRadUnit()) {mstruct /= CALCULATOR->getRadUnit();} break;} + } + mstruct.add(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + } else { + return false; + } + } else { + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.divide_nocopy(new MathStructure(180, 1, 0)); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.divide_nocopy(new MathStructure(200, 1, 0)); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_RADIANS: {break;} + default: {if(CALCULATOR->getRadUnit()) {mstruct /= CALCULATOR->getRadUnit();} break;} + } + } + } + return true; + } + if(!msave.isZero()) { + mstruct = msave; + } + return false; + +} + +SqrtFunction::SqrtFunction() : MathFunction("sqrt", 1) { + Argument *arg = new Argument("", false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +int SqrtFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + if(!vargs[0].representsScalar()) { + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + } + mstruct.raise(nr_half); + return 1; +} +bool SqrtFunction::representsPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsPositive(allow_units);} +bool SqrtFunction::representsNegative(const MathStructure&, bool) const {return false;} +bool SqrtFunction::representsNonNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNonNegative(allow_units);} +bool SqrtFunction::representsNonPositive(const MathStructure&, bool) const {return false;} +bool SqrtFunction::representsInteger(const MathStructure&, bool) const {return false;} +bool SqrtFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} +bool SqrtFunction::representsRational(const MathStructure&, bool) const {return false;} +bool SqrtFunction::representsReal(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNonNegative(allow_units);} +bool SqrtFunction::representsNonComplex(const MathStructure &vargs, bool allow_units) const {return representsReal(vargs, allow_units);} +bool SqrtFunction::representsComplex(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNegative(allow_units);} +bool SqrtFunction::representsNonZero(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNonZero(allow_units);} +bool SqrtFunction::representsEven(const MathStructure&, bool) const {return false;} +bool SqrtFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool SqrtFunction::representsUndefined(const MathStructure&) const {return false;} +CbrtFunction::CbrtFunction() : MathFunction("cbrt", 1) { + Argument *arg = new Argument("", false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +int CbrtFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + if(vargs[0].representsNegative(true)) { + mstruct = vargs[0]; + mstruct.negate(); + mstruct.raise(Number(1, 3, 0)); + mstruct.negate(); + } else if(vargs[0].representsNonNegative(true)) { + mstruct = vargs[0]; + mstruct.raise(Number(1, 3, 0)); + } else { + MathStructure mroot(3, 1, 0); + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ROOT), &vargs[0], &mroot, NULL); + } + return 1; +} +RootFunction::RootFunction() : MathFunction("root", 2) { + NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + arg->setComplexAllowed(false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); + NumberArgument *arg2 = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, true); + arg2->setComplexAllowed(false); + arg2->setRationalNumber(true); + arg2->setHandleVector(true); + setArgumentDefinition(2, arg2); +} +int RootFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + if(vargs[1].number().isOne()) { + mstruct = vargs[0]; + return 1; + } + if(!vargs[1].number().isInteger() || !vargs[1].number().isPositive()) { + mstruct = vargs[0]; + if(!vargs[0].representsScalar()) { + mstruct.eval(eo); + } + if(mstruct.isVector()) return -1; + Number nr_root(vargs[1].number().numerator()); + nr_root.setPrecisionAndApproximateFrom(vargs[1].number()); + Number nr_pow(vargs[1].number().denominator()); + nr_pow.setPrecisionAndApproximateFrom(vargs[1].number()); + if(nr_root.isNegative()) { + nr_root.negate(); + nr_pow.negate(); + } + if(nr_root.isOne()) { + mstruct ^= nr_pow; + } else if(nr_root.isZero()) { + mstruct ^= nr_zero; + } else { + mstruct ^= nr_pow; + mstruct.transform(this); + mstruct.addChild(nr_root); + } + return 1; + } + if(vargs[0].representsNonNegative(true)) { + mstruct = vargs[0]; + Number nr_exp(vargs[1].number()); + nr_exp.recip(); + mstruct.raise(nr_exp); + return 1; + } else if(vargs[1].number().isOdd() && vargs[0].representsNegative(true)) { + mstruct = vargs[0]; + mstruct.negate(); + Number nr_exp(vargs[1].number()); + nr_exp.recip(); + mstruct.raise(nr_exp); + mstruct.negate(); + return 1; + } + bool eval_mstruct = !vargs[0].isNumber(); + Number nr; + if(eval_mstruct) { + mstruct = vargs[0]; + if(eo.approximation == APPROXIMATION_TRY_EXACT && mstruct.representsScalar()) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_EXACT; + mstruct.eval(eo2); + } else { + mstruct.eval(eo); + } + if(mstruct.isVector()) { + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + return -1; + } + if(mstruct.representsNonNegative(true)) { + Number nr_exp(vargs[1].number()); + nr_exp.recip(); + mstruct.raise(nr_exp); + return 1; + } else if(vargs[1].number().isOdd() && mstruct.representsNegative(true)) { + mstruct.negate(); + Number nr_exp(vargs[1].number()); + nr_exp.recip(); + mstruct.raise(nr_exp); + mstruct.negate(); + return 1; + } + if(!mstruct.isNumber()) { + if(mstruct.isPower() && mstruct[1].isNumber() && mstruct[1].number().isInteger()) { + if(mstruct[1] == vargs[1]) { + if(mstruct[1].number().isEven()) { + if(!mstruct[0].representsReal(true)) return -1; + mstruct.delChild(2); + mstruct.setType(STRUCT_FUNCTION); + mstruct.setFunctionId(FUNCTION_ID_ABS); + } else { + mstruct.setToChild(1); + } + return 1; + } else if(mstruct[1].number().isIntegerDivisible(vargs[1].number())) { + if(mstruct[1].number().isEven()) { + if(!mstruct[0].representsReal(true)) return -1; + mstruct[0].transform(STRUCT_FUNCTION); + mstruct[0].setFunctionId(FUNCTION_ID_ABS); + } + mstruct[1].divide(vargs[1].number()); + return 1; + } else if(!mstruct[1].number().isMinusOne() && vargs[1].number().isIntegerDivisible(mstruct[1].number())) { + if(mstruct[1].number().isEven()) { + if(!mstruct[0].representsReal(true)) return -1; + mstruct[0].transform(STRUCT_FUNCTION); + mstruct[0].setFunctionId(FUNCTION_ID_ABS); + } + Number new_root(vargs[1].number()); + new_root.divide(mstruct[1].number()); + bool bdiv = new_root.isNegative(); + if(bdiv) new_root.negate(); + mstruct[1] = new_root; + mstruct.setType(STRUCT_FUNCTION); + mstruct.setFunction(this); + if(bdiv) mstruct.raise(nr_minus_one); + return 1; + } else if(mstruct[1].number().isMinusOne()) { + mstruct[0].transform(STRUCT_FUNCTION, vargs[1]); + mstruct[0].setFunction(this); + return 1; + } else if(mstruct[1].number().isNegative()) { + mstruct[1].number().negate(); + mstruct.transform(STRUCT_FUNCTION, vargs[1]); + mstruct.setFunction(this); + mstruct.raise(nr_minus_one); + return 1; + } + } else if(mstruct.isPower() && mstruct[1].isNumber() && mstruct[1].number().isRational() && mstruct[1].number().denominatorIsTwo()) { + Number new_root(vargs[1].number()); + new_root.multiply(Number(2, 1, 0)); + if(mstruct[1].number().numeratorIsOne()) { + mstruct[1].number().set(new_root, true); + mstruct.setType(STRUCT_FUNCTION); + mstruct.setFunction(this); + } else { + mstruct[1].number().set(mstruct[1].number().numerator(), true); + mstruct.transform(STRUCT_FUNCTION); + mstruct.addChild(new_root); + mstruct.setFunction(this); + } + return 1; + } else if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_SQRT && mstruct.size() == 1) { + Number new_root(vargs[1].number()); + new_root.multiply(Number(2, 1, 0)); + mstruct.addChild(new_root); + mstruct.setFunction(this); + return 1; + } else if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_ROOT && mstruct.size() == 2 && mstruct[1].isNumber() && mstruct[1].number().isInteger() && mstruct[1].number().isPositive()) { + Number new_root(vargs[1].number()); + new_root.multiply(mstruct[1].number()); + mstruct[1] = new_root; + return 1; + } else if(mstruct.isMultiplication()) { + bool b = true; + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct[i].representsReal(true)) { + b = false; + break; + } + } + if(b) { + if(vargs[1].number().isOdd()) { + bool b_neg = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isNumber() && mstruct[i].number().isNegative() && !mstruct[i].isMinusOne()) { + mstruct[i].negate(); + b_neg = !b_neg; + } + mstruct[i].transform(STRUCT_FUNCTION, vargs[1]); + mstruct[i].setFunction(this); + } + if(b_neg) mstruct.insertChild_nocopy(new MathStructure(-1, 1, 0), 1); + return 1; + } else { + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isNumber() && mstruct[i].number().isNegative() && !mstruct[i].isMinusOne()) { + MathStructure *mmul = new MathStructure(this, &mstruct[i], &vargs[1], NULL); + (*mmul)[0].negate(); + mstruct[i] = nr_minus_one; + mstruct.transform(STRUCT_FUNCTION, vargs[1]); + mstruct.setFunction(this); + mstruct.multiply_nocopy(mmul); + return true; + } else if(mstruct[i].representsPositive()) { + mstruct[i].transform(STRUCT_FUNCTION, vargs[1]); + mstruct[i].setFunction(this); + mstruct[i].ref(); + MathStructure *mmul = &mstruct[i]; + mstruct.delChild(i + 1, true); + mstruct.transform(STRUCT_FUNCTION, vargs[1]); + mstruct.setFunction(this); + mstruct.multiply_nocopy(mmul); + return true; + } + } + } + } + } + return -1; + } + nr = mstruct.number(); + } else { + nr = vargs[0].number(); + } + if(!nr.root(vargs[1].number()) || (eo.approximation < APPROXIMATION_APPROXIMATE && nr.isApproximate() && !vargs[0].isApproximate() && !mstruct.isApproximate() && !vargs[1].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity())) { + if(!eval_mstruct) { + if(vargs[0].number().isNegative() && vargs[1].number().isOdd()) { + mstruct.set(this, &vargs[0], &vargs[1], NULL); + mstruct[0].number().negate(); + mstruct.negate(); + return 1; + } + return 0; + } else if(mstruct.number().isNegative() && vargs[1].number().isOdd()) { + mstruct.number().negate(); + mstruct.transform(STRUCT_FUNCTION, vargs[1]); + mstruct.setFunction(this); + mstruct.negate(); + return 1; + } + } else { + mstruct.set(nr); + return 1; + } + return -1; +} +bool RootFunction::representsPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsPositive(allow_units);} +bool RootFunction::representsNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsOdd() && vargs[1].representsPositive() && vargs[0].representsNegative(allow_units);} +bool RootFunction::representsNonNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsNonNegative(allow_units);} +bool RootFunction::representsNonPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsOdd() && vargs[1].representsPositive() && vargs[0].representsNonPositive(allow_units);} +bool RootFunction::representsInteger(const MathStructure&, bool) const {return false;} +bool RootFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsNumber(allow_units);} +bool RootFunction::representsRational(const MathStructure&, bool) const {return false;} +bool RootFunction::representsReal(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsReal(allow_units) && (vargs[0].representsNonNegative(allow_units) || vargs[1].representsOdd());} +bool RootFunction::representsNonComplex(const MathStructure &vargs, bool allow_units) const {return representsReal(vargs, allow_units);} +bool RootFunction::representsComplex(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && (vargs[0].representsComplex(allow_units) || (vargs[1].representsEven() && vargs[0].representsNegative(allow_units)));} +bool RootFunction::representsNonZero(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsInteger() && vargs[1].representsPositive() && vargs[0].representsNonZero(allow_units);} +bool RootFunction::representsEven(const MathStructure&, bool) const {return false;} +bool RootFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool RootFunction::representsUndefined(const MathStructure&) const {return false;} + +SquareFunction::SquareFunction() : MathFunction("sq", 1) { + Argument *arg = new Argument("", false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +int SquareFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = vargs[0]; + mstruct ^= 2; + return 1; +} + +ExpFunction::ExpFunction() : MathFunction("exp", 1) { + Argument *arg = new Argument("", false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +int ExpFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = CALCULATOR->getVariableById(VARIABLE_ID_E); + mstruct ^= vargs[0]; + return 1; +} + +LogFunction::LogFunction() : MathFunction("ln", 1) { + Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONZERO, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +bool LogFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsPositive() && ((vargs[0].isNumber() && vargs[0].number().isGreaterThan(nr_one)) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && ((KnownVariable*) vargs[0].variable())->get().number().isGreaterThan(nr_one)));} +bool LogFunction::representsNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative() && ((vargs[0].isNumber() && vargs[0].number().isLessThan(nr_one)) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && ((KnownVariable*) vargs[0].variable())->get().number().isLessThan(nr_one)));} +bool LogFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsPositive() && ((vargs[0].isNumber() && vargs[0].number().isGreaterThanOrEqualTo(nr_one)) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && ((KnownVariable*) vargs[0].variable())->get().number().isGreaterThanOrEqualTo(nr_one)));} +bool LogFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative() && ((vargs[0].isNumber() && vargs[0].number().isLessThanOrEqualTo(nr_one)) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && ((KnownVariable*) vargs[0].variable())->get().number().isLessThanOrEqualTo(nr_one)));} +bool LogFunction::representsInteger(const MathStructure&, bool) const {return false;} +bool LogFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units) && vargs[0].representsNonZero(allow_units);} +bool LogFunction::representsRational(const MathStructure&, bool) const {return false;} +bool LogFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsPositive();} +bool LogFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();} +bool LogFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNegative();} +bool LogFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && (vargs[0].representsNonPositive() || (vargs[0].isNumber() && COMPARISON_IS_NOT_EQUAL(vargs[0].number().compare(nr_one))) || (vargs[0].isVariable() && vargs[0].variable()->isKnown() && ((KnownVariable*) vargs[0].variable())->get().isNumber() && COMPARISON_IS_NOT_EQUAL(((KnownVariable*) vargs[0].variable())->get().number().compare(nr_one))));} +bool LogFunction::representsEven(const MathStructure&, bool) const {return false;} +bool LogFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool LogFunction::representsUndefined(const MathStructure&) const {return false;} +int LogFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + + mstruct = vargs[0]; + + if(mstruct.isVariable() && mstruct.variable()->id() == VARIABLE_ID_E) { + mstruct.set(m_one); + return true; + } else if(mstruct.isPower()) { + if(mstruct[0].isVariable() && mstruct[0].variable()->id() == VARIABLE_ID_E) { + if(mstruct[1].representsReal()) { + mstruct.setToChild(2, true); + return true; + } + } else if(eo.approximation != APPROXIMATION_APPROXIMATE && ((mstruct[0].representsPositive(true) && mstruct[1].representsReal()) || (mstruct[1].isNumber() && mstruct[1].number().isFraction()))) { + MathStructure mstruct2; + mstruct2.set(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &mstruct[0], NULL); + mstruct2 *= mstruct[1]; + mstruct = mstruct2; + return true; + } + } + + if(eo.approximation == APPROXIMATION_TRY_EXACT) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_EXACT; + CALCULATOR->beginTemporaryStopMessages(); + mstruct.eval(eo2); + if(mstruct.isVector()) {CALCULATOR->endTemporaryStopMessages(true); return -1;} + } else { + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + } + + bool b = false; + if(mstruct.isVariable() && mstruct.variable()->id() == VARIABLE_ID_E) { + mstruct.set(m_one); + b = true; + } else if(mstruct.isPower()) { + if(mstruct[0].isVariable() && mstruct[0].variable()->id() == VARIABLE_ID_E) { + if(mstruct[1].representsReal()) { + mstruct.setToChild(2, true); + b = true; + } + } else if((mstruct[0].representsPositive(true) && mstruct[1].representsReal()) || (mstruct[1].isNumber() && mstruct[1].number().isFraction())) { + MathStructure mstruct2; + mstruct2.set(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &mstruct[0], NULL); + mstruct2 *= mstruct[1]; + mstruct = mstruct2; + b = true; + } + } else if(mstruct.isMultiplication()) { + b = true; + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct[i].representsPositive()) { + b = false; + break; + } + } + if(b) { + MathStructure mstruct2; + mstruct2.set(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &mstruct[0], NULL); + for(size_t i = 1; i < mstruct.size(); i++) { + mstruct2.add(MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &mstruct[i], NULL), i > 1); + } + mstruct = mstruct2; + } + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(b); + if(b) return 1; + if(eo.approximation == APPROXIMATION_TRY_EXACT && !mstruct.isNumber()) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + mstruct = vargs[0]; + mstruct.eval(eo2); + } + + if(mstruct.isNumber()) { + if(eo.allow_complex && mstruct.number().isMinusOne()) { + mstruct = nr_one_i; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + return 1; + } else if(mstruct.number().isI()) { + mstruct.set(1, 2, 0); + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct *= nr_one_i; + return 1; + } else if(mstruct.number().isMinusI()) { + mstruct.set(-1, 2, 0); + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct *= nr_one_i; + return 1; + } else if(eo.allow_complex && eo.allow_infinite && mstruct.number().isMinusInfinity()) { + mstruct = CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct *= nr_one_i; + Number nr; nr.setPlusInfinity(); + mstruct += nr; + return 1; + } + Number nr(mstruct.number()); + if(nr.ln() && !(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + mstruct.set(nr, true); + return 1; + } + if(mstruct.number().isRational() && mstruct.number().isPositive()) { + if(mstruct.number().isInteger()) { + if(mstruct.number().isLessThanOrEqualTo(PRIMES[NR_OF_PRIMES - 1])) { + vector factors; + mstruct.number().factorize(factors); + if(factors.size() > 1) { + mstruct.clear(true); + mstruct.setType(STRUCT_ADDITION); + for(size_t i = 0; i < factors.size(); i++) { + if(i > 0 && factors[i] == factors[i - 1]) { + if(mstruct.last().isMultiplication()) mstruct.last().last().number()++; + else mstruct.last() *= nr_two; + } else { + mstruct.addChild(MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), NULL)); + mstruct.last().addChild(factors[i]); + } + } + if(mstruct.size() == 1) mstruct.setToChild(1, true); + return 1; + } + } + } else { + MathStructure mstruct2(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), NULL); + mstruct2.addChild(mstruct.number().denominator()); + mstruct.number().set(mstruct.number().numerator()); + mstruct.transformById(FUNCTION_ID_LOG); + mstruct -= mstruct2; + return 1; + } + } else if(mstruct.number().hasImaginaryPart()) { + if(mstruct.number().hasRealPart()) { + MathStructure *marg = new MathStructure(mstruct); + if(calculate_arg(*marg, eo)) { + mstruct.transformById(FUNCTION_ID_ABS); + mstruct.transformById(FUNCTION_ID_LOG); + marg->multiply(nr_one_i); + mstruct.add_nocopy(marg); + return 1; + } + marg->unref(); + } else { + bool b_neg = mstruct.number().imaginaryPartIsNegative(); + if(mstruct.number().abs()) { + mstruct.transform(this); + mstruct += b_neg ? nr_minus_half : nr_half; + mstruct.last() *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.last().multiply(nr_one_i, true); + } + return 1; + } + } + } else if(mstruct.isPower()) { + if((mstruct[0].representsPositive(true) && mstruct[1].representsReal()) || (mstruct[1].isNumber() && mstruct[1].number().isFraction())) { + MathStructure mstruct2; + mstruct2.set(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &mstruct[0], NULL); + mstruct2 *= mstruct[1]; + mstruct = mstruct2; + return 1; + } + if(mstruct[1].isNumber() && mstruct[1].number().isTwo() && mstruct[0].representsPositive()) { + mstruct.setToChild(1, true); + mstruct.transform(this); + mstruct *= nr_two; + return 1; + } + if(eo.approximation == APPROXIMATION_EXACT && !mstruct[1].isNumber()) { + CALCULATOR->beginTemporaryStopMessages(); + MathStructure mtest(mstruct[1]); + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + mtest.eval(eo2); + if(!CALCULATOR->endTemporaryStopMessages() && mtest.isNumber() && mtest.number().isFraction()) { + MathStructure mstruct2; + mstruct2.set(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &mstruct[0], NULL); + mstruct2 *= mstruct[1]; + mstruct = mstruct2; + return 1; + } + } + } + if(eo.allow_complex && mstruct.representsNegative()) { + mstruct.negate(); + mstruct.transformById(FUNCTION_ID_LOG); + mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.last() *= nr_one_i; + return 1; + } + if(!mstruct.representsReal()) { + MathStructure *marg = new MathStructure(mstruct); + if(calculate_arg(*marg, eo)) { + mstruct.transformById(FUNCTION_ID_ABS); + mstruct.transformById(FUNCTION_ID_LOG); + marg->multiply(nr_one_i); + mstruct.add_nocopy(marg); + return 1; + } + marg->unref(); + } + + return -1; + +} +LognFunction::LognFunction() : MathFunction("log", 1, 2) { + Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONZERO, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); + arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONZERO, false); + arg->setHandleVector(true); + setArgumentDefinition(2, arg); + setDefaultValue(2, "e"); +} +int LognFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector() || vargs[1].isVector()) return 0; + if(vargs[1].isVariable() && vargs[1].variable()->id() == VARIABLE_ID_E) { + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &vargs[0], NULL); + return 1; + } + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + MathStructure mstructv2 = vargs[1]; + mstructv2.eval(eo); + if(mstructv2.isVector()) return -2; + if(mstruct.isPower()) { + if((mstruct[0].representsPositive(true) && mstruct[1].representsReal()) || (mstruct[1].isNumber() && mstruct[1].number().isFraction())) { + MathStructure mstruct2; + mstruct2.set(CALCULATOR->getFunctionById(FUNCTION_ID_LOGN), &mstruct[0], &mstructv2, NULL); + mstruct2 *= mstruct[1]; + mstruct = mstruct2; + return 1; + } + } else if(mstruct.isMultiplication()) { + bool b = true; + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct[i].representsPositive()) { + b = false; + break; + } + } + if(b) { + MathStructure mstruct2; + mstruct2.set(CALCULATOR->getFunctionById(FUNCTION_ID_LOGN), &mstruct[0], &mstructv2, NULL); + for(size_t i = 1; i < mstruct.size(); i++) { + mstruct2.add(MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_LOGN), &mstruct[i], &mstructv2, NULL), i > 1); + } + mstruct = mstruct2; + return 1; + } + } else if(mstruct.isNumber() && mstructv2.isNumber()) { + Number nr(mstruct.number()); + if(nr.log(mstructv2.number()) && !(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + mstruct.set(nr, true); + return 1; + } + } + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &vargs[0], NULL); + mstruct.divide_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &vargs[1], NULL)); + return 1; +} +CisFunction::CisFunction() : MathFunction("cis", 1) { + Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +int CisFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + + if(vargs[0].isVector()) return 0; + if(contains_angle_unit(vargs[0], eo.parse_options)) { + if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getRadUnit()) { + mstruct = vargs[0][0]; + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getRadUnit()) { + mstruct = vargs[0][1]; + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getDegUnit()) { + mstruct = vargs[0][0]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 180), true); + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getDegUnit()) { + mstruct = vargs[0][1]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 180), true); + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getGraUnit()) { + mstruct = vargs[0][0]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 200), true); + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getGraUnit()) { + mstruct = vargs[0][1]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 200), true); + } else { + mstruct = vargs[0]; + mstruct.convert(CALCULATOR->getRadUnit()); + mstruct /= CALCULATOR->getRadUnit(); + } + } else { + mstruct = vargs[0]; + } + + if(mstruct.isVariable() && mstruct.variable()->id() == VARIABLE_ID_PI) { + mstruct.set(-1, 1, 0, true); + return 1; + } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isInteger() && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI) { + if(mstruct[0].number().isEven()) { + mstruct.set(1, 1, 0, true); + return 1; + } else if(mstruct[0].number().isOdd()) { + mstruct.set(-1, 1, 0, true); + return 1; + } + } + + mstruct *= nr_one_i; + mstruct ^= CALCULATOR->getVariableById(VARIABLE_ID_E); + mstruct.swapChildren(1, 2); + + return 1; + +} +LambertWFunction::LambertWFunction() : MathFunction("lambertw", 1, 2) { + NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + arg->setComplexAllowed(false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); + setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, false)); + setDefaultValue(2, "0"); +} +bool LambertWFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[0].representsNumber() && (vargs[1].isZero() || vargs[0].representsNonZero()));} +bool LambertWFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[1].isZero() && vargs[0].representsNonNegative());} +bool LambertWFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[0].isZero() || (vargs[1].isZero() && vargs[0].representsNonNegative()));} +bool LambertWFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[0].representsComplex() || (vargs[0].representsNonZero() && (vargs[1].isInteger() && (!vargs[1].isMinusOne() || vargs[0].representsPositive()) && !vargs[1].isZero())));} +bool LambertWFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 2 && (vargs[1].representsNonZero() || vargs[0].representsNonZero());} +int LambertWFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + + if(eo.approximation == APPROXIMATION_TRY_EXACT) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_EXACT; + CALCULATOR->beginTemporaryStopMessages(); + mstruct.eval(eo2); + if(mstruct.isVector()) {CALCULATOR->endTemporaryStopMessages(true); return -1;} + } else { + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + } + + bool b = false; + if(!vargs[1].isZero()) { + if(mstruct.isZero()) { + mstruct.set(nr_minus_inf, true); + b = true; + } else if(vargs[1].isMinusOne()) { + if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[1].isPower() && mstruct[1][0].isVariable() && mstruct[1][0].variable()->id() == VARIABLE_ID_E && mstruct[0].number() <= nr_minus_one && mstruct[1][1] == mstruct[0]) { + mstruct.setToChild(1, true); + b = true; + } + } + + } else { + if(mstruct.isZero()) { + b = true; + } else if(mstruct.isVariable() && mstruct.variable()->id() == VARIABLE_ID_E) { + mstruct.set(1, 1, 0, true); + b = true; + } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isMinusOne() && mstruct[1].isPower() && mstruct[1][0].isVariable() && mstruct[1][0].variable()->id() == VARIABLE_ID_E && mstruct[1][1].isMinusOne()) { + mstruct.set(-1, 1, 0, true); + b = true; + } + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(b); + if(b) return 1; + if(eo.approximation == APPROXIMATION_EXACT) return -1; + if(eo.approximation == APPROXIMATION_TRY_EXACT && !mstruct.isNumber()) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + mstruct = vargs[0]; + mstruct.eval(eo2); + } + if(mstruct.isNumber()) { + Number nr(mstruct.number()); + if(nr.lambertW(vargs[1].number()) && !(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + mstruct.set(nr, true); + return 1; + } + } + return -1; +} + diff -Nru libqalculate-3.6.0/libqalculate/BuiltinFunctions.h libqalculate-3.7.0/libqalculate/BuiltinFunctions.h --- libqalculate-3.6.0/libqalculate/BuiltinFunctions.h 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/BuiltinFunctions.h 2020-01-21 22:54:40.000000000 +0000 @@ -1,4 +1,3 @@ - /* Qalculate (library) @@ -16,24 +15,26 @@ #include #include -#define DECLARE_BUILTIN_FUNCTION(x) class x : public MathFunction { \ +#define DECLARE_BUILTIN_FUNCTION(x, i) class x : public MathFunction { \ public: \ int calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo); \ x(); \ x(const x *function) {set(function);} \ ExpressionItem *copy() const {return new x(this);} \ + int id() const {return i;}\ }; -#define DECLARE_BUILTIN_FUNCTION_B(x) class x : public MathFunction { \ +#define DECLARE_BUILTIN_FUNCTION_B(x, i) class x : public MathFunction { \ public: \ int calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo); \ x(); \ x(const x *function) {set(function);} \ ExpressionItem *copy() const {return new x(this);} \ bool representsBoolean(const MathStructure&) const {return true;}\ + int id() const {return i;}\ }; -#define DECLARE_BUILTIN_FUNCTION_PI(x) class x : public MathFunction { \ +#define DECLARE_BUILTIN_FUNCTION_PI(x, i) class x : public MathFunction { \ public: \ int calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo); \ x(); \ @@ -41,9 +42,10 @@ ExpressionItem *copy() const {return new x(this);} \ bool representsInteger(const MathStructure&, bool) const {return true;}\ bool representsPositive(const MathStructure&, bool) const {return true;}\ + int id() const {return i;}\ }; -#define DECLARE_BUILTIN_FUNCTION_RPI(x) class x : public MathFunction { \ +#define DECLARE_BUILTIN_FUNCTION_RPI(x, i) class x : public MathFunction { \ public: \ int calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo); \ x(); \ @@ -52,9 +54,10 @@ bool representsReal(const MathStructure&, bool) const;\ bool representsInteger(const MathStructure&, bool) const;\ bool representsNonNegative(const MathStructure&, bool) const;\ + int id() const {return i;}\ }; -#define DECLARE_BUILTIN_FUNCTION_R(x) class x : public MathFunction { \ +#define DECLARE_BUILTIN_FUNCTION_R(x, i) class x : public MathFunction { \ public: \ int calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo); \ x(); \ @@ -74,9 +77,10 @@ bool representsEven(const MathStructure &vargs, bool allow_units = false) const;\ bool representsOdd(const MathStructure &vargs, bool allow_units = false) const;\ bool representsUndefined(const MathStructure &vargs) const;\ + int id() const {return i;}\ }; -#define DECLARE_BUILTIN_FUNCTION_R2(x) class x : public MathFunction { \ +#define DECLARE_BUILTIN_FUNCTION_R2(x, i) class x : public MathFunction { \ public: \ int calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo); \ x(); \ @@ -85,10 +89,10 @@ bool representsNumber(const MathStructure &vargs, bool allow_units = false) const;\ bool representsReal(const MathStructure &vargs, bool allow_units = false) const;\ bool representsNonComplex(const MathStructure &vargs, bool allow_units = false) const;\ + int id() const {return i;}\ }; - -#define DECLARE_BUILTIN_FUNCTION_R3(x) class x : public MathFunction { \ +#define DECLARE_BUILTIN_FUNCTION_R3(x, i) class x : public MathFunction { \ public: \ int calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo); \ x(); \ @@ -99,226 +103,414 @@ bool representsNonComplex(const MathStructure &vargs, bool allow_units = false) const;\ bool representsComplex(const MathStructure &vargs, bool allow_units = false) const;\ bool representsNonZero(const MathStructure &vargs, bool allow_units = false) const;\ + int id() const {return i;}\ }; -#define DECLARE_BUILTIN_FUNCTION_R1(x) class x : public MathFunction { \ +#define DECLARE_BUILTIN_FUNCTION_R1(x, i) class x : public MathFunction { \ public: \ int calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo); \ x(); \ x(const x *function) {set(function);} \ ExpressionItem *copy() const {return new x(this);} \ bool representsNumber(const MathStructure &vargs, bool allow_units = false) const;\ + int id() const {return i;}\ }; -DECLARE_BUILTIN_FUNCTION(VectorFunction) -DECLARE_BUILTIN_FUNCTION(LimitsFunction) -DECLARE_BUILTIN_FUNCTION(RankFunction) -DECLARE_BUILTIN_FUNCTION(SortFunction) -DECLARE_BUILTIN_FUNCTION(ComponentFunction) -DECLARE_BUILTIN_FUNCTION_PI(DimensionFunction) - -DECLARE_BUILTIN_FUNCTION(MatrixFunction) -DECLARE_BUILTIN_FUNCTION(MergeVectorsFunction) -DECLARE_BUILTIN_FUNCTION(MatrixToVectorFunction) -DECLARE_BUILTIN_FUNCTION(AreaFunction) -DECLARE_BUILTIN_FUNCTION_PI(RowsFunction) -DECLARE_BUILTIN_FUNCTION_PI(ColumnsFunction) -DECLARE_BUILTIN_FUNCTION(RowFunction) -DECLARE_BUILTIN_FUNCTION(ColumnFunction) -DECLARE_BUILTIN_FUNCTION_PI(ElementsFunction) -DECLARE_BUILTIN_FUNCTION(ElementFunction) -DECLARE_BUILTIN_FUNCTION(TransposeFunction) -DECLARE_BUILTIN_FUNCTION(IdentityFunction) -DECLARE_BUILTIN_FUNCTION(DeterminantFunction) -DECLARE_BUILTIN_FUNCTION(PermanentFunction) -DECLARE_BUILTIN_FUNCTION(AdjointFunction) -DECLARE_BUILTIN_FUNCTION(CofactorFunction) -DECLARE_BUILTIN_FUNCTION(InverseFunction) -DECLARE_BUILTIN_FUNCTION(MagnitudeFunction) -DECLARE_BUILTIN_FUNCTION(HadamardFunction) -DECLARE_BUILTIN_FUNCTION(EntrywiseFunction) - -DECLARE_BUILTIN_FUNCTION_R(FactorialFunction) -DECLARE_BUILTIN_FUNCTION_R(DoubleFactorialFunction) -DECLARE_BUILTIN_FUNCTION_R(MultiFactorialFunction) -DECLARE_BUILTIN_FUNCTION(BinomialFunction) - -DECLARE_BUILTIN_FUNCTION(BitXorFunction) -DECLARE_BUILTIN_FUNCTION_B(XorFunction) -DECLARE_BUILTIN_FUNCTION(BitCmpFunction) -DECLARE_BUILTIN_FUNCTION_B(OddFunction) -DECLARE_BUILTIN_FUNCTION_B(EvenFunction) -DECLARE_BUILTIN_FUNCTION(ShiftFunction) -DECLARE_BUILTIN_FUNCTION(CircularShiftFunction) - -DECLARE_BUILTIN_FUNCTION_R(AbsFunction) -DECLARE_BUILTIN_FUNCTION(GcdFunction) -DECLARE_BUILTIN_FUNCTION(LcmFunction) -DECLARE_BUILTIN_FUNCTION_R(SignumFunction) -DECLARE_BUILTIN_FUNCTION_R(HeavisideFunction) -DECLARE_BUILTIN_FUNCTION_R(DiracFunction) -DECLARE_BUILTIN_FUNCTION_R(RoundFunction) -DECLARE_BUILTIN_FUNCTION_R(FloorFunction) -DECLARE_BUILTIN_FUNCTION_R(CeilFunction) -DECLARE_BUILTIN_FUNCTION_R(TruncFunction) -DECLARE_BUILTIN_FUNCTION(NumeratorFunction) -DECLARE_BUILTIN_FUNCTION(DenominatorFunction) -DECLARE_BUILTIN_FUNCTION(IntFunction) -DECLARE_BUILTIN_FUNCTION(FracFunction) -DECLARE_BUILTIN_FUNCTION(RemFunction) -DECLARE_BUILTIN_FUNCTION(ModFunction) - -DECLARE_BUILTIN_FUNCTION(PolynomialUnitFunction) -DECLARE_BUILTIN_FUNCTION(PolynomialPrimpartFunction) -DECLARE_BUILTIN_FUNCTION(PolynomialContentFunction) -DECLARE_BUILTIN_FUNCTION(CoeffFunction) -DECLARE_BUILTIN_FUNCTION(LCoeffFunction) -DECLARE_BUILTIN_FUNCTION(TCoeffFunction) -DECLARE_BUILTIN_FUNCTION(DegreeFunction) -DECLARE_BUILTIN_FUNCTION(LDegreeFunction) - -DECLARE_BUILTIN_FUNCTION_R(ReFunction) -DECLARE_BUILTIN_FUNCTION_R(ImFunction) -DECLARE_BUILTIN_FUNCTION_R2(ArgFunction) - -DECLARE_BUILTIN_FUNCTION_R(IntervalFunction) -DECLARE_BUILTIN_FUNCTION(UncertaintyFunction) - -DECLARE_BUILTIN_FUNCTION_R(SqrtFunction) -DECLARE_BUILTIN_FUNCTION(CbrtFunction) -DECLARE_BUILTIN_FUNCTION_R(RootFunction) -DECLARE_BUILTIN_FUNCTION(SquareFunction) - -DECLARE_BUILTIN_FUNCTION(ExpFunction) - -DECLARE_BUILTIN_FUNCTION_R(LogFunction) -DECLARE_BUILTIN_FUNCTION(LognFunction) - -DECLARE_BUILTIN_FUNCTION_R3(LambertWFunction) - -DECLARE_BUILTIN_FUNCTION_R2(SinFunction) -DECLARE_BUILTIN_FUNCTION_R2(CosFunction) -DECLARE_BUILTIN_FUNCTION_R2(TanFunction) -DECLARE_BUILTIN_FUNCTION_R1(AsinFunction) -DECLARE_BUILTIN_FUNCTION_R1(AcosFunction) -DECLARE_BUILTIN_FUNCTION_R2(AtanFunction) -DECLARE_BUILTIN_FUNCTION_R2(SinhFunction) -DECLARE_BUILTIN_FUNCTION_R2(CoshFunction) -DECLARE_BUILTIN_FUNCTION_R2(TanhFunction) -DECLARE_BUILTIN_FUNCTION_R2(AsinhFunction) -DECLARE_BUILTIN_FUNCTION_R1(AcoshFunction) -DECLARE_BUILTIN_FUNCTION(AtanhFunction) -DECLARE_BUILTIN_FUNCTION_R1(Atan2Function) -DECLARE_BUILTIN_FUNCTION(RadiansToDefaultAngleUnitFunction) -DECLARE_BUILTIN_FUNCTION_R2(SincFunction) -DECLARE_BUILTIN_FUNCTION(CisFunction) - -DECLARE_BUILTIN_FUNCTION(ZetaFunction) -DECLARE_BUILTIN_FUNCTION(GammaFunction) -DECLARE_BUILTIN_FUNCTION(DigammaFunction) -DECLARE_BUILTIN_FUNCTION(BetaFunction) -DECLARE_BUILTIN_FUNCTION(AiryFunction) -DECLARE_BUILTIN_FUNCTION(BesseljFunction) -DECLARE_BUILTIN_FUNCTION(BesselyFunction) -DECLARE_BUILTIN_FUNCTION(ErfFunction) -DECLARE_BUILTIN_FUNCTION(ErfcFunction) - -DECLARE_BUILTIN_FUNCTION(TotalFunction) -DECLARE_BUILTIN_FUNCTION(PercentileFunction) -DECLARE_BUILTIN_FUNCTION(MinFunction) -DECLARE_BUILTIN_FUNCTION(MaxFunction) -DECLARE_BUILTIN_FUNCTION(ModeFunction) -DECLARE_BUILTIN_FUNCTION_RPI(RandFunction) -DECLARE_BUILTIN_FUNCTION_R2(RandnFunction) -DECLARE_BUILTIN_FUNCTION_RPI(RandPoissonFunction) - -DECLARE_BUILTIN_FUNCTION(DateFunction) -DECLARE_BUILTIN_FUNCTION(DateTimeFunction) -DECLARE_BUILTIN_FUNCTION(TimeValueFunction) -DECLARE_BUILTIN_FUNCTION(TimestampFunction) -DECLARE_BUILTIN_FUNCTION(TimestampToDateFunction) -DECLARE_BUILTIN_FUNCTION(DaysFunction) -DECLARE_BUILTIN_FUNCTION(YearFracFunction) -DECLARE_BUILTIN_FUNCTION(WeekFunction) -DECLARE_BUILTIN_FUNCTION(WeekdayFunction) -DECLARE_BUILTIN_FUNCTION(MonthFunction) -DECLARE_BUILTIN_FUNCTION(DayFunction) -DECLARE_BUILTIN_FUNCTION(YearFunction) -DECLARE_BUILTIN_FUNCTION(YeardayFunction) -DECLARE_BUILTIN_FUNCTION(TimeFunction) -DECLARE_BUILTIN_FUNCTION(AddDaysFunction) -DECLARE_BUILTIN_FUNCTION(AddMonthsFunction) -DECLARE_BUILTIN_FUNCTION(AddYearsFunction) - -DECLARE_BUILTIN_FUNCTION(LunarPhaseFunction) -DECLARE_BUILTIN_FUNCTION(NextLunarPhaseFunction) - -DECLARE_BUILTIN_FUNCTION(BinFunction) -DECLARE_BUILTIN_FUNCTION(OctFunction) -DECLARE_BUILTIN_FUNCTION(DecFunction) -DECLARE_BUILTIN_FUNCTION(HexFunction) -DECLARE_BUILTIN_FUNCTION(BaseFunction) -DECLARE_BUILTIN_FUNCTION(RomanFunction) -DECLARE_BUILTIN_FUNCTION(BijectiveFunction) - -DECLARE_BUILTIN_FUNCTION_PI(AsciiFunction) -DECLARE_BUILTIN_FUNCTION(CharFunction) - -DECLARE_BUILTIN_FUNCTION_PI(LengthFunction) -DECLARE_BUILTIN_FUNCTION(ConcatenateFunction) - -DECLARE_BUILTIN_FUNCTION(ReplaceFunction) -DECLARE_BUILTIN_FUNCTION(StripUnitsFunction) - -DECLARE_BUILTIN_FUNCTION(GenerateVectorFunction) -DECLARE_BUILTIN_FUNCTION(ForFunction) -DECLARE_BUILTIN_FUNCTION(SumFunction) -DECLARE_BUILTIN_FUNCTION(ProductFunction) -DECLARE_BUILTIN_FUNCTION(ProcessFunction) -DECLARE_BUILTIN_FUNCTION(ProcessMatrixFunction) -DECLARE_BUILTIN_FUNCTION(CustomSumFunction) -DECLARE_BUILTIN_FUNCTION(FunctionFunction) -DECLARE_BUILTIN_FUNCTION(SelectFunction) -DECLARE_BUILTIN_FUNCTION(TitleFunction) -DECLARE_BUILTIN_FUNCTION(IFFunction) -DECLARE_BUILTIN_FUNCTION(IsNumberFunction) -DECLARE_BUILTIN_FUNCTION(IsRealFunction) -DECLARE_BUILTIN_FUNCTION(IsRationalFunction) -DECLARE_BUILTIN_FUNCTION(IsIntegerFunction) -DECLARE_BUILTIN_FUNCTION(RepresentsNumberFunction) -DECLARE_BUILTIN_FUNCTION(RepresentsRealFunction) -DECLARE_BUILTIN_FUNCTION(RepresentsRationalFunction) -DECLARE_BUILTIN_FUNCTION(RepresentsIntegerFunction) -DECLARE_BUILTIN_FUNCTION(ErrorFunction) -DECLARE_BUILTIN_FUNCTION(WarningFunction) -DECLARE_BUILTIN_FUNCTION(MessageFunction) -DECLARE_BUILTIN_FUNCTION(SaveFunction) -DECLARE_BUILTIN_FUNCTION(LoadFunction) -DECLARE_BUILTIN_FUNCTION(ExportFunction) - -DECLARE_BUILTIN_FUNCTION(RegisterFunction) -DECLARE_BUILTIN_FUNCTION(StackFunction) - -DECLARE_BUILTIN_FUNCTION(DeriveFunction) -DECLARE_BUILTIN_FUNCTION(IntegrateFunction) -DECLARE_BUILTIN_FUNCTION(MonteCarloFunction) -DECLARE_BUILTIN_FUNCTION(RombergFunction) -DECLARE_BUILTIN_FUNCTION(SolveFunction) -DECLARE_BUILTIN_FUNCTION(SolveMultipleFunction) -DECLARE_BUILTIN_FUNCTION(DSolveFunction) -DECLARE_BUILTIN_FUNCTION(LimitFunction) - -DECLARE_BUILTIN_FUNCTION_R2(liFunction) -DECLARE_BUILTIN_FUNCTION_R2(LiFunction) -DECLARE_BUILTIN_FUNCTION_R2(EiFunction) -DECLARE_BUILTIN_FUNCTION_R2(SiFunction) -DECLARE_BUILTIN_FUNCTION_R2(CiFunction) -DECLARE_BUILTIN_FUNCTION_R2(ShiFunction) -DECLARE_BUILTIN_FUNCTION_R2(ChiFunction) -DECLARE_BUILTIN_FUNCTION_R2(IGammaFunction) -DECLARE_BUILTIN_FUNCTION_R2(GammaIncFunction) - -DECLARE_BUILTIN_FUNCTION(PlotFunction) +enum { + FUNCTION_ID_VECTOR = 1100, + FUNCTION_ID_LIMITS = 1101, + FUNCTION_ID_RANK = 1102, + FUNCTION_ID_SORT = 1103, + FUNCTION_ID_COMPONENT = 1104, + FUNCTION_ID_DIMENSION = 1105, + FUNCTION_ID_MATRIX = 1106, + FUNCTION_ID_MERGE_VECTORS = 1107, + FUNCTION_ID_MATRIX_TO_VECTOR = 1108, + FUNCTION_ID_AREA = 1109, + FUNCTION_ID_ROWS = 1110, + FUNCTION_ID_COLUMNS = 1111, + FUNCTION_ID_ROW = 1112, + FUNCTION_ID_COLUMN = 1113, + FUNCTION_ID_ELEMENTS = 1114, + FUNCTION_ID_ELEMENT = 1115, + FUNCTION_ID_TRANSPOSE = 1116, + FUNCTION_ID_IDENTITY = 1117, + FUNCTION_ID_DETERMINANT = 1118, + FUNCTION_ID_PERMANENT = 1119, + FUNCTION_ID_ADJOINT = 1120, + FUNCTION_ID_COFACTOR = 1121, + FUNCTION_ID_INVERSE = 1122, + FUNCTION_ID_MAGNITUDE = 1123, + FUNCTION_ID_HADAMARD = 1124, + FUNCTION_ID_ENTRYWISE = 1125, + FUNCTION_ID_LOAD = 1126, + FUNCTION_ID_EXPORT = 1127, + FUNCTION_ID_GENERATE_VECTOR = 1128, + FUNCTION_ID_SELECT = 1129, + FUNCTION_ID_PROCESS = 1130, + FUNCTION_ID_PROCESS_MATRIX = 1131, + FUNCTION_ID_SQRT = 1200, + FUNCTION_ID_CBRT = 1201, + FUNCTION_ID_ROOT = 1202, + FUNCTION_ID_SQUARE = 1203, + FUNCTION_ID_EXP = 1204, + FUNCTION_ID_LOG = 1205, + FUNCTION_ID_LOGN = 1206, + FUNCTION_ID_LAMBERT_W = 1207, + FUNCTION_ID_CIS = 1208, + FUNCTION_ID_SIN = 1300, + FUNCTION_ID_COS = 1301, + FUNCTION_ID_TAN = 1302, + FUNCTION_ID_ASIN = 1303, + FUNCTION_ID_ACOS = 1304, + FUNCTION_ID_ATAN = 1305, + FUNCTION_ID_SINH = 1306, + FUNCTION_ID_COSH = 1307, + FUNCTION_ID_TANH = 1308, + FUNCTION_ID_ASINH = 1309, + FUNCTION_ID_ACOSH = 1310, + FUNCTION_ID_ATANH = 1311, + FUNCTION_ID_SINC = 1312, + FUNCTION_ID_ATAN2 = 1313, + FUNCTION_ID_RADIANS_TO_DEFAULT_ANGLE_UNIT = 1314, + FUNCTION_ID_ZETA = 1400, + FUNCTION_ID_GAMMA = 1401, + FUNCTION_ID_DIGAMMA = 1402, + FUNCTION_ID_BETA = 1403, + FUNCTION_ID_AIRY = 1404, + FUNCTION_ID_BESSELJ = 1405, + FUNCTION_ID_BESSELY = 1406, + FUNCTION_ID_ERF = 1407, + FUNCTION_ID_ERFI = 1408, + FUNCTION_ID_ERFC = 1409, + FUNCTION_ID_POLYLOG = 1410, + FUNCTION_ID_HEAVISIDE = 1411, + FUNCTION_ID_DIRAC = 1412, + FUNCTION_ID_FACTORIAL = 1500, + FUNCTION_ID_DOUBLE_FACTORIAL = 1501, + FUNCTION_ID_MULTI_FACTORIAL = 1502, + FUNCTION_ID_BINOMIAL = 1503, + FUNCTION_ID_LOGINT = 1600, + FUNCTION_ID_FRESNEL_S = 1601, + FUNCTION_ID_FRESNEL_C = 1602, + FUNCTION_ID_EXPINT = 1603, + FUNCTION_ID_SININT = 1604, + FUNCTION_ID_COSINT = 1605, + FUNCTION_ID_SINHINT = 1606, + FUNCTION_ID_COSHINT = 1607, + FUNCTION_ID_I_GAMMA = 1608, + FUNCTION_ID_ABS = 1700, + FUNCTION_ID_GCD = 1701, + FUNCTION_ID_LCM = 1702, + FUNCTION_ID_SIGNUM = 1710, + FUNCTION_ID_ROUND = 1720, + FUNCTION_ID_FLOOR = 1721, + FUNCTION_ID_CEIL = 1722, + FUNCTION_ID_TRUNC = 1723, + FUNCTION_ID_NUMERATOR = 1730, + FUNCTION_ID_DENOMINATOR = 1731, + FUNCTION_ID_INT = 1732, + FUNCTION_ID_FRAC = 1733, + FUNCTION_ID_REM = 1734, + FUNCTION_ID_MOD = 1735, + FUNCTION_ID_BERNOULLI = 1740, + FUNCTION_ID_RE = 1750, + FUNCTION_ID_IM = 1751, + FUNCTION_ID_ARG = 1752, + FUNCTION_ID_DIFFERENTIATE = 1800, + FUNCTION_ID_LIMIT = 1810, + FUNCTION_ID_INTEGRATE = 1820, + FUNCTION_ID_MONTE_CARLO = 1821, + FUNCTION_ID_ROMBERG = 1822, + FUNCTION_ID_SUM = 1830, + FUNCTION_ID_PRODUCT = 1831, + FUNCTION_ID_SOLVE = 1840, + FUNCTION_ID_SOLVE_MULTIPLE = 1841, + FUNCTION_ID_D_SOLVE = 1842, + FUNCTION_ID_BIN = 1900, + FUNCTION_ID_OCT = 1901, + FUNCTION_ID_DEC = 1902, + FUNCTION_ID_HEX = 1903, + FUNCTION_ID_BASE = 1904, + FUNCTION_ID_ROMAN = 1905, + FUNCTION_ID_BIJECTIVE = 1906, + FUNCTION_ID_IS_NUMBER = 1920, + FUNCTION_ID_IS_REAL = 1921, + FUNCTION_ID_IS_RATIONAL = 1922, + FUNCTION_ID_IS_INTEGER = 1923, + FUNCTION_ID_ODD = 1924, + FUNCTION_ID_EVEN = 1925, + FUNCTION_ID_POLYNOMIAL_UNIT = 2000, + FUNCTION_ID_POLYNOMIAL_PRIMPART = 2001, + FUNCTION_ID_POLYNOMIAL_CONTENT = 2002, + FUNCTION_ID_COEFF = 2003, + FUNCTION_ID_L_COEFF = 2004, + FUNCTION_ID_T_COEFF = 2005, + FUNCTION_ID_DEGREE = 2006, + FUNCTION_ID_L_DEGREE = 2007, + FUNCTION_ID_BIT_XOR = 2100, + FUNCTION_ID_XOR = 2101, + FUNCTION_ID_BIT_CMP = 2102, + FUNCTION_ID_SHIFT = 2103, + FUNCTION_ID_CIRCULAR_SHIFT = 2104, + FUNCTION_ID_FOR = 2150, + FUNCTION_ID_IF = 2151, + FUNCTION_ID_TOTAL = 2200, + FUNCTION_ID_PERCENTILE = 2201, + FUNCTION_ID_MIN = 2202, + FUNCTION_ID_MAX = 2203, + FUNCTION_ID_MODE = 2204, + FUNCTION_ID_RAND = 2220, + FUNCTION_ID_RANDN = 2221, + FUNCTION_ID_RAND_POISSON = 2222, + FUNCTION_ID_DATE = 2300, + FUNCTION_ID_DATE_TIME = 2301, + FUNCTION_ID_TIME_VALUE = 2302, + FUNCTION_ID_TIMESTAMP = 2303, + FUNCTION_ID_TIMESTAMP_TO_DATE = 2304, + FUNCTION_ID_DAYS = 2305, + FUNCTION_ID_YEAR_FRAC = 2306, + FUNCTION_ID_WEEK = 2307, + FUNCTION_ID_WEEKDAY = 2308, + FUNCTION_ID_MONTH = 2309, + FUNCTION_ID_DAY = 2310, + FUNCTION_ID_YEAR = 2311, + FUNCTION_ID_YEARDAY = 2312, + FUNCTION_ID_TIME = 2313, + FUNCTION_ID_ADD_DAYS = 2320, + FUNCTION_ID_ADD_MONTHS = 2321, + FUNCTION_ID_ADD_YEARS = 2322, + FUNCTION_ID_LUNAR_PHASE = 2350, + FUNCTION_ID_NEXT_LUNAR_PHASE = 2351, + FUNCTION_ID_INTERVAL = 2400, + FUNCTION_ID_UNCERTAINTY = 2401, + FUNCTION_ID_ASCII = 2500, + FUNCTION_ID_CHAR = 2501, + FUNCTION_ID_LENGTH = 2502, + FUNCTION_ID_CONCATENATE = 2503, + FUNCTION_ID_REPRESENTS_NUMBER = 2600, + FUNCTION_ID_REPRESENTS_REAL = 2601, + FUNCTION_ID_REPRESENTS_RATIONAL = 2602, + FUNCTION_ID_REPRESENTS_INTEGER = 2603, + FUNCTION_ID_REPLACE = 2610, + FUNCTION_ID_STRIP_UNITS = 2620, + FUNCTION_ID_CUSTOM_SUM = 2630, + FUNCTION_ID_FUNCTION = 2640, + FUNCTION_ID_TITLE = 2650, + FUNCTION_ID_ERROR = 2660, + FUNCTION_ID_WARNING = 2661, + FUNCTION_ID_MESSAGE = 2662, + FUNCTION_ID_SAVE = 2670, + FUNCTION_ID_REGISTER = 2680, + FUNCTION_ID_STACK = 2681, + FUNCTION_ID_PLOT = 2690 +}; + +DECLARE_BUILTIN_FUNCTION(VectorFunction, FUNCTION_ID_VECTOR) +DECLARE_BUILTIN_FUNCTION(LimitsFunction, FUNCTION_ID_LIMITS) +DECLARE_BUILTIN_FUNCTION(RankFunction, FUNCTION_ID_RANK) +DECLARE_BUILTIN_FUNCTION(SortFunction, FUNCTION_ID_SORT) +DECLARE_BUILTIN_FUNCTION(ComponentFunction, FUNCTION_ID_COMPONENT) +DECLARE_BUILTIN_FUNCTION_PI(DimensionFunction, FUNCTION_ID_DIMENSION) +DECLARE_BUILTIN_FUNCTION(MatrixFunction, FUNCTION_ID_MATRIX) +DECLARE_BUILTIN_FUNCTION(MergeVectorsFunction, FUNCTION_ID_MERGE_VECTORS) +DECLARE_BUILTIN_FUNCTION(MatrixToVectorFunction, FUNCTION_ID_MATRIX_TO_VECTOR) +DECLARE_BUILTIN_FUNCTION(AreaFunction, FUNCTION_ID_AREA) +DECLARE_BUILTIN_FUNCTION_PI(RowsFunction, FUNCTION_ID_ROWS) +DECLARE_BUILTIN_FUNCTION_PI(ColumnsFunction, FUNCTION_ID_COLUMNS) +DECLARE_BUILTIN_FUNCTION(RowFunction, FUNCTION_ID_ROW) +DECLARE_BUILTIN_FUNCTION(ColumnFunction, FUNCTION_ID_COLUMN) +DECLARE_BUILTIN_FUNCTION_PI(ElementsFunction, FUNCTION_ID_ELEMENTS) +DECLARE_BUILTIN_FUNCTION(ElementFunction, FUNCTION_ID_ELEMENT) +DECLARE_BUILTIN_FUNCTION(TransposeFunction, FUNCTION_ID_TRANSPOSE) +DECLARE_BUILTIN_FUNCTION(IdentityMatrixFunction, FUNCTION_ID_IDENTITY) +DECLARE_BUILTIN_FUNCTION(DeterminantFunction, FUNCTION_ID_DETERMINANT) +DECLARE_BUILTIN_FUNCTION(PermanentFunction, FUNCTION_ID_PERMANENT) +DECLARE_BUILTIN_FUNCTION(AdjointFunction, FUNCTION_ID_ADJOINT) +DECLARE_BUILTIN_FUNCTION(CofactorFunction, FUNCTION_ID_COFACTOR) +DECLARE_BUILTIN_FUNCTION(InverseFunction, FUNCTION_ID_INVERSE) +DECLARE_BUILTIN_FUNCTION(MagnitudeFunction, FUNCTION_ID_MAGNITUDE) +DECLARE_BUILTIN_FUNCTION(HadamardFunction, FUNCTION_ID_HADAMARD) +DECLARE_BUILTIN_FUNCTION(EntrywiseFunction, FUNCTION_ID_ENTRYWISE) +DECLARE_BUILTIN_FUNCTION(LoadFunction, FUNCTION_ID_LOAD) +DECLARE_BUILTIN_FUNCTION(ExportFunction, FUNCTION_ID_EXPORT) +DECLARE_BUILTIN_FUNCTION(GenerateVectorFunction, FUNCTION_ID_GENERATE_VECTOR) +DECLARE_BUILTIN_FUNCTION(SelectFunction, FUNCTION_ID_SELECT) +DECLARE_BUILTIN_FUNCTION(ProcessFunction, FUNCTION_ID_PROCESS) +DECLARE_BUILTIN_FUNCTION(ProcessMatrixFunction, FUNCTION_ID_PROCESS_MATRIX) + +DECLARE_BUILTIN_FUNCTION_R(SqrtFunction, FUNCTION_ID_SQRT) +DECLARE_BUILTIN_FUNCTION(CbrtFunction, FUNCTION_ID_CBRT) +DECLARE_BUILTIN_FUNCTION_R(RootFunction, FUNCTION_ID_ROOT) +DECLARE_BUILTIN_FUNCTION(SquareFunction, FUNCTION_ID_SQUARE) +DECLARE_BUILTIN_FUNCTION(ExpFunction, FUNCTION_ID_EXP) +DECLARE_BUILTIN_FUNCTION_R(LogFunction, FUNCTION_ID_LOG) +DECLARE_BUILTIN_FUNCTION(LognFunction, FUNCTION_ID_LOGN) +DECLARE_BUILTIN_FUNCTION_R3(LambertWFunction, FUNCTION_ID_LAMBERT_W) +DECLARE_BUILTIN_FUNCTION(CisFunction, FUNCTION_ID_CIS) + +DECLARE_BUILTIN_FUNCTION_R2(SinFunction, FUNCTION_ID_SIN) +DECLARE_BUILTIN_FUNCTION_R2(CosFunction, FUNCTION_ID_COS) +DECLARE_BUILTIN_FUNCTION_R2(TanFunction, FUNCTION_ID_TAN) +DECLARE_BUILTIN_FUNCTION_R1(AsinFunction, FUNCTION_ID_ASIN) +DECLARE_BUILTIN_FUNCTION_R1(AcosFunction, FUNCTION_ID_ACOS) +DECLARE_BUILTIN_FUNCTION_R2(AtanFunction, FUNCTION_ID_ATAN) +DECLARE_BUILTIN_FUNCTION_R2(SinhFunction, FUNCTION_ID_SINH) +DECLARE_BUILTIN_FUNCTION_R2(CoshFunction, FUNCTION_ID_COSH) +DECLARE_BUILTIN_FUNCTION_R2(TanhFunction, FUNCTION_ID_TANH) +DECLARE_BUILTIN_FUNCTION_R2(AsinhFunction, FUNCTION_ID_ASINH) +DECLARE_BUILTIN_FUNCTION_R1(AcoshFunction, FUNCTION_ID_ACOSH) +DECLARE_BUILTIN_FUNCTION(AtanhFunction, FUNCTION_ID_ATANH) +DECLARE_BUILTIN_FUNCTION_R2(SincFunction, FUNCTION_ID_SINC) +DECLARE_BUILTIN_FUNCTION_R1(Atan2Function, FUNCTION_ID_ATAN2) +DECLARE_BUILTIN_FUNCTION(RadiansToDefaultAngleUnitFunction, FUNCTION_ID_RADIANS_TO_DEFAULT_ANGLE_UNIT) + +DECLARE_BUILTIN_FUNCTION(ZetaFunction, FUNCTION_ID_ZETA) +DECLARE_BUILTIN_FUNCTION(GammaFunction, FUNCTION_ID_GAMMA) +DECLARE_BUILTIN_FUNCTION(DigammaFunction, FUNCTION_ID_DIGAMMA) +DECLARE_BUILTIN_FUNCTION(BetaFunction, FUNCTION_ID_BETA) +DECLARE_BUILTIN_FUNCTION(AiryFunction, FUNCTION_ID_AIRY) +DECLARE_BUILTIN_FUNCTION(BesseljFunction, FUNCTION_ID_BESSELJ) +DECLARE_BUILTIN_FUNCTION(BesselyFunction, FUNCTION_ID_BESSELY) +DECLARE_BUILTIN_FUNCTION_R(ErfFunction, FUNCTION_ID_ERF) +DECLARE_BUILTIN_FUNCTION_R(ErfiFunction, FUNCTION_ID_ERFI) +DECLARE_BUILTIN_FUNCTION_R(ErfcFunction, FUNCTION_ID_ERFC) +DECLARE_BUILTIN_FUNCTION_R2(LiFunction, FUNCTION_ID_POLYLOG) + +DECLARE_BUILTIN_FUNCTION_R(HeavisideFunction, FUNCTION_ID_HEAVISIDE) +DECLARE_BUILTIN_FUNCTION_R(DiracFunction, FUNCTION_ID_DIRAC) + +DECLARE_BUILTIN_FUNCTION_R2(liFunction, FUNCTION_ID_LOGINT) +DECLARE_BUILTIN_FUNCTION_R(FresnelSFunction, FUNCTION_ID_FRESNEL_S) +DECLARE_BUILTIN_FUNCTION_R(FresnelCFunction, FUNCTION_ID_FRESNEL_C) +DECLARE_BUILTIN_FUNCTION_R2(EiFunction, FUNCTION_ID_EXPINT) +DECLARE_BUILTIN_FUNCTION_R2(SiFunction, FUNCTION_ID_SININT) +DECLARE_BUILTIN_FUNCTION_R2(CiFunction, FUNCTION_ID_COSINT) +DECLARE_BUILTIN_FUNCTION_R2(ShiFunction, FUNCTION_ID_SINHINT) +DECLARE_BUILTIN_FUNCTION_R2(ChiFunction, FUNCTION_ID_COSHINT) +DECLARE_BUILTIN_FUNCTION_R2(IGammaFunction, FUNCTION_ID_I_GAMMA) + +DECLARE_BUILTIN_FUNCTION(DeriveFunction, FUNCTION_ID_DIFFERENTIATE) +DECLARE_BUILTIN_FUNCTION(IntegrateFunction, FUNCTION_ID_INTEGRATE) +DECLARE_BUILTIN_FUNCTION(LimitFunction, FUNCTION_ID_LIMIT) +DECLARE_BUILTIN_FUNCTION(MonteCarloFunction, FUNCTION_ID_MONTE_CARLO) +DECLARE_BUILTIN_FUNCTION(RombergFunction, FUNCTION_ID_ROMBERG) + +DECLARE_BUILTIN_FUNCTION(SumFunction, FUNCTION_ID_SUM) +DECLARE_BUILTIN_FUNCTION(ProductFunction, FUNCTION_ID_PRODUCT) +DECLARE_BUILTIN_FUNCTION(SolveFunction, FUNCTION_ID_SOLVE) +DECLARE_BUILTIN_FUNCTION(SolveMultipleFunction, FUNCTION_ID_SOLVE_MULTIPLE) +DECLARE_BUILTIN_FUNCTION(DSolveFunction, FUNCTION_ID_D_SOLVE) + +DECLARE_BUILTIN_FUNCTION_R(FactorialFunction, FUNCTION_ID_FACTORIAL) +DECLARE_BUILTIN_FUNCTION_R(DoubleFactorialFunction, FUNCTION_ID_DOUBLE_FACTORIAL) +DECLARE_BUILTIN_FUNCTION_R(MultiFactorialFunction, FUNCTION_ID_MULTI_FACTORIAL) +DECLARE_BUILTIN_FUNCTION(BinomialFunction, FUNCTION_ID_BINOMIAL) + +DECLARE_BUILTIN_FUNCTION_R(ReFunction, FUNCTION_ID_RE) +DECLARE_BUILTIN_FUNCTION_R(ImFunction, FUNCTION_ID_IM) +DECLARE_BUILTIN_FUNCTION_R2(ArgFunction, FUNCTION_ID_ARG) + +DECLARE_BUILTIN_FUNCTION_R(AbsFunction, FUNCTION_ID_ABS) +DECLARE_BUILTIN_FUNCTION(GcdFunction, FUNCTION_ID_GCD) +DECLARE_BUILTIN_FUNCTION(LcmFunction, FUNCTION_ID_LCM) +DECLARE_BUILTIN_FUNCTION_R(SignumFunction, FUNCTION_ID_SIGNUM) +DECLARE_BUILTIN_FUNCTION_R(RoundFunction, FUNCTION_ID_ROUND) +DECLARE_BUILTIN_FUNCTION_R(FloorFunction, FUNCTION_ID_FLOOR) +DECLARE_BUILTIN_FUNCTION_R(CeilFunction, FUNCTION_ID_CEIL) +DECLARE_BUILTIN_FUNCTION_R(TruncFunction, FUNCTION_ID_TRUNC) +DECLARE_BUILTIN_FUNCTION(NumeratorFunction, FUNCTION_ID_NUMERATOR) +DECLARE_BUILTIN_FUNCTION(DenominatorFunction, FUNCTION_ID_DENOMINATOR) +DECLARE_BUILTIN_FUNCTION(IntFunction, FUNCTION_ID_INT) +DECLARE_BUILTIN_FUNCTION(FracFunction, FUNCTION_ID_FRAC) +DECLARE_BUILTIN_FUNCTION(RemFunction, FUNCTION_ID_REM) +DECLARE_BUILTIN_FUNCTION(ModFunction, FUNCTION_ID_MOD) +DECLARE_BUILTIN_FUNCTION(BernoulliFunction, FUNCTION_ID_BERNOULLI) + +DECLARE_BUILTIN_FUNCTION(BinFunction, FUNCTION_ID_BIN) +DECLARE_BUILTIN_FUNCTION(OctFunction, FUNCTION_ID_OCT) +DECLARE_BUILTIN_FUNCTION(DecFunction, FUNCTION_ID_DEC) +DECLARE_BUILTIN_FUNCTION(HexFunction, FUNCTION_ID_HEX) +DECLARE_BUILTIN_FUNCTION(BaseFunction, FUNCTION_ID_BASE) +DECLARE_BUILTIN_FUNCTION(RomanFunction, FUNCTION_ID_ROMAN) +DECLARE_BUILTIN_FUNCTION(BijectiveFunction, FUNCTION_ID_BIJECTIVE) + +DECLARE_BUILTIN_FUNCTION(IsNumberFunction, FUNCTION_ID_IS_NUMBER) +DECLARE_BUILTIN_FUNCTION(IsRealFunction, FUNCTION_ID_IS_REAL) +DECLARE_BUILTIN_FUNCTION(IsRationalFunction, FUNCTION_ID_IS_RATIONAL) +DECLARE_BUILTIN_FUNCTION(IsIntegerFunction, FUNCTION_ID_IS_INTEGER) +DECLARE_BUILTIN_FUNCTION_B(OddFunction, FUNCTION_ID_ODD) +DECLARE_BUILTIN_FUNCTION_B(EvenFunction, FUNCTION_ID_EVEN) + +DECLARE_BUILTIN_FUNCTION(PolynomialUnitFunction, FUNCTION_ID_POLYNOMIAL_UNIT) +DECLARE_BUILTIN_FUNCTION(PolynomialPrimpartFunction, FUNCTION_ID_POLYNOMIAL_PRIMPART) +DECLARE_BUILTIN_FUNCTION(PolynomialContentFunction, FUNCTION_ID_POLYNOMIAL_CONTENT) +DECLARE_BUILTIN_FUNCTION(CoeffFunction, FUNCTION_ID_COEFF) +DECLARE_BUILTIN_FUNCTION(LCoeffFunction, FUNCTION_ID_L_COEFF) +DECLARE_BUILTIN_FUNCTION(TCoeffFunction, FUNCTION_ID_T_COEFF) +DECLARE_BUILTIN_FUNCTION(DegreeFunction, FUNCTION_ID_DEGREE) +DECLARE_BUILTIN_FUNCTION(LDegreeFunction, FUNCTION_ID_L_DEGREE) + +DECLARE_BUILTIN_FUNCTION(BitXorFunction, FUNCTION_ID_BIT_XOR) +DECLARE_BUILTIN_FUNCTION_B(XorFunction, FUNCTION_ID_XOR) +DECLARE_BUILTIN_FUNCTION(BitCmpFunction, FUNCTION_ID_BIT_CMP) +DECLARE_BUILTIN_FUNCTION(ShiftFunction, FUNCTION_ID_SHIFT) +DECLARE_BUILTIN_FUNCTION(CircularShiftFunction, FUNCTION_ID_CIRCULAR_SHIFT) + +DECLARE_BUILTIN_FUNCTION(ForFunction, FUNCTION_ID_FOR) +DECLARE_BUILTIN_FUNCTION(IFFunction, FUNCTION_ID_IF) + +DECLARE_BUILTIN_FUNCTION(TotalFunction, FUNCTION_ID_TOTAL) +DECLARE_BUILTIN_FUNCTION(PercentileFunction, FUNCTION_ID_PERCENTILE) +DECLARE_BUILTIN_FUNCTION(MinFunction, FUNCTION_ID_MIN) +DECLARE_BUILTIN_FUNCTION(MaxFunction, FUNCTION_ID_MAX) +DECLARE_BUILTIN_FUNCTION(ModeFunction, FUNCTION_ID_MODE) +DECLARE_BUILTIN_FUNCTION_RPI(RandFunction, FUNCTION_ID_RAND) +DECLARE_BUILTIN_FUNCTION_R2(RandnFunction, FUNCTION_ID_RANDN) +DECLARE_BUILTIN_FUNCTION_RPI(RandPoissonFunction, FUNCTION_ID_RAND_POISSON) + +DECLARE_BUILTIN_FUNCTION(DateFunction, FUNCTION_ID_DATE) +DECLARE_BUILTIN_FUNCTION(DateTimeFunction, FUNCTION_ID_DATE_TIME) +DECLARE_BUILTIN_FUNCTION(TimeValueFunction, FUNCTION_ID_TIME_VALUE) +DECLARE_BUILTIN_FUNCTION(TimestampFunction, FUNCTION_ID_TIMESTAMP) +DECLARE_BUILTIN_FUNCTION(TimestampToDateFunction, FUNCTION_ID_TIMESTAMP_TO_DATE) +DECLARE_BUILTIN_FUNCTION(DaysFunction, FUNCTION_ID_DAYS) +DECLARE_BUILTIN_FUNCTION(YearFracFunction, FUNCTION_ID_YEAR_FRAC) +DECLARE_BUILTIN_FUNCTION(WeekFunction, FUNCTION_ID_WEEK) +DECLARE_BUILTIN_FUNCTION(WeekdayFunction, FUNCTION_ID_WEEKDAY) +DECLARE_BUILTIN_FUNCTION(MonthFunction, FUNCTION_ID_MONTH) +DECLARE_BUILTIN_FUNCTION(DayFunction, FUNCTION_ID_DAY) +DECLARE_BUILTIN_FUNCTION(YearFunction, FUNCTION_ID_YEAR) +DECLARE_BUILTIN_FUNCTION(YeardayFunction, FUNCTION_ID_YEARDAY) +DECLARE_BUILTIN_FUNCTION(TimeFunction, FUNCTION_ID_TIME) +DECLARE_BUILTIN_FUNCTION(AddDaysFunction, FUNCTION_ID_ADD_DAYS) +DECLARE_BUILTIN_FUNCTION(AddMonthsFunction, FUNCTION_ID_ADD_MONTHS) +DECLARE_BUILTIN_FUNCTION(AddYearsFunction, FUNCTION_ID_ADD_YEARS) +DECLARE_BUILTIN_FUNCTION(LunarPhaseFunction, FUNCTION_ID_LUNAR_PHASE) +DECLARE_BUILTIN_FUNCTION(NextLunarPhaseFunction, FUNCTION_ID_NEXT_LUNAR_PHASE) + +DECLARE_BUILTIN_FUNCTION_PI(AsciiFunction, FUNCTION_ID_ASCII) +DECLARE_BUILTIN_FUNCTION(CharFunction, FUNCTION_ID_CHAR) +DECLARE_BUILTIN_FUNCTION_PI(LengthFunction, FUNCTION_ID_LENGTH) +DECLARE_BUILTIN_FUNCTION(ConcatenateFunction, FUNCTION_ID_CONCATENATE) +DECLARE_BUILTIN_FUNCTION(ReplaceFunction, FUNCTION_ID_REPLACE) +DECLARE_BUILTIN_FUNCTION(StripUnitsFunction, FUNCTION_ID_STRIP_UNITS) +DECLARE_BUILTIN_FUNCTION(CustomSumFunction, FUNCTION_ID_CUSTOM_SUM) +DECLARE_BUILTIN_FUNCTION(FunctionFunction, FUNCTION_ID_FUNCTION) +DECLARE_BUILTIN_FUNCTION(TitleFunction, FUNCTION_ID_TITLE) +DECLARE_BUILTIN_FUNCTION(RepresentsNumberFunction, FUNCTION_ID_REPRESENTS_NUMBER) +DECLARE_BUILTIN_FUNCTION(RepresentsRealFunction, FUNCTION_ID_REPRESENTS_REAL) +DECLARE_BUILTIN_FUNCTION(RepresentsRationalFunction, FUNCTION_ID_REPRESENTS_RATIONAL) +DECLARE_BUILTIN_FUNCTION(RepresentsIntegerFunction, FUNCTION_ID_REPRESENTS_INTEGER) +DECLARE_BUILTIN_FUNCTION(ErrorFunction, FUNCTION_ID_ERROR) +DECLARE_BUILTIN_FUNCTION(WarningFunction, FUNCTION_ID_WARNING) +DECLARE_BUILTIN_FUNCTION(MessageFunction, FUNCTION_ID_MESSAGE) +DECLARE_BUILTIN_FUNCTION(SaveFunction, FUNCTION_ID_SAVE) +DECLARE_BUILTIN_FUNCTION(RegisterFunction, FUNCTION_ID_REGISTER) +DECLARE_BUILTIN_FUNCTION(StackFunction, FUNCTION_ID_STACK) +DECLARE_BUILTIN_FUNCTION(PlotFunction, FUNCTION_ID_PLOT) +DECLARE_BUILTIN_FUNCTION_R(IntervalFunction, FUNCTION_ID_INTERVAL) +DECLARE_BUILTIN_FUNCTION(UncertaintyFunction, FUNCTION_ID_UNCERTAINTY) #endif diff -Nru libqalculate-3.6.0/libqalculate/BuiltinFunctions-logical.cc libqalculate-3.7.0/libqalculate/BuiltinFunctions-logical.cc --- libqalculate-3.6.0/libqalculate/BuiltinFunctions-logical.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/BuiltinFunctions-logical.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,318 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Number.h" +#include "Calculator.h" +#include "Variable.h" +#include "Unit.h" + +#include +#include +#include +#include + +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +#define FR_FUNCTION_2(FUNC) Number nr(vargs[0].number()); if(!nr.FUNC(vargs[1].number()) || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate() && !vargs[1].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex() && !vargs[1].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity() && !vargs[1].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;} + +BitXorFunction::BitXorFunction() : MathFunction("xor", 2) { + ArgumentSet *arg = new ArgumentSet(); + arg->addArgument(new IntegerArgument("", ARGUMENT_MIN_MAX_NONE)); + arg->addArgument(new VectorArgument); + setArgumentDefinition(1, arg); + arg = new ArgumentSet(); + arg->addArgument(new IntegerArgument("", ARGUMENT_MIN_MAX_NONE)); + arg->addArgument(new VectorArgument); + setArgumentDefinition(2, arg); +} +int BitXorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isNumber() && vargs[1].isNumber()) { + Number nr(vargs[0].number()); + if(nr.bitXor(vargs[1].number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || vargs[0].number().isApproximate() || vargs[1].number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || vargs[0].number().isComplex() || vargs[1].number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || vargs[0].number().includesInfinity() || vargs[1].number().includesInfinity())) { + mstruct.set(nr, true); + return 1; + } + } else if(vargs[0].isVector() && vargs[1].isVector()) { + int i1 = 0, i2 = 1; + if(vargs[0].size() < vargs[1].size()) { + i1 = 1; + i2 = 0; + } + mstruct.clearVector(); + mstruct.resizeVector(vargs[i1].size(), m_undefined); + size_t i = 0; + for(; i < vargs[i2].size(); i++) { + mstruct[i].set(CALCULATOR->getFunctionById(FUNCTION_ID_XOR), &vargs[i1][i], &vargs[i2][0], NULL); + } + for(; i < vargs[i1].size(); i++) { + mstruct[i] = vargs[i1][i]; + mstruct[i].add(m_zero, OPERATION_GREATER); + } + return 1; + } + mstruct = vargs[0]; + mstruct.add(vargs[1], OPERATION_BITWISE_XOR); + return 0; +} +XorFunction::XorFunction() : MathFunction("lxor", 2) { +} +int XorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + int b0, b1; + if(vargs[0].representsNonPositive(true)) { + b0 = 0; + } else if(vargs[0].representsPositive(true)) { + b0 = 1; + } else { + b0 = -1; + } + if(vargs[1].representsNonPositive(true)) { + b1 = 0; + } else if(vargs[1].representsPositive(true)) { + b1 = 1; + } else { + b1 = -1; + } + if((b0 == 1 && b1 == 0) || (b0 == 0 && b1 == 1)) { + mstruct = m_one; + return 1; + } else if(b0 >= 0 && b1 >= 0) { + return 1; + } else if(b0 == 0) { + mstruct = vargs[1]; + mstruct.add(m_zero, OPERATION_GREATER); + return 1; + } else if(b0 == 1) { + mstruct = vargs[1]; + mstruct.add(m_zero, OPERATION_EQUALS_LESS); + return 1; + } else if(b1 == 0) { + mstruct = vargs[0]; + mstruct.add(m_zero, OPERATION_GREATER); + return 1; + } else if(b1 == 1) { + mstruct = vargs[0]; + mstruct.add(m_zero, OPERATION_EQUALS_LESS); + return 1; + } + mstruct = vargs[1]; + mstruct.setLogicalNot(); + mstruct.add(vargs[0], OPERATION_LOGICAL_AND); + MathStructure mstruct2(vargs[0]); + mstruct2.setLogicalNot(); + mstruct2.add(vargs[1], OPERATION_LOGICAL_AND); + mstruct.add(mstruct2, OPERATION_LOGICAL_OR); + return 1; +} + +ShiftFunction::ShiftFunction() : MathFunction("shift", 2, 3) { + setArgumentDefinition(1, new IntegerArgument()); + setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG)); + setArgumentDefinition(3, new BooleanArgument()); + setDefaultValue(3, "1"); +} +int ShiftFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs.size() >= 3 && !vargs[2].number().getBoolean() && vargs[1].number().isNegative()) { + Number nr(vargs[0].number()); + Number nr_div(vargs[1].number()); + if(!nr_div.negate() || !nr_div.exp2() || !nr.divide(nr_div) || !nr.trunc()) return false; + mstruct.set(nr); + return 1; + } + FR_FUNCTION_2(shift) +} +CircularShiftFunction::CircularShiftFunction() : MathFunction("bitrot", 2, 4) { + setArgumentDefinition(1, new IntegerArgument()); + setArgumentDefinition(2, new IntegerArgument()); + setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_UINT)); + setArgumentDefinition(4, new BooleanArgument()); + setDefaultValue(3, "0"); + setDefaultValue(4, "1"); +} +int CircularShiftFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].number().isZero()) { + mstruct.clear(); + return 1; + } + Number nr(vargs[0].number()); + unsigned int bits = vargs[2].number().uintValue(); + if(bits == 0) { + bits = nr.integerLength(); + if(bits <= 8) bits = 8; + else if(bits <= 16) bits = 16; + else if(bits <= 32) bits = 32; + else if(bits <= 64) bits = 64; + else if(bits <= 128) bits = 128; + else { + bits = (unsigned int) ::ceil(::log2(bits)); + bits = ::pow(2, bits); + } + } + Number nr_n(vargs[1].number()); + nr_n.rem(bits); + if(nr_n.isZero()) { + mstruct = nr; + return 1; + } + PrintOptions po; + po.base = BASE_BINARY; + po.base_display = BASE_DISPLAY_NORMAL; + po.binary_bits = bits; + string str = nr.print(po); + remove_blanks(str); + if(str.length() < bits) return 0; + if(nr_n.isNegative()) { + nr_n.negate(); + std::rotate(str.rbegin(), str.rbegin() + nr_n.uintValue(), str.rend()); + } else { + std::rotate(str.begin(), str.begin() + nr_n.uintValue(), str.end()); + } + ParseOptions pao; + pao.base = BASE_BINARY; + pao.twos_complement = vargs[3].number().getBoolean(); + mstruct = Number(str, pao); + return 1; +} +BitCmpFunction::BitCmpFunction() : MathFunction("bitcmp", 1, 3) { + setArgumentDefinition(1, new IntegerArgument()); + setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_UINT)); + setDefaultValue(2, "0"); + setArgumentDefinition(3, new BooleanArgument()); + setDefaultValue(3, "0"); +} +int BitCmpFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + Number nr(vargs[0].number()); + if(vargs.size() >= 3 && vargs[2].number().getBoolean()) { + if(nr.bitNot()) { + mstruct = nr; + return 1; + } + return 0; + } + unsigned int bits = vargs[1].number().uintValue(); + if(bits == 0) { + bits = nr.integerLength(); + if(bits <= 8) bits = 8; + else if(bits <= 16) bits = 16; + else if(bits <= 32) bits = 32; + else if(bits <= 64) bits = 64; + else if(bits <= 128) bits = 128; + else { + bits = (unsigned int) ::ceil(::log2(bits)); + bits = ::pow(2, bits); + } + } + if(nr.bitCmp(bits)) { + mstruct = nr; + return 1; + } + return 0; +} + +IFFunction::IFFunction() : MathFunction("if", 3, 4) { + setArgumentDefinition(4, new BooleanArgument()); + setDefaultValue(4, "0"); +} +int IFFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isNumber()) { + int result = vargs[0].number().getBoolean(); + if(result > 0) { + mstruct = vargs[1]; + } else if(result == 0 || vargs[3].isOne()) { + mstruct = vargs[2]; + } else { + return 0; + } + return 1; + } + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct[i].isNumber() && vargs[3].isZero()) { + return -1; + } + int result = mstruct[i].number().getBoolean(); + if(result > 0) { + if(vargs[1].isVector() && vargs[1].size() == vargs[0].size()) { + mstruct = vargs[1][i]; + } else { + mstruct = vargs[1]; + } + return 1; + } else if(result < 0 && vargs[3].isZero()) { + return -1; + } + } + mstruct = vargs[2]; + return 1; + } + if(mstruct.isNumber()) { + int result = mstruct.number().getBoolean(); + if(result > 0) { + mstruct = vargs[1]; + } else if(result == 0 || vargs[3].isOne()) { + mstruct = vargs[2]; + } else { + return -1; + } + return 1; + } + if(vargs[3].isOne()) { + mstruct = vargs[2]; + return 1; + } + return -1; +} +ForFunction::ForFunction() : MathFunction("for", 7) { + setArgumentDefinition(2, new SymbolicArgument()); + setArgumentDefinition(7, new SymbolicArgument()); +} +int ForFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + + mstruct = vargs[4]; + MathStructure mcounter = vargs[0]; + MathStructure mtest; + MathStructure mcount; + MathStructure mupdate; + while(true) { + mtest = vargs[2]; + mtest.replace(vargs[1], mcounter); + mtest.eval(eo); + if(!mtest.isNumber() || CALCULATOR->aborted()) return 0; + if(!mtest.number().getBoolean()) { + break; + } + if(vargs[5].isComparison() && vargs[5].comparisonType() == COMPARISON_EQUALS && vargs[5][0] == vargs[6]) mupdate = vargs[5][1]; + else mupdate = vargs[5]; + mupdate.replace(vargs[1], mcounter, vargs[6], mstruct); + mstruct = mupdate; + mstruct.calculatesub(eo, eo, false); + + if(vargs[3].isComparison() && vargs[3].comparisonType() == COMPARISON_EQUALS && vargs[3][0] == vargs[1]) mcount = vargs[3][1]; + else mcount = vargs[3]; + mcount.replace(vargs[1], mcounter); + mcounter = mcount; + mcounter.calculatesub(eo, eo, false); + } + return 1; + +} + diff -Nru libqalculate-3.6.0/libqalculate/BuiltinFunctions-matrixvector.cc libqalculate-3.7.0/libqalculate/BuiltinFunctions-matrixvector.cc --- libqalculate-3.6.0/libqalculate/BuiltinFunctions-matrixvector.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/BuiltinFunctions-matrixvector.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,639 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Number.h" +#include "Calculator.h" +#include "Variable.h" +#include "Unit.h" + +#include +#include +#include +#include + +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +VectorFunction::VectorFunction() : MathFunction("vector", -1) { +} +int VectorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = vargs; + mstruct.setType(STRUCT_VECTOR); + return 1; +} +MatrixFunction::MatrixFunction() : MathFunction("matrix", 3) { + Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE); + arg->setHandleVector(false); + setArgumentDefinition(1, arg); + arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE); + arg->setHandleVector(false); + setArgumentDefinition(2, arg); + setArgumentDefinition(3, new VectorArgument()); +} +int MatrixFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + size_t rows = (size_t) vargs[0].number().uintValue(); + size_t columns = (size_t) vargs[1].number().uintValue(); + mstruct.clearMatrix(); mstruct.resizeMatrix(rows, columns, m_zero); + size_t r = 1, c = 1; + for(size_t i = 0; i < vargs[2].size(); i++) { + if(r > rows || c > columns) { + CALCULATOR->error(false, _("Too many elements (%s) for the dimensions (%sx%s) of the matrix."), i2s(vargs[2].size()).c_str(), i2s(rows).c_str(), i2s(columns).c_str(), NULL); + break; + } + mstruct[r - 1][c - 1] = vargs[2][i]; + if(c == columns) { + c = 1; + r++; + } else { + c++; + } + } + return 1; +} +RankFunction::RankFunction() : MathFunction("rank", 1, 2) { + setArgumentDefinition(1, new VectorArgument("")); + setArgumentDefinition(2, new BooleanArgument("")); + setDefaultValue(2, "1"); +} +int RankFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = vargs[0]; + return mstruct.rankVector(vargs[1].number().getBoolean()); +} +SortFunction::SortFunction() : MathFunction("sort", 1, 2) { + setArgumentDefinition(1, new VectorArgument("")); + setArgumentDefinition(2, new BooleanArgument("")); + setDefaultValue(2, "1"); +} +int SortFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = vargs[0]; + return mstruct.sortVector(vargs[1].number().getBoolean()); +} +MergeVectorsFunction::MergeVectorsFunction() : MathFunction("mergevectors", 1, -1) { + setArgumentDefinition(1, new VectorArgument("")); + setArgumentDefinition(2, new VectorArgument("")); +} +int MergeVectorsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct.clearVector(); + for(size_t i = 0; i < vargs.size(); i++) { + if(CALCULATOR->aborted()) return 0; + if(vargs[i].isVector()) { + for(size_t i2 = 0; i2 < vargs[i].size(); i2++) { + mstruct.addChild(vargs[i][i2]); + } + } else { + mstruct.addChild(vargs[i]); + } + } + return 1; +} +MatrixToVectorFunction::MatrixToVectorFunction() : MathFunction("matrix2vector", 1) { + setArgumentDefinition(1, new MatrixArgument()); +} +int MatrixToVectorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + vargs[0].matrixToVector(mstruct); + return 1; +} +RowFunction::RowFunction() : MathFunction("row", 2) { + setArgumentDefinition(1, new MatrixArgument()); + setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); +} +int RowFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + size_t row = (size_t) vargs[1].number().uintValue(); + if(row > vargs[0].rows()) { + CALCULATOR->error(true, _("Row %s does not exist in matrix."), format_and_print(vargs[1]).c_str(), NULL); + return 0; + } + vargs[0].rowToVector(row, mstruct); + return 1; +} +ColumnFunction::ColumnFunction() : MathFunction("column", 2) { + setArgumentDefinition(1, new MatrixArgument()); + setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); +} +int ColumnFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + size_t col = (size_t) vargs[1].number().uintValue(); + if(col > vargs[0].columns()) { + CALCULATOR->error(true, _("Column %s does not exist in matrix."), format_and_print(vargs[1]).c_str(), NULL); + return 0; + } + vargs[0].columnToVector(col, mstruct); + return 1; +} +RowsFunction::RowsFunction() : MathFunction("rows", 1) { + setArgumentDefinition(1, new VectorArgument("")); +} +int RowsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + if(!vargs[0].isMatrix()) mstruct = m_one; + else mstruct = (int) vargs[0].rows(); + return 1; +} +ColumnsFunction::ColumnsFunction() : MathFunction("columns", 1) { + setArgumentDefinition(1, new VectorArgument("")); +} +int ColumnsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + if(!vargs[0].isMatrix()) mstruct = (int) vargs[0].countChildren(); + else mstruct = (int) vargs[0].columns(); + return 1; +} +ElementsFunction::ElementsFunction() : MathFunction("elements", 1) { + setArgumentDefinition(1, new VectorArgument("")); +} +int ElementsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + if(vargs[0].isMatrix()) { + mstruct = (int) (vargs[0].rows() * vargs[0].columns()); + } else { + mstruct = (int) vargs[0].countChildren(); + } + return 1; +} +ElementFunction::ElementFunction() : MathFunction("element", 2, 3) { + setArgumentDefinition(1, new VectorArgument("")); + setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); + setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SIZE)); + setDefaultValue(3, "0"); +} +int ElementFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + if(vargs[2].number().isPositive() && vargs[0].isMatrix()) { + size_t row = (size_t) vargs[1].number().uintValue(); + size_t col = (size_t) vargs[2].number().uintValue(); + bool b = true; + if(col > vargs[0].columns()) { + CALCULATOR->error(true, _("Column %s does not exist in matrix."), format_and_print(vargs[2]).c_str(), NULL); + b = false; + } + if(row > vargs[0].rows()) { + CALCULATOR->error(true, _("Row %s does not exist in matrix."), format_and_print(vargs[1]).c_str(), NULL); + b = false; + } + if(b) { + const MathStructure *em = vargs[0].getElement(row, col); + if(em) mstruct = *em; + else b = false; + } + return b; + } else { + if(vargs[2].number().isGreaterThan(1)) { + CALCULATOR->error(false, _("Argument 3, %s, is ignored for vectors."), getArgumentDefinition(3)->name().c_str(), NULL); + } + size_t row = (size_t) vargs[1].number().uintValue(); + if(row > vargs[0].countChildren()) { + CALCULATOR->error(true, _("Element %s does not exist in vector."), format_and_print(vargs[1]).c_str(), NULL); + return 0; + } + mstruct = *vargs[0].getChild(row); + return 1; + } +} +DimensionFunction::DimensionFunction() : MathFunction("dimension", 1) { + setArgumentDefinition(1, new VectorArgument("")); +} +int DimensionFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = (int) vargs[0].countChildren(); + return 1; +} +ComponentFunction::ComponentFunction() : MathFunction("component", 2) { + setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); + setArgumentDefinition(2, new VectorArgument("")); +} +int ComponentFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + size_t i = (size_t) vargs[0].number().uintValue(); + if(i > vargs[1].countChildren()) { + CALCULATOR->error(true, _("Element %s does not exist in vector."), format_and_print(vargs[0]).c_str(), NULL); + return 0; + } + mstruct = *vargs[1].getChild(i); + return 1; +} +LimitsFunction::LimitsFunction() : MathFunction("limits", 3) { + setArgumentDefinition(1, new VectorArgument("")); + Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SINT); + arg->setHandleVector(false); + setArgumentDefinition(2, arg); + arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SINT); + arg->setHandleVector(false); + setArgumentDefinition(3, arg); +} +int LimitsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + vargs[0].getRange(vargs[1].number().intValue(), vargs[2].number().intValue(), mstruct); + return 1; +} +AreaFunction::AreaFunction() : MathFunction("area", 5) { + setArgumentDefinition(1, new MatrixArgument("")); + Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE); + arg->setHandleVector(false); + setArgumentDefinition(2, arg); + arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE); + arg->setHandleVector(false); + setArgumentDefinition(3, arg); + arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE); + arg->setHandleVector(false); + setArgumentDefinition(4, arg); + arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE); + arg->setHandleVector(false); + setArgumentDefinition(5, arg); +} +int AreaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + vargs[0].getArea(vargs[1].number().uintValue(), vargs[2].number().uintValue(), vargs[3].number().uintValue(), vargs[4].number().uintValue(), mstruct); + return 1; +} +TransposeFunction::TransposeFunction() : MathFunction("transpose", 1) { + setArgumentDefinition(1, new MatrixArgument()); +} +int TransposeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = vargs[0]; + return mstruct.transposeMatrix(); +} +IdentityMatrixFunction::IdentityMatrixFunction() : MathFunction("identity", 1) { + ArgumentSet *arg = new ArgumentSet(); + arg->addArgument(new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); + MatrixArgument *marg = new MatrixArgument(); + marg->setSquareDemanded(true); + arg->addArgument(marg); + setArgumentDefinition(1, arg); +} +int IdentityMatrixFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + if(vargs[0].isMatrix()) { + if(vargs[0].rows() != vargs[0].columns()) { + return 0; + } + mstruct.setToIdentityMatrix(vargs[0].size()); + } else { + mstruct.setToIdentityMatrix((size_t) vargs[0].number().uintValue()); + } + return 1; +} +DeterminantFunction::DeterminantFunction() : MathFunction("det", 1) { + MatrixArgument *marg = new MatrixArgument(); + marg->setSquareDemanded(true); + setArgumentDefinition(1, marg); +} +int DeterminantFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + vargs[0].determinant(mstruct, eo); + return !mstruct.isUndefined(); +} +PermanentFunction::PermanentFunction() : MathFunction("permanent", 1) { + MatrixArgument *marg = new MatrixArgument(); + marg->setSquareDemanded(true); + setArgumentDefinition(1, marg); +} +int PermanentFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + vargs[0].permanent(mstruct, eo); + return !mstruct.isUndefined(); +} +CofactorFunction::CofactorFunction() : MathFunction("cofactor", 3) { + setArgumentDefinition(1, new MatrixArgument()); + setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); + setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); +} +int CofactorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + vargs[0].cofactor((size_t) vargs[1].number().uintValue(), (size_t) vargs[2].number().uintValue(), mstruct, eo); + return !mstruct.isUndefined(); +} +AdjointFunction::AdjointFunction() : MathFunction("adj", 1) { + MatrixArgument *marg = new MatrixArgument(); + marg->setSquareDemanded(true); + setArgumentDefinition(1, marg); +} +int AdjointFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct = vargs[0]; + if(!mstruct.adjointMatrix(eo)) return 0; + return !mstruct.isUndefined(); +} +InverseFunction::InverseFunction() : MathFunction("inverse", 1) { + MatrixArgument *marg = new MatrixArgument(); + marg->setSquareDemanded(true); + setArgumentDefinition(1, marg); +} +int InverseFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct = vargs[0]; + return mstruct.invertMatrix(eo); +} +MagnitudeFunction::MagnitudeFunction() : MathFunction("magnitude", 1) { +} +int MagnitudeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct = vargs[0]; + if(mstruct.isVector()) { + mstruct ^= nr_two; + mstruct.raise(nr_half); + return 1; + } else if(mstruct.representsScalar()) { + mstruct.transformById(FUNCTION_ID_ABS); + return 1; + } + mstruct.eval(eo); + if(mstruct.isVector()) { + mstruct ^= nr_two; + mstruct.raise(nr_half); + return 1; + } + mstruct = vargs[0]; + mstruct.transformById(FUNCTION_ID_ABS); + return 1; +} +HadamardFunction::HadamardFunction() : MathFunction("hadamard", 1, -1) { + setArgumentDefinition(1, new VectorArgument()); + setArgumentDefinition(2, new VectorArgument()); +} +int HadamardFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + bool b_matrix = vargs[0].isMatrix(); + for(size_t i3 = 1; i3 < vargs.size(); i3++) { + if(b_matrix) { + if(!vargs[i3].isMatrix() || vargs[i3].columns() != vargs[0].columns() || vargs[i3].rows() != vargs[0].rows()) { + CALCULATOR->error(true, _("%s() requires that all matrices/vectors have the same dimensions."), preferredDisplayName().name.c_str(), NULL); + return 0; + } + } else if(vargs[i3].size() != vargs[0].size()) { + CALCULATOR->error(true, _("%s() requires that all matrices/vectors have the same dimensions."), preferredDisplayName().name.c_str(), NULL); + return 0; + } + } + mstruct = vargs[0]; + for(size_t i = 0; i < mstruct.size(); i++) { + if(b_matrix) { + for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { + for(size_t i3 = 1; i3 < vargs.size(); i3++) mstruct[i][i2] *= vargs[i3][i][i2]; + } + } else { + for(size_t i3 = 1; i3 < vargs.size(); i3++) mstruct[i] *= vargs[i3][i]; + } + } + return 1; +} +EntrywiseFunction::EntrywiseFunction() : MathFunction("entrywise", 2) { + VectorArgument *arg = new VectorArgument(); + arg->addArgument(new VectorArgument()); + arg->addArgument(new SymbolicArgument()); + arg->setReoccuringArguments(true); + setArgumentDefinition(2, arg); +} +int EntrywiseFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[1].size() == 0) { + mstruct = vargs[0]; + return 1; + } + bool b_matrix = vargs[1][0].isMatrix(); + for(size_t i3 = 2; i3 < vargs[1].size(); i3 += 2) { + if(b_matrix) { + if(!vargs[1][i3].isMatrix() || vargs[1][i3].columns() != vargs[1][0].columns() || vargs[1][i3].rows() != vargs[1][0].rows()) { + CALCULATOR->error(true, _("%s() requires that all matrices/vectors have the same dimensions."), preferredDisplayName().name.c_str(), NULL); + return 0; + } + } else if(vargs[1][i3].size() != vargs[1][0].size()) { + CALCULATOR->error(true, _("%s() requires that all matrices/vectors have the same dimensions."), preferredDisplayName().name.c_str(), NULL); + return 0; + } + } + MathStructure mexpr(vargs[0]); + EvaluationOptions eo2 = eo; + eo2.calculate_functions = false; + mexpr.eval(eo2); + mstruct = vargs[1][0]; + for(size_t i = 0; i < mstruct.size(); i++) { + if(b_matrix) { + for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { + mstruct[i][i2] = mexpr; + for(size_t i3 = 1; i3 < vargs[1].size(); i3 += 2) { + mstruct[i][i2].replace(vargs[1][i3], vargs[1][i3 - 1][i][i2]); + } + } + } else { + mstruct[i] = mexpr; + for(size_t i3 = 1; i3 < vargs[1].size(); i3 += 2) { + mstruct[i].replace(vargs[1][i3], vargs[1][i3 - 1][i]); + } + } + } + return 1; +} + +bool process_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t index); +bool process_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t index) { + if(mprocess == vargs[1]) { + mprocess = mstruct[index]; + return true; + } + if(!vargs[3].isEmptySymbol() && mprocess == vargs[3]) { + mprocess = (int) index + 1; + return true; + } + if(!vargs[4].isEmptySymbol() && mprocess == vargs[4]) { + mprocess = vargs[2]; + return true; + } + bool b = false; + for(size_t i = 0; i < mprocess.size(); i++) { + if(process_replace(mprocess[i], mstruct, vargs, index)) { + mprocess.childUpdated(i + 1); + b = true; + } + } + return b; +} + +ProcessFunction::ProcessFunction() : MathFunction("process", 3, 5) { + setArgumentDefinition(2, new SymbolicArgument()); + setArgumentDefinition(3, new VectorArgument()); + setArgumentDefinition(4, new SymbolicArgument()); + setDefaultValue(4, "\"\""); + setArgumentDefinition(5, new SymbolicArgument()); + setDefaultValue(5, "\"\""); +} +int ProcessFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + + mstruct = vargs[2]; + MathStructure mprocess; + for(size_t index = 0; index < mstruct.size(); index++) { + mprocess = vargs[0]; + process_replace(mprocess, mstruct, vargs, index); + mstruct[index] = mprocess; + } + return 1; + +} + + +bool process_matrix_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t rindex, size_t cindex); +bool process_matrix_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t rindex, size_t cindex) { + if(mprocess == vargs[1]) { + mprocess = mstruct[rindex][cindex]; + return true; + } + if(!vargs[3].isEmptySymbol() && mprocess == vargs[3]) { + mprocess = (int) rindex + 1; + return true; + } + if(!vargs[4].isEmptySymbol() && mprocess == vargs[4]) { + mprocess = (int) cindex + 1; + return true; + } + if(!vargs[5].isEmptySymbol() && mprocess == vargs[5]) { + mprocess = vargs[2]; + return true; + } + bool b = false; + for(size_t i = 0; i < mprocess.size(); i++) { + if(process_matrix_replace(mprocess[i], mstruct, vargs, rindex, cindex)) { + mprocess.childUpdated(i + 1); + b = true; + } + } + return b; +} + +ProcessMatrixFunction::ProcessMatrixFunction() : MathFunction("processm", 3, 6) { + setArgumentDefinition(2, new SymbolicArgument()); + setArgumentDefinition(3, new MatrixArgument()); + setArgumentDefinition(4, new SymbolicArgument()); + setDefaultValue(4, "\"\""); + setArgumentDefinition(5, new SymbolicArgument()); + setDefaultValue(5, "\"\""); + setArgumentDefinition(6, new SymbolicArgument()); + setDefaultValue(6, "\"\""); +} +int ProcessMatrixFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + + mstruct = vargs[2]; + MathStructure mprocess; + for(size_t rindex = 0; rindex < mstruct.size(); rindex++) { + for(size_t cindex = 0; cindex < mstruct[rindex].size(); cindex++) { + if(CALCULATOR->aborted()) return 0; + mprocess = vargs[0]; + process_matrix_replace(mprocess, mstruct, vargs, rindex, cindex); + mstruct[rindex][cindex] = mprocess; + } + } + return 1; + +} +GenerateVectorFunction::GenerateVectorFunction() : MathFunction("genvector", 4, 6) { + setArgumentDefinition(5, new SymbolicArgument()); + setDefaultValue(5, "undefined"); + setArgumentDefinition(6, new BooleanArgument()); + setDefaultValue(6, "0"); +} +int GenerateVectorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(CALCULATOR->aborted()) return 0; + if(vargs[5].number().getBoolean()) { + mstruct = vargs[0].generateVector(vargs[4], vargs[1], vargs[2], vargs[3], NULL, eo); + } else { + bool overflow = false; + int steps = vargs[3].number().intValue(&overflow); + if(!vargs[3].isNumber() || overflow || steps < 1) { + CALCULATOR->error(true, _("The number of requested elements in generate vector function must be a positive integer."), NULL); + return 0; + } + mstruct = vargs[0].generateVector(vargs[4], vargs[1], vargs[2], steps, NULL, eo); + } + if(CALCULATOR->aborted()) return 0; + return 1; +} +SelectFunction::SelectFunction() : MathFunction("select", 2, 4) { + setArgumentDefinition(3, new SymbolicArgument()); + setDefaultValue(3, "undefined"); + setArgumentDefinition(4, new BooleanArgument()); + setDefaultValue(4, "0"); +} +int SelectFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + MathStructure mtest; + mstruct = vargs[0]; + mstruct.eval(eo); + if(!mstruct.isVector()) { + mtest = vargs[1]; + mtest.replace(vargs[2], mstruct); + mtest.eval(eo); + if(!mtest.isNumber() || mtest.number().getBoolean() < 0) { + CALCULATOR->error(true, _("Comparison failed."), NULL); + return -1; + } + if(mtest.number().getBoolean() == 0) { + if(vargs[3].number().getBoolean() > 0) { + CALCULATOR->error(true, _("No matching item found."), NULL); + return -1; + } + mstruct.clearVector(); + } + return 1; + } + for(size_t i = 0; i < mstruct.size();) { + mtest = vargs[1]; + mtest.replace(vargs[2], mstruct[i]); + mtest.eval(eo); + if(!mtest.isNumber() || mtest.number().getBoolean() < 0) { + CALCULATOR->error(true, _("Comparison failed."), NULL); + return -1; + } + if(mtest.number().getBoolean() == 0) { + if(vargs[3].number().getBoolean() == 0) { + mstruct.delChild(i + 1); + } else { + i++; + } + } else if(vargs[3].number().getBoolean() > 0) { + MathStructure msave(mstruct[i]); + mstruct = msave; + return 1; + } else { + i++; + } + } + if(vargs[3].number().getBoolean() > 0) { + CALCULATOR->error(true, _("No matching item found."), NULL); + return -1; + } + return 1; +} +LoadFunction::LoadFunction() : MathFunction("load", 1, 3) { + setArgumentDefinition(1, new FileArgument()); + Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SINT); + arg->setHandleVector(false); + setArgumentDefinition(2, arg); + setDefaultValue(2, "1"); + setArgumentDefinition(3, new TextArgument()); + setDefaultValue(3, ","); +} +int LoadFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + string delim = vargs[2].symbol(); + if(delim == "tab") { + delim = "\t"; + } + if(!CALCULATOR->importCSV(mstruct, vargs[0].symbol().c_str(), vargs[1].number().intValue(), delim)) { + CALCULATOR->error(true, "Failed to load %s.", vargs[0].symbol().c_str(), NULL); + return 0; + } + return 1; +} +ExportFunction::ExportFunction() : MathFunction("export", 2, 3) { + setArgumentDefinition(1, new VectorArgument()); + setArgumentDefinition(2, new FileArgument()); + setArgumentDefinition(3, new TextArgument()); + setDefaultValue(3, ","); +} +int ExportFunction::calculate(MathStructure&, const MathStructure &vargs, const EvaluationOptions&) { + string delim = vargs[2].symbol(); + if(delim == "tab") { + delim = "\t"; + } + if(!CALCULATOR->exportCSV(vargs[0], vargs[1].symbol().c_str(), delim)) { + CALCULATOR->error(true, "Failed to export to %s.", vargs[1].symbol().c_str(), NULL); + return 0; + } + return 1; +} + diff -Nru libqalculate-3.6.0/libqalculate/BuiltinFunctions-number.cc libqalculate-3.7.0/libqalculate/BuiltinFunctions-number.cc --- libqalculate-3.6.0/libqalculate/BuiltinFunctions-number.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/BuiltinFunctions-number.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,1201 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Number.h" +#include "Calculator.h" +#include "Variable.h" +#include "Unit.h" + +#include +#include +#include +#include + +#include "MathStructure-support.h" + +#if HAVE_UNORDERED_MAP +# include + using std::unordered_map; +#elif defined(__GNUC__) + +# ifndef __has_include +# define __has_include(x) 0 +# endif + +# if (defined(__clang__) && __has_include()) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 3) +# include + namespace Sgi = std; +# define unordered_map std::tr1::unordered_map +# else +# if __GNUC__ < 3 +# include + namespace Sgi { using ::hash_map; }; // inherit globals +# else +# include +# if __GNUC__ == 3 && __GNUC_MINOR__ == 0 + namespace Sgi = std; // GCC 3.0 +# else + namespace Sgi = ::__gnu_cxx; // GCC 3.1 and later +# endif +# endif +# define unordered_map Sgi::hash_map +# endif +#else // ... there are other compilers, right? + namespace Sgi = std; +# define unordered_map Sgi::hash_map +#endif + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +#define FR_FUNCTION(FUNC) Number nr(vargs[0].number()); if(!nr.FUNC() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;} +#define FR_FUNCTION_2(FUNC) Number nr(vargs[0].number()); if(!nr.FUNC(vargs[1].number()) || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate() && !vargs[1].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex() && !vargs[1].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity() && !vargs[1].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;} + +#define NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(i) NumberArgument *arg_non_complex##i = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false); arg_non_complex##i->setComplexAllowed(false); setArgumentDefinition(i, arg_non_complex##i); +#define NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR_NONZERO(i) NumberArgument *arg_non_complex##i = new NumberArgument("", ARGUMENT_MIN_MAX_NONZERO, true, false); arg_non_complex##i->setComplexAllowed(false); setArgumentDefinition(i, arg_non_complex##i); +#define RATIONAL_NUMBER_ARGUMENT_NO_ERROR(i) NumberArgument *arg_rational##i = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false); arg_rational##i->setRationalNumber(true); setArgumentDefinition(i, arg_rational##i); +#define RATIONAL_POLYNOMIAL_ARGUMENT(i) Argument *arg_poly##i = new Argument(); arg_poly##i->setRationalPolynomial(true); setArgumentDefinition(i, arg_poly##i); +#define RATIONAL_POLYNOMIAL_ARGUMENT_HV(i) Argument *arg_poly##i = new Argument(); arg_poly##i->setRationalPolynomial(true); arg_poly##i->setHandleVector(true); setArgumentDefinition(i, arg_poly##i); + +OddFunction::OddFunction() : MathFunction("odd", 1) { + Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +int OddFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + if(vargs[0].representsOdd()) { + mstruct.set(1, 1, 0); + return 1; + } else if(vargs[0].representsEven()) { + mstruct.clear(); + return 1; + } + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(mstruct.representsOdd()) { + mstruct.set(1, 1, 0); + return 1; + } else if(mstruct.representsEven()) { + mstruct.clear(); + return 1; + } + return -1; +} +EvenFunction::EvenFunction() : MathFunction("even", 1) { + Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +int EvenFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + if(vargs[0].representsEven()) { + mstruct.set(1, 1, 0); + return 1; + } else if(vargs[0].representsOdd()) { + mstruct.clear(); + return 1; + } + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(mstruct.representsEven()) { + mstruct.set(1, 1, 0); + return 1; + } else if(mstruct.representsOdd()) { + mstruct.clear(); + return 1; + } + return -1; +} +AbsFunction::AbsFunction() : MathFunction("abs", 1) { + Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +bool AbsFunction::representsPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units) && vargs[0].representsNonZero(allow_units);} +bool AbsFunction::representsNegative(const MathStructure&, bool) const {return false;} +bool AbsFunction::representsNonNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} +bool AbsFunction::representsNonPositive(const MathStructure&, bool) const {return false;} +bool AbsFunction::representsInteger(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsInteger(allow_units);} +bool AbsFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} +bool AbsFunction::representsRational(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsRational(allow_units);} +bool AbsFunction::representsReal(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} +bool AbsFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} +bool AbsFunction::representsComplex(const MathStructure&, bool) const {return false;} +bool AbsFunction::representsNonZero(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units) && vargs[0].representsNonZero(allow_units);} +bool AbsFunction::representsEven(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsEven(allow_units);} +bool AbsFunction::representsOdd(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsOdd(allow_units);} +bool AbsFunction::representsUndefined(const MathStructure &vargs) const {return vargs.size() == 1 && vargs[0].representsUndefined();} +int AbsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(mstruct.isNumber()) { + if(eo.approximation != APPROXIMATION_APPROXIMATE && mstruct.number().hasImaginaryPart() && mstruct.number().hasRealPart()) { + MathStructure m_i(mstruct.number().imaginaryPart()); + m_i ^= nr_two; + mstruct.number().clearImaginary(); + mstruct.numberUpdated(); + mstruct ^= nr_two; + mstruct += m_i; + mstruct ^= nr_half; + return 1; + } + Number nr(mstruct.number()); + if(!nr.abs() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate())) { + return -1; + } + mstruct = nr; + return 1; + } + if(mstruct.isPower() && mstruct[0].representsPositive()) { + if(mstruct[1].isNumber() && !mstruct[1].number().hasRealPart()) { + mstruct.set(1, 1, 0, true); + return 1; + } else if(mstruct[1].isMultiplication() && mstruct.size() > 0 && mstruct[1][0].isNumber() && !mstruct[1][0].number().hasRealPart()) { + bool b = true; + for(size_t i = 1; i < mstruct[1].size(); i++) { + if(!mstruct[1][i].representsNonComplex()) {b = false; break;} + } + if(b) { + mstruct.set(1, 1, 0, true); + return 1; + } + } + } + if(mstruct.representsNegative(true)) { + mstruct.negate(); + return 1; + } + if(mstruct.representsNonNegative(true)) { + return 1; + } + if(mstruct.isMultiplication()) { + for(size_t i = 0; i < mstruct.size(); i++) { + mstruct[i].transform(STRUCT_FUNCTION); + mstruct[i].setFunction(this); + } + mstruct.childrenUpdated(); + return 1; + } + if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2) { + mstruct[0].transform(this); + mstruct.childUpdated(1); + return 1; + } + if(mstruct.isPower() && mstruct[1].representsReal()) { + mstruct[0].transform(this); + return 1; + } + if(eo.approximation == APPROXIMATION_EXACT || has_interval_unknowns(mstruct)) { + ComparisonResult cr = mstruct.compare(m_zero); + if(COMPARISON_IS_EQUAL_OR_LESS(cr)) { + return 1; + } else if(COMPARISON_IS_EQUAL_OR_GREATER(cr)) { + mstruct.negate(); + return 1; + } + } + return -1; +} +GcdFunction::GcdFunction() : MathFunction("gcd", 2) { + RATIONAL_POLYNOMIAL_ARGUMENT_HV(1) + RATIONAL_POLYNOMIAL_ARGUMENT_HV(2) +} +int GcdFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(MathStructure::gcd(vargs[0], vargs[1], mstruct, eo)) { + return 1; + } + return 0; +} +LcmFunction::LcmFunction() : MathFunction("lcm", 2) { + RATIONAL_POLYNOMIAL_ARGUMENT_HV(1) + RATIONAL_POLYNOMIAL_ARGUMENT_HV(2) +} +int LcmFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(MathStructure::lcm(vargs[0], vargs[1], mstruct, eo)) { + return 1; + } + return 0; +} + +SignumFunction::SignumFunction() : MathFunction("sgn", 1, 2) { + Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); + setDefaultValue(2, "0"); +} +bool SignumFunction::representsPositive(const MathStructure&, bool allow_units) const {return false;} +bool SignumFunction::representsNegative(const MathStructure&, bool) const {return false;} +bool SignumFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsNonNegative(true);} +bool SignumFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsNonPositive(true);} +bool SignumFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsReal(true);} +bool SignumFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsNumber(true);} +bool SignumFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsReal(true);} +bool SignumFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsNonComplex(true);} +bool SignumFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsReal(true);} +bool SignumFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() >= 1 && vargs[0].representsComplex(true);} +bool SignumFunction::representsNonZero(const MathStructure &vargs, bool) const {return (vargs.size() == 2 && !vargs[1].isZero()) || (vargs.size() >= 1 && vargs[0].representsNonZero(true));} +bool SignumFunction::representsEven(const MathStructure&, bool) const {return false;} +bool SignumFunction::representsOdd(const MathStructure &vargs, bool b) const {return representsNonZero(vargs, b);} +bool SignumFunction::representsUndefined(const MathStructure &vargs) const {return vargs.size() >= 1 && vargs[0].representsUndefined();} +int SignumFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(mstruct.isNumber() && (vargs.size() == 1 || vargs[1].isZero())) { + Number nr(mstruct.number()); + if(!nr.signum() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate())) { + if(mstruct.number().isNonZero()) { + MathStructure *mabs = new MathStructure(mstruct); + mabs->transformById(FUNCTION_ID_ABS); + mstruct.divide_nocopy(mabs); + return 1; + } + return -1; + } else { + mstruct = nr; + return 1; + } + } + if((vargs.size() > 1 && vargs[1].isOne() && mstruct.representsNonNegative(true)) || mstruct.representsPositive(true)) { + mstruct.set(1, 1, 0); + return 1; + } + if((vargs.size() > 1 && vargs[1].isMinusOne() && mstruct.representsNonPositive(true)) || mstruct.representsNegative(true)) { + mstruct.set(-1, 1, 0); + return 1; + } + if(mstruct.isMultiplication()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(vargs.size() > 1) mstruct[i].transform(STRUCT_FUNCTION, vargs[1]); + else mstruct[i].transform(STRUCT_FUNCTION); + mstruct[i].setFunction(this); + + } + mstruct.childrenUpdated(); + return 1; + } + if(vargs.size() > 1 && mstruct.isZero()) { + mstruct.set(vargs[1], true); + return 1; + } + if(eo.approximation == APPROXIMATION_EXACT || has_interval_unknowns(mstruct)) { + ComparisonResult cr = mstruct.compare(m_zero); + if(cr == COMPARISON_RESULT_LESS || (vargs.size() > 1 && vargs[1].isOne() && COMPARISON_IS_EQUAL_OR_LESS(cr))) { + mstruct.set(1, 1, 0); + return 1; + } else if(cr == COMPARISON_RESULT_GREATER || (vargs.size() > 1 && vargs[1].isMinusOne() && COMPARISON_IS_EQUAL_OR_GREATER(cr))) { + mstruct.set(-1, 1, 0); + return 1; + } + } + return -1; +} + +CeilFunction::CeilFunction() : MathFunction("ceil", 1) { + NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) +} +int CeilFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION(ceil) +} +bool CeilFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsPositive();} +bool CeilFunction::representsNegative(const MathStructure&, bool) const {return false;} +bool CeilFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();} +bool CeilFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonPositive();} +bool CeilFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool CeilFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool CeilFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} +bool CeilFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool CeilFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool CeilFunction::representsComplex(const MathStructure&, bool) const {return false;} +bool CeilFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsPositive();} +bool CeilFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsEven();} +bool CeilFunction::representsOdd(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsOdd();} +bool CeilFunction::representsUndefined(const MathStructure&) const {return false;} + +FloorFunction::FloorFunction() : MathFunction("floor", 1) { + NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) +} +int FloorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION(floor) +} +bool FloorFunction::representsPositive(const MathStructure&, bool) const {return false;} +bool FloorFunction::representsNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNegative();} +bool FloorFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();} +bool FloorFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonPositive();} +bool FloorFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool FloorFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool FloorFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool FloorFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} +bool FloorFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool FloorFunction::representsComplex(const MathStructure&, bool) const {return false;} +bool FloorFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNegative();} +bool FloorFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsEven();} +bool FloorFunction::representsOdd(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsOdd();} +bool FloorFunction::representsUndefined(const MathStructure&) const {return false;} + +TruncFunction::TruncFunction() : MathFunction("trunc", 1) { + NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) +} +int TruncFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION(trunc) +} +bool TruncFunction::representsPositive(const MathStructure&, bool) const {return false;} +bool TruncFunction::representsNegative(const MathStructure&, bool) const {return false;} +bool TruncFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();} +bool TruncFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonPositive();} +bool TruncFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool TruncFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool TruncFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool TruncFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool TruncFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} +bool TruncFunction::representsComplex(const MathStructure&, bool) const {return false;} +bool TruncFunction::representsNonZero(const MathStructure&, bool) const {return false;} +bool TruncFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsEven();} +bool TruncFunction::representsOdd(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsOdd();} +bool TruncFunction::representsUndefined(const MathStructure&) const {return false;} + +RoundFunction::RoundFunction() : MathFunction("round", 1) { + NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) +} +int RoundFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION(round) +} +bool RoundFunction::representsPositive(const MathStructure&, bool) const {return false;} +bool RoundFunction::representsNegative(const MathStructure&, bool) const {return false;} +bool RoundFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonNegative();} +bool RoundFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal() && vargs[0].representsNonPositive();} +bool RoundFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool RoundFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool RoundFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool RoundFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool RoundFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} +bool RoundFunction::representsComplex(const MathStructure&, bool) const {return false;} +bool RoundFunction::representsNonZero(const MathStructure&, bool) const {return false;} +bool RoundFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsEven();} +bool RoundFunction::representsOdd(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsInteger() && vargs[0].representsOdd();} +bool RoundFunction::representsUndefined(const MathStructure&) const {return false;} + +FracFunction::FracFunction() : MathFunction("frac", 1) { + NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) +} +int FracFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION(frac) +} +IntFunction::IntFunction() : MathFunction("int", 1) { + NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) +} +int IntFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION(trunc) +} +NumeratorFunction::NumeratorFunction() : MathFunction("numerator", 1) { + NumberArgument *arg_rational_1 = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + arg_rational_1->setRationalNumber(true); + arg_rational_1->setHandleVector(true); + setArgumentDefinition(1, arg_rational_1); +} +int NumeratorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + if(vargs[0].isNumber()) { + if(vargs[0].number().isInteger()) { + mstruct = vargs[0]; + return 1; + } else if(vargs[0].number().isRational()) { + mstruct.set(vargs[0].number().numerator()); + return 1; + } + return 0; + } else if(vargs[0].representsInteger()) { + mstruct = vargs[0]; + return 1; + } + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(mstruct.representsInteger()) { + return 1; + } else if(mstruct.isNumber() && mstruct.number().isRational()) { + Number nr(mstruct.number().numerator()); + mstruct.set(nr); + return 1; + } + return -1; +} +DenominatorFunction::DenominatorFunction() : MathFunction("denominator", 1) { + RATIONAL_NUMBER_ARGUMENT_NO_ERROR(1) +} +int DenominatorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct.set(vargs[0].number().denominator()); + return 1; +} +RemFunction::RemFunction() : MathFunction("rem", 2) { + NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) + NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR_NONZERO(2) +} +int RemFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION_2(rem) +} +ModFunction::ModFunction() : MathFunction("mod", 2) { + NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1) + NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR_NONZERO(2) +} +int ModFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION_2(mod) +} + +BernoulliFunction::BernoulliFunction() : MathFunction("bernoulli", 1, 2) { + setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONNEGATIVE)); + setDefaultValue(2, "0"); +} +int BernoulliFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs.size() > 1 && !vargs[1].isZero()) { + MathStructure m2(vargs[1]); + replace_f_interval(m2, eo); + replace_intervals_f(m2); + mstruct.clear(); + Number bin, k, nmk(vargs[0].number()), nrB; + while(k <= vargs[0].number()) { + if(nmk.isEven() || nmk.isOne()) { + nrB.set(nmk); + if(!bin.binomial(vargs[0].number(), k) || !nrB.bernoulli() || !nrB.multiply(bin)) return 0; + if(eo.approximation == APPROXIMATION_EXACT && nrB.isApproximate()) return 0; + mstruct.add(nrB, true); + mstruct.last().multiply(m2); + mstruct.last().last().raise(k); + mstruct.childUpdated(mstruct.size()); + } + nmk--; + k++; + } + if(mstruct.isAddition()) mstruct.delChild(1, true); + return 1; + } + FR_FUNCTION(bernoulli) +} + +PolynomialUnitFunction::PolynomialUnitFunction() : MathFunction("punit", 1, 2) { + RATIONAL_POLYNOMIAL_ARGUMENT(1) + setArgumentDefinition(2, new SymbolicArgument()); + setDefaultValue(2, "undefined"); +} +int PolynomialUnitFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct.set(vargs[0].polynomialUnit(vargs[1]), 0); + return 1; +} +PolynomialPrimpartFunction::PolynomialPrimpartFunction() : MathFunction("primpart", 1, 2) { + RATIONAL_POLYNOMIAL_ARGUMENT(1) + setArgumentDefinition(2, new SymbolicArgument()); + setDefaultValue(2, "undefined"); +} +int PolynomialPrimpartFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + vargs[0].polynomialPrimpart(vargs[1], mstruct, eo); + return 1; +} +PolynomialContentFunction::PolynomialContentFunction() : MathFunction("pcontent", 1, 2) { + RATIONAL_POLYNOMIAL_ARGUMENT(1) + setArgumentDefinition(2, new SymbolicArgument()); + setDefaultValue(2, "undefined"); +} +int PolynomialContentFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + vargs[0].polynomialContent(vargs[1], mstruct, eo); + return 1; +} +CoeffFunction::CoeffFunction() : MathFunction("coeff", 2, 3) { + RATIONAL_POLYNOMIAL_ARGUMENT(1) + setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_NONNEGATIVE)); + setArgumentDefinition(3, new SymbolicArgument()); + setDefaultValue(3, "undefined"); +} +int CoeffFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + vargs[0].coefficient(vargs[2], vargs[1].number(), mstruct); + return 1; +} +LCoeffFunction::LCoeffFunction() : MathFunction("lcoeff", 1, 2) { + RATIONAL_POLYNOMIAL_ARGUMENT(1) + setArgumentDefinition(2, new SymbolicArgument()); + setDefaultValue(2, "undefined"); +} +int LCoeffFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + vargs[0].lcoefficient(vargs[1], mstruct); + return 1; +} +TCoeffFunction::TCoeffFunction() : MathFunction("tcoeff", 1, 2) { + RATIONAL_POLYNOMIAL_ARGUMENT(1) + setArgumentDefinition(2, new SymbolicArgument()); + setDefaultValue(2, "undefined"); +} +int TCoeffFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + vargs[0].tcoefficient(vargs[1], mstruct); + return 1; +} +DegreeFunction::DegreeFunction() : MathFunction("degree", 1, 2) { + RATIONAL_POLYNOMIAL_ARGUMENT(1) + setArgumentDefinition(2, new SymbolicArgument()); + setDefaultValue(2, "undefined"); +} +int DegreeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = vargs[0].degree(vargs[1]); + return 1; +} +LDegreeFunction::LDegreeFunction() : MathFunction("ldegree", 1, 2) { + RATIONAL_POLYNOMIAL_ARGUMENT(1) + setArgumentDefinition(2, new SymbolicArgument()); + setDefaultValue(2, "undefined"); +} +int LDegreeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = vargs[0].ldegree(vargs[1]); + return 1; +} + + +BinFunction::BinFunction() : MathFunction("bin", 1, 2) { + setArgumentDefinition(1, new TextArgument()); + setArgumentDefinition(2, new BooleanArgument()); + setDefaultValue(2, "0"); +} +int BinFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + ParseOptions po = eo.parse_options; + po.base = BASE_BINARY; + po.twos_complement = vargs[1].number().getBoolean(); + CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); + return 1; +} +OctFunction::OctFunction() : MathFunction("oct", 1) { + setArgumentDefinition(1, new TextArgument()); +} +int OctFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + ParseOptions po = eo.parse_options; + po.base = BASE_OCTAL; + CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); + return 1; +} +DecFunction::DecFunction() : MathFunction("dec", 1) { + setArgumentDefinition(1, new TextArgument()); +} +int DecFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + ParseOptions po = eo.parse_options; + po.base = BASE_DECIMAL; + CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); + return 1; +} +HexFunction::HexFunction() : MathFunction("hex", 1, 2) { + setArgumentDefinition(1, new TextArgument()); + setArgumentDefinition(2, new BooleanArgument()); + setDefaultValue(2, "0"); +} +int HexFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + ParseOptions po = eo.parse_options; + po.base = BASE_HEXADECIMAL; + po.hexadecimal_twos_complement = vargs[1].number().getBoolean(); + CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); + return 1; +} + +BaseFunction::BaseFunction() : MathFunction("base", 2, 3) { + setArgumentDefinition(1, new TextArgument()); + Argument *arg = new Argument(); + arg->setHandleVector(true); + setArgumentDefinition(2, arg); + IntegerArgument *arg2 = new IntegerArgument(); + arg2->setMin(&nr_zero); + arg2->setMax(&nr_three); + setArgumentDefinition(3, arg2); + setArgumentDefinition(3, new TextArgument()); + setDefaultValue(3, "0"); +} +int BaseFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[1].isVector()) return 0; + Number nbase; + int idigits = 0; + string sdigits; + if(vargs.size() > 2) sdigits = vargs[2].symbol(); + if(sdigits.empty() || sdigits == "0" || sdigits == "auto") idigits = 0; + else if(sdigits == "1") idigits = 1; + else if(sdigits == "2") idigits = 2; + else if(sdigits == "3" || sdigits == "Unicode" || sdigits == "unicode" || sdigits == "escaped") idigits = 3; + else idigits = -1; + if(vargs[1].isNumber() && idigits == 0) { + nbase = vargs[1].number(); + } else { + mstruct = vargs[1]; + mstruct.eval(eo); + if(mstruct.isVector()) return -2; + if(idigits == 0 && !mstruct.isNumber() && eo.approximation == APPROXIMATION_EXACT) { + MathStructure mstruct2(mstruct); + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_TRY_EXACT; + CALCULATOR->beginTemporaryStopMessages(); + mstruct2.eval(eo2); + if(mstruct2.isVector() || mstruct2.isNumber()) { + mstruct = mstruct2; + CALCULATOR->endTemporaryStopMessages(true); + if(mstruct.isVector()) return -2; + } else { + CALCULATOR->endTemporaryStopMessages(); + } + } + if(mstruct.isNumber() && idigits == 0) { + nbase = mstruct.number(); + } else { + string number = vargs[0].symbol(); + size_t i_dot = number.length(); + vector digits; + bool b_minus = false; + if(idigits < 0) { + unordered_map vdigits; + string schar; + long int v = 0; + for(size_t i = 0; i < sdigits.length(); v++) { + size_t l = 1; + while(i + l < sdigits.length() && sdigits[i + l] <= 0 && (unsigned char) sdigits[i + l] < 0xC0) l++; + vdigits[sdigits.substr(i, l)] = v; + i += l; + } + remove_blanks(number); + i_dot = number.length(); + for(size_t i = 0; i < number.length();) { + size_t l = 1; + while(i + l < number.length() && number[i + l] <= 0 && (unsigned char) number[i + l] < 0xC0) l++; + unordered_map::iterator it = vdigits.find(number.substr(i, l)); + if(it == vdigits.end()) { + if(l == 1 && (number[i] == CALCULATOR->getDecimalPoint()[0] || (!eo.parse_options.dot_as_separator && number[i] == '.'))) { + if(i_dot == number.length()) i_dot = digits.size(); + } else { + CALCULATOR->error(true, _("Character \'%s\' was ignored in the number \"%s\" with base %s."), number.substr(i, l).c_str(), number.c_str(), format_and_print(mstruct).c_str(), NULL); + } + } else { + digits.push_back(it->second); + } + i += l; + } + } else if(idigits <= 2) { + remove_blanks(number); + bool b_case = (idigits == 2); + i_dot = number.length(); + for(size_t i = 0; i < number.length(); i++) { + long int c = -1; + if(number[i] >= '0' && number[i] <= '9') { + c = number[i] - '0'; + } else if(number[i] >= 'a' && number[i] <= 'z') { + if(b_case) c = number[i] - 'a' + 36; + else c = number[i] - 'a' + 10; + } else if(number[i] >= 'A' && number[i] <= 'Z') { + c = number[i] - 'A' + 10; + } else if(number[i] == CALCULATOR->getDecimalPoint()[0] || (!eo.parse_options.dot_as_separator && number[i] == '.')) { + if(i_dot == number.length()) i_dot = digits.size(); + } else if(number[i] == '-' && digits.empty()) { + b_minus = !b_minus; + } else { + string str_char = number.substr(i, 1); + while(i + 1 < number.length() && number[i + 1] < 0 && number[i + 1] && (unsigned char) number[i + 1] < 0xC0) { + i++; + str_char += number[i]; + } + CALCULATOR->error(true, _("Character \'%s\' was ignored in the number \"%s\" with base %s."), str_char.c_str(), number.c_str(), format_and_print(mstruct).c_str(), NULL); + } + if(c >= 0) { + digits.push_back(c); + } + } + } else { + for(size_t i = 0; i < number.length(); i++) { + long int c = (unsigned char) number[i]; + bool b_esc = false; + if(number[i] == '\\' && i < number.length() - 1) { + i++; + Number nrd; + if(is_in(NUMBERS, number[i])) { + size_t i2 = number.find_first_not_of(NUMBERS, i); + if(i2 == string::npos) i2 = number.length(); + nrd.set(number.substr(i, i2 - i)); + i = i2 - 1; + b_esc = true; + } else if(number[i] == 'x' && i < number.length() - 1 && is_in(NUMBERS "ABCDEFabcdef", number[i + 1])) { + i++; + size_t i2 = number.find_first_not_of(NUMBERS "ABCDEFabcdef", i); + if(i2 == string::npos) i2 = number.length(); + ParseOptions po; + po.base = BASE_HEXADECIMAL; + nrd.set(number.substr(i, i2 - i), po); + i = i2 - 1; + b_esc = true; + } + if(digits.empty() && number[i] == (char) -30 && i + 3 < number.length() && number[i + 1] == (char) -120 && number[i + 2] == (char) -110) { + i += 2; + b_minus = !b_minus; + b_esc = true; + } else if(digits.empty() && number[i] == '-') { + b_minus = !b_minus; + b_esc = true; + } else if(i_dot == number.size() && (number[i] == CALCULATOR->getDecimalPoint()[0] || (!eo.parse_options.dot_as_separator && number[i] == '.'))) { + i_dot = digits.size(); + b_esc = true; + } else if(b_esc) { + digits.push_back(nrd); + + } else if(number[i] != '\\') { + i--; + } + } + if(!b_esc) { + if((c & 0x80) != 0) { + if(c<0xe0) { + i++; + if(i >= number.length()) return -2; + c = ((c & 0x1f) << 6) | (((unsigned char) number[i]) & 0x3f); + } else if(c<0xf0) { + i++; + if(i + 1 >= number.length()) return -2; + c = (((c & 0xf) << 12) | ((((unsigned char) number[i]) & 0x3f) << 6)|(((unsigned char) number[i + 1]) & 0x3f)); + i++; + } else { + i++; + if(i + 2 >= number.length()) return -2; + c = ((c & 7) << 18) | ((((unsigned char) number[i]) & 0x3f) << 12) | ((((unsigned char) number[i + 1]) & 0x3f) << 6) | (((unsigned char) number[i + 2]) & 0x3f); + i += 2; + } + } + digits.push_back(c); + } + } + } + MathStructure mbase = mstruct; + mstruct.clear(); + if(i_dot > digits.size()) i_dot = digits.size(); + for(size_t i = 0; i < digits.size(); i++) { + long int exp = i_dot - 1 - i; + MathStructure m; + if(exp != 0) { + m = mbase; + m.raise(Number(exp, 1)); + m.multiply(digits[i]); + } else { + m.set(digits[i]); + } + if(mstruct.isZero()) mstruct = m; + else mstruct.add(m, true); + } + if(b_minus) mstruct.negate(); + return 1; + } + } + ParseOptions po = eo.parse_options; + if(nbase.isInteger() && nbase >= 2 && nbase <= 36) { + po.base = nbase.intValue(); + CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); + } else { + po.base = BASE_CUSTOM; + Number cb_save = CALCULATOR->customInputBase(); + CALCULATOR->setCustomInputBase(nbase); + CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); + CALCULATOR->setCustomInputBase(cb_save); + } + return 1; +} +RomanFunction::RomanFunction() : MathFunction("roman", 1) { + setArgumentDefinition(1, new TextArgument()); +} +int RomanFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].symbol().find_first_not_of("0123456789.:" SIGNS) == string::npos && vargs[0].symbol().find_first_not_of("0" SIGNS) != string::npos) { + CALCULATOR->parse(&mstruct, vargs[0].symbol(), eo.parse_options); + PrintOptions po; po.base = BASE_ROMAN_NUMERALS; + mstruct.eval(eo); + mstruct.set(mstruct.print(po), true, true); + return 1; + } + ParseOptions po = eo.parse_options; + po.base = BASE_ROMAN_NUMERALS; + CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); + return 1; +} +BijectiveFunction::BijectiveFunction() : MathFunction("bijective", 1) { + setArgumentDefinition(1, new TextArgument()); +} +int BijectiveFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].symbol().find_first_not_of("0123456789.:" SIGNS) == string::npos && vargs[0].symbol().find_first_not_of(SIGNS) != string::npos) { + CALCULATOR->parse(&mstruct, vargs[0].symbol(), eo.parse_options); + PrintOptions po; po.base = BASE_BIJECTIVE_26; + mstruct.eval(eo); + mstruct.set(mstruct.print(po), true, true); + return 1; + } + ParseOptions po = eo.parse_options; + po.base = BASE_BIJECTIVE_26; + CALCULATOR->parse(&mstruct, vargs[0].symbol(), po); + return 1; +} +ImFunction::ImFunction() : MathFunction("im", 1) { + Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +int ImFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(mstruct.isNumber()) { + mstruct = mstruct.number().imaginaryPart(); + return 1; + } else if(mstruct.representsReal(!eo.keep_zero_units)) { + mstruct.clear(true); + return 1; + } else if(mstruct.isUnit_exp()) { + mstruct *= m_zero; + mstruct.swapChildren(1, 2); + return 1; + } else if(mstruct.isPower() && mstruct[1].isNumber() && mstruct[1].number().denominatorIsTwo() && mstruct[0].representsNegative()) { + mstruct[0].negate(); + Number num = mstruct[1].number().numerator(); + num.rem(4); + if(num == 3 || num == -1) mstruct.negate(); + return 1; + } else if(mstruct.isMultiplication() && mstruct.size() > 0) { + if(mstruct[0].isNumber()) { + Number nr = mstruct[0].number(); + mstruct.delChild(1, true); + if(nr.hasImaginaryPart()) { + if(nr.hasRealPart()) { + MathStructure *madd = new MathStructure(mstruct); + mstruct.transformById(FUNCTION_ID_RE); + madd->transform(this); + madd->multiply(nr.realPart()); + mstruct.multiply(nr.imaginaryPart()); + mstruct.add_nocopy(madd); + return 1; + } + mstruct.transformById(FUNCTION_ID_RE); + mstruct.multiply(nr.imaginaryPart()); + return 1; + } + mstruct.transform(this); + mstruct.multiply(nr.realPart()); + return 1; + } + MathStructure *mreal = NULL; + for(size_t i = 0; i < mstruct.size();) { + if(mstruct[i].representsReal(true)) { + if(!mreal) { + mreal = new MathStructure(mstruct[i]); + } else { + mstruct[i].ref(); + if(!mreal->isMultiplication()) mreal->transform(STRUCT_MULTIPLICATION); + mreal->addChild_nocopy(&mstruct[i]); + } + mstruct.delChild(i + 1); + } else { + i++; + } + } + if(mreal) { + if(mstruct.size() == 0) mstruct.clear(true); + else if(mstruct.size() == 1) mstruct.setToChild(1, true); + mstruct.transform(this); + mstruct.multiply_nocopy(mreal); + return 1; + } + } + return -1; +} +bool ImFunction::representsPositive(const MathStructure&, bool) const {return false;} +bool ImFunction::representsNegative(const MathStructure&, bool) const {return false;} +bool ImFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool ImFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool ImFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool ImFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} +bool ImFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool ImFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} +bool ImFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} +bool ImFunction::representsComplex(const MathStructure&, bool) const {return false;} +bool ImFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsComplex();} +bool ImFunction::representsEven(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool ImFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool ImFunction::representsUndefined(const MathStructure&) const {return false;} + +ReFunction::ReFunction() : MathFunction("re", 1) { + Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +int ReFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(mstruct.isNumber()) { + mstruct = mstruct.number().realPart(); + return 1; + } else if(mstruct.representsReal(true)) { + return 1; + } else if(mstruct.isPower() && mstruct[1].isNumber() && mstruct[1].number().denominatorIsTwo() && mstruct[0].representsNegative()) { + mstruct.clear(true); + return 1; + } else if(mstruct.isMultiplication() && mstruct.size() > 0) { + if(mstruct[0].isNumber()) { + Number nr = mstruct[0].number(); + mstruct.delChild(1, true); + if(nr.hasImaginaryPart()) { + if(nr.hasRealPart()) { + MathStructure *madd = new MathStructure(mstruct); + mstruct.transformById(FUNCTION_ID_IM); + madd->transform(this); + madd->multiply(nr.realPart()); + mstruct.multiply(-nr.imaginaryPart()); + mstruct.add_nocopy(madd); + return 1; + } + mstruct.transformById(FUNCTION_ID_IM); + mstruct.multiply(-nr.imaginaryPart()); + return 1; + } + mstruct.transform(this); + mstruct.multiply(nr.realPart()); + return 1; + } + MathStructure *mreal = NULL; + for(size_t i = 0; i < mstruct.size();) { + if(mstruct[i].representsReal(true)) { + if(!mreal) { + mreal = new MathStructure(mstruct[i]); + } else { + mstruct[i].ref(); + if(!mreal->isMultiplication()) mreal->transform(STRUCT_MULTIPLICATION); + mreal->addChild_nocopy(&mstruct[i]); + } + mstruct.delChild(i + 1); + } else { + i++; + } + } + if(mreal) { + if(mstruct.size() == 0) mstruct.clear(true); + else if(mstruct.size() == 1) mstruct.setToChild(1, true); + mstruct.transform(this); + mstruct.multiply_nocopy(mreal); + return 1; + } + } + return -1; +} +bool ReFunction::representsPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsPositive(allow_units);} +bool ReFunction::representsNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNegative(allow_units);} +bool ReFunction::representsNonNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNonNegative(allow_units);} +bool ReFunction::representsNonPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNonPositive(allow_units);} +bool ReFunction::representsInteger(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsInteger(allow_units);} +bool ReFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} +bool ReFunction::representsRational(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsRational(allow_units);} +bool ReFunction::representsReal(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} +bool ReFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} +bool ReFunction::representsComplex(const MathStructure&, bool) const {return false;} +bool ReFunction::representsNonZero(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsReal(allow_units) && vargs[0].representsNonZero(true);} +bool ReFunction::representsEven(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsEven(allow_units);} +bool ReFunction::representsOdd(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsOdd(allow_units);} +bool ReFunction::representsUndefined(const MathStructure&) const {return false;} + +ArgFunction::ArgFunction() : MathFunction("arg", 1) { + Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +bool ArgFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber(true);} +bool ArgFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber(true);} +bool ArgFunction::representsNonComplex(const MathStructure &vargs, bool) const {return true;} +int ArgFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + + MathStructure msave; + + arg_test_non_number: + if(!mstruct.isNumber()) { + if(mstruct.representsPositive(true)) { + mstruct.clear(); + return 1; + } + if(mstruct.representsNegative(true)) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.set(180, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 1, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;} + default: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();} + } + return 1; + } + if(!msave.isZero()) { + mstruct = msave; + return -1; + } + if(mstruct.isMultiplication()) { + bool b = false; + for(size_t i = 0; i < mstruct.size();) { + if(mstruct[i].representsPositive()) { + mstruct.delChild(i + 1); + b = true; + } else { + if(!mstruct[i].isMinusOne() && mstruct[i].representsNegative()) { + mstruct[i].set(-1, 1, 0, true); + b = true; + } + i++; + } + } + if(b) { + if(mstruct.size() == 1) { + mstruct.setToChild(1); + } else if(mstruct.size() == 0) { + mstruct.clear(true); + } + mstruct.transform(STRUCT_FUNCTION); + mstruct.setFunction(this); + return 1; + } + } + if(mstruct.isPower() && mstruct[0].representsComplex() && mstruct[1].representsInteger()) { + mstruct.setType(STRUCT_MULTIPLICATION); + mstruct[0].transform(STRUCT_FUNCTION); + mstruct[0].setFunction(this); + return 1; + } + if(mstruct.isPower() && mstruct[0].isVariable() && mstruct[0].variable()->id() == VARIABLE_ID_E && mstruct[1].isNumber() && mstruct[1].number().hasImaginaryPart() && !mstruct[1].number().hasRealPart()) { + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(CALCULATOR->usesIntervalArithmetic()) { + CALCULATOR->beginTemporaryStopMessages(); + Number nr(*mstruct[1].number().internalImaginary()); + Number nrpi; nrpi.pi(); + nr.add(nrpi); + nr.divide(nrpi); + nr.divide(2); + Number nr_u(nr.upperEndPoint()); + nr = nr.lowerEndPoint(); + nr_u.floor(); + nr.floor(); + if(!CALCULATOR->endTemporaryStopMessages() && nr == nr_u) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + nr.setApproximate(false); + nr *= 2; + nr.negate(); + mstruct = mstruct[1].number().imaginaryPart(); + if(!nr.isZero()) { + mstruct += nr; + mstruct.last() *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + } + return true; + } + } + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + } + if(eo.approximation == APPROXIMATION_EXACT) { + msave = mstruct; + if(!test_eval(mstruct, eo)) { + mstruct = msave; + return -1; + } + } + } + if(mstruct.isNumber()) { + if(!mstruct.number().hasImaginaryPart()) { + if(!mstruct.number().isNonZero()) { + if(!msave.isZero()) mstruct = msave; + return -1; + } + if(mstruct.number().isNegative()) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.set(180, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 1, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;} + default: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();} + } + } else { + mstruct.clear(); + } + } else if(!mstruct.number().hasRealPart() && mstruct.number().imaginaryPartIsNonZero()) { + bool b_neg = mstruct.number().imaginaryPartIsNegative(); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.set(90, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.set(100, 1, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); mstruct.multiply(nr_half); break;} + default: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); mstruct.multiply(nr_half); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();} + } + if(b_neg) mstruct.negate(); + } else if(!msave.isZero()) { + mstruct = msave; + return -1; + } else if(!mstruct.number().realPartIsNonZero()) { + FR_FUNCTION(arg) + } else { + MathStructure new_nr(mstruct.number().imaginaryPart()); + if(!new_nr.number().divide(mstruct.number().realPart())) return -1; + if(mstruct.number().realPartIsNegative()) { + if(mstruct.number().imaginaryPartIsNegative()) { + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.add(-180); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.add(-200); break;} + case ANGLE_UNIT_RADIANS: {mstruct.subtract(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;} + default: {MathStructure msub(CALCULATOR->getVariableById(VARIABLE_ID_PI)); if(CALCULATOR->getRadUnit()) msub *= CALCULATOR->getRadUnit(); mstruct.subtract(msub);} + } + } else if(mstruct.number().imaginaryPartIsNonNegative()) { + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.add(180); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.add(200); break;} + case ANGLE_UNIT_RADIANS: {mstruct.add(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;} + default: {MathStructure madd(CALCULATOR->getVariableById(VARIABLE_ID_PI)); if(CALCULATOR->getRadUnit()) madd *= CALCULATOR->getRadUnit(); mstruct.add(madd);} + } + } else { + FR_FUNCTION(arg) + } + } else { + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL); + } + } + return 1; + } + if(!msave.isZero()) { + goto arg_test_non_number; + } + return -1; +} + +IsNumberFunction::IsNumberFunction() : MathFunction("isNumber", 1) { +} +int IsNumberFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct = vargs[0]; + if(!mstruct.isNumber()) mstruct.eval(eo); + if(mstruct.isNumber()) { + mstruct.number().setTrue(); + } else { + mstruct.clear(); + mstruct.number().setFalse(); + } + return 1; +} + +#define IS_NUMBER_FUNCTION(x, y) x::x() : MathFunction(#y, 1) {} int x::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {mstruct = vargs[0]; if(!mstruct.isNumber()) mstruct.eval(eo); if(mstruct.isNumber() && mstruct.number().y()) {mstruct.number().setTrue();} else {mstruct.clear(); mstruct.number().setFalse();} return 1;} + +IS_NUMBER_FUNCTION(IsIntegerFunction, isInteger) +IS_NUMBER_FUNCTION(IsRealFunction, isReal) +IS_NUMBER_FUNCTION(IsRationalFunction, isRational) + diff -Nru libqalculate-3.6.0/libqalculate/BuiltinFunctions-special.cc libqalculate-3.7.0/libqalculate/BuiltinFunctions-special.cc --- libqalculate-3.6.0/libqalculate/BuiltinFunctions-special.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/BuiltinFunctions-special.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,530 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Number.h" +#include "Calculator.h" +#include "Variable.h" +#include "Unit.h" + +#include +#include +#include +#include + +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +#define FR_FUNCTION(FUNC) Number nr(vargs[0].number()); if(!nr.FUNC() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;} +#define FR_FUNCTION_2(FUNC) Number nr(vargs[0].number()); if(!nr.FUNC(vargs[1].number()) || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate() && !vargs[1].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex() && !vargs[1].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity() && !vargs[1].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;} +#define FR_FUNCTION_2R(FUNC) Number nr(vargs[1].number()); if(!nr.FUNC(vargs[0].number()) || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate() && !vargs[1].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex() && !vargs[1].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity() && !vargs[1].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;} +#define NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(i) NumberArgument *arg_non_complex##i = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false); arg_non_complex##i->setComplexAllowed(false); setArgumentDefinition(i, arg_non_complex##i); + +bool has_interval_unknowns(MathStructure &m) { + if(m.isVariable() && !m.variable()->isKnown()) { + Assumptions *ass = ((UnknownVariable*) m.variable())->assumptions(); + return !((UnknownVariable*) m.variable())->interval().isUndefined() || (ass && ((ass->sign() != ASSUMPTION_SIGN_UNKNOWN && ass->sign() != ASSUMPTION_SIGN_NONZERO) || ass->min() || ass->max())); + } + for(size_t i = 0; i < m.size(); i++) { + if(has_interval_unknowns(m[i])) return true; + } + return false; +} + +bool bernoulli_poly(MathStructure &m, Number n, const MathStructure &mx, const EvaluationOptions &eo) { + m.clear(); + Number bin, k, nmk(n), nrB; + while(k <= n) { + if(nmk.isEven() || nmk.isOne()) { + nrB.set(nmk); + if(!bin.binomial(n, k) || !nrB.bernoulli() || !nrB.multiply(bin)) return false; + if(eo.approximation == APPROXIMATION_EXACT && nrB.isApproximate()) return false; + m.add(nrB, true); + m.last().multiply(mx); + m.last().last().raise(k); + m.childUpdated(m.size()); + } + nmk--; + k++; + } + if(m.isAddition()) m.delChild(1, true); + return true; +} + +ZetaFunction::ZetaFunction() : MathFunction("zeta", 1, 2, SIGN_ZETA) { + NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false); + setArgumentDefinition(1, arg); + arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false); + setArgumentDefinition(2, arg); + setDefaultValue(2, "1"); +} +int ZetaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs.size() == 1 || vargs[1].isOne()) { + if(vargs[0].number().isInteger()) { + if(vargs[0].number().isZero()) { + mstruct.set(-1, 2, 0); + return 1; + } else if(vargs[0].number().isMinusOne()) { + mstruct.set(-1, 12, 0); + return 1; + } else if(vargs[0].number().isNegative() && vargs[0].number().isEven()) { + mstruct.clear(); + return 1; + } else if(vargs[0].number().isNegative() && vargs[0].number() >= -497) { + Number nr(vargs[0].number()); + nr.negate(); + nr++; + nr.bernoulli(); + nr.divide(vargs[0].number() - 1); + if(vargs[0].number().isEven()) nr.negate(); + mstruct.set(nr); + mstruct.mergePrecision(vargs[0]); + return 1; + } else if(vargs[0].number().isEven() && vargs[0].number() <= 498) { + Number nr(vargs[0].number()); + nr.bernoulli(); + mstruct.set(nr); + mstruct.multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + mstruct.last().multiply(nr_two); + mstruct.last().raise(vargs[0]); + mstruct.multiply(vargs[0]); + mstruct.last().transformById(FUNCTION_ID_FACTORIAL); + mstruct.last().inverse(); + if(vargs[0].number().isIntegerDivisible(4)) mstruct.multiply(Number(-1, 2)); + else mstruct.multiply(nr_half); + mstruct.childrenUpdated(true); + return 1; + } + } + FR_FUNCTION(zeta) + } + if(vargs[0].number().isZero()) { + mstruct.set(1, 2, 0); + if(!vargs[1].isZero()) mstruct.subtract(vargs[1]); + return 1; + } else if(vargs[0].number().isInteger() && vargs[0].number().isNegative()) { + Number nr(vargs[0].number()); + nr.negate(); + nr++; + MathStructure m2(vargs[1]); + replace_f_interval(m2, eo); + replace_intervals_f(m2); + if(bernoulli_poly(mstruct, nr, m2, eo)) { + mstruct.divide(nr); + mstruct.negate(); + return 1; + } + } else if(vargs[1].number().isInteger() && vargs[1].number() >= 2 && ((eo.approximation == APPROXIMATION_EXACT && vargs[1].number() <= 1000) || (vargs[1].number() <= 50 && vargs[0].number() >= -10 && vargs[0].number() <= 10))) { + MathStructure m1(vargs[0]); + replace_f_interval(m1, eo); + replace_intervals_f(m1); + mstruct = m1; + m1.negate(); + mstruct.transform(this); + mstruct.addChild(m_one); + mstruct.add(m_minus_one); + for(long int i = 2; vargs[1].number() > i; i++) { + mstruct.add(Number(i, 1), true); + mstruct.last().raise(m1); + mstruct.last().negate(); + } + return true; + } + FR_FUNCTION_2(zeta) +} +GammaFunction::GammaFunction() : MathFunction("gamma", 1, 1, SIGN_CAPITAL_GAMMA) { + NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1); +} +int GammaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].number().isRational() && (eo.approximation == APPROXIMATION_EXACT || (eo.approximation == APPROXIMATION_TRY_EXACT && vargs[0].number().isLessThan(1000)))) { + if(vargs[0].number().isInteger() && vargs[0].number().isPositive()) { + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_FACTORIAL), &vargs[0], NULL); + mstruct[0] -= 1; + return 1; + } else if(vargs[0].number().denominatorIsTwo()) { + Number nr(vargs[0].number()); + nr.floor(); + if(nr.isZero()) { + MathStructure mtmp(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_SQRT), &mtmp, NULL); + return 1; + } else if(nr.isPositive()) { + Number nr2(nr); + nr2 *= 2; + nr2 -= 1; + nr2.doubleFactorial(); + Number nr3(2, 1, 0); + nr3 ^= nr; + nr2 /= nr3; + mstruct = nr2; + MathStructure mtmp1(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + MathStructure mtmp2(CALCULATOR->getFunctionById(FUNCTION_ID_SQRT), &mtmp1, NULL); + mstruct *= mtmp2; + return 1; + } else { + nr.negate(); + Number nr2(nr); + nr2 *= 2; + nr2 -= 1; + nr2.doubleFactorial(); + Number nr3(2, 1, 0); + nr3 ^= nr; + if(nr.isOdd()) nr3.negate(); + nr3 /= nr2; + mstruct = nr3; + MathStructure mtmp1(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + MathStructure mtmp2(CALCULATOR->getFunctionById(FUNCTION_ID_SQRT), &mtmp1, NULL); + mstruct *= mtmp2; + return 1; + } + } + } + FR_FUNCTION(gamma) +} +DigammaFunction::DigammaFunction() : MathFunction("digamma", 1) { + NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(1); +} +int DigammaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].number().isOne()) { + mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_EULER)); + mstruct.negate(); + return 1; + } + FR_FUNCTION(digamma) +} +BetaFunction::BetaFunction() : MathFunction("beta", 2, 2, SIGN_CAPITAL_BETA) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false)); + setArgumentDefinition(2, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false)); +} +int BetaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = vargs[0]; + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_GAMMA), &vargs[0], NULL); + MathStructure mstruct2(CALCULATOR->getFunctionById(FUNCTION_ID_GAMMA), &vargs[1], NULL); + mstruct *= mstruct2; + mstruct2[0] += vargs[0]; + mstruct /= mstruct2; + return 1; +} +AiryFunction::AiryFunction() : MathFunction("airy", 1) { + NumberArgument *arg = new NumberArgument(); + Number fr(-500, 1, 0); + arg->setMin(&fr); + fr.set(500, 1, 0); + arg->setMax(&fr); + setArgumentDefinition(1, arg); +} +int AiryFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION(airy) +} +BesseljFunction::BesseljFunction() : MathFunction("besselj", 2) { + setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG)); + NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(2); +} +int BesseljFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION_2R(besselj) +} +BesselyFunction::BesselyFunction() : MathFunction("bessely", 2) { + IntegerArgument *iarg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SLONG); + Number nmax(1000); + iarg->setMax(&nmax); + setArgumentDefinition(1, iarg); + NON_COMPLEX_NUMBER_ARGUMENT_NO_ERROR(2); +} +int BesselyFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION_2R(bessely) +} +ErfFunction::ErfFunction() : MathFunction("erf", 1) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false)); +} +bool ErfFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsPositive();} +bool ErfFunction::representsNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNegative();} +bool ErfFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative();} +bool ErfFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonPositive();} +bool ErfFunction::representsInteger(const MathStructure&, bool) const {return false;} +bool ErfFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} +bool ErfFunction::representsRational(const MathStructure&, bool) const {return false;} +bool ErfFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +bool ErfFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +bool ErfFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsComplex();} +bool ErfFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonZero();} +bool ErfFunction::representsEven(const MathStructure&, bool) const {return false;} +bool ErfFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool ErfFunction::representsUndefined(const MathStructure&) const {return false;} +int ErfFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + Number nr(vargs[0].number()); + if(!nr.erf() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity())) { + if(vargs[0].number().hasImaginaryPart() && !vargs[0].number().hasRealPart()) { + mstruct = vargs[0].number().imaginaryPart(); + MathFunction *f = CALCULATOR->getFunctionById(FUNCTION_ID_ERFI); + mstruct.transform(f); + mstruct *= nr_one_i; + return 1; + } + return 0; + } + mstruct.set(nr); + return 1; +} +ErfiFunction::ErfiFunction() : MathFunction("erfi", 1) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false)); +} +bool ErfiFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsPositive();} +bool ErfiFunction::representsNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNegative();} +bool ErfiFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative();} +bool ErfiFunction::representsNonPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonPositive();} +bool ErfiFunction::representsInteger(const MathStructure&, bool) const {return false;} +bool ErfiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} +bool ErfiFunction::representsRational(const MathStructure&, bool) const {return false;} +bool ErfiFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool ErfiFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +bool ErfiFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsComplex();} +bool ErfiFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonZero();} +bool ErfiFunction::representsEven(const MathStructure&, bool) const {return false;} +bool ErfiFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool ErfiFunction::representsUndefined(const MathStructure&) const {return false;} +int ErfiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + Number nr(vargs[0].number()); + if(!nr.erfi() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity())) { + if(vargs[0].number().hasImaginaryPart() && !vargs[0].number().hasRealPart()) { + mstruct = vargs[0].number().imaginaryPart(); + mstruct.transformById(FUNCTION_ID_ERF); + mstruct *= nr_one_i; + return 1; + } + return 0; + } + mstruct.set(nr); + return 1; +} +ErfcFunction::ErfcFunction() : MathFunction("erfc", 1) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false)); +} +bool ErfcFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool ErfcFunction::representsNegative(const MathStructure&, bool) const {return false;} +bool ErfcFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool ErfcFunction::representsNonPositive(const MathStructure&, bool) const {return false;} +bool ErfcFunction::representsInteger(const MathStructure&, bool) const {return false;} +bool ErfcFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNumber();} +bool ErfcFunction::representsRational(const MathStructure&, bool) const {return false;} +bool ErfcFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +bool ErfcFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +bool ErfcFunction::representsComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsComplex();} +bool ErfcFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool ErfcFunction::representsEven(const MathStructure&, bool) const {return false;} +bool ErfcFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool ErfcFunction::representsUndefined(const MathStructure&) const {return false;} +int ErfcFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + FR_FUNCTION(erfc) +} + +LiFunction::LiFunction() : MathFunction("Li", 2) { + names[0].case_sensitive = true; + Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); + arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false); + arg->setHandleVector(true); + setArgumentDefinition(2, arg); +} +bool LiFunction::representsReal(const MathStructure &vargs, bool) const { + return vargs.size() == 2 && vargs[0].representsInteger() && vargs[1].representsReal() && (vargs[1].representsNonPositive() || ((vargs[1].isNumber() && vargs[1].number().isLessThanOrEqualTo(1)) || (vargs[1].isVariable() && vargs[1].variable()->isKnown() && ((KnownVariable*) vargs[1].variable())->get().isNumber() && ((KnownVariable*) vargs[1].variable())->get().number().isLessThanOrEqualTo(1)))) && ((vargs[0].representsPositive() || ((vargs[1].isNumber() && COMPARISON_IS_NOT_EQUAL(vargs[1].number().compare(nr_one))) || (vargs[1].isVariable() && vargs[1].variable()->isKnown() && ((KnownVariable*) vargs[1].variable())->get().isNumber() && COMPARISON_IS_NOT_EQUAL(((KnownVariable*) vargs[1].variable())->get().number().compare(nr_one)))))); +} +bool LiFunction::representsNonComplex(const MathStructure &vargs, bool) const { + return vargs.size() == 2 && vargs[0].representsInteger() && vargs[1].representsNonComplex() && (vargs[1].representsNonPositive() || ((vargs[1].isNumber() && vargs[1].number().isLessThanOrEqualTo(1)) || (vargs[1].isVariable() && vargs[1].variable()->isKnown() && ((KnownVariable*) vargs[1].variable())->get().isNumber() && ((KnownVariable*) vargs[1].variable())->get().number().isLessThanOrEqualTo(1)))); +} +bool LiFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[0].representsInteger() && (vargs[0].representsPositive() || (vargs[1].representsNumber() && ((vargs[1].isNumber() && COMPARISON_IS_NOT_EQUAL(vargs[1].number().compare(nr_one))) || (vargs[1].isVariable() && vargs[1].variable()->isKnown() && ((KnownVariable*) vargs[1].variable())->get().isNumber() && COMPARISON_IS_NOT_EQUAL(((KnownVariable*) vargs[1].variable())->get().number().compare(nr_one))))));} +int LiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[1].isVector()) return 0; + if(vargs[0].isInteger()) { + if(vargs[0].number().isOne()) { + mstruct.set(1, 1, 0); + mstruct -= vargs[1]; + mstruct.transformById(FUNCTION_ID_LOG); + mstruct.negate(); + return true; + } else if(vargs[0].number().isZero()) { + mstruct.set(1, 1, 0); + mstruct -= vargs[1]; + mstruct.inverse(); + mstruct += nr_minus_one; + return true; + } else if(vargs[0].number().isNegative()) { + if(vargs[0].number().isMinusOne()) { + mstruct.set(1, 1, 0); + mstruct -= vargs[1]; + mstruct ^= Number(-2, 1); + mstruct *= vargs[1]; + return true; + } else if(vargs[0].number() == -2) { + mstruct.set(1, 1, 0); + mstruct -= vargs[1]; + mstruct ^= Number(-3, 1); + mstruct *= vargs[1]; + mstruct.last() += m_one; + mstruct.last() *= vargs[1]; + return true; + } else if(vargs[0].number() == -3) { + mstruct.set(1, 1, 0); + mstruct -= vargs[1]; + mstruct ^= Number(-4, 1); + mstruct *= vargs[1]; + mstruct.last() ^= nr_two; + mstruct.last() += Number(4, 1); + mstruct.last().last() *= vargs[1]; + mstruct.last() += m_one; + mstruct.last() *= vargs[1]; + return true; + } else if(vargs[0].number() == -4) { + mstruct.set(1, 1, 0); + mstruct -= vargs[1]; + mstruct ^= Number(-5, 1); + mstruct *= vargs[1]; + mstruct.last() ^= nr_two; + mstruct.last() += Number(10, 1); + mstruct.last().last() *= vargs[1]; + mstruct.last() += m_one; + mstruct.last() *= vargs[1]; + mstruct.last().last() += m_one; + mstruct.last() *= vargs[1]; + return true; + } + } + } + mstruct = vargs[1]; + mstruct.eval(eo); + if(mstruct.isVector()) return -2; + if(vargs[0].number() >= 1 && mstruct.isOne()) { + mstruct = vargs[0]; + mstruct.transformById(FUNCTION_ID_ZETA); + return true; + } + if(mstruct.isNumber()) { + Number nr(mstruct.number()); + if(nr.polylog(vargs[0].number()) && (eo.approximation != APPROXIMATION_EXACT || !nr.isApproximate() || vargs[0].isApproximate() || mstruct.isApproximate()) && (eo.allow_complex || !nr.isComplex() || vargs[0].number().isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || vargs[0].number().includesInfinity() || mstruct.number().includesInfinity())) { + mstruct.set(nr); return 1; + } + } + return -2; +} + +HeavisideFunction::HeavisideFunction() : MathFunction("heaviside", 1) { + NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + arg->setHandleVector(true); + arg->setComplexAllowed(false); + setArgumentDefinition(1, arg); +} +bool HeavisideFunction::representsPositive(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative(true);} +bool HeavisideFunction::representsNegative(const MathStructure&, bool) const {return false;} +bool HeavisideFunction::representsNonNegative(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal(true);} +bool HeavisideFunction::representsNonPositive(const MathStructure&, bool) const {return false;} +bool HeavisideFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonZero() && vargs[0].representsReal(true);} +bool HeavisideFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal(true);} +bool HeavisideFunction::representsRational(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal(true);} +bool HeavisideFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);} +bool HeavisideFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal(true);} +bool HeavisideFunction::representsComplex(const MathStructure&, bool) const {return false;} +bool HeavisideFunction::representsNonZero(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonNegative(true);} +bool HeavisideFunction::representsEven(const MathStructure&, bool) const {return false;} +bool HeavisideFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool HeavisideFunction::representsUndefined(const MathStructure &vargs) const {return vargs.size() == 1 && vargs[0].representsUndefined();} +int HeavisideFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(!mstruct.representsNonComplex(true)) return false; + if(mstruct.representsPositive(true)) { + mstruct.set(1, 1, 0); + return 1; + } + if(mstruct.representsNegative(true)) { + mstruct.clear(); + return 1; + } + if(mstruct.isZero()) { + mstruct = nr_half; + return 1; + } + if(mstruct.isNumber() && mstruct.number().isInterval()) { + if(!mstruct.number().isNonNegative()) { + mstruct.number().setInterval(nr_half, nr_one); + } else if(!mstruct.number().isNonPositive()) { + mstruct.number().setInterval(nr_zero, nr_half); + } else { + mstruct.number().setInterval(nr_zero, nr_one); + } + return 1; + } + if(eo.approximation == APPROXIMATION_EXACT || has_interval_unknowns(mstruct)) { + ComparisonResult cr = mstruct.compare(m_zero); + if(cr == COMPARISON_RESULT_LESS) { + mstruct.set(1, 1, 0); + return 1; + } else if(cr == COMPARISON_RESULT_GREATER) { + mstruct.clear(); + return 1; + } + } + return -1; +} +DiracFunction::DiracFunction() : MathFunction("dirac", 1) { + NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false); + arg->setComplexAllowed(false); + setArgumentDefinition(1, arg); +} +bool DiracFunction::representsPositive(const MathStructure&, bool allow_units) const {return false;} +bool DiracFunction::representsNegative(const MathStructure&, bool) const {return false;} +bool DiracFunction::representsNonNegative(const MathStructure&, bool) const {return true;} +bool DiracFunction::representsNonPositive(const MathStructure&, bool) const {return false;} +bool DiracFunction::representsInteger(const MathStructure&, bool) const {return false;} +bool DiracFunction::representsNumber(const MathStructure&, bool) const {return false;} +bool DiracFunction::representsRational(const MathStructure&, bool) const {return false;} +bool DiracFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);} +bool DiracFunction::representsReal(const MathStructure&, bool) const {return false;} +bool DiracFunction::representsComplex(const MathStructure&, bool) const {return false;} +bool DiracFunction::representsNonZero(const MathStructure&, bool) const {return false;} +bool DiracFunction::representsEven(const MathStructure&, bool) const {return false;} +bool DiracFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool DiracFunction::representsUndefined(const MathStructure &vargs) const {return vargs.size() == 1 && vargs[0].representsUndefined();} +int DiracFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct = vargs[0]; + mstruct.eval(eo); + if(!mstruct.representsNonComplex(true)) return false; + if(mstruct.representsNonZero(true)) { + mstruct.clear(); + return 1; + } + if(mstruct.isZero()) { + mstruct = nr_plus_inf; + return 1; + } + if(mstruct.isNumber() && mstruct.number().isInterval() && !mstruct.number().isNonZero()) { + mstruct.number().setInterval(nr_zero, nr_plus_inf); + return 1; + } + if(eo.approximation == APPROXIMATION_EXACT || has_interval_unknowns(mstruct)) { + ComparisonResult cr = mstruct.compare(m_zero); + if(COMPARISON_IS_NOT_EQUAL(cr)) { + mstruct.clear(); + return 1; + } + } + return -1; +} + diff -Nru libqalculate-3.6.0/libqalculate/BuiltinFunctions-statistics.cc libqalculate-3.7.0/libqalculate/BuiltinFunctions-statistics.cc --- libqalculate-3.6.0/libqalculate/BuiltinFunctions-statistics.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/BuiltinFunctions-statistics.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,389 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Number.h" +#include "Calculator.h" + +#include +#include +#include +#include + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +TotalFunction::TotalFunction() : MathFunction("total", 1) { + setArgumentDefinition(1, new VectorArgument("")); +} +int TotalFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct.clear(); + for(size_t index = 0; index < vargs[0].size(); index++) { + if(CALCULATOR->aborted()) return 0; + mstruct.calculateAdd(vargs[0][index], eo); + } + return 1; +} +PercentileFunction::PercentileFunction() : MathFunction("percentile", 2, 3) { + setArgumentDefinition(1, new VectorArgument("")); + NumberArgument *arg = new NumberArgument(); + Number fr; + arg->setMin(&fr); + fr.set(100, 1, 0); + arg->setMax(&fr); + arg->setIncludeEqualsMin(true); + arg->setIncludeEqualsMax(true); + setArgumentDefinition(2, arg); + IntegerArgument *iarg = new IntegerArgument(); + fr.set(1, 1, 0); + iarg->setMin(&fr); + fr.set(9, 1, 0); + iarg->setMax(&fr); + setArgumentDefinition(3, iarg); + setDefaultValue(3, "8"); +} +int PercentileFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + MathStructure v(vargs[0]); + if(v.size() == 0) {mstruct.clear(); return 1;} + MathStructure *mp; + Number fr100(100, 1, 0); + int i_variant = vargs[2].number().intValue(); + if(!v.sortVector()) { + return 0; + } else { + Number pfr(vargs[1].number()); + if(pfr == fr100) { + // Max value + mstruct = v[v.size() - 1]; + return 1; + } else if(pfr.isZero()) { + // Min value + mstruct = v[0]; + return 1; + } + pfr /= 100; + if(pfr == nr_half) { + // Median + if(v.size() % 2 == 1) { + mstruct = v[v.size() / 2]; + } else { + mstruct = v[v.size() / 2 - 1]; + mstruct += v[v.size() / 2]; + mstruct *= nr_half; + } + return 1; + } + // Method numbers as in R + switch(i_variant) { + case 2: { + Number ufr(pfr); + ufr *= (long int) v.countChildren(); + if(ufr.isInteger()) { + pfr = ufr; + ufr++; + mstruct = v[pfr.uintValue() - 1]; + if(ufr.uintValue() > v.size()) return 1; + mstruct += v[ufr.uintValue() - 1]; + mstruct *= nr_half; + return 1; + } + } + case 1: { + pfr *= (long int) v.countChildren(); + pfr.ceil(); + size_t index = pfr.uintValue(); + if(index > v.size()) index = v.size(); + if(index == 0) index = 1; + mstruct = v[index - 1]; + return 1; + } + case 3: { + pfr *= (long int) v.countChildren(); + pfr.round(); + size_t index = pfr.uintValue(); + if(index > v.size()) index = v.size(); + if(index == 0) index = 1; + mstruct = v[index - 1]; + return 1; + } + case 4: {pfr *= (long int) v.countChildren(); break;} + case 5: {pfr *= (long int) v.countChildren(); pfr += nr_half; break;} + case 6: {pfr *= (long int) v.countChildren() + 1; break;} + case 7: {pfr *= (long int) v.countChildren() - 1; pfr += 1; break;} + case 9: {pfr *= Number(v.countChildren() * 4 + 1, 4); pfr += Number(3, 8); break;} + case 8: {} + default: {pfr *= Number(v.countChildren() * 3 + 1, 3); pfr += Number(1, 3); break;} + } + Number ufr(pfr); + ufr.ceil(); + Number lfr(pfr); + lfr.floor(); + pfr -= lfr; + size_t u_index = ufr.uintValue(); + size_t l_index = lfr.uintValue(); + if(u_index > v.size()) { + mstruct = v[v.size() - 1]; + return 1; + } + if(l_index == 0) { + mstruct = v[0]; + return 1; + } + mp = v.getChild(u_index); + if(!mp) return 0; + MathStructure gap(*mp); + mp = v.getChild(l_index); + if(!mp) return 0; + gap -= *mp; + gap *= pfr; + mp = v.getChild(l_index); + if(!mp) return 0; + mstruct = *mp; + mstruct += gap; + } + return 1; +} +MinFunction::MinFunction() : MathFunction("min", 1) { + setArgumentDefinition(1, new VectorArgument("")); +} +int MinFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + ComparisonResult cmp; + const MathStructure *min = NULL; + vector unsolveds; + bool b = false; + for(size_t index = 0; index < vargs[0].size(); index++) { + if(min == NULL) { + min = &vargs[0][index]; + } else { + cmp = min->compare(vargs[0][index]); + if(cmp == COMPARISON_RESULT_LESS) { + min = &vargs[0][index]; + b = true; + } else if(COMPARISON_NOT_FULLY_KNOWN(cmp)) { + if(CALCULATOR->showArgumentErrors()) { + CALCULATOR->error(true, _("Unsolvable comparison in %s()."), name().c_str(), NULL); + } + unsolveds.push_back(&vargs[0][index]); + } else { + b = true; + } + } + } + if(min) { + if(unsolveds.size() > 0) { + if(!b) return 0; + MathStructure margs; margs.clearVector(); + margs.addChild(*min); + for(size_t i = 0; i < unsolveds.size(); i++) { + margs.addChild(*unsolveds[i]); + } + mstruct.set(this, &margs, NULL); + return 1; + } else { + mstruct = *min; + return 1; + } + } + return 0; +} +MaxFunction::MaxFunction() : MathFunction("max", 1) { + setArgumentDefinition(1, new VectorArgument("")); +} +int MaxFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + ComparisonResult cmp; + const MathStructure *max = NULL; + vector unsolveds; + bool b = false; + for(size_t index = 0; index < vargs[0].size(); index++) { + if(max == NULL) { + max = &vargs[0][index]; + } else { + cmp = max->compare(vargs[0][index]); + if(cmp == COMPARISON_RESULT_GREATER) { + max = &vargs[0][index]; + b = true; + } else if(COMPARISON_NOT_FULLY_KNOWN(cmp)) { + if(CALCULATOR->showArgumentErrors()) { + CALCULATOR->error(true, _("Unsolvable comparison in %s()."), name().c_str(), NULL); + } + unsolveds.push_back(&vargs[0][index]); + } else { + b = true; + } + } + } + if(max) { + if(unsolveds.size() > 0) { + if(!b) return 0; + MathStructure margs; margs.clearVector(); + margs.addChild(*max); + for(size_t i = 0; i < unsolveds.size(); i++) { + margs.addChild(*unsolveds[i]); + } + mstruct.set(this, &margs, NULL); + return 1; + } else { + mstruct = *max; + return 1; + } + } + return 0; +} +ModeFunction::ModeFunction() : MathFunction("mode", 1) { + setArgumentDefinition(1, new VectorArgument("")); +} +int ModeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + if(vargs[0].size() <= 0) { + return 0; + } + size_t n = 0; + bool b; + vector vargs_nodup; + vector is; + const MathStructure *value = NULL; + for(size_t index_c = 0; index_c < vargs[0].size(); index_c++) { + b = true; + for(size_t index = 0; index < vargs_nodup.size(); index++) { + if(vargs_nodup[index]->equals(vargs[0][index_c])) { + is[index]++; + b = false; + break; + } + } + if(b) { + vargs_nodup.push_back(&vargs[0][index_c]); + is.push_back(1); + } + } + for(size_t index = 0; index < is.size(); index++) { + if(is[index] > n) { + n = is[index]; + value = vargs_nodup[index]; + } + } + if(value) { + mstruct = *value; + return 1; + } + return 0; +} + +RandFunction::RandFunction() : MathFunction("rand", 0, 2) { + setArgumentDefinition(1, new IntegerArgument()); + setDefaultValue(1, "0"); + setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); + setDefaultValue(2, "1"); +} +int RandFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + size_t n = (size_t) vargs[1].number().uintValue(); + if(n > 1) {mstruct.clearVector(); mstruct.resizeVector(n, m_zero);} + Number nr; + for(size_t i = 0; i < n; i++) { + if(vargs[0].number().isZero() || vargs[0].number().isNegative()) { + nr.rand(); + } else { + nr.intRand(vargs[0].number()); + nr++; + } + if(n > 1) mstruct[i] = nr; + else mstruct = nr; + } + return 1; +} +bool RandFunction::representsReal(const MathStructure&, bool) const {return true;} +bool RandFunction::representsInteger(const MathStructure &vargs, bool) const {return vargs.size() > 0 && vargs[0].isNumber() && vargs[0].number().isPositive();} +bool RandFunction::representsNonNegative(const MathStructure&, bool) const {return true;} + +RandnFunction::RandnFunction() : MathFunction("randnorm", 0, 3) { + setDefaultValue(1, "0"); + setDefaultValue(2, "1"); + setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); + setDefaultValue(3, "1"); +} +int RandnFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + size_t n = (size_t) vargs[2].number().uintValue(); + if(n > 1) {mstruct.clearVector(); mstruct.resizeVector(n, m_zero);} +#if MPFR_VERSION_MAJOR < 4 + Number nr_u, nr_v, nr_r2; + for(size_t i = 0; i < n; i++) { + do { + nr_u.rand(); nr_u *= 2; nr_u -= 1; + nr_v.rand(); nr_v *= 2; nr_v -= 1; + nr_r2 = (nr_u ^ 2) + (nr_v ^ 2); + } while(nr_r2 > 1 || nr_r2.isZero()); + Number nr_rsq(nr_r2); + nr_rsq.ln(); + nr_rsq /= nr_r2; + nr_rsq *= -2; + nr_rsq.sqrt(); + nr_u *= nr_rsq; + if(n > 1) { + mstruct[i] = nr_u; + i++; + if(i < n) { + nr_v *= nr_rsq; + mstruct[i] = nr_v; + } + } else { + mstruct = nr_u; + } + } +#else + Number nr; + for(size_t i = 0; i < n; i++) { + nr.randn(); + if(n > 1) mstruct[i] = nr; + else mstruct = nr; + } +#endif + if(!vargs[1].isOne()) mstruct *= vargs[1]; + if(!vargs[0].isZero()) mstruct += vargs[0]; + return 1; +} +bool RandnFunction::representsReal(const MathStructure&, bool) const {return true;} +bool RandnFunction::representsNonComplex(const MathStructure&, bool) const {return true;} +bool RandnFunction::representsNumber(const MathStructure&, bool) const {return true;} + +RandPoissonFunction::RandPoissonFunction() : MathFunction("randpoisson", 1, 2) { + setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_NONNEGATIVE)); + setDefaultValue(1, "0"); + setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); + setDefaultValue(2, "1"); +} +int RandPoissonFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + size_t n = (size_t) vargs[2].number().uintValue(); + if(n > 1) {mstruct.clearVector(); mstruct.resizeVector(n, m_zero);} + Number nr_L(vargs[1].number()); + nr_L.exp(); + Number nr_k, nr_p, nr_u; + for(size_t i = 0; i < n; i++) { + nr_k.clear(); nr_p = 1; + do { + nr_k++; + nr_u.rand(); + nr_p *= nr_u; + } while(nr_p > nr_L); + nr_k--; + if(n > 1) mstruct[i] = nr_k; + else mstruct = nr_k; + } + return 1; +} +bool RandPoissonFunction::representsReal(const MathStructure&, bool) const {return true;} +bool RandPoissonFunction::representsInteger(const MathStructure &vargs, bool) const {return true;} +bool RandPoissonFunction::representsNonNegative(const MathStructure&, bool) const {return true;} + diff -Nru libqalculate-3.6.0/libqalculate/BuiltinFunctions-trigonometry.cc libqalculate-3.7.0/libqalculate/BuiltinFunctions-trigonometry.cc --- libqalculate-3.6.0/libqalculate/BuiltinFunctions-trigonometry.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/BuiltinFunctions-trigonometry.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,1762 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Number.h" +#include "Calculator.h" +#include "Variable.h" +#include "Unit.h" + +#include +#include +#include +#include + +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +#define FR_FUNCTION_2(FUNC) Number nr(vargs[0].number()); if(!nr.FUNC(vargs[1].number()) || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !vargs[0].isApproximate() && !vargs[1].isApproximate()) || (!eo.allow_complex && nr.isComplex() && !vargs[0].number().isComplex() && !vargs[1].number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !vargs[0].number().includesInfinity() && !vargs[1].number().includesInfinity())) {return 0;} else {mstruct.set(nr); return 1;} + +bool is_real_angle_value(const MathStructure &mstruct) { + if(mstruct.isUnit()) { + return mstruct.unit()->baseUnit() == CALCULATOR->getRadUnit()->baseUnit(); + } else if(mstruct.isMultiplication()) { + bool b = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(!b && mstruct[i].isUnit()) { + if(mstruct[i].unit()->baseUnit() == CALCULATOR->getRadUnit()->baseUnit()) { + b = true; + } else { + return false; + } + } else if(!mstruct[i].representsReal()) { + return false; + } + } + return b; + } else if(mstruct.isAddition()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(!is_real_angle_value(mstruct[i])) return false; + } + return true; + } + return false; +} +bool is_infinite_angle_value(const MathStructure &mstruct) { + if(mstruct.isMultiplication() && mstruct.size() == 2) { + bool b = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(!b && mstruct[i].isUnit()) { + if(mstruct[i].unit()->baseUnit() == CALCULATOR->getRadUnit()->baseUnit()) { + b = true; + } else { + return false; + } + } else if(!mstruct[i].isNumber() || !mstruct[i].number().isInfinite()) { + return false; + } + } + return b; + } + return false; +} +bool is_number_angle_value(const MathStructure &mstruct, bool allow_infinity = false) { + if(mstruct.isUnit()) { + return mstruct.unit()->baseUnit() == CALCULATOR->getRadUnit()->baseUnit(); + } else if(mstruct.isMultiplication()) { + bool b = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(!b && mstruct[i].isUnit()) { + if(mstruct[i].unit()->baseUnit() == CALCULATOR->getRadUnit()->baseUnit()) { + b = true; + } else { + return false; + } + } else if(!mstruct[i].representsNumber()) { + if(!allow_infinity || ((!mstruct[i].isNumber() || !mstruct[i].number().isInfinite()) && (!mstruct[i].isPower() || !mstruct[i][0].representsNumber() || !mstruct[i][1].representsNumber())) || mstruct[i].representsUndefined(true)) { + return false; + } + } + } + return b; + } else if(mstruct.isAddition()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(!is_number_angle_value(mstruct[i])) return false; + } + return true; + } + return false; +} + +bool has_predominately_negative_sign(const MathStructure &mstruct) { + if(mstruct.hasNegativeSign() && !mstruct.containsType(STRUCT_ADDITION, true)) return true; + if(mstruct.containsInfinity(false, false, false) > 0) return false; + if(mstruct.isAddition() && mstruct.size() > 0) { + size_t p_count = 0; + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].hasNegativeSign()) { + p_count++; + if(p_count > mstruct.size() / 2) return true; + } + } + if(mstruct.size() % 2 == 0 && p_count == mstruct.size() / 2) return mstruct[0].hasNegativeSign(); + } + return false; +} + +void negate_struct(MathStructure &mstruct) { + if(mstruct.isAddition()) { + for(size_t i = 0; i < mstruct.size(); i++) { + mstruct[i].negate(); + } + } else { + mstruct.negate(); + } +} + +bool trig_remove_i(MathStructure &mstruct) { + if(mstruct.isNumber() && mstruct.number().hasImaginaryPart() && !mstruct.number().hasRealPart()) { + mstruct.number() /= nr_one_i; + return true; + } else if(mstruct.isMultiplication() && mstruct.size() > 1 && mstruct[0].isNumber() && mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().hasRealPart()) { + mstruct[0].number() /= nr_one_i; + return true; + } else if(mstruct.isAddition() && mstruct.size() > 0) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(!(mstruct[i].isNumber() && mstruct[i].number().hasImaginaryPart() && !mstruct[i].number().hasRealPart()) && !(mstruct[i].isMultiplication() && mstruct[i].size() > 1 && mstruct[i][0].isNumber() && mstruct[i][0].number().hasImaginaryPart() && !mstruct[i][0].number().hasRealPart())) { + return false; + } + } + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isNumber()) mstruct[i].number() /= nr_one_i; + else mstruct[i][0].number() /= nr_one_i; + } + return true; + } + return false; +} + +SinFunction::SinFunction() : MathFunction("sin", 1) { + Argument *arg = new AngleArgument(); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +bool SinFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && ((allow_units && (vargs[0].representsNumber(true) || vargs[0].representsNonComplex(true))) || (!allow_units && is_number_angle_value(vargs[0], true)));} +bool SinFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && (is_real_angle_value(vargs[0]) || is_infinite_angle_value(vargs[0]));} +bool SinFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);} +int SinFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + + if(vargs[0].isVector()) return 0; + if(CALCULATOR->getRadUnit()) { + if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getRadUnit()) { + mstruct = vargs[0][0]; + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getRadUnit()) { + mstruct = vargs[0][1]; + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getDegUnit()) { + mstruct = vargs[0][0]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 180), true); + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getDegUnit()) { + mstruct = vargs[0][1]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 180), true); + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getGraUnit()) { + mstruct = vargs[0][0]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 200), true); + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getGraUnit()) { + mstruct = vargs[0][1]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 200), true); + } else { + mstruct = vargs[0]; + mstruct.convert(CALCULATOR->getRadUnit()); + mstruct /= CALCULATOR->getRadUnit(); + } + } else { + mstruct = vargs[0]; + } + + MathFunction *f = NULL; + if(eo.approximation == APPROXIMATION_APPROXIMATE && (eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS)) { + if(mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[0].isFunction() && mstruct[0].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI && mstruct[2].isNumber() && mstruct[2].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) { + f = mstruct[0].function(); + } + } + + if(eo.approximation == APPROXIMATION_TRY_EXACT) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_EXACT; + CALCULATOR->beginTemporaryStopMessages(); + mstruct.eval(eo2); + } else if(!f) { + mstruct.eval(eo); + } + + if(mstruct.isVector()) { + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + if(CALCULATOR->getRadUnit()) { + for(size_t i = 0; i < mstruct.size(); i++) { + mstruct[i] *= CALCULATOR->getRadUnit(); + } + } + return -1; + } + + bool b = false, b_recalc = true; + + if(eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS) { + if(!f && mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[2].isFunction() && mstruct[2].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI && mstruct[0].isNumber() && mstruct[0].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) { + f = mstruct[2].function(); + } + } else if(mstruct.isFunction() && mstruct.size() == 1) { + f = mstruct.function(); + } + + if(mstruct.isVariable() && mstruct.variable()->id() == VARIABLE_ID_PI) { + mstruct.clear(); + b = true; + } else if(f) { + if(f->id() == FUNCTION_ID_ASIN) { + if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); + mstruct.setToChild(1, true); + b = true; + } else if(f->id() == FUNCTION_ID_ACOS) { + if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); + mstruct.setToChild(1); + mstruct ^= nr_two; + mstruct.negate(); + mstruct += nr_one; + mstruct ^= nr_half; + b = true; + } else if(f->id() == FUNCTION_ID_ATAN && (mstruct.isFunction() ? !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : (mstruct[0][0].isFunction() ? mstruct[2][0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)))) { + if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); + mstruct.setToChild(1); + MathStructure *mmul = new MathStructure(mstruct); + mstruct ^= nr_two; + mstruct += nr_one; + mstruct ^= nr_minus_half; + mstruct.multiply_nocopy(mmul); + b = true; + } + } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI) { + if(mstruct[0].number().isInteger()) { + mstruct.clear(); + b = true; + } else if(!mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().includesInfinity() && !mstruct[0].number().isInterval()) { + Number nr(mstruct[0].number()); + nr.frac(); + Number nr_int(mstruct[0].number()); + nr_int.floor(); + bool b_even = nr_int.isEven(); + nr.setNegative(false); + if(nr.equals(Number(1, 2, 0))) { + if(b_even) mstruct.set(1, 1, 0); + else mstruct.set(-1, 1, 0); + b = true; + } else if(nr.equals(Number(1, 4, 0)) || nr.equals(Number(3, 4, 0))) { + mstruct.set(2, 1, 0); + mstruct.raise_nocopy(new MathStructure(1, 2, 0)); + mstruct.divide_nocopy(new MathStructure(2, 1, 0)); + if(!b_even) mstruct.negate(); + b = true; + } else if(nr.equals(Number(1, 3, 0)) || nr.equals(Number(2, 3, 0))) { + mstruct.set(3, 1, 0); + mstruct.raise_nocopy(new MathStructure(1, 2, 0)); + mstruct.divide_nocopy(new MathStructure(2, 1, 0)); + if(!b_even) mstruct.negate(); + b = true; + } else if(nr.equals(Number(1, 6, 0)) || nr.equals(Number(5, 6, 0))) { + if(b_even) mstruct.set(1, 2, 0); + else mstruct.set(-1, 2, 0); + b = true; + } else if(eo.approximation == APPROXIMATION_EXACT && (mstruct[0].number().isNegative() || !mstruct[0].number().isFraction() || mstruct[0].number().isGreaterThan(nr_half))) { + nr_int = mstruct[0].number(); + nr_int.floor(); + Number nr_frac = mstruct[0].number(); + nr_frac -= nr_int; + if(nr_frac.isGreaterThan(nr_half)) { + nr_frac -= nr_half; + mstruct[0].number() = nr_half; + mstruct[0].number() -= nr_frac; + } else { + mstruct[0].number() = nr_frac; + } + if(nr_int.isOdd()) { + if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); + mstruct.transform(this); + mstruct.negate(); + b = true; + } + } + } + } else if(mstruct.isAddition()) { + size_t i = 0; + bool b_negate = false; + for(; i < mstruct.size(); i++) { + if((mstruct[i].isVariable() && mstruct[i].variable()->id() == VARIABLE_ID_PI) || (mstruct[i].isMultiplication() && mstruct[i].size() == 2 && mstruct[i][1].isVariable() && mstruct[i][1].variable()->id() == VARIABLE_ID_PI && mstruct[i][0].isNumber())) { + if(mstruct[i].isVariable() || mstruct[i][0].number().isInteger()) { + b_negate = mstruct[i].isVariable() || mstruct[i][0].number().isOdd(); + mstruct.delChild(i + 1); + b_recalc = false; + break; + } else if(mstruct[i][0].number().isReal() && (mstruct[i][0].number().isNegative() || !mstruct[i][0].number().isFraction())) { + Number nr_int = mstruct[i][0].number(); + nr_int.floor(); + mstruct[i][0].number() -= nr_int; + b_negate = nr_int.isOdd(); + b_recalc = false; + break; + } + } + } + b = b_negate; + if(b_negate) { + if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); + mstruct.transform(this); + mstruct.negate(); + } + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(b); + if(b) return 1; + if(eo.approximation == APPROXIMATION_TRY_EXACT && !mstruct.isNumber()) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + if(b_recalc) { + mstruct = vargs[0]; + if(CALCULATOR->getRadUnit()) { + mstruct.convert(CALCULATOR->getRadUnit()); + mstruct /= CALCULATOR->getRadUnit(); + } + } + mstruct.eval(eo2); + } + + if(mstruct.isNumber()) { + Number nr(mstruct.number()); + if(nr.sin() && !(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + mstruct.set(nr, true); + return 1; + } + } + + if(trig_remove_i(mstruct)) { + mstruct.transformById(FUNCTION_ID_SINH); + mstruct *= nr_one_i; + return 1; + } + + if(has_predominately_negative_sign(mstruct)) { + negate_struct(mstruct); + if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); + mstruct.transform(this); + mstruct.negate(); + return 1; + } + + + if(CALCULATOR->getRadUnit()) { + if(mstruct.isVector()) { + for(size_t i = 0; i < mstruct.size(); i++) { + mstruct[i] *= CALCULATOR->getRadUnit(); + } + } else { + mstruct *= CALCULATOR->getRadUnit(); + } + } + return -1; +} + +CosFunction::CosFunction() : MathFunction("cos", 1) { + Argument *arg = new AngleArgument(); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +bool CosFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && ((allow_units && (vargs[0].representsNumber(true) || vargs[0].representsNonComplex(true))) || (!allow_units && is_number_angle_value(vargs[0], true)));} +bool CosFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && (is_real_angle_value(vargs[0]) || is_infinite_angle_value(vargs[0]));} +bool CosFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);} +int CosFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + + if(vargs[0].isVector()) return 0; + if(CALCULATOR->getRadUnit()) { + if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getRadUnit()) { + mstruct = vargs[0][0]; + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getRadUnit()) { + mstruct = vargs[0][1]; + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getDegUnit()) { + mstruct = vargs[0][0]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 180), true); + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getDegUnit()) { + mstruct = vargs[0][1]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 180), true); + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getGraUnit()) { + mstruct = vargs[0][0]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 200), true); + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getGraUnit()) { + mstruct = vargs[0][1]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 200), true); + } else { + mstruct = vargs[0]; + mstruct.convert(CALCULATOR->getRadUnit()); + mstruct /= CALCULATOR->getRadUnit(); + } + } else { + mstruct = vargs[0]; + } + + MathFunction *f = NULL; + if(eo.approximation == APPROXIMATION_APPROXIMATE && (eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS)) { + if(mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[0].isFunction() && mstruct[0].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI && mstruct[2].isNumber() && mstruct[2].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) { + f = mstruct[0].function(); + } + } + + if(eo.approximation == APPROXIMATION_TRY_EXACT) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_EXACT; + CALCULATOR->beginTemporaryStopMessages(); + mstruct.eval(eo2); + } else if(!f) { + mstruct.eval(eo); + } + + if(mstruct.isVector()) { + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + if(CALCULATOR->getRadUnit()) { + for(size_t i = 0; i < mstruct.size(); i++) { + mstruct[i] *= CALCULATOR->getRadUnit(); + } + } + return -1; + } + + bool b = false, b_recalc = true; + + if(eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS) { + if(!f && mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[2].isFunction() && mstruct[2].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI && mstruct[0].isNumber() && mstruct[0].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) { + f = mstruct[2].function(); + } + } else if(mstruct.isFunction() && mstruct.size() == 1) { + f = mstruct.function(); + } + + if(mstruct.isVariable() && mstruct.variable()->id() == VARIABLE_ID_PI) { + mstruct = -1; + b = true; + } else if(f) { + if(f->id() == FUNCTION_ID_ACOS) { + if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); + mstruct.setToChild(1, true); + b = true; + } else if(f->id() == FUNCTION_ID_ASIN) { + if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); + mstruct.setToChild(1); + mstruct ^= nr_two; + mstruct.negate(); + mstruct += nr_one; + mstruct ^= nr_half; + b = true; + } else if(f->id() == FUNCTION_ID_ATAN) { + if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); + mstruct.setToChild(1); + mstruct ^= nr_two; + mstruct += nr_one; + mstruct ^= nr_minus_half; + b = true; + } + } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI) { + if(mstruct[0].number().isInteger()) { + if(mstruct[0].number().isEven()) { + mstruct = 1; + } else { + mstruct = -1; + } + b = true; + } else if(!mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().includesInfinity() && !mstruct[0].number().isInterval()) { + Number nr(mstruct[0].number()); + nr.frac(); + Number nr_int(mstruct[0].number()); + nr_int.trunc(); + bool b_even = nr_int.isEven(); + nr.setNegative(false); + if(nr.equals(Number(1, 2, 0))) { + mstruct.clear(); + b = true; + } else if(nr.equals(Number(1, 4, 0))) { + mstruct.set(2, 1, 0); + mstruct.raise_nocopy(new MathStructure(1, 2, 0)); + mstruct.divide_nocopy(new MathStructure(2, 1, 0)); + if(!b_even) mstruct.negate(); + b = true; + } else if(nr.equals(Number(3, 4, 0))) { + mstruct.set(2, 1, 0); + mstruct.raise_nocopy(new MathStructure(1, 2, 0)); + mstruct.divide_nocopy(new MathStructure(2, 1, 0)); + if(b_even) mstruct.negate(); + b = true; + } else if(nr.equals(Number(1, 3, 0))) { + if(b_even) mstruct.set(1, 2, 0); + else mstruct.set(-1, 2, 0); + b = true; + } else if(nr.equals(Number(2, 3, 0))) { + if(b_even) mstruct.set(-1, 2, 0); + else mstruct.set(1, 2, 0); + b = true; + } else if(nr.equals(Number(1, 6, 0))) { + mstruct.set(3, 1, 0); + mstruct.raise_nocopy(new MathStructure(1, 2, 0)); + mstruct.divide_nocopy(new MathStructure(2, 1, 0)); + if(!b_even) mstruct.negate(); + b = true; + } else if(nr.equals(Number(5, 6, 0))) { + mstruct.set(3, 1, 0); + mstruct.raise_nocopy(new MathStructure(1, 2, 0)); + mstruct.divide_nocopy(new MathStructure(2, 1, 0)); + if(b_even) mstruct.negate(); + b = true; + } else if(eo.approximation == APPROXIMATION_EXACT && (mstruct[0].number().isNegative() || !mstruct[0].number().isFraction() || mstruct[0].number().isGreaterThan(nr_half))) { + nr_int = mstruct[0].number(); + nr_int.floor(); + Number nr_frac = mstruct[0].number(); + nr_frac -= nr_int; + if(nr_frac.isGreaterThan(nr_half)) { + nr_frac -= nr_half; + mstruct[0].number() = nr_half; + mstruct[0].number() -= nr_frac; + nr_int++; + } else { + mstruct[0].number() = nr_frac; + } + if(nr_int.isOdd()) { + if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); + mstruct.transform(this); + mstruct.negate(); + b = true; + } + } + } + } else if(mstruct.isAddition()) { + size_t i = 0; + bool b_negate = false; + for(; i < mstruct.size(); i++) { + if((mstruct[i].isVariable() && mstruct[i].variable()->id() == VARIABLE_ID_PI) || (mstruct[i].isMultiplication() && mstruct[i].size() == 2 && mstruct[i][1].isVariable() && mstruct[i][1].variable()->id() == VARIABLE_ID_PI && mstruct[i][0].isNumber())) { + if(mstruct[i].isVariable() || mstruct[i][0].number().isInteger()) { + b_negate = mstruct[i].isVariable() || mstruct[i][0].number().isOdd(); + mstruct.delChild(i + 1); + b_recalc = false; + break; + } else if(mstruct[i][0].number().isReal() && (mstruct[i][0].number().isNegative() || !mstruct[i][0].number().isFraction())) { + Number nr_int = mstruct[i][0].number(); + nr_int.floor(); + mstruct[i][0].number() -= nr_int; + b_negate = nr_int.isOdd(); + b_recalc = false; + break; + } + } + } + b = b_negate; + if(b_negate) { + if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); + mstruct.transform(this); + mstruct.negate(); + } + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(b); + if(b) return 1; + if(eo.approximation == APPROXIMATION_TRY_EXACT && !mstruct.isNumber()) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + if(b_recalc) { + mstruct = vargs[0]; + if(CALCULATOR->getRadUnit()) { + mstruct.convert(CALCULATOR->getRadUnit()); + mstruct /= CALCULATOR->getRadUnit(); + } + } + mstruct.eval(eo2); + } + if(mstruct.isNumber()) { + Number nr(mstruct.number()); + if(nr.cos() && !(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + mstruct.set(nr, true); + return 1; + } + } + if(trig_remove_i(mstruct)) { + mstruct.transformById(FUNCTION_ID_COSH); + return 1; + } + if(has_predominately_negative_sign(mstruct)) { + negate_struct(mstruct); + } + if(CALCULATOR->getRadUnit()) { + if(mstruct.isVector()) { + for(size_t i = 0; i < mstruct.size(); i++) { + mstruct[i] *= CALCULATOR->getRadUnit(); + } + } else { + mstruct *= CALCULATOR->getRadUnit(); + } + } + return -1; +} + +TanFunction::TanFunction() : MathFunction("tan", 1) { + Argument *arg = new AngleArgument(); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +bool TanFunction::representsNumber(const MathStructure&, bool) const {return false;} +bool TanFunction::representsReal(const MathStructure&, bool) const {return false;} +bool TanFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex(true);} +int TanFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + + if(vargs[0].isVector()) return 0; + if(CALCULATOR->getRadUnit()) { + if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getRadUnit()) { + mstruct = vargs[0][0]; + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getRadUnit()) { + mstruct = vargs[0][1]; + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getDegUnit()) { + mstruct = vargs[0][0]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 180), true); + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getDegUnit()) { + mstruct = vargs[0][1]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 180), true); + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][1] == CALCULATOR->getGraUnit()) { + mstruct = vargs[0][0]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 200), true); + } else if(vargs[0].isMultiplication() && vargs[0].size() == 2 && vargs[0][0] == CALCULATOR->getGraUnit()) { + mstruct = vargs[0][1]; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.multiply(Number(1, 200), true); + } else { + mstruct = vargs[0]; + mstruct.convert(CALCULATOR->getRadUnit()); + mstruct /= CALCULATOR->getRadUnit(); + } + } else { + mstruct = vargs[0]; + } + + MathFunction *f = NULL; + if(eo.approximation == APPROXIMATION_APPROXIMATE && (eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS)) { + if(mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[0].isFunction() && mstruct[0].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI && mstruct[2].isNumber() && mstruct[2].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) { + f = mstruct[0].function(); + } + } + + if(eo.approximation == APPROXIMATION_TRY_EXACT) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_EXACT; + CALCULATOR->beginTemporaryStopMessages(); + mstruct.eval(eo2); + } else if(!f) { + mstruct.eval(eo); + } + + if(mstruct.isVector()) { + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + if(CALCULATOR->getRadUnit()) { + for(size_t i = 0; i < mstruct.size(); i++) { + mstruct[i] *= CALCULATOR->getRadUnit(); + } + } + return -1; + } + + bool b = false, b_recalc = true; + + if(eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES || eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS) { + if(!f && mstruct.isMultiplication() && mstruct.size() == 3 && mstruct[2].isFunction() && mstruct[2].size() == 1 && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI && mstruct[0].isNumber() && mstruct[0].number().equals(Number(1, eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES ? 180 : 200))) { + f = mstruct[2].function(); + } + } else if(mstruct.isFunction() && mstruct.size() == 1) { + f = mstruct.function(); + } + + if(mstruct.isVariable() && mstruct.variable()->id() == VARIABLE_ID_PI) { + mstruct.clear(); + b = true; + } else if(f) { + if(f->id() == FUNCTION_ID_ATAN) { + if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); + mstruct.setToChild(1, true); + b = true; + } else if(f->id() == FUNCTION_ID_ASIN && (mstruct.isFunction() ? !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : (mstruct[0][0].isFunction() ? mstruct[2][0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)))) { + if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); + mstruct.setToChild(1); + MathStructure *mmul = new MathStructure(mstruct); + mstruct ^= nr_two; + mstruct.negate(); + mstruct += nr_one; + mstruct ^= nr_minus_half; + mstruct.multiply_nocopy(mmul); + b = true; + } else if(f->id() == FUNCTION_ID_ACOS && (mstruct.isFunction() ? !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : (mstruct[0][0].isFunction() ? mstruct[2][0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true) : mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation != APPROXIMATION_EXACT, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)))) { + if(!mstruct.isFunction()) mstruct.setToChild(mstruct[0].isFunction() ? 1 : 3, true); + mstruct.setToChild(1); + MathStructure *mmul = new MathStructure(mstruct); + mstruct ^= nr_two; + mstruct.negate(); + mstruct += nr_one; + mstruct ^= nr_half; + mstruct.divide_nocopy(mmul); + b = true; + } + } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI) { + if(mstruct[0].number().isInteger()) { + mstruct.clear(); + b = true; + } else if(!mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().includesInfinity() && !mstruct[0].number().isInterval()) { + Number nr(mstruct[0].number()); + nr.frac(); + bool b_neg = nr.isNegative(); + nr.setNegative(false); + if(nr.equals(nr_half)) { + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + if(!mstruct[0].number().numeratorIsOne() && !mstruct[0].number().numeratorEquals(3)) { + Number nr_int(mstruct[0].number()); + nr_int.floor(); + bool b_even = nr_int.isEven(); + if(b_even) mstruct[0].set(nr_half, true); + else mstruct[0].set(Number(3, 2), true); + mstruct.childUpdated(1); + } + if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); + return -1; + } else if(nr.equals(Number(1, 4, 0))) { + if(b_neg) mstruct.set(-1, 1, 0); + else mstruct.set(1, 1, 0); + b = true; + } else if(nr.equals(Number(3, 4, 0))) { + if(!b_neg) mstruct.set(-1, 1, 0); + else mstruct.set(1, 1, 0); + b = true; + } else if(nr.equals(Number(1, 3, 0))) { + mstruct.set(3, 1, 0); + mstruct.raise_nocopy(new MathStructure(1, 2, 0)); + if(b_neg) mstruct.negate(); + b = true; + } else if(nr.equals(Number(2, 3, 0))) { + mstruct.set(3, 1, 0); + mstruct.raise_nocopy(new MathStructure(1, 2, 0)); + if(!b_neg) mstruct.negate(); + b = true; + } else if(nr.equals(Number(1, 6, 0))) { + mstruct.set(3, 1, 0); + mstruct.raise_nocopy(new MathStructure(-1, 2, 0)); + if(b_neg) mstruct.negate(); + b = true; + } else if(nr.equals(Number(5, 6, 0))) { + mstruct.set(3, 1, 0); + mstruct.raise_nocopy(new MathStructure(-1, 2, 0)); + if(!b_neg) mstruct.negate(); + b = true; + } else if(eo.approximation == APPROXIMATION_EXACT && (mstruct[0].number().isNegative() || !mstruct[0].number().isFraction() || mstruct[0].number().isGreaterThan(nr_half))) { + Number nr_int(mstruct[0].number()); + nr_int.floor(); + Number nr_frac = mstruct[0].number(); + nr_frac -= nr_int; + if(nr_frac.isGreaterThan(nr_half)) { + nr_frac -= nr_half; + mstruct[0].number() = nr_half; + mstruct[0].number() -= nr_frac; + if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); + mstruct.transform(this); + mstruct.negate(); + b = true; + } else { + mstruct[0].number() = nr_frac; + } + } + } + } else if(mstruct.isAddition()) { + size_t i = 0; + for(; i < mstruct.size(); i++) { + if((mstruct[i].isVariable() && mstruct[i].variable()->id() == VARIABLE_ID_PI) || (mstruct[i].isMultiplication() && mstruct[i].size() == 2 && mstruct[i][1].isVariable() && mstruct[i][1].variable()->id() == VARIABLE_ID_PI && mstruct[i][0].isNumber())) { + if(mstruct[i].isVariable() || mstruct[i][0].number().isInteger()) { + mstruct.delChild(i + 1); + b_recalc = false; + break; + } else if(mstruct[i][0].number().isReal() && (mstruct[i][0].number().isNegative() || !mstruct[i][0].number().isFraction())) { + Number nr_int = mstruct[i][0].number(); + nr_int.floor(); + mstruct[i][0].number() -= nr_int; + b_recalc = false; + break; + } + } + } + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(b); + if(b) return 1; + if(eo.approximation == APPROXIMATION_TRY_EXACT && !mstruct.isNumber()) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + if(b_recalc) { + mstruct = vargs[0]; + if(CALCULATOR->getRadUnit()) { + mstruct.convert(CALCULATOR->getRadUnit()); + mstruct /= CALCULATOR->getRadUnit(); + } + mstruct.eval(eo2); + } + } + + if(mstruct.isNumber()) { + Number nr(mstruct.number()); + if(nr.tan() && !(eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) && !(!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) && !(!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + mstruct.set(nr, true); + return 1; + } + } + + if(trig_remove_i(mstruct)) { + mstruct.transformById(FUNCTION_ID_TANH); + mstruct *= nr_one_i; + return 1; + } + + if(has_predominately_negative_sign(mstruct)) { + negate_struct(mstruct); + if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit(); + mstruct.transform(this); + mstruct.negate(); + return 1; + } + + if(CALCULATOR->getRadUnit()) { + if(mstruct.isVector()) { + for(size_t i = 0; i < mstruct.size(); i++) { + mstruct[i] *= CALCULATOR->getRadUnit(); + } + } else { + mstruct *= CALCULATOR->getRadUnit(); + } + } + + return -1; +} + +AsinFunction::AsinFunction() : MathFunction("asin", 1) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); +} +bool AsinFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} +int AsinFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + if(eo.approximation == APPROXIMATION_TRY_EXACT) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_EXACT; + CALCULATOR->beginTemporaryStopMessages(); + mstruct.eval(eo2); + } else { + mstruct.eval(eo); + } + if(mstruct.isVector()) { + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + return -1; + } + if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0] == nr_half && mstruct[1].isPower() && mstruct[1][1] == nr_half) { + if(mstruct[1][0] == nr_two) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.set(45, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.set(50, 1, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + default: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + return 1; + } else if(mstruct[1][0] == nr_three) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.set(60, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 3, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct.set(1, 3, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + default: {mstruct.set(1, 3, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + return 1; + } + } else if(mstruct.isPower() && mstruct[1] == nr_minus_half && mstruct[0] == nr_two) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.set(45, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.set(50, 1, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + default: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + return 1; + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) { + if(!mstruct.isNumber()) { + CALCULATOR->endTemporaryStopMessages(false); + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + mstruct = vargs[0]; + mstruct.eval(eo2); + } else { + CALCULATOR->endTemporaryStopMessages(true); + } + } + if(!mstruct.isNumber()) { + if(trig_remove_i(mstruct)) { + mstruct.transformById(FUNCTION_ID_ASINH); + mstruct *= nr_one_i; + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_RADIANS: {break;} + default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} + } + return 1; + } + if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;} + return -1; + } + if(mstruct.number().isZero()) { + mstruct.clear(); + } else if(mstruct.number().isOne()) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + mstruct.set(90, 1, 0); + break; + } + case ANGLE_UNIT_GRADIANS: { + mstruct.set(100, 1, 0); + break; + } + case ANGLE_UNIT_RADIANS: { + mstruct.set(1, 2, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + break; + } + default: { + mstruct.set(1, 2, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + if(CALCULATOR->getRadUnit()) { + mstruct *= CALCULATOR->getRadUnit(); + } + } + } + } else if(mstruct.number().isMinusOne()) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + mstruct.set(-90, 1, 0); + break; + } + case ANGLE_UNIT_GRADIANS: { + mstruct.set(-100, 1, 0); + break; + } + case ANGLE_UNIT_RADIANS: { + mstruct.set(-1, 2, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + break; + } + default: { + mstruct.set(-1, 2, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + if(CALCULATOR->getRadUnit()) { + mstruct *= CALCULATOR->getRadUnit(); + } + } + } + } else if(mstruct.number().equals(nr_half)) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + mstruct.set(30, 1, 0); + break; + } + case ANGLE_UNIT_GRADIANS: { + mstruct.set(100, 3, 0); + break; + } + case ANGLE_UNIT_RADIANS: { + mstruct.set(1, 6, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + break; + } + default: { + mstruct.set(1, 6, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + if(CALCULATOR->getRadUnit()) { + mstruct *= CALCULATOR->getRadUnit(); + } + } + } + } else { + Number nr = mstruct.number(); + if(!nr.asin() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + if(trig_remove_i(mstruct)) { + mstruct.transformById(FUNCTION_ID_ASINH); + mstruct *= nr_one_i; + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_RADIANS: {break;} + default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} + } + return 1; + } + if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;} + return -1; + } + mstruct = nr; + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_RADIANS: {break;} + default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} + } + } + return 1; + +} + +AcosFunction::AcosFunction() : MathFunction("acos", 1) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); +} +bool AcosFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} +int AcosFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + if(eo.approximation == APPROXIMATION_TRY_EXACT) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_EXACT; + CALCULATOR->beginTemporaryStopMessages(); + mstruct.eval(eo2); + } else { + mstruct.eval(eo); + } + if(mstruct.isVector()) { + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + return -1; + } + if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0] == nr_half && mstruct[1].isPower() && mstruct[1][1] == nr_half) { + if(mstruct[1][0] == nr_two) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.set(45, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.set(50, 1, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + default: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + return 1; + } else if(mstruct[1][0] == nr_three) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.set(30, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.set(100, 3, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct.set(1, 6, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + default: {mstruct.set(1, 6, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + return 1; + } + } else if(mstruct.isPower() && mstruct[1] == nr_minus_half && mstruct[0] == nr_two) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.set(45, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.set(50, 1, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + default: {mstruct.set(1, 4, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + return 1; + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) { + if(!mstruct.isNumber()) { + CALCULATOR->endTemporaryStopMessages(false); + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + mstruct = vargs[0]; + mstruct.eval(eo2); + } else { + CALCULATOR->endTemporaryStopMessages(true); + } + } + if(!mstruct.isNumber()) { + if(has_predominately_negative_sign(mstruct)) { + negate_struct(mstruct); mstruct.transformById(FUNCTION_ID_ASIN); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct += Number(90, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct += Number(100, 1, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI); mstruct.last() *= nr_half; break;} + default: {mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI); mstruct.last() *= nr_half; if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} + } + return 1; + } + return -1; + } + if(mstruct.number().isZero()) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + mstruct.set(90, 1, 0); + break; + } + case ANGLE_UNIT_GRADIANS: { + mstruct.set(100, 1, 0); + break; + } + case ANGLE_UNIT_RADIANS: { + mstruct.set(1, 2, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + break; + } + default: { + mstruct.set(1, 2, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + if(CALCULATOR->getRadUnit()) { + mstruct *= CALCULATOR->getRadUnit(); + } + } + } + } else if(mstruct.number().isOne()) { + mstruct.clear(); + } else if(mstruct.number().isMinusOne()) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + mstruct.set(180, 1, 0); + break; + } + case ANGLE_UNIT_GRADIANS: { + mstruct.set(200, 1, 0); + break; + } + case ANGLE_UNIT_RADIANS: { + mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + break; + } + default: { + mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + if(CALCULATOR->getRadUnit()) { + mstruct *= CALCULATOR->getRadUnit(); + } + } + } + } else if(mstruct.number().equals(nr_half)) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + mstruct.set(60, 1, 0); + break; + } + case ANGLE_UNIT_GRADIANS: { + mstruct.set(200, 3, 0); + break; + } + case ANGLE_UNIT_RADIANS: { + mstruct.set(1, 3, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + break; + } + default: { + mstruct.set(1, 3, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + if(CALCULATOR->getRadUnit()) { + mstruct *= CALCULATOR->getRadUnit(); + } + } + } + } else { + Number nr = mstruct.number(); + if(!nr.acos() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + if(has_predominately_negative_sign(mstruct)) { + mstruct.number().negate(); + mstruct.transformById(FUNCTION_ID_ASIN); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct += Number(90, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct += Number(100, 1, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI); mstruct.last() *= nr_half; break;} + default: {mstruct += CALCULATOR->getVariableById(VARIABLE_ID_PI); mstruct.last() *= nr_half; if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} + } + return 1; + } + return -1; + } + mstruct = nr; + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_RADIANS: {break;} + default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} + } + } + return 1; + +} + +AtanFunction::AtanFunction() : MathFunction("atan", 1) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); +} +bool AtanFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && (vargs[0].representsReal(allow_units) || (vargs[0].isNumber() && !vargs[0].number().isI() && !vargs[0].number().isMinusI()));} +bool AtanFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool AtanFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +int AtanFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + if(eo.approximation == APPROXIMATION_TRY_EXACT) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_EXACT; + CALCULATOR->beginTemporaryStopMessages(); + mstruct.eval(eo2); + } else { + mstruct.eval(eo); + } + if(mstruct.isVector()) { + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + return -1; + } + if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[1].isPower() && mstruct[1][1] == nr_half && mstruct[1][0] == nr_three && mstruct[0].number() == Number(1, 3)) { + if(mstruct[1][0] == nr_three) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.set(30, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.set(100, 3, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct.set(1, 6, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + default: {mstruct.set(1, 6, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + return 1; + } + } else if(mstruct.isPower() && mstruct[1] == nr_half && mstruct[0] == nr_three) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.set(60, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 3, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct.set(1, 3, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + default: {mstruct.set(1, 3, 0); mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();}} + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) CALCULATOR->endTemporaryStopMessages(true); + return 1; + } + if(eo.approximation == APPROXIMATION_TRY_EXACT) { + if(!mstruct.isNumber()) { + CALCULATOR->endTemporaryStopMessages(false); + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + mstruct = vargs[0]; + mstruct.eval(eo2); + } else { + CALCULATOR->endTemporaryStopMessages(true); + } + } + if(!mstruct.isNumber()) { + if(trig_remove_i(mstruct)) { + mstruct.transformById(FUNCTION_ID_ATANH); + mstruct *= nr_one_i; + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_RADIANS: {break;} + default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} + } + return 1; + } + if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;} + return -1; + } + if(mstruct.number().isZero()) { + mstruct.clear(); + } else if(eo.allow_infinite && mstruct.number().isI()) { + Number nr; nr.setImaginaryPart(nr_plus_inf); + mstruct = nr; + } else if(eo.allow_infinite && mstruct.number().isMinusI()) { + Number nr; nr.setImaginaryPart(nr_minus_inf); + mstruct = nr; + } else if(mstruct.number().isPlusInfinity()) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + mstruct.set(90, 1, 0); + break; + } + case ANGLE_UNIT_GRADIANS: { + mstruct.set(100, 1, 0); + break; + } + case ANGLE_UNIT_RADIANS: { + mstruct.set(1, 2, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + break; + } + default: { + mstruct.set(1, 2, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + if(CALCULATOR->getRadUnit()) { + mstruct *= CALCULATOR->getRadUnit(); + } + } + } + } else if(mstruct.number().isMinusInfinity()) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + mstruct.set(-90, 1, 0); + break; + } + case ANGLE_UNIT_GRADIANS: { + mstruct.set(-100, 1, 0); + break; + } + case ANGLE_UNIT_RADIANS: { + mstruct.set(-1, 2, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + break; + } + default: { + mstruct.set(-1, 2, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + if(CALCULATOR->getRadUnit()) { + mstruct *= CALCULATOR->getRadUnit(); + } + } + } + } else if(mstruct.number().isOne()) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + mstruct.set(45, 1, 0); + break; + } + case ANGLE_UNIT_GRADIANS: { + mstruct.set(50, 1, 0); + break; + } + case ANGLE_UNIT_RADIANS: { + mstruct.set(1, 4, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + break; + } + default: { + mstruct.set(1, 4, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + if(CALCULATOR->getRadUnit()) { + mstruct *= CALCULATOR->getRadUnit(); + } + } + } + } else if(mstruct.number().isMinusOne()) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + mstruct.set(-45, 1, 0); + break; + } + case ANGLE_UNIT_GRADIANS: { + mstruct.set(-50, 1, 0); + break; + } + case ANGLE_UNIT_RADIANS: { + mstruct.set(-1, 4, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + break; + } + default: { + mstruct.set(-1, 4, 0); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); + if(CALCULATOR->getRadUnit()) { + mstruct *= CALCULATOR->getRadUnit(); + } + } + } + } else { + Number nr = mstruct.number(); + if(!nr.atan() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + if(trig_remove_i(mstruct)) { + mstruct.transformById(FUNCTION_ID_ATANH); + mstruct *= nr_one_i; + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_RADIANS: {break;} + default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} + } + return 1; + } + if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;} + return -1; + } + mstruct = nr; + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.multiply_nocopy(new MathStructure(180, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.multiply_nocopy(new MathStructure(200, 1, 0)); mstruct.divide_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_PI))); break;} + case ANGLE_UNIT_RADIANS: {break;} + default: {if(CALCULATOR->getRadUnit()) {mstruct *= CALCULATOR->getRadUnit();} break;} + } + } + return 1; + +} + +SinhFunction::SinhFunction() : MathFunction("sinh", 1) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); +} +bool SinhFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} +bool SinhFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool SinhFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +int SinhFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(mstruct.isFunction() && mstruct.size() == 1) { + if(mstruct.function()->id() == FUNCTION_ID_ASINH) { + mstruct.setToChild(1, true); + return 1; + } else if(mstruct.function()->id() == FUNCTION_ID_ACOSH && !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, false, false, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)) { + mstruct.setToChild(1); + MathStructure *mmul = new MathStructure(mstruct); + mstruct += nr_minus_one; + mstruct ^= nr_half; + *mmul += nr_one; + *mmul ^= nr_half; + mstruct.multiply_nocopy(mmul); + return 1; + } else if(mstruct.function()->id() == FUNCTION_ID_ATANH && !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, false, false, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)) { + mstruct.setToChild(1); + MathStructure *mmul = new MathStructure(mstruct); + mstruct ^= nr_two; + mstruct.negate(); + mstruct += nr_one; + mstruct ^= nr_minus_half; + mstruct.multiply_nocopy(mmul); + return 1; + } + } + if(!mstruct.isNumber()) { + if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transformById(FUNCTION_ID_SIN); mstruct *= nr_one_i; return 1;} + if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;} + return -1; + } + Number nr = mstruct.number(); + if(!nr.sinh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transformById(FUNCTION_ID_SIN); mstruct *= nr_one_i; return 1;} + if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;} + return -1; + } + mstruct = nr; + return 1; +} +CoshFunction::CoshFunction() : MathFunction("cosh", 1) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); +} +bool CoshFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} +bool CoshFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool CoshFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +int CoshFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(mstruct.isFunction() && mstruct.size() == 1) { + if(mstruct.function()->id() == FUNCTION_ID_ACOSH) { + mstruct.setToChild(1, true); + return 1; + } else if(mstruct.function()->id() == FUNCTION_ID_ASINH) { + mstruct.setToChild(1); + mstruct ^= nr_two; + mstruct += nr_one; + mstruct ^= nr_half; + return 1; + } else if(mstruct.function()->id() == FUNCTION_ID_ATANH) { + mstruct.setToChild(1); + mstruct ^= nr_two; + mstruct.negate(); + mstruct += nr_one; + mstruct ^= nr_minus_half; + return 1; + } + } + if(!mstruct.isNumber()) { + if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transformById(FUNCTION_ID_COS); return 1;} + if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); return -1;} + return -1; + } + Number nr = mstruct.number(); + if(!nr.cosh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transformById(FUNCTION_ID_COS); return 1;} + if(has_predominately_negative_sign(mstruct)) mstruct.number().negate(); + return -1; + } + mstruct = nr; + return 1; +} +TanhFunction::TanhFunction() : MathFunction("tanh", 1) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); +} +bool TanhFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} +bool TanhFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool TanhFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +int TanhFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(mstruct.isFunction() && mstruct.size() == 1) { + if(mstruct.function()->id() == FUNCTION_ID_ATANH) { + mstruct.setToChild(1, true); + return 1; + } else if(mstruct.function()->id() == FUNCTION_ID_ASINH && !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, false, false, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)) { + mstruct.setToChild(1); + MathStructure *mmul = new MathStructure(mstruct); + mstruct ^= nr_two; + mstruct += nr_one; + mstruct ^= nr_minus_half; + mstruct.multiply_nocopy(mmul); + return 1; + } else if(mstruct.function()->id() == FUNCTION_ID_ACOSH && !mstruct[0].containsInterval(eo.approximation == APPROXIMATION_EXACT, false, false, eo.approximation == APPROXIMATION_EXACT ? 1 : 0, true)) { + mstruct.setToChild(1); + MathStructure *mmul = new MathStructure(mstruct); + MathStructure *mmul2 = new MathStructure(mstruct); + *mmul2 ^= nr_minus_one; + mstruct += nr_minus_one; + mstruct ^= nr_half; + *mmul += nr_one; + *mmul ^= nr_half; + mstruct.multiply_nocopy(mmul); + mstruct.multiply_nocopy(mmul2); + return 1; + } + } + if(!mstruct.isNumber()) { + if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transformById(FUNCTION_ID_TAN); mstruct *= nr_one_i; return 1;} + if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;} + return -1; + } + Number nr = mstruct.number(); + if(!nr.tanh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;} + if(trig_remove_i(mstruct)) {mstruct *= CALCULATOR->getRadUnit(); mstruct.transformById(FUNCTION_ID_TAN); mstruct *= nr_one_i; return 1;} + return -1; + } + mstruct = nr; + return 1; +} +AsinhFunction::AsinhFunction() : MathFunction("asinh", 1) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); +} +bool AsinhFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} +bool AsinhFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsReal();} +bool AsinhFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +int AsinhFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(!mstruct.isNumber()) { + if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;} + return -1; + } + Number nr = mstruct.number(); + if(!nr.asinh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;} + return -1; + } + mstruct = nr; + return 1; +} +AcoshFunction::AcoshFunction() : MathFunction("acosh", 1) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false)); +} +bool AcoshFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 1 && vargs[0].representsNumber(allow_units);} +int AcoshFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(eo.allow_complex && vargs[0].isZero()) { + mstruct.set(1, 2, 0); + mstruct.number() *= nr_one_i; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + return 1; + } else if(vargs[0].isOne()) { + mstruct.clear(); + return 1; + } else if(eo.approximation != APPROXIMATION_APPROXIMATE && eo.allow_complex && vargs[0].number() <= -1) { + mstruct = nr_one_i; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.add_nocopy(new MathStructure(this, &vargs[0], NULL)); + mstruct.last()[0].negate(); + return 1; + } + Number nr(vargs[0].number()); + if(!nr.acosh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + return 0; + } + mstruct = nr; + return 1; +} +AtanhFunction::AtanhFunction() : MathFunction("atanh", 1) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false, false)); +} +int AtanhFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isVector()) return 0; + mstruct = vargs[0]; + mstruct.eval(eo); + if(mstruct.isVector()) return -1; + if(!mstruct.isNumber()) { + if(has_predominately_negative_sign(mstruct)) {negate_struct(mstruct); mstruct.transform(this); mstruct.negate(); return 1;} + return -1; + } + if(eo.allow_complex && mstruct.number().includesInfinity()) { + if(mstruct.number().isPlusInfinity() || (!mstruct.number().hasRealPart() && mstruct.number().hasImaginaryPart() && mstruct.number().internalImaginary()->isMinusInfinity())) { + mstruct = nr_minus_half; + mstruct *= nr_one_i; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + return true; + } else if(mstruct.number().isMinusInfinity() || (!mstruct.number().hasRealPart() && mstruct.number().hasImaginaryPart() && mstruct.number().internalImaginary()->isPlusInfinity())) { + mstruct = nr_half; + mstruct *= nr_one_i; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + return true; + } + } else if(eo.approximation != APPROXIMATION_APPROXIMATE && eo.allow_complex && mstruct.number() > 1) { + mstruct.set(-1, 2, 0); + mstruct.number() *= nr_one_i; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.add_nocopy(new MathStructure(this, &vargs[0], NULL)); + mstruct.last()[0].inverse(); + return 1; + } else if(eo.approximation != APPROXIMATION_APPROXIMATE && eo.allow_complex && mstruct.number() < -1) { + mstruct.set(1, 2, 0); + mstruct.number() *= nr_one_i; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.add_nocopy(new MathStructure(this, &vargs[0], NULL)); + mstruct.last()[0].inverse(); + mstruct.last()[0].negate(); + mstruct.last().negate(); + return 1; + } + Number nr = mstruct.number(); + if(!nr.atanh() || (eo.approximation == APPROXIMATION_EXACT && nr.isApproximate() && !mstruct.isApproximate()) || (!eo.allow_complex && nr.isComplex() && !mstruct.number().isComplex()) || (!eo.allow_infinite && nr.includesInfinity() && !mstruct.number().includesInfinity())) { + if(has_predominately_negative_sign(mstruct)) {mstruct.number().negate(); mstruct.transform(this); mstruct.negate(); return 1;} + return -1; + } + mstruct = nr; + return 1; +} +SincFunction::SincFunction() : MathFunction("sinc", 1) { + Argument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, false); + arg->setHandleVector(true); + setArgumentDefinition(1, arg); +} +bool SincFunction::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 1 && (vargs[0].representsNumber() || is_number_angle_value(vargs[0]));} +bool SincFunction::representsReal(const MathStructure &vargs, bool) const {return vargs.size() == 1 && (vargs[0].representsReal() || is_real_angle_value(vargs[0]));} +bool SincFunction::representsNonComplex(const MathStructure &vargs, bool) const {return vargs.size() == 1 && vargs[0].representsNonComplex();} +int SincFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].isZero()) { + mstruct.set(1, 1, 0, true); + return 1; + } else if(vargs[0].representsNonZero(true)) { + mstruct = vargs[0]; + bool b = replace_f_interval(mstruct, eo); + b = replace_intervals_f(mstruct) || b; + MathStructure *m_sin = new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SIN), &mstruct, NULL); + if(CALCULATOR->getRadUnit()) (*m_sin)[0].multiply(CALCULATOR->getRadUnit()); + mstruct.inverse(); + mstruct.multiply_nocopy(m_sin); + if(b) mstruct.eval(eo); + return 1; + } + return -1; +} + +Atan2Function::Atan2Function() : MathFunction("atan2", 2) { + NumberArgument *arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, true); + arg->setComplexAllowed(false); + setArgumentDefinition(1, arg); + arg = new NumberArgument("", ARGUMENT_MIN_MAX_NONE, true, true); + arg->setComplexAllowed(false); + setArgumentDefinition(2, arg); +} +bool Atan2Function::representsNumber(const MathStructure &vargs, bool) const {return vargs.size() == 2 && vargs[0].representsNumber() && vargs[1].representsNumber();} +int Atan2Function::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(vargs[0].number().isZero()) { + if(!vargs[1].number().isNonZero()) return 0; + if(vargs[1].number().isNegative()) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.set(180, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.set(200, 1, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;} + default: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();} + } + } else { + mstruct.clear(); + } + } else if(vargs[1].number().isZero() && vargs[0].number().isNonZero()) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.set(90, 1, 0); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.set(100, 1, 0); break;} + case ANGLE_UNIT_RADIANS: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); mstruct.multiply(nr_half); break;} + default: {mstruct.set(CALCULATOR->getVariableById(VARIABLE_ID_PI)); mstruct.multiply(nr_half); if(CALCULATOR->getRadUnit()) mstruct *= CALCULATOR->getRadUnit();} + } + if(vargs[0].number().hasNegativeSign()) mstruct.negate(); + } else if(!vargs[1].number().isNonZero()) { + FR_FUNCTION_2(atan2) + } else { + MathStructure new_nr(vargs[0]); + if(!new_nr.number().divide(vargs[1].number())) return -1; + if(vargs[1].number().isNegative() && vargs[0].number().isNonZero()) { + if(vargs[0].number().isNegative()) { + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.add(-180); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.add(-200); break;} + case ANGLE_UNIT_RADIANS: {mstruct.subtract(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;} + default: {MathStructure msub(CALCULATOR->getVariableById(VARIABLE_ID_PI)); if(CALCULATOR->getRadUnit()) msub *= CALCULATOR->getRadUnit(); mstruct.subtract(msub);} + } + } else { + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct.add(180); break;} + case ANGLE_UNIT_GRADIANS: {mstruct.add(200); break;} + case ANGLE_UNIT_RADIANS: {mstruct.add(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;} + default: {MathStructure madd(CALCULATOR->getVariableById(VARIABLE_ID_PI)); if(CALCULATOR->getRadUnit()) madd *= CALCULATOR->getRadUnit(); mstruct.add(madd);} + } + } + } else { + mstruct.set(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &new_nr, NULL); + } + } + return 1; +} +RadiansToDefaultAngleUnitFunction::RadiansToDefaultAngleUnitFunction() : MathFunction("radtodef", 1) { +} +int RadiansToDefaultAngleUnitFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct = vargs[0]; + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + mstruct *= 180; + mstruct /= CALCULATOR->getVariableById(VARIABLE_ID_PI); + break; + } + case ANGLE_UNIT_GRADIANS: { + mstruct *= 200; + mstruct /= CALCULATOR->getVariableById(VARIABLE_ID_PI); + break; + } + case ANGLE_UNIT_RADIANS: { + break; + } + default: { + if(CALCULATOR->getRadUnit()) { + mstruct *= CALCULATOR->getRadUnit(); + } + } + } + return 1; +} + diff -Nru libqalculate-3.6.0/libqalculate/BuiltinFunctions-util.cc libqalculate-3.7.0/libqalculate/BuiltinFunctions-util.cc --- libqalculate-3.6.0/libqalculate/BuiltinFunctions-util.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/BuiltinFunctions-util.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,918 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Number.h" +#include "Calculator.h" +#include "Variable.h" +#include "Unit.h" + +#include +#include +#include +#include + +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::ostream; +using std::endl; + +#define REPRESENTS_FUNCTION(x, y) x::x() : MathFunction(#y, 1) {} int x::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {mstruct = vargs[0]; mstruct.eval(eo); if(mstruct.y()) {mstruct.clear(); mstruct.number().setTrue();} else {mstruct.clear(); mstruct.number().setFalse();} return 1;} + +bool replace_infinity_v(MathStructure &m) { + if(m.isVariable() && m.variable()->isKnown() && ((KnownVariable*) m.variable())->get().isNumber() && ((KnownVariable*) m.variable())->get().number().isInfinite(false)) { + m = ((KnownVariable*) m.variable())->get(); + return true; + } + bool b_ret = false; + for(size_t i = 0; i < m.size(); i++) { + if(replace_infinity_v(m[i])) b_ret = true; + } + return b_ret; +} +bool contains_infinity_v(const MathStructure &m) { + if(m.isVariable() && m.variable()->isKnown() && ((KnownVariable*) m.variable())->get().isNumber() && ((KnownVariable*) m.variable())->get().number().isInfinite(false)) { + return true; + } + bool b_ret = false; + for(size_t i = 0; i < m.size(); i++) { + if(contains_infinity_v(m[i])) b_ret = true; + } + return b_ret; +} + +bool create_interval(MathStructure &mstruct, const MathStructure &m1, const MathStructure &m2) { + if(contains_infinity_v(m1) || contains_infinity_v(m2)) { + MathStructure m1b(m1), m2b(m2); + if(replace_infinity_v(m1b) || replace_infinity_v(m2b)) return create_interval(mstruct, m1b, m2b); + } + if(m1 == m2) { + mstruct.set(m1, true); + return 1; + } else if(m1.isNumber() && m2.isNumber()) { + Number nr; + if(!nr.setInterval(m1.number(), m2.number())) return false; + mstruct.set(nr, true); + return true; + } else if(m1.isMultiplication() && m2.isMultiplication() && m1.size() > 1 && m2.size() > 1) { + size_t i0 = 0, i1 = 0; + if(m1[0].isNumber()) i0++; + if(m2[0].isNumber()) i1++; + if(i0 == 0 && i1 == 0) return false; + if(m1.size() - i0 != m2.size() - i1) return false; + for(size_t i = 0; i < m1.size() - i0; i++) { + if(!m1[i + i0].equals(m2[i + i1], true)) { + return false; + } + } + Number nr; + if(!nr.setInterval(i0 == 1 ? m1[0].number() : nr_one, i1 == 1 ? m2[0].number() : nr_one)) return 0; + mstruct.set(m1, true); + if(i0 == 1) mstruct.delChild(1, true); + mstruct *= nr; + mstruct.evalSort(false); + return 1; + } else if(m1.isAddition() && m2.isAddition() && m1.size() > 1 && m2.size() > 1) { + size_t i0 = 0, i1 = 0; + if(m1.last().isNumber()) i0++; + if(m2.last().isNumber()) i1++; + if(i0 == 0 && i1 == 0) return false; + if(m1.size() - i0 != m2.size() - i1) return false; + for(size_t i = 0; i < m1.size() - i0; i++) { + if(!m1[i].equals(m2[i], true)) { + return false; + } + } + Number nr; + if(!nr.setInterval(i0 == 1 ? m1.last().number() : nr_one, i1 == 1 ? m2.last().number() : nr_one)) return false; + mstruct.set(m1, true); + if(i0 == 1) mstruct.delChild(mstruct.size(), true); + mstruct += nr; + mstruct.evalSort(false); + return true; + } else if(m1.isMultiplication() && m1.size() == 2 && m1[0].isNumber() && m2.equals(m1[1], true)) { + Number nr; + if(!nr.setInterval(m1[0].number(), nr_one)) return false; + mstruct.set(nr, true); + mstruct *= m2; + return true; + } else if(m2.isMultiplication() && m2.size() == 2 && m2[0].isNumber() && m1.equals(m2[1], true)) { + Number nr; + if(!nr.setInterval(nr_one, m2[0].number())) return false; + mstruct.set(nr, true); + mstruct *= m1; + return true; + } + return false; +} + +IntervalFunction::IntervalFunction() : MathFunction("interval", 2) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false)); + setArgumentDefinition(2, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false)); +} +int IntervalFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + if(create_interval(mstruct, vargs[0], vargs[1])) return 1; + MathStructure marg1(vargs[0]); + marg1.eval(eo); + MathStructure marg2(vargs[1]); + marg2.eval(eo); + if(create_interval(mstruct, marg1, marg2)) return 1; + return 0; +} +bool IntervalFunction::representsPositive(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[1].representsPositive(allow_units) && vargs[0].representsPositive(allow_units);} +bool IntervalFunction::representsNegative(const MathStructure&vargs, bool allow_units) const {return vargs.size() == 2 && vargs[0].representsNegative(allow_units) && vargs[1].representsNegative(allow_units);} +bool IntervalFunction::representsNonNegative(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[0].representsNonNegative(allow_units) && vargs[1].representsNonNegative(allow_units);} +bool IntervalFunction::representsNonPositive(const MathStructure&vargs, bool allow_units) const {return vargs.size() == 2 && vargs[0].representsNonPositive(allow_units) && vargs[1].representsNonPositive(allow_units);} +bool IntervalFunction::representsInteger(const MathStructure &, bool) const {return false;} +bool IntervalFunction::representsNumber(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[0].representsNumber(allow_units) && vargs[1].representsNumber(allow_units);} +bool IntervalFunction::representsRational(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[0].representsRational(allow_units) && vargs[1].representsRational(allow_units);} +bool IntervalFunction::representsReal(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[0].representsReal(allow_units) && vargs[1].representsReal(allow_units);} +bool IntervalFunction::representsNonComplex(const MathStructure &vargs, bool allow_units) const {return vargs.size() == 2 && vargs[0].representsNonComplex(allow_units) && vargs[1].representsNonComplex(allow_units);} +bool IntervalFunction::representsComplex(const MathStructure&, bool) const {return false;} +bool IntervalFunction::representsNonZero(const MathStructure &vargs, bool allow_units) const {return representsPositive(vargs, allow_units) || representsNegative(vargs, allow_units);} +bool IntervalFunction::representsEven(const MathStructure&, bool) const {return false;} +bool IntervalFunction::representsOdd(const MathStructure&, bool) const {return false;} +bool IntervalFunction::representsUndefined(const MathStructure &vargs) const {return vargs.size() == 2 && (vargs[0].representsUndefined() || vargs[1].representsUndefined());} + + +bool set_uncertainty(MathStructure &mstruct, MathStructure &munc, const EvaluationOptions &eo, bool do_eval) { + if(munc.isFunction() && munc.function()->id() == FUNCTION_ID_ABS && munc.size() == 1) { + munc.setToChild(1, true); + } + test_munc: + if(munc.isNumber()) { + if(munc.isZero()) { + return 1; + } else if(mstruct.isNumber()) { + mstruct.number().setUncertainty(munc.number(), eo.interval_calculation == INTERVAL_CALCULATION_NONE); + mstruct.numberUpdated(); + return 1; + } else if(mstruct.isAddition()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isNumber()) { + mstruct[i].number().setUncertainty(munc.number(), eo.interval_calculation == INTERVAL_CALCULATION_NONE); + mstruct[i].numberUpdated(); + mstruct.childUpdated(i + 1); + return 1; + } + } + } + mstruct.add(m_zero, true); + mstruct.last().number().setUncertainty(munc.number(), eo.interval_calculation == INTERVAL_CALCULATION_NONE); + mstruct.last().numberUpdated(); + mstruct.childUpdated(mstruct.size()); + return 1; + } else { + if(munc.isMultiplication()) { + if(!munc[0].isNumber()) { + munc.insertChild(m_one, 1); + } + } else { + munc.transform(STRUCT_MULTIPLICATION); + munc.insertChild(m_one, 1); + } + if(munc.isMultiplication()) { + if(munc.size() == 2) { + if(mstruct.isMultiplication() && mstruct[0].isNumber() && (munc[1] == mstruct[1] || (munc[1].isFunction() && munc[1].function()->id() == FUNCTION_ID_ABS && munc[1].size() == 1 && mstruct[1] == munc[1][0]))) { + mstruct[0].number().setUncertainty(munc[0].number(), eo.interval_calculation == INTERVAL_CALCULATION_NONE); + mstruct[0].numberUpdated(); + mstruct.childUpdated(1); + return 1; + } else if(mstruct.equals(munc[1]) || (munc[1].isFunction() && munc[1].function()->id() == FUNCTION_ID_ABS && munc[1].size() == 1 && mstruct.equals(munc[1][0]))) { + mstruct.transform(STRUCT_MULTIPLICATION); + mstruct.insertChild(m_one, 1); + mstruct[0].number().setUncertainty(munc[0].number(), eo.interval_calculation == INTERVAL_CALCULATION_NONE); + mstruct[0].numberUpdated(); + mstruct.childUpdated(1); + return 1; + } + } else if(mstruct.isMultiplication()) { + size_t i2 = 0; + if(mstruct[0].isNumber()) i2++; + if(mstruct.size() + 1 - i2 == munc.size()) { + bool b = true; + for(size_t i = 1; i < munc.size(); i++, i2++) { + if(!munc[i].equals(mstruct[i2]) && !(munc[i].isFunction() && munc[i].function()->id() == FUNCTION_ID_ABS && munc[i].size() == 1 && mstruct[i2] == munc[i][0])) { + b = false; + break; + } + } + if(b) { + if(!mstruct[0].isNumber()) { + mstruct.insertChild(m_one, 1); + } + mstruct[0].number().setUncertainty(munc[0].number(), eo.interval_calculation == INTERVAL_CALCULATION_NONE); + mstruct[0].numberUpdated(); + mstruct.childUpdated(1); + return 1; + } + } + } + if(do_eval) { + bool b = false; + for(size_t i = 0; i < munc.size(); i++) { + if(munc[i].isFunction() && munc[i].function()->id() == FUNCTION_ID_ABS && munc[i].size() == 1) { + munc[i].setToChild(1); + b = true; + } + } + if(b) { + munc.eval(eo); + goto test_munc; + } + } + } + } + return false; +} + +UncertaintyFunction::UncertaintyFunction() : MathFunction("uncertainty", 2, 3) { + setArgumentDefinition(1, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false)); + setArgumentDefinition(2, new NumberArgument("", ARGUMENT_MIN_MAX_NONE, false)); + setArgumentDefinition(3, new BooleanArgument()); + setDefaultValue(3, "1"); +} +int UncertaintyFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct = vargs[0]; + MathStructure munc(vargs[1]); + mstruct.eval(eo); + munc.eval(eo); + if(vargs[2].number().getBoolean()) { + if(munc.isNumber() && mstruct.isNumber()) { + mstruct.number().setRelativeUncertainty(munc.number(), eo.interval_calculation == INTERVAL_CALCULATION_NONE); + mstruct.numberUpdated(); + return 1; + } + mstruct = vargs[0]; + mstruct *= m_one; + mstruct.last() -= vargs[1]; + mstruct.transformById(FUNCTION_ID_INTERVAL); + MathStructure *m2 = new MathStructure(vargs[0]); + m2->multiply(m_one); + m2->last() += vargs[1]; + mstruct.addChild_nocopy(m2); + return 1; + } else { + if(set_uncertainty(mstruct, munc, eo, true)) return 1; + mstruct = vargs[0]; + mstruct -= vargs[1]; + mstruct.transformById(FUNCTION_ID_INTERVAL); + MathStructure *m2 = new MathStructure(vargs[0]); + m2->add(vargs[1]); + mstruct.addChild_nocopy(m2); + return 1; + } + return 0; +} + +AsciiFunction::AsciiFunction() : MathFunction("code", 1) { + setArgumentDefinition(1, new TextArgument()); +} +int AsciiFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + if(vargs[0].symbol().empty()) { + return false; + } + const string &str = vargs[0].symbol(); + mstruct.clear(); + for(size_t i = 0; i < str.length(); i++) { + long int c = (unsigned char) str[i]; + if((c & 0x80) != 0) { + if(c<0xe0) { + i++; + if(i >= str.length()) return false; + c = ((c & 0x1f) << 6) | (((unsigned char) str[i]) & 0x3f); + } else if(c<0xf0) { + i++; + if(i + 1 >= str.length()) return false; + c = (((c & 0xf) << 12) | ((((unsigned char) str[i]) & 0x3f) << 6)|(((unsigned char) str[i + 1]) & 0x3f)); + i++; + } else { + i++; + if(i + 2 >= str.length()) return false; + c = ((c & 7) << 18) | ((((unsigned char) str[i]) & 0x3f) << 12) | ((((unsigned char) str[i + 1]) & 0x3f) << 6) | (((unsigned char) str[i + 2]) & 0x3f); + i += 2; + } + } + if(mstruct.isZero()) { + mstruct.set(c, 1L, 0L); + } else if(mstruct.isVector()) { + mstruct.addChild(MathStructure(c, 1L, 0L)); + } else { + mstruct.transform(STRUCT_VECTOR, MathStructure(c, 1L, 0L)); + } + } + return 1; +} +CharFunction::CharFunction() : MathFunction("char", 1) { + IntegerArgument *arg = new IntegerArgument(); + Number fr(32, 1, 0); + arg->setMin(&fr); + fr.set(0x10ffff, 1, 0); + arg->setMax(&fr); + setArgumentDefinition(1, arg); +} +int CharFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + + long int v = vargs[0].number().lintValue(); + string str; + if(v <= 0x7f) { + str = (char) v; + } else if(v <= 0x7ff) { + str = (char) ((v >> 6) | 0xc0); + str += (char) ((v & 0x3f) | 0x80); + } else if((v <= 0xd7ff || (0xe000 <= v && v <= 0xffff))) { + str = (char) ((v >> 12) | 0xe0); + str += (char) (((v >> 6) & 0x3f) | 0x80); + str += (char) ((v & 0x3f) | 0x80); + } else if(0xffff < v && v <= 0x10ffff) { + str = (char) ((v >> 18) | 0xf0); + str += (char) (((v >> 12) & 0x3f) | 0x80); + str += (char) (((v >> 6) & 0x3f) | 0x80); + str += (char) ((v & 0x3f) | 0x80); + } else { + return 0; + } + mstruct = str; + return 1; + +} + +ConcatenateFunction::ConcatenateFunction() : MathFunction("concatenate", 1, -1) { + setArgumentDefinition(1, new TextArgument()); + setArgumentDefinition(2, new TextArgument()); +} +int ConcatenateFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + string str; + for(size_t i = 0; i < vargs.size(); i++) { + str += vargs[i].symbol(); + } + mstruct = str; + return 1; +} +LengthFunction::LengthFunction() : MathFunction("len", 1) { + setArgumentDefinition(1, new TextArgument()); +} +int LengthFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + mstruct = (int) vargs[0].symbol().length(); + return 1; +} + +bool replace_function(MathStructure &m, MathFunction *f1, MathFunction *f2, const EvaluationOptions &eo) { + bool ret = false; + if(m.isFunction() && m.function() == f1) { + m.setFunction(f2); + while(f2->maxargs() >= 0 && m.size() > (size_t) f2->maxargs()) { + m.delChild(m.countChildren()); + } + if(m.size() >= 1) { + if((f1->getArgumentDefinition(1) && f1->getArgumentDefinition(1)->type() == ARGUMENT_TYPE_ANGLE) && (!f2->getArgumentDefinition(1) || f2->getArgumentDefinition(1)->type() != ARGUMENT_TYPE_ANGLE)) { + if(m[0].contains(CALCULATOR->getRadUnit(), false, true, true) > 0) m[0] /= CALCULATOR->getRadUnit(); + else if(m[0].contains(CALCULATOR->getDegUnit(), false, true, true) > 0) m[0] /= CALCULATOR->getDegUnit(); + else if(m[0].contains(CALCULATOR->getGraUnit(), false, true, true) > 0) m[0] /= CALCULATOR->getGraUnit(); + } else if((f2->getArgumentDefinition(1) && f2->getArgumentDefinition(1)->type() == ARGUMENT_TYPE_ANGLE) && (!f1->getArgumentDefinition(1) || f1->getArgumentDefinition(1)->type() != ARGUMENT_TYPE_ANGLE)) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {m[0] *= CALCULATOR->getDegUnit(); break;} + case ANGLE_UNIT_GRADIANS: {m[0] *= CALCULATOR->getGraUnit(); break;} + case ANGLE_UNIT_RADIANS: {m[0] *= CALCULATOR->getRadUnit(); break;} + default: {} + } + } + } + ret = true; + } + for(size_t i = 0; i < m.size(); i++) { + if(replace_function(m[i], f1, f2, eo)) ret = true; + } + return ret; +} +ReplaceFunction::ReplaceFunction() : MathFunction("replace", 3, 4) { + setArgumentDefinition(4, new BooleanArgument()); + setDefaultValue(4, "0"); +} +int ReplaceFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct = vargs[0]; + bool b_evaled = false; + if(vargs[3].number().getBoolean()) {mstruct.eval(eo); b_evaled = true;} + if(vargs[1].isVector() && vargs[2].isVector() && vargs[1].size() == vargs[2].size()) { + for(size_t i = 0; i < vargs[1].size(); i++) { + if(vargs[1][i].isFunction() && vargs[2][i].isFunction() && vargs[1][i].size() == 0 && vargs[2][i].size() == 0) { + if(!replace_function(mstruct, vargs[1][i].function(), vargs[2][i].function(), eo)) CALCULATOR->error(false, _("Original value (%s) was not found."), (vargs[1][i].function()->name() + "()").c_str(), NULL); + } else if(vargs[2][i].containsInterval(true, false, false, 0, true)) { + MathStructure mv(vargs[2][i]); + replace_f_interval(mv, eo); + replace_intervals_f(mv); + if(!mstruct.replace(vargs[1][i], mv)) CALCULATOR->error(false, _("Original value (%s) was not found."), format_and_print(vargs[1][i]).c_str(), NULL); + } else { + if(!mstruct.replace(vargs[1][i], vargs[2][i])) CALCULATOR->error(false, _("Original value (%s) was not found."), format_and_print(vargs[1][i]).c_str(), NULL); + } + } + } else { + while(true) { + if(vargs[1].isFunction() && vargs[2].isFunction() && vargs[1].size() == 0 && vargs[2].size() == 0) { + if(replace_function(mstruct, vargs[1].function(), vargs[2].function(), eo)) break; + } else if(vargs[2].containsInterval(true, false, false, 0, true)) { + MathStructure mv(vargs[2]); + replace_f_interval(mv, eo); + replace_intervals_f(mv); + if(mstruct.replace(vargs[1], mv)) break; + } else { + if(mstruct.replace(vargs[1], vargs[2])) break; + } + if(b_evaled) { + CALCULATOR->error(false, _("Original value (%s) was not found."), format_and_print(vargs[1]).c_str(), NULL); + break; + } else { + mstruct.eval(); + b_evaled = true; + } + } + } + return 1; +} +void remove_nounit(MathStructure &mstruct) { + if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_STRIP_UNITS && mstruct.size() == 1) { + mstruct.setToChild(1, true); + } + if(mstruct.isMultiplication() || mstruct.isAddition()) { + for(size_t i = 0; i < mstruct.size(); i++) { + remove_nounit(mstruct[i]); + } + } +} +StripUnitsFunction::StripUnitsFunction() : MathFunction("nounit", 1) {} +int StripUnitsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct = vargs[0]; + remove_nounit(mstruct); + mstruct.removeType(STRUCT_UNIT); + if(mstruct.containsType(STRUCT_UNIT, false, true, true) == 0) return 1; + if(mstruct.isMultiplication() || mstruct.isAddition()) { + MathStructure *mleft = NULL; + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].containsType(STRUCT_UNIT, false, true, true) == 0) { + mstruct[i].ref(); + if(mleft) { + if(mstruct.isMultiplication()) mleft->multiply_nocopy(&mstruct[i], true); + else mleft->add_nocopy(&mstruct[i], true); + } else { + mleft = &mstruct[i]; + } + mstruct.delChild(i + 1); + } + } + if(mleft) { + if(mstruct.size() == 0) { + mstruct.set_nocopy(*mleft); + mleft->unref(); + } else { + bool b_multi = mstruct.isMultiplication(); + if(mstruct.size() == 1) { + mstruct.setType(STRUCT_FUNCTION); + mstruct.setFunction(this); + } else { + mstruct.transform(this); + } + if(b_multi) mstruct.multiply_nocopy(mleft, true); + else mstruct.add_nocopy(mleft, true); + } + return 1; + } + } + EvaluationOptions eo2 = eo; + eo2.sync_units = false; + eo2.keep_prefixes = true; + mstruct.eval(eo2); + remove_nounit(mstruct); + mstruct.removeType(STRUCT_UNIT); + if(mstruct.containsType(STRUCT_UNIT, false, true, true) == 0) return 1; + if(mstruct.isMultiplication() || mstruct.isAddition()) { + MathStructure *mleft = NULL; + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].containsType(STRUCT_UNIT, false, true, true) == 0) { + mstruct[i].ref(); + if(mleft) { + if(mstruct.isMultiplication()) mleft->multiply_nocopy(&mstruct[i], true); + else mleft->add_nocopy(&mstruct[i], true); + } else { + mleft = &mstruct[i]; + } + mstruct.delChild(i + 1); + } + } + if(mleft) { + if(mstruct.size() == 0) { + mstruct.set_nocopy(*mleft); + mleft->unref(); + } else { + bool b_multi = mstruct.isMultiplication(); + if(mstruct.size() == 1) { + mstruct.setType(STRUCT_FUNCTION); + mstruct.setFunction(this); + } else { + mstruct.transform(this); + } + if(b_multi) mstruct.multiply_nocopy(mleft, true); + else mstruct.add_nocopy(mleft, true); + } + return 1; + } + } + return -1; +} + +ErrorFunction::ErrorFunction() : MathFunction("error", 1) { + setArgumentDefinition(1, new TextArgument()); +} +int ErrorFunction::calculate(MathStructure&, const MathStructure &vargs, const EvaluationOptions&) { + CALCULATOR->error(true, vargs[0].symbol().c_str(), NULL); + return 1; +} +WarningFunction::WarningFunction() : MathFunction("warning", 1) { + setArgumentDefinition(1, new TextArgument()); +} +int WarningFunction::calculate(MathStructure&, const MathStructure &vargs, const EvaluationOptions&) { + CALCULATOR->error(false, vargs[0].symbol().c_str(), NULL); + return 1; +} +MessageFunction::MessageFunction() : MathFunction("message", 1) { + setArgumentDefinition(1, new TextArgument()); +} +int MessageFunction::calculate(MathStructure&, const MathStructure &vargs, const EvaluationOptions&) { + CALCULATOR->message(MESSAGE_INFORMATION, vargs[0].symbol().c_str(), NULL); + return 1; +} + +bool csum_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t index, const EvaluationOptions &eo2); +bool csum_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t index, const EvaluationOptions &eo2) { + if(mprocess == vargs[4]) { + mprocess = vargs[6][index]; + return true; + } + if(mprocess == vargs[5]) { + mprocess = mstruct; + return true; + } + if(!vargs[7].isEmptySymbol() && mprocess == vargs[7]) { + mprocess = (int) index + 1; + return true; + } + if(!vargs[8].isEmptySymbol()) { + if(mprocess.isFunction() && mprocess.function()->id() == FUNCTION_ID_ELEMENT && mprocess.size() >= 2 && mprocess[0] == vargs[8]) { + bool b = csum_replace(mprocess[1], mstruct, vargs, index, eo2); + mprocess[1].eval(eo2); + if(mprocess[1].isNumber() && mprocess[1].number().isInteger() && mprocess[1].number().isPositive() && mprocess[1].number().isLessThanOrEqualTo(vargs[6].size())) { + mprocess = vargs[6][mprocess[1].number().intValue() - 1]; + return true; + } + return csum_replace(mprocess[0], mstruct, vargs, index, eo2) || b; + } else if(mprocess.isFunction() && mprocess.function()->id() == FUNCTION_ID_COMPONENT && mprocess.size() == 2 && mprocess[1] == vargs[8]) { + bool b = csum_replace(mprocess[0], mstruct, vargs, index, eo2); + mprocess[0].eval(eo2); + if(mprocess[0].isNumber() && mprocess[0].number().isInteger() && mprocess[0].number().isPositive() && mprocess[0].number().isLessThanOrEqualTo(vargs[6].size())) { + mprocess = vargs[6][mprocess[0].number().intValue() - 1]; + return true; + } + return csum_replace(mprocess[1], mstruct, vargs, index, eo2) || b; + } else if(mprocess == vargs[8]) { + mprocess = vargs[6]; + return true; + } + } + bool b = false; + for(size_t i = 0; i < mprocess.size(); i++) { + if(csum_replace(mprocess[i], mstruct, vargs, index, eo2)) { + mprocess.childUpdated(i + 1); + b = true; + } + } + return b; +} +CustomSumFunction::CustomSumFunction() : MathFunction("csum", 7, 9) { + Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SINT); + setArgumentDefinition(1, arg); //begin + arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SINT); + arg->setHandleVector(false); + setArgumentDefinition(2, arg); //end + //3. initial + //4. function + setArgumentDefinition(5, new SymbolicArgument()); //x var + setArgumentDefinition(6, new SymbolicArgument()); //y var + setArgumentDefinition(7, new VectorArgument()); + setArgumentDefinition(8, new SymbolicArgument()); //i var + setDefaultValue(8, "\"\""); + setArgumentDefinition(9, new SymbolicArgument()); //v var + setDefaultValue(9, "\"\""); +} +int CustomSumFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + + int start = vargs[0].number().intValue(); + if(start < 1) start = 1; + int end = vargs[1].number().intValue(); + int n = vargs[6].countChildren(); + if(start > n) { + CALCULATOR->error(true, _("Too few elements (%s) in vector (%s required)"), i2s(n).c_str(), i2s(start).c_str(), NULL); + start = n; + } + if(end < 1 || end > n) { + if(end > n) CALCULATOR->error(true, _("Too few elements (%s) in vector (%s required)"), i2s(n).c_str(), i2s(end).c_str(), NULL); + end = n; + } else if(end < start) { + end = start; + } + + mstruct = vargs[2]; + MathStructure mexpr(vargs[3]); + MathStructure mprocess; + EvaluationOptions eo2 = eo; + eo2.calculate_functions = false; + mstruct.eval(eo2); + for(size_t index = (size_t) start - 1; index < (size_t) end; index++) { + if(CALCULATOR->aborted()) return 0; + mprocess = mexpr; + csum_replace(mprocess, mstruct, vargs, index, eo2); + mprocess.eval(eo2); + mstruct = mprocess; + } + return 1; + +} + +FunctionFunction::FunctionFunction() : MathFunction("function", 2) { + setArgumentDefinition(1, new TextArgument()); + setArgumentDefinition(2, new VectorArgument()); +} +int FunctionFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + UserFunction f = new UserFunction("", "Generated MathFunction", vargs[0].symbol()); + MathStructure args = vargs[1]; + mstruct = f.MathFunction::calculate(args, eo); + if(mstruct.isFunction() && mstruct.function() == &f) mstruct.setUndefined(); + return 1; +} + +REPRESENTS_FUNCTION(RepresentsIntegerFunction, representsInteger) +REPRESENTS_FUNCTION(RepresentsRealFunction, representsReal) +REPRESENTS_FUNCTION(RepresentsRationalFunction, representsRational) +REPRESENTS_FUNCTION(RepresentsNumberFunction, representsNumber) + +TitleFunction::TitleFunction() : MathFunction("title", 1) { + setArgumentDefinition(1, new ExpressionItemArgument()); +} +int TitleFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + ExpressionItem *item = CALCULATOR->getExpressionItem(vargs[0].symbol()); + if(!item) { + CALCULATOR->error(true, _("Object %s does not exist."), vargs[0].symbol().c_str(), NULL); + return 0; + } else { + mstruct = item->title(); + } + return 1; +} +SaveFunction::SaveFunction() : MathFunction("save", 2, 4) { + setArgumentDefinition(2, new TextArgument()); + setArgumentDefinition(3, new TextArgument()); + setArgumentDefinition(4, new TextArgument()); + setDefaultValue(3, CALCULATOR->temporaryCategory()); + setDefaultValue(4, ""); +} +int SaveFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + mstruct = vargs[0]; + mstruct.eval(eo); + if(!CALCULATOR->variableNameIsValid(vargs[1].symbol())) { + CALCULATOR->error(true, _("Invalid variable name (%s)."), vargs[1].symbol().c_str(), NULL); + return -1; + } + if(CALCULATOR->variableNameTaken(vargs[1].symbol())) { + Variable *v = CALCULATOR->getActiveVariable(vargs[1].symbol()); + if(v && v->isLocal() && v->isKnown()) { + if(!vargs[2].symbol().empty()) v->setCategory(vargs[2].symbol()); + if(!vargs[3].symbol().empty()) v->setTitle(vargs[3].symbol()); + ((KnownVariable*) v)->set(mstruct); + if(v->countNames() == 0) { + ExpressionName ename(vargs[1].symbol()); + ename.reference = true; + v->setName(ename, 1); + } else { + v->setName(vargs[1].symbol(), 1); + } + } else { + CALCULATOR->error(false, _("A global unit or variable was deactivated. It will be restored after the new variable has been removed."), NULL); + CALCULATOR->addVariable(new KnownVariable(vargs[2].symbol(), vargs[1].symbol(), mstruct, vargs[3].symbol())); + } + } else { + CALCULATOR->addVariable(new KnownVariable(vargs[2].symbol(), vargs[1].symbol(), mstruct, vargs[3].symbol())); + } + CALCULATOR->saveFunctionCalled(); + return 1; +} + +RegisterFunction::RegisterFunction() : MathFunction("register", 1) { + setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE)); +} +int RegisterFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) { + if(vargs[0].number().isGreaterThan(CALCULATOR->RPNStackSize())) { + CALCULATOR->error(false, _("Register %s does not exist. Returning zero."), format_and_print(vargs[0]).c_str(), NULL); + mstruct.clear(); + return 1; + } + mstruct.set(*CALCULATOR->getRPNRegister((size_t) vargs[0].number().uintValue())); + return 1; +} +StackFunction::StackFunction() : MathFunction("stack", 0) { +} +int StackFunction::calculate(MathStructure &mstruct, const MathStructure&, const EvaluationOptions&) { + mstruct.clearVector(); + for(size_t i = 1; i <= CALCULATOR->RPNStackSize(); i++) { + mstruct.addChild(*CALCULATOR->getRPNRegister(i)); + } + return 1; +} + +PlotFunction::PlotFunction() : MathFunction("plot", 1, 6) { + NumberArgument *arg = new NumberArgument(); + arg->setComplexAllowed(false); + arg->setHandleVector(false); + setArgumentDefinition(2, arg); + setDefaultValue(2, "0"); + arg = new NumberArgument(); + arg->setHandleVector(false); + arg->setComplexAllowed(false); + setArgumentDefinition(3, arg); + setDefaultValue(3, "10"); + setDefaultValue(4, "1001"); + setArgumentDefinition(5, new SymbolicArgument()); + setDefaultValue(5, "x"); + setArgumentDefinition(6, new BooleanArgument()); + setDefaultValue(6, "0"); + setCondition("\\y < \\z"); +} +int PlotFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) { + + EvaluationOptions eo2; + eo2.parse_options = eo.parse_options; + eo2.approximation = APPROXIMATION_APPROXIMATE; + eo2.parse_options.read_precision = DONT_READ_PRECISION; + eo2.interval_calculation = INTERVAL_CALCULATION_NONE; + bool use_step_size = vargs[5].number().getBoolean(); + mstruct = vargs[0]; + CALCULATOR->beginTemporaryStopIntervalArithmetic(); + if(!mstruct.contains(vargs[4], true)) { + mstruct.eval(eo2); + } else { + eo2.calculate_functions = false; + eo2.expand = false; + CALCULATOR->beginTemporaryStopMessages(); + mstruct.eval(eo2); + int im = 0; + if(CALCULATOR->endTemporaryStopMessages(NULL, &im) > 0 || im > 0) mstruct = vargs[0]; + eo2.calculate_functions = eo.calculate_functions; + eo2.expand = eo.expand; + } + CALCULATOR->endTemporaryStopIntervalArithmetic(); + vector x_vectors, y_vectors; + vector dpds; + if(mstruct.isMatrix() && mstruct.columns() == 2) { + MathStructure x_vector, y_vector; + mstruct.columnToVector(1, x_vector); + mstruct.columnToVector(2, y_vector); + y_vectors.push_back(y_vector); + x_vectors.push_back(x_vector); + PlotDataParameters *dpd = new PlotDataParameters; + dpd->title = _("Matrix"); + dpds.push_back(dpd); + } else if(mstruct.isVector()) { + int matrix_index = 1, vector_index = 1; + if(mstruct.size() > 0 && (mstruct[0].isVector() || mstruct[0].contains(vargs[4], false, true, true))) { + for(size_t i = 0; i < mstruct.size() && !CALCULATOR->aborted(); i++) { + MathStructure x_vector; + if(mstruct[i].isMatrix() && mstruct[i].columns() == 2) { + MathStructure y_vector; + mstruct[i].columnToVector(1, x_vector); + mstruct[i].columnToVector(2, y_vector); + y_vectors.push_back(y_vector); + x_vectors.push_back(x_vector); + PlotDataParameters *dpd = new PlotDataParameters; + dpd->title = _("Matrix"); + if(matrix_index > 1) { + dpd->title += " "; + dpd->title += i2s(matrix_index); + } + matrix_index++; + dpds.push_back(dpd); + } else if(mstruct[i].isVector()) { + y_vectors.push_back(mstruct[i]); + x_vectors.push_back(x_vector); + PlotDataParameters *dpd = new PlotDataParameters; + dpd->title = _("Vector"); + if(vector_index > 1) { + dpd->title += " "; + dpd->title += i2s(vector_index); + } + vector_index++; + dpds.push_back(dpd); + } else { + MathStructure y_vector; + if(use_step_size) { + CALCULATOR->beginTemporaryStopMessages(); + CALCULATOR->beginTemporaryStopIntervalArithmetic(); + y_vector.set(mstruct[i].generateVector(vargs[4], vargs[1], vargs[2], vargs[3], &x_vector, eo2)); + CALCULATOR->endTemporaryStopIntervalArithmetic(); + CALCULATOR->endTemporaryStopMessages(); + if(y_vector.size() == 0) CALCULATOR->error(true, _("Unable to generate plot data with current min, max and step size."), NULL); + } else if(!vargs[3].isInteger() || !vargs[3].representsPositive()) { + CALCULATOR->error(true, _("Sampling rate must be a positive integer."), NULL); + } else { + bool overflow = false; + int steps = vargs[3].number().intValue(&overflow); + CALCULATOR->beginTemporaryStopMessages(); + CALCULATOR->beginTemporaryStopIntervalArithmetic(); + if(steps <= 1000000 && !overflow) y_vector.set(mstruct[i].generateVector(vargs[4], vargs[1], vargs[2], steps, &x_vector, eo2)); + CALCULATOR->endTemporaryStopIntervalArithmetic(); + CALCULATOR->endTemporaryStopMessages(); + if(y_vector.size() == 0) CALCULATOR->error(true, _("Unable to generate plot data with current min, max and sampling rate."), NULL); + } + if(CALCULATOR->aborted()) { + mstruct.clear(); + return 1; + } + if(y_vector.size() > 0) { + x_vectors.push_back(x_vector); + y_vectors.push_back(y_vector); + PlotDataParameters *dpd = new PlotDataParameters; + MathStructure mprint; + if(vargs[0].isVector() && vargs[0].size() == mstruct.size()) mprint = vargs[0][i]; + else mprint = mstruct[i]; + dpd->title = format_and_print(mprint); + dpd->test_continuous = true; + dpds.push_back(dpd); + } + } + } + } else { + MathStructure x_vector; + y_vectors.push_back(mstruct); + x_vectors.push_back(x_vector); + PlotDataParameters *dpd = new PlotDataParameters; + dpd->title = _("Vector"); + dpds.push_back(dpd); + } + } else { + MathStructure x_vector, y_vector; + if(use_step_size) { + CALCULATOR->beginTemporaryStopMessages(); + CALCULATOR->beginTemporaryStopIntervalArithmetic(); + y_vector.set(mstruct.generateVector(vargs[4], vargs[1], vargs[2], vargs[3], &x_vector, eo2)); + CALCULATOR->endTemporaryStopIntervalArithmetic(); + CALCULATOR->endTemporaryStopMessages(); + if(y_vector.size() == 0) CALCULATOR->error(true, _("Unable to generate plot data with current min, max and step size."), NULL); + } else if(!vargs[3].isInteger() || !vargs[3].representsPositive()) { + CALCULATOR->error(true, _("Sampling rate must be a positive integer."), NULL); + } else { + bool overflow = false; + int steps = vargs[3].number().intValue(&overflow); + CALCULATOR->beginTemporaryStopMessages(); + CALCULATOR->beginTemporaryStopIntervalArithmetic(); + if(steps <= 1000000 && !overflow) y_vector.set(mstruct.generateVector(vargs[4], vargs[1], vargs[2], steps, &x_vector, eo2)); + CALCULATOR->endTemporaryStopIntervalArithmetic(); + CALCULATOR->endTemporaryStopMessages(); + if(y_vector.size() == 0) CALCULATOR->error(true, _("Unable to generate plot data with current min, max and sampling rate."), NULL); + } + if(CALCULATOR->aborted()) { + mstruct.clear(); + return 1; + } + if(y_vector.size() > 0) { + x_vectors.push_back(x_vector); + y_vectors.push_back(y_vector); + PlotDataParameters *dpd = new PlotDataParameters; + MathStructure mprint(vargs[0]); + dpd->title = format_and_print(mprint); + dpd->test_continuous = true; + dpds.push_back(dpd); + } + } + if(x_vectors.size() > 0 && !CALCULATOR->aborted()) { + PlotParameters param; + CALCULATOR->plotVectors(¶m, y_vectors, x_vectors, dpds, false, 0); + for(size_t i = 0; i < dpds.size(); i++) { + if(dpds[i]) delete dpds[i]; + } + } + mstruct.clear(); + return 1; + +} + diff -Nru libqalculate-3.6.0/libqalculate/Calculator-calculate.cc libqalculate-3.7.0/libqalculate/Calculator-calculate.cc --- libqalculate-3.6.0/libqalculate/Calculator-calculate.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Calculator-calculate.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,1625 @@ +/* + Qalculate + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Unit.h" +#include "Variable.h" +#include "Function.h" +#include "DataSet.h" +#include "ExpressionItem.h" +#include "Prefix.h" +#include "Number.h" +#include "QalculateDateTime.h" + +#include +#include +#include +#include +#include + +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +#include "Calculator_p.h" + +void autoConvert(const MathStructure &morig, MathStructure &mconv, const EvaluationOptions &eo) { + if(!morig.containsType(STRUCT_UNIT, true)) { + if(&mconv != &morig) mconv.set(morig); + return; + } + switch(eo.auto_post_conversion) { + case POST_CONVERSION_OPTIMAL: { + mconv.set(CALCULATOR->convertToOptimalUnit(morig, eo, false)); + break; + } + case POST_CONVERSION_BASE: { + mconv.set(CALCULATOR->convertToBaseUnits(morig, eo)); + break; + } + case POST_CONVERSION_OPTIMAL_SI: { + mconv.set(CALCULATOR->convertToOptimalUnit(morig, eo, true)); + break; + } + default: { + if(&mconv != &morig) mconv.set(morig); + } + } + if(eo.mixed_units_conversion != MIXED_UNITS_CONVERSION_NONE) mconv.set(CALCULATOR->convertToMixedUnits(mconv, eo)); +} + +void CalculateThread::run() { + enableAsynchronousCancel(); + while(true) { + bool b_parse = true; + if(!read(&b_parse)) break; + void *x = NULL; + if(!read(&x) || !x) break; + MathStructure *mstruct = (MathStructure*) x; + CALCULATOR->startControl(); + if(b_parse) { + mstruct->setAborted(); + if(CALCULATOR->tmp_parsedstruct) CALCULATOR->tmp_parsedstruct->setAborted(); + //if(CALCULATOR->tmp_tostruct) CALCULATOR->tmp_tostruct->setUndefined(); + mstruct->set(CALCULATOR->calculate(CALCULATOR->expression_to_calculate, CALCULATOR->tmp_evaluationoptions, CALCULATOR->tmp_parsedstruct, CALCULATOR->tmp_tostruct, CALCULATOR->tmp_maketodivision)); + } else { + MathStructure meval(*mstruct); + mstruct->setAborted(); + mstruct->set(CALCULATOR->calculate(meval, CALCULATOR->tmp_evaluationoptions, CALCULATOR->tmp_tostruct ? CALCULATOR->tmp_tostruct->symbol() : "")); + } + switch(CALCULATOR->tmp_proc_command) { + case PROC_RPN_ADD: { + CALCULATOR->RPNStackEnter(mstruct, false); + break; + } + case PROC_RPN_SET: { + CALCULATOR->setRPNRegister(CALCULATOR->tmp_rpnindex, mstruct, false); + break; + } + case PROC_RPN_OPERATION_1: { + if(CALCULATOR->RPNStackSize() > 0) { + CALCULATOR->setRPNRegister(1, mstruct, false); + } else { + CALCULATOR->RPNStackEnter(mstruct, false); + } + break; + } + case PROC_RPN_OPERATION_2: { + if(CALCULATOR->RPNStackSize() > 1) { + CALCULATOR->deleteRPNRegister(1); + } + if(CALCULATOR->RPNStackSize() > 0) { + CALCULATOR->setRPNRegister(1, mstruct, false); + } else { + CALCULATOR->RPNStackEnter(mstruct, false); + } + break; + } + case PROC_RPN_OPERATION_F: { + for(size_t i = 0; (CALCULATOR->tmp_proc_registers < 0 || (int) i < CALCULATOR->tmp_proc_registers - 1) && CALCULATOR->RPNStackSize() > 1; i++) { + CALCULATOR->deleteRPNRegister(1); + } + if(CALCULATOR->RPNStackSize() > 0 && CALCULATOR->tmp_proc_registers != 0) { + CALCULATOR->setRPNRegister(1, mstruct, false); + } else { + CALCULATOR->RPNStackEnter(mstruct, false); + } + break; + } + case PROC_NO_COMMAND: {} + } + CALCULATOR->stopControl(); + CALCULATOR->b_busy = false; + } +} +void Calculator::saveState() { +} +void Calculator::restoreState() { +} +void Calculator::clearBuffers() { + for(unordered_map::iterator it = priv->ids_p.begin(); it != priv->ids_p.end(); ++it) { + if(!it->second) { + priv->freed_ids.push_back(it->first); + priv->id_structs.erase(it->first); + priv->ids_p.erase(it); + } + } +} +bool Calculator::abort() { + i_aborted = 1; + if(!b_busy) return true; + if(!calculate_thread->running) { + b_busy = false; + } else { + // wait 5 seconds for clean abortation + int msecs = 5000; + while(b_busy && msecs > 0) { + sleep_ms(10); + msecs -= 10; + } + if(b_busy) { + + // force thread cancellation + calculate_thread->cancel(); + stopControl(); + + // clean up + stopped_messages_count.clear(); + stopped_warnings_count.clear(); + stopped_errors_count.clear(); + stopped_messages.clear(); + disable_errors_ref = 0; + if(tmp_rpn_mstruct) tmp_rpn_mstruct->unref(); + tmp_rpn_mstruct = NULL; + + // thread cancellation is not safe + error(true, _("The calculation has been forcibly terminated. Please restart the application and report this as a bug."), NULL); + + b_busy = false; + calculate_thread->start(); + return false; + } + } + return true; +} +bool Calculator::busy() { + return b_busy; +} +void Calculator::terminateThreads() { + if(calculate_thread->running) { + if(!calculate_thread->write(false) || !calculate_thread->write(NULL)) calculate_thread->cancel(); + for(size_t i = 0; i < 10 && calculate_thread->running; i++) { + sleep_ms(1); + } + if(calculate_thread->running) calculate_thread->cancel(); + } +} +bool Calculator::calculateRPNRegister(size_t index, int msecs, const EvaluationOptions &eo) { + if(index <= 0 || index > rpn_stack.size()) return false; + return calculateRPN(new MathStructure(*rpn_stack[rpn_stack.size() - index]), PROC_RPN_SET, index, msecs, eo); +} + +bool Calculator::calculateRPN(MathStructure *mstruct, int command, size_t index, int msecs, const EvaluationOptions &eo, int function_arguments) { + b_busy = true; + if(!calculate_thread->running && !calculate_thread->start()) {mstruct->setAborted(); return false;} + bool had_msecs = msecs > 0; + tmp_evaluationoptions = eo; + tmp_proc_command = command; + tmp_rpnindex = index; + tmp_rpn_mstruct = mstruct; + tmp_proc_registers = function_arguments; + if(!calculate_thread->write(false)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} + if(!calculate_thread->write((void*) mstruct)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} + while(msecs > 0 && b_busy) { + sleep_ms(10); + msecs -= 10; + } + if(had_msecs && b_busy) { + abort(); + return false; + } + return true; +} +bool Calculator::calculateRPN(string str, int command, size_t index, int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct, MathStructure *to_struct, bool make_to_division, int function_arguments) { + MathStructure *mstruct = new MathStructure(); + b_busy = true; + if(!calculate_thread->running && !calculate_thread->start()) {mstruct->setAborted(); return false;} + bool had_msecs = msecs > 0; + expression_to_calculate = str; + tmp_evaluationoptions = eo; + tmp_proc_command = command; + tmp_rpnindex = index; + tmp_rpn_mstruct = mstruct; + tmp_parsedstruct = parsed_struct; + tmp_tostruct = to_struct; + tmp_maketodivision = make_to_division; + tmp_proc_registers = function_arguments; + if(!calculate_thread->write(true)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} + if(!calculate_thread->write((void*) mstruct)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} + while(msecs > 0 && b_busy) { + sleep_ms(10); + msecs -= 10; + } + if(had_msecs && b_busy) { + abort(); + return false; + } + return true; +} + +bool Calculator::calculateRPN(MathOperation op, int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct) { + MathStructure *mstruct; + if(rpn_stack.size() == 0) { + mstruct = new MathStructure(); + mstruct->add(m_zero, op); + if(parsed_struct) parsed_struct->clear(); + } else if(rpn_stack.size() == 1) { + if(parsed_struct) { + parsed_struct->set(*rpn_stack.back()); + if(op == OPERATION_SUBTRACT) { + parsed_struct->transform(STRUCT_NEGATE); + } else if(op == OPERATION_DIVIDE) { + parsed_struct->transform(STRUCT_INVERSE); + } else { + parsed_struct->add(*rpn_stack.back(), op); + } + } + if(op == OPERATION_SUBTRACT) { + mstruct = new MathStructure(); + } else if(op == OPERATION_DIVIDE) { + mstruct = new MathStructure(1, 1, 0); + } else { + mstruct = new MathStructure(*rpn_stack.back()); + } + mstruct->add(*rpn_stack.back(), op); + } else { + if(parsed_struct) { + parsed_struct->set(*rpn_stack[rpn_stack.size() - 2]); + if(op == OPERATION_SUBTRACT) { + parsed_struct->transform(STRUCT_ADDITION, *rpn_stack.back()); + (*parsed_struct)[1].transform(STRUCT_NEGATE); + } else if(op == OPERATION_DIVIDE) { + parsed_struct->transform(STRUCT_DIVISION, *rpn_stack.back()); + } else { + parsed_struct->add(*rpn_stack.back(), op); + } + } + mstruct = new MathStructure(*rpn_stack[rpn_stack.size() - 2]); + mstruct->add(*rpn_stack.back(), op); + } + return calculateRPN(mstruct, PROC_RPN_OPERATION_2, 0, msecs, eo); +} +bool Calculator::calculateRPN(MathFunction *f, int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct) { + MathStructure *mstruct = new MathStructure(f, NULL); + int iregs = 0; + if(f->args() != 0) { + size_t i = f->minargs(); + bool fill_vector = (i > 0 && f->getArgumentDefinition(i) && f->getArgumentDefinition(i)->type() == ARGUMENT_TYPE_VECTOR); + if(fill_vector && rpn_stack.size() < i) fill_vector = false; + if(fill_vector && rpn_stack.size() > 0 && rpn_stack.back()->isVector()) fill_vector = false; + if(fill_vector) { + i = rpn_stack.size(); + } else if(i < 1) { + i = 1; + } + for(; i > 0; i--) { + if(i > rpn_stack.size()) { + error(false, _("Stack is empty. Filling remaining function arguments with zeroes."), NULL); + mstruct->addChild(m_zero); + } else { + if(fill_vector && rpn_stack.size() - i == (size_t) f->minargs() - 1) mstruct->addChild(m_empty_vector); + if(fill_vector && rpn_stack.size() - i >= (size_t) f->minargs() - 1) mstruct->getChild(f->minargs())->addChild(*rpn_stack[rpn_stack.size() - i]); + else mstruct->addChild(*rpn_stack[rpn_stack.size() - i]); + iregs++; + } + if(!fill_vector && f->getArgumentDefinition(i) && f->getArgumentDefinition(i)->type() == ARGUMENT_TYPE_ANGLE) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + (*mstruct)[i - 1].multiply(getDegUnit()); + break; + } + case ANGLE_UNIT_GRADIANS: { + (*mstruct)[i - 1].multiply(getGraUnit()); + break; + } + case ANGLE_UNIT_RADIANS: { + (*mstruct)[i - 1].multiply(getRadUnit()); + break; + } + default: {} + } + } + } + if(fill_vector) mstruct->childrenUpdated(); + f->appendDefaultValues(*mstruct); + } + if(parsed_struct) parsed_struct->set(*mstruct); + return calculateRPN(mstruct, PROC_RPN_OPERATION_F, 0, msecs, eo, iregs); +} +bool Calculator::calculateRPNBitwiseNot(int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct) { + MathStructure *mstruct; + if(rpn_stack.size() == 0) { + mstruct = new MathStructure(); + mstruct->setBitwiseNot(); + } else { + mstruct = new MathStructure(*rpn_stack.back()); + mstruct->setBitwiseNot(); + } + if(parsed_struct) parsed_struct->set(*mstruct); + return calculateRPN(mstruct, PROC_RPN_OPERATION_1, 0, msecs, eo); +} +bool Calculator::calculateRPNLogicalNot(int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct) { + MathStructure *mstruct; + if(rpn_stack.size() == 0) { + mstruct = new MathStructure(); + mstruct->setLogicalNot(); + } else { + mstruct = new MathStructure(*rpn_stack.back()); + mstruct->setLogicalNot(); + } + if(parsed_struct) parsed_struct->set(*rpn_stack.back()); + return calculateRPN(mstruct, PROC_RPN_OPERATION_1, 0, msecs, eo); +} +MathStructure *Calculator::calculateRPN(MathOperation op, const EvaluationOptions &eo, MathStructure *parsed_struct) { + current_stage = MESSAGE_STAGE_PARSING; + MathStructure *mstruct; + if(rpn_stack.size() == 0) { + mstruct = new MathStructure(); + mstruct->add(m_zero, op); + if(parsed_struct) parsed_struct->clear(); + } else if(rpn_stack.size() == 1) { + if(parsed_struct) { + parsed_struct->clear(); + if(op == OPERATION_SUBTRACT) { + parsed_struct->transform(STRUCT_ADDITION, *rpn_stack.back()); + (*parsed_struct)[1].transform(STRUCT_NEGATE); + } else if(op == OPERATION_DIVIDE) { + parsed_struct->transform(STRUCT_DIVISION, *rpn_stack.back()); + } else { + parsed_struct->add(*rpn_stack.back(), op); + } + } + mstruct = new MathStructure(); + mstruct->add(*rpn_stack.back(), op); + } else { + if(parsed_struct) { + parsed_struct->set(*rpn_stack[rpn_stack.size() - 2]); + if(op == OPERATION_SUBTRACT) { + parsed_struct->transform(STRUCT_ADDITION, *rpn_stack.back()); + (*parsed_struct)[1].transform(STRUCT_NEGATE); + } else if(op == OPERATION_DIVIDE) { + parsed_struct->transform(STRUCT_DIVISION, *rpn_stack.back()); + } else { + parsed_struct->add(*rpn_stack.back(), op); + } + } + mstruct = new MathStructure(*rpn_stack[rpn_stack.size() - 2]); + mstruct->add(*rpn_stack.back(), op); + } + current_stage = MESSAGE_STAGE_CALCULATION; + mstruct->eval(eo); + current_stage = MESSAGE_STAGE_CONVERSION; + autoConvert(*mstruct, *mstruct, eo); + current_stage = MESSAGE_STAGE_UNSET; + if(rpn_stack.size() > 1) { + rpn_stack.back()->unref(); + rpn_stack.erase(rpn_stack.begin() + (rpn_stack.size() - 1)); + } + if(rpn_stack.size() > 0) { + rpn_stack.back()->unref(); + rpn_stack.back() = mstruct; + } else { + rpn_stack.push_back(mstruct); + } + return rpn_stack.back(); +} +MathStructure *Calculator::calculateRPN(MathFunction *f, const EvaluationOptions &eo, MathStructure *parsed_struct) { + current_stage = MESSAGE_STAGE_PARSING; + MathStructure *mstruct = new MathStructure(f, NULL); + size_t iregs = 0; + if(f->args() != 0) { + size_t i = f->minargs(); + bool fill_vector = (i > 0 && f->getArgumentDefinition(i) && f->getArgumentDefinition(i)->type() == ARGUMENT_TYPE_VECTOR); + if(fill_vector && rpn_stack.size() < i) fill_vector = false; + if(fill_vector && rpn_stack.size() > 0 && rpn_stack.back()->isVector()) fill_vector = false; + if(fill_vector) { + i = rpn_stack.size(); + } else if(i < 1) { + i = 1; + } + for(; i > 0; i--) { + if(i > rpn_stack.size()) { + error(false, _("Stack is empty. Filling remaining function arguments with zeroes."), NULL); + mstruct->addChild(m_zero); + } else { + if(fill_vector && rpn_stack.size() - i == (size_t) f->minargs() - 1) mstruct->addChild(m_empty_vector); + if(fill_vector && rpn_stack.size() - i >= (size_t) f->minargs() - 1) mstruct->getChild(f->minargs())->addChild(*rpn_stack[rpn_stack.size() - i]); + else mstruct->addChild(*rpn_stack[rpn_stack.size() - i]); + iregs++; + } + if(!fill_vector && f->getArgumentDefinition(i) && f->getArgumentDefinition(i)->type() == ARGUMENT_TYPE_ANGLE) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + (*mstruct)[i - 1].multiply(getDegUnit()); + break; + } + case ANGLE_UNIT_GRADIANS: { + (*mstruct)[i - 1].multiply(getGraUnit()); + break; + } + case ANGLE_UNIT_RADIANS: { + (*mstruct)[i - 1].multiply(getRadUnit()); + break; + } + default: {} + } + } + } + if(fill_vector) mstruct->childrenUpdated(); + f->appendDefaultValues(*mstruct); + } + if(parsed_struct) parsed_struct->set(*mstruct); + current_stage = MESSAGE_STAGE_CALCULATION; + mstruct->eval(eo); + current_stage = MESSAGE_STAGE_CONVERSION; + autoConvert(*mstruct, *mstruct, eo); + current_stage = MESSAGE_STAGE_UNSET; + if(iregs == 0) { + rpn_stack.push_back(mstruct); + } else { + for(size_t i = 0; i < iregs - 1 && rpn_stack.size() > 1; i++) { + rpn_stack.back()->unref(); + rpn_stack.pop_back(); + deleteRPNRegister(1); + } + rpn_stack.back()->unref(); + rpn_stack.back() = mstruct; + } + return rpn_stack.back(); +} +MathStructure *Calculator::calculateRPNBitwiseNot(const EvaluationOptions &eo, MathStructure *parsed_struct) { + current_stage = MESSAGE_STAGE_PARSING; + MathStructure *mstruct; + if(rpn_stack.size() == 0) { + mstruct = new MathStructure(); + mstruct->setBitwiseNot(); + } else { + mstruct = new MathStructure(*rpn_stack.back()); + mstruct->setBitwiseNot(); + } + if(parsed_struct) parsed_struct->set(*mstruct); + current_stage = MESSAGE_STAGE_CALCULATION; + mstruct->eval(eo); + current_stage = MESSAGE_STAGE_CONVERSION; + autoConvert(*mstruct, *mstruct, eo); + current_stage = MESSAGE_STAGE_UNSET; + if(rpn_stack.size() == 0) { + rpn_stack.push_back(mstruct); + } else { + rpn_stack.back()->unref(); + rpn_stack.back() = mstruct; + } + return rpn_stack.back(); +} +MathStructure *Calculator::calculateRPNLogicalNot(const EvaluationOptions &eo, MathStructure *parsed_struct) { + current_stage = MESSAGE_STAGE_PARSING; + MathStructure *mstruct; + if(rpn_stack.size() == 0) { + mstruct = new MathStructure(); + mstruct->setLogicalNot(); + } else { + mstruct = new MathStructure(*rpn_stack.back()); + mstruct->setLogicalNot(); + } + if(parsed_struct) parsed_struct->set(*mstruct); + current_stage = MESSAGE_STAGE_CALCULATION; + mstruct->eval(eo); + current_stage = MESSAGE_STAGE_CONVERSION; + autoConvert(*mstruct, *mstruct, eo); + current_stage = MESSAGE_STAGE_UNSET; + if(rpn_stack.size() == 0) { + rpn_stack.push_back(mstruct); + } else { + rpn_stack.back()->unref(); + rpn_stack.back() = mstruct; + } + return rpn_stack.back(); +} +bool Calculator::RPNStackEnter(MathStructure *mstruct, int msecs, const EvaluationOptions &eo) { + return calculateRPN(mstruct, PROC_RPN_ADD, 0, msecs, eo); +} +bool Calculator::RPNStackEnter(string str, int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct, MathStructure *to_struct, bool make_to_division) { + remove_blank_ends(str); + if(str.empty() && rpn_stack.size() > 0) { + rpn_stack.push_back(new MathStructure(*rpn_stack.back())); + return true; + } + return calculateRPN(str, PROC_RPN_ADD, 0, msecs, eo, parsed_struct, to_struct, make_to_division); +} +void Calculator::RPNStackEnter(MathStructure *mstruct, bool eval, const EvaluationOptions &eo) { + if(eval) { + current_stage = MESSAGE_STAGE_CALCULATION; + mstruct->eval(eo); + current_stage = MESSAGE_STAGE_CONVERSION; + autoConvert(*mstruct, *mstruct, eo); + current_stage = MESSAGE_STAGE_UNSET; + } + rpn_stack.push_back(mstruct); +} +void Calculator::RPNStackEnter(string str, const EvaluationOptions &eo, MathStructure *parsed_struct, MathStructure *to_struct, bool make_to_division) { + remove_blank_ends(str); + if(str.empty() && rpn_stack.size() > 0) rpn_stack.push_back(new MathStructure(*rpn_stack.back())); + else rpn_stack.push_back(new MathStructure(calculate(str, eo, parsed_struct, to_struct, make_to_division))); +} +bool Calculator::setRPNRegister(size_t index, MathStructure *mstruct, int msecs, const EvaluationOptions &eo) { + if(mstruct == NULL) { + deleteRPNRegister(index); + return true; + } + if(index <= 0 || index > rpn_stack.size()) return false; + return calculateRPN(mstruct, PROC_RPN_SET, index, msecs, eo); +} +bool Calculator::setRPNRegister(size_t index, string str, int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct, MathStructure *to_struct, bool make_to_division) { + if(index <= 0 || index > rpn_stack.size()) return false; + return calculateRPN(str, PROC_RPN_SET, index, msecs, eo, parsed_struct, to_struct, make_to_division); +} +void Calculator::setRPNRegister(size_t index, MathStructure *mstruct, bool eval, const EvaluationOptions &eo) { + if(mstruct == NULL) { + deleteRPNRegister(index); + return; + } + if(eval) { + current_stage = MESSAGE_STAGE_CALCULATION; + mstruct->eval(eo); + current_stage = MESSAGE_STAGE_CONVERSION; + autoConvert(*mstruct, *mstruct, eo); + current_stage = MESSAGE_STAGE_UNSET; + } + if(index <= 0 || index > rpn_stack.size()) return; + index = rpn_stack.size() - index; + rpn_stack[index]->unref(); + rpn_stack[index] = mstruct; +} +void Calculator::setRPNRegister(size_t index, string str, const EvaluationOptions &eo, MathStructure *parsed_struct, MathStructure *to_struct, bool make_to_division) { + if(index <= 0 || index > rpn_stack.size()) return; + index = rpn_stack.size() - index; + MathStructure *mstruct = new MathStructure(calculate(str, eo, parsed_struct, to_struct, make_to_division)); + rpn_stack[index]->unref(); + rpn_stack[index] = mstruct; +} +void Calculator::deleteRPNRegister(size_t index) { + if(index <= 0 || index > rpn_stack.size()) return; + index = rpn_stack.size() - index; + rpn_stack[index]->unref(); + rpn_stack.erase(rpn_stack.begin() + index); +} +MathStructure *Calculator::getRPNRegister(size_t index) const { + if(index > 0 && index <= rpn_stack.size()) { + index = rpn_stack.size() - index; + return rpn_stack[index]; + } + return NULL; +} +size_t Calculator::RPNStackSize() const { + return rpn_stack.size(); +} +void Calculator::clearRPNStack() { + for(size_t i = 0; i < rpn_stack.size(); i++) { + rpn_stack[i]->unref(); + } + rpn_stack.clear(); +} +void Calculator::moveRPNRegister(size_t old_index, size_t new_index) { + if(old_index == new_index) return; + if(old_index > 0 && old_index <= rpn_stack.size()) { + old_index = rpn_stack.size() - old_index; + MathStructure *mstruct = rpn_stack[old_index]; + if(new_index > rpn_stack.size()) { + new_index = 0; + } else if(new_index <= 1) { + rpn_stack.push_back(mstruct); + rpn_stack.erase(rpn_stack.begin() + old_index); + return; + } else { + new_index = rpn_stack.size() - new_index; + } + if(new_index > old_index) { + rpn_stack.erase(rpn_stack.begin() + old_index); + rpn_stack.insert(rpn_stack.begin() + new_index, mstruct); + } else if(new_index < old_index) { + rpn_stack.insert(rpn_stack.begin() + new_index, mstruct); + rpn_stack.erase(rpn_stack.begin() + (old_index + 1)); + } + } +} +void Calculator::moveRPNRegisterUp(size_t index) { + if(index > 1 && index <= rpn_stack.size()) { + index = rpn_stack.size() - index; + MathStructure *mstruct = rpn_stack[index]; + rpn_stack.erase(rpn_stack.begin() + index); + index++; + if(index == rpn_stack.size()) rpn_stack.push_back(mstruct); + else rpn_stack.insert(rpn_stack.begin() + index, mstruct); + } +} +void Calculator::moveRPNRegisterDown(size_t index) { + if(index > 0 && index < rpn_stack.size()) { + index = rpn_stack.size() - index; + MathStructure *mstruct = rpn_stack[index]; + rpn_stack.erase(rpn_stack.begin() + index); + index--; + rpn_stack.insert(rpn_stack.begin() + index, mstruct); + } +} + +int has_information_unit(const MathStructure &m, bool top) { + if(m.isUnit_exp()) { + if(m.isUnit()) { + if(m.unit()->baseUnit()->referenceName() == "bit") return 1; + } else { + if(m[0].unit()->baseUnit()->referenceName() == "bit") { + if(m[1].isInteger() && m[1].number().isPositive()) return 1; + return 2; + } + } + return 0; + } + for(size_t i = 0; i < m.size(); i++) { + int ret = has_information_unit(m[i], false); + if(ret > 0) { + if(ret == 1 && top && m.isMultiplication() && m[0].isNumber() && m[0].number().isFraction()) return 2; + return ret; + } + } + return 0; +} + +void fix_to_struct(MathStructure &m) { + if(m.isPower() && m[0].isUnit()) { + if(m[0].prefix() == NULL && m[0].unit()->referenceName() == "g") { + m[0].setPrefix(CALCULATOR->getOptimalDecimalPrefix(3)); + } else if(m[0].unit() == CALCULATOR->getUnitById(UNIT_ID_EURO)) { + Unit *u = CALCULATOR->getLocalCurrency(); + if(u) m[0].setUnit(u); + } + } else if(m.isUnit()) { + if(m.prefix() == NULL && m.unit()->referenceName() == "g") { + m.setPrefix(CALCULATOR->getOptimalDecimalPrefix(3)); + } else if(m.unit() == CALCULATOR->getUnitById(UNIT_ID_EURO)) { + Unit *u = CALCULATOR->getLocalCurrency(); + if(u) m.setUnit(u); + } + } else { + for(size_t i = 0; i < m.size();) { + if(m[i].isUnit()) { + if(m[i].prefix() == NULL && m[i].unit()->referenceName() == "g") { + m[i].setPrefix(CALCULATOR->getOptimalDecimalPrefix(3)); + } else if(m[i].unit() == CALCULATOR->getUnitById(UNIT_ID_EURO)) { + Unit *u = CALCULATOR->getLocalCurrency(); + if(u) m[i].setUnit(u); + } + i++; + } else if(m[i].isPower() && m[i][0].isUnit()) { + if(m[i][0].prefix() == NULL && m[i][0].unit()->referenceName() == "g") { + m[i][0].setPrefix(CALCULATOR->getOptimalDecimalPrefix(3)); + } else if(m[i][0].unit() == CALCULATOR->getUnitById(UNIT_ID_EURO)) { + Unit *u = CALCULATOR->getLocalCurrency(); + if(u) m[i][0].setUnit(u); + } + i++; + } else { + m.delChild(i + 1); + } + } + if(m.size() == 0) m.clear(); + if(m.size() == 1) m.setToChild(1); + } +} + +#define EQUALS_IGNORECASE_AND_LOCAL(x,y,z) (equalsIgnoreCase(x, y) || equalsIgnoreCase(x, z)) +string Calculator::calculateAndPrint(string str, int msecs, const EvaluationOptions &eo, const PrintOptions &po) { + + if(msecs > 0) startControl(msecs); + + PrintOptions printops = po; + EvaluationOptions evalops = eo; + MathStructure mstruct; + bool do_bases = false, do_factors = false, do_fraction = false, do_pfe = false, do_calendars = false, do_expand = false, do_binary_prefixes = false, complex_angle_form = false; + + // separate and handle string after "to" + string from_str = str, to_str; + Number base_save; + if(printops.base == BASE_CUSTOM) base_save = customOutputBase(); + int save_bin = priv->use_binary_prefixes; + if(separateToExpression(from_str, to_str, evalops, true)) { + remove_duplicate_blanks(to_str); + string to_str1, to_str2; + size_t ispace = to_str.find_first_of(SPACES); + if(ispace != string::npos) { + to_str1 = to_str.substr(0, ispace); + remove_blank_ends(to_str1); + to_str2 = to_str.substr(ispace + 1); + remove_blank_ends(to_str2); + } + if(equalsIgnoreCase(to_str, "hex") || EQUALS_IGNORECASE_AND_LOCAL(to_str, "hexadecimal", _("hexadecimal"))) { + str = from_str; + printops.base = BASE_HEXADECIMAL; + } else if(equalsIgnoreCase(to_str, "bin") || EQUALS_IGNORECASE_AND_LOCAL(to_str, "binary", _("binary"))) { + str = from_str; + printops.base = BASE_BINARY; + } else if(equalsIgnoreCase(to_str, "dec") || EQUALS_IGNORECASE_AND_LOCAL(to_str, "decimal", _("decimal"))) { + str = from_str; + printops.base = BASE_DECIMAL; + } else if(equalsIgnoreCase(to_str, "oct") || EQUALS_IGNORECASE_AND_LOCAL(to_str, "octal", _("octal"))) { + str = from_str; + printops.base = BASE_OCTAL; + } else if(equalsIgnoreCase(to_str, "duo") || EQUALS_IGNORECASE_AND_LOCAL(to_str, "duodecimal", _("duodecimal"))) { + str = from_str; + printops.base = BASE_DUODECIMAL; + } else if(equalsIgnoreCase(to_str, "roman") || equalsIgnoreCase(to_str, _("roman"))) { + str = from_str; + printops.base = BASE_ROMAN_NUMERALS; + } else if(equalsIgnoreCase(to_str, "bijective") || equalsIgnoreCase(to_str, _("bijective"))) { + str = from_str; + printops.base = BASE_BIJECTIVE_26; + } else if(equalsIgnoreCase(to_str, "sexa") || equalsIgnoreCase(to_str, "sexagesimal") || equalsIgnoreCase(to_str, _("sexagesimal"))) { + str = from_str; + printops.base = BASE_SEXAGESIMAL; + } else if(equalsIgnoreCase(to_str, "time") || equalsIgnoreCase(to_str, _("time"))) { + str = from_str; + printops.base = BASE_TIME; + } else if(equalsIgnoreCase(to_str, "unicode")) { + str = from_str; + printops.base = BASE_UNICODE; + } else if(equalsIgnoreCase(to_str, "utc") || equalsIgnoreCase(to_str, "gmt")) { + str = from_str; + printops.time_zone = TIME_ZONE_UTC; + } else if(to_str.length() > 3 && (equalsIgnoreCase(to_str.substr(0, 3), "utc") || equalsIgnoreCase(to_str.substr(0, 3), "gmt"))) { + to_str = to_str.substr(3); + remove_blanks(to_str); + bool b_minus = false; + if(to_str[0] == '+') { + to_str.erase(0, 1); + } else if(to_str[0] == '-') { + b_minus = true; + to_str.erase(0, 1); + } else if(to_str.find(SIGN_MINUS) == 0) { + b_minus = true; + to_str.erase(0, strlen(SIGN_MINUS)); + } + unsigned int tzh = 0, tzm = 0; + int itz = 0; + if(!to_str.empty() && sscanf(to_str.c_str(), "%2u:%2u", &tzh, &tzm) > 0) { + itz = tzh * 60 + tzm; + if(b_minus) itz = -itz; + } else { + error(true, _("Time zone parsing failed."), NULL); + } + printops.time_zone = TIME_ZONE_CUSTOM; + printops.custom_time_zone = itz; + str = from_str; + } else if(to_str == "CET") { + printops.time_zone = TIME_ZONE_CUSTOM; + printops.custom_time_zone = 60; + str = from_str; + } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "rectangular", _("rectangular")) || EQUALS_IGNORECASE_AND_LOCAL(to_str, "cartesian", _("cartesian")) || str == "rect") { + str = from_str; + evalops.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; + } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "exponential", _("exponential")) || to_str == "exp") { + str = from_str; + evalops.complex_number_form = COMPLEX_NUMBER_FORM_EXPONENTIAL; + } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "polar", _("polar"))) { + str = from_str; + evalops.complex_number_form = COMPLEX_NUMBER_FORM_POLAR; + } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "angle", _("angle")) || EQUALS_IGNORECASE_AND_LOCAL(to_str, "phasor", _("phasor"))) { + str = from_str; + evalops.complex_number_form = COMPLEX_NUMBER_FORM_CIS; + complex_angle_form = true; + } else if(to_str == "cis") { + str = from_str; + evalops.complex_number_form = COMPLEX_NUMBER_FORM_CIS; + } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "fraction", _("fraction"))) { + str = from_str; + do_fraction = true; + } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "factors", _("factors")) || equalsIgnoreCase(to_str, "factor")) { + str = from_str; + evalops.structuring = STRUCTURING_FACTORIZE; + do_factors = true; + } else if(equalsIgnoreCase(to_str, "partial fraction") || equalsIgnoreCase(to_str, _("partial fraction"))) { + str = from_str; + do_pfe = true; + } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "bases", _("bases"))) { + do_bases = true; + str = from_str; + } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "calendars", _("calendars"))) { + do_calendars = true; + str = from_str; + } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "optimal", _("optimal"))) { + str = from_str; + evalops.parse_options.units_enabled = true; + evalops.auto_post_conversion = POST_CONVERSION_OPTIMAL_SI; + } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "base", _("base"))) { + str = from_str; + evalops.parse_options.units_enabled = true; + evalops.auto_post_conversion = POST_CONVERSION_BASE; + } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str1, "base", _("base"))) { + str = from_str; + if(to_str2 == "b26" || to_str2 == "B26") printops.base = BASE_BIJECTIVE_26; + else if(equalsIgnoreCase(to_str2, "golden") || equalsIgnoreCase(to_str2, "golden ratio") || to_str2 == "φ") printops.base = BASE_GOLDEN_RATIO; + else if(equalsIgnoreCase(to_str2, "unicode")) printops.base = BASE_UNICODE; + else if(equalsIgnoreCase(to_str2, "supergolden") || equalsIgnoreCase(to_str2, "supergolden ratio") || to_str2 == "ψ") printops.base = BASE_SUPER_GOLDEN_RATIO; + else if(equalsIgnoreCase(to_str2, "pi") || to_str2 == "π") printops.base = BASE_PI; + else if(to_str2 == "e") printops.base = BASE_E; + else if(to_str2 == "sqrt(2)" || to_str2 == "sqrt 2" || to_str2 == "sqrt2" || to_str2 == "√2") printops.base = BASE_SQRT2; + else { + EvaluationOptions eo = evalops; + eo.parse_options.base = 10; + MathStructure m = calculate(to_str2, eo); + if(m.isInteger() && m.number() >= 2 && m.number() <= 36) { + printops.base = m.number().intValue(); + } else { + printops.base = BASE_CUSTOM; + base_save = customOutputBase(); + setCustomOutputBase(m.number()); + } + } + } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "mixed", _("mixed"))) { + str = from_str; + evalops.parse_options.units_enabled = true; + evalops.auto_post_conversion = POST_CONVERSION_NONE; + evalops.mixed_units_conversion = MIXED_UNITS_CONVERSION_FORCE_INTEGER; + } else { + // ? in front of unit epxression is interpreted as a request for the optimal prefix. + evalops.parse_options.units_enabled = true; + if(to_str[0] == '?' || (to_str.length() > 1 && to_str[1] == '?' && (to_str[0] == 'a' || to_str[0] == 'd'))) { + printops.use_unit_prefixes = true; + printops.use_prefixes_for_currencies = true; + printops.use_prefixes_for_all_units = true; + if(to_str[0] == 'a') printops.use_all_prefixes = true; + else if(to_str[0] == 'd') priv->use_binary_prefixes = 0; + } else if(to_str.length() > 1 && to_str[1] == '?' && to_str[0] == 'b') { + // b? in front of unit epxression: use binary prefixes + do_binary_prefixes = true; + } + } + // expression after "to" is by default interpreted as unit epxression + } else { + // check for factor or expand instruction at front a expression + size_t i = str.find_first_of(SPACES LEFT_PARENTHESIS); + if(i != string::npos) { + to_str = str.substr(0, i); + if(to_str == "factor" || EQUALS_IGNORECASE_AND_LOCAL(to_str, "factorize", _("factorize"))) { + str = str.substr(i + 1); + do_factors = true; + evalops.structuring = STRUCTURING_FACTORIZE; + } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "expand", _("expand"))) { + str = str.substr(i + 1); + evalops.structuring = STRUCTURING_SIMPLIFY; + do_expand = true; + } + } + } + + + // perform calculation + if(to_str.empty() || str == from_str) { + mstruct = calculate(str, evalops); + } else { + // handle case where conversion to units requested, but original expression and result does not contains any unit + MathStructure parsed_struct, to_struct; + mstruct = calculate(str, evalops, &parsed_struct, &to_struct); + if(to_struct.containsType(STRUCT_UNIT, true) && !mstruct.contains(STRUCT_UNIT, false, true, true) && !parsed_struct.containsType(STRUCT_UNIT, false, true, true)) { + // convert "to"-expression to base units + to_struct = CALCULATOR->convertToBaseUnits(to_struct); + // remove non-units, set local currency and use kg instead of g + fix_to_struct(to_struct); + // recalculate + if(!to_struct.isZero()) mstruct = calculate(mstruct, evalops, to_str); + } + } + + // handle "to factors", and "factor" or "expand" in front of the expression + if(do_factors) { + mstruct.integerFactorize(); + } else if(do_expand) { + mstruct.expand(evalops, false); + } + + // handle "to partial fraction" + if(do_pfe) mstruct.expandPartialFractions(evalops); + + printops.allow_factorization = printops.allow_factorization || evalops.structuring == STRUCTURING_FACTORIZE || do_factors; + + if(do_calendars && mstruct.isDateTime()) { + // handle "to calendars" + str = ""; + bool b_fail; + long int y, m, d; +#define PRINT_CALENDAR(x, c) if(!str.empty()) {str += "\n";} str += x; str += " "; b_fail = !dateToCalendar(*mstruct.datetime(), y, m, d, c); if(b_fail) {str += _("failed");} else {str += i2s(d); str += " "; str += monthName(m, c, true); str += " "; str += i2s(y);} + PRINT_CALENDAR(string(_("Gregorian:")), CALENDAR_GREGORIAN); + PRINT_CALENDAR(string(_("Hebrew:")), CALENDAR_HEBREW); + PRINT_CALENDAR(string(_("Islamic:")), CALENDAR_ISLAMIC); + PRINT_CALENDAR(string(_("Persian:")), CALENDAR_PERSIAN); + PRINT_CALENDAR(string(_("Indian national:")), CALENDAR_INDIAN); + PRINT_CALENDAR(string(_("Chinese:")), CALENDAR_CHINESE); + long int cy, yc, st, br; + chineseYearInfo(y, cy, yc, st, br); + if(!b_fail) {str += " ("; str += chineseStemName(st); str += string(" "); str += chineseBranchName(br); str += ")";} + PRINT_CALENDAR(string(_("Julian:")), CALENDAR_JULIAN); + PRINT_CALENDAR(string(_("Revised julian:")), CALENDAR_MILANKOVIC); + PRINT_CALENDAR(string(_("Coptic:")), CALENDAR_COPTIC); + PRINT_CALENDAR(string(_("Ethiopian:")), CALENDAR_ETHIOPIAN); + stopControl(); + return str; + } else if(do_bases) { + // handle "to bases" + printops.base = BASE_BINARY; + str = print(mstruct, 0, printops); + str += " = "; + printops.base = BASE_OCTAL; + str += print(mstruct, 0, printops); + str += " = "; + printops.base = BASE_DECIMAL; + str += print(mstruct, 0, printops); + str += " = "; + printops.base = BASE_HEXADECIMAL; + str += print(mstruct, 0, printops); + stopControl(); + return str; + } else if(do_fraction) { + // handle "to fraction" + if(mstruct.isNumber()) printops.number_fraction_format = FRACTION_COMBINED; + else printops.number_fraction_format = FRACTION_FRACTIONAL; + } else if(do_binary_prefixes) { + // b? in front of unit expression: use binary prefixes + printops.use_unit_prefixes = true; + // check for information units in unit expression: if found use only binary prefixes for information units + int i = has_information_unit(mstruct); + priv->use_binary_prefixes = (i > 0 ? 1 : 2); + if(i == 1) { + printops.use_denominator_prefix = false; + } else if(i > 1) { + printops.use_denominator_prefix = true; + } else { + printops.use_prefixes_for_currencies = true; + printops.use_prefixes_for_all_units = true; + } + } + // do not display the default angle unit in trigonometric functions + mstruct.removeDefaultAngleUnit(evalops); + + // format and print + mstruct.format(printops); + str = mstruct.print(printops); + + // "to angle": replace "cis" with angle symbol + if(complex_angle_form) gsub(" cis ", "∠", str); + + if(msecs > 0) stopControl(); + + // restore options + if(printops.base == BASE_CUSTOM) setCustomOutputBase(base_save); + priv->use_binary_prefixes = save_bin; + + return str; +} +bool Calculator::calculate(MathStructure *mstruct, string str, int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct, MathStructure *to_struct, bool make_to_division) { + + mstruct->set(string(_("calculating...")), false, true); + b_busy = true; + if(!calculate_thread->running && !calculate_thread->start()) {mstruct->setAborted(); return false;} + bool had_msecs = msecs > 0; + + // send calculation command to calculation thread + expression_to_calculate = str; + tmp_evaluationoptions = eo; + tmp_proc_command = PROC_NO_COMMAND; + tmp_rpn_mstruct = NULL; + tmp_parsedstruct = parsed_struct; + tmp_tostruct = to_struct; + tmp_maketodivision = make_to_division; + if(!calculate_thread->write(true)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} + if(!calculate_thread->write((void*) mstruct)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} + + // check time while calculation proceeds + while(msecs > 0 && b_busy) { + sleep_ms(10); + msecs -= 10; + } + if(had_msecs && b_busy) { + if(!abort()) mstruct->setAborted(); + return false; + } + return true; +} +bool Calculator::calculate(MathStructure *mstruct, int msecs, const EvaluationOptions &eo, string to_str) { + + b_busy = true; + if(!calculate_thread->running && !calculate_thread->start()) {mstruct->setAborted(); return false;} + bool had_msecs = msecs > 0; + + // send calculation command to calculation thread + expression_to_calculate = ""; + tmp_evaluationoptions = eo; + tmp_proc_command = PROC_NO_COMMAND; + tmp_rpn_mstruct = NULL; + tmp_parsedstruct = NULL; + if(!to_str.empty()) tmp_tostruct = new MathStructure(to_str); + else tmp_tostruct = NULL; + tmp_maketodivision = false; + if(!calculate_thread->write(false)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} + if(!calculate_thread->write((void*) mstruct)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} + + // check time while calculation proceeds + while(msecs > 0 && b_busy) { + sleep_ms(10); + msecs -= 10; + } + if(had_msecs && b_busy) { + if(!abort()) mstruct->setAborted(); + return false; + } + return true; +} +bool Calculator::hasToExpression(const string &str, bool allow_empty_from) const { + if(str.empty()) return false; + size_t i = str.length() - 1, i2 = i; + int l = 2; + while(i != 0) { + i2 = str.rfind(_("to"), i - 1); + i = str.rfind("to", i - 1); + if(i2 != string::npos && (i == string::npos || i < i2)) {l = strlen(_("to")); i = i2;} + else l = 2; + if(i == string::npos) break; + if(((i > 0 && is_in(SPACES, str[i - 1])) || (allow_empty_from && i == 0)) && i + l < str.length() && is_in(SPACES, str[i + l])) return true; + } + return false; +} +bool Calculator::hasToExpression(const string &str, bool allow_empty_from, const EvaluationOptions &eo) const { + if(eo.parse_options.base == BASE_UNICODE || (eo.parse_options.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) return false; + if(str.empty()) return false; + size_t i = str.length() - 1, i2 = i; + int l = 2; + while(i != 0) { + i2 = str.rfind(_("to"), i - 1); + i = str.rfind("to", i - 1); + if(i2 != string::npos && (i == string::npos || i < i2)) {l = strlen(_("to")); i = i2;} + else l = 2; + if(i == string::npos) break; + if(((i > 0 && is_in(SPACES, str[i - 1])) || (allow_empty_from && i == 0)) && i + l < str.length() && is_in(SPACES, str[i + l])) return true; + } + return false; +} +bool Calculator::separateToExpression(string &str, string &to_str, const EvaluationOptions &eo, bool keep_modifiers, bool allow_empty_from) const { + if(eo.parse_options.base == BASE_UNICODE || (eo.parse_options.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) return false; + to_str = ""; + if(str.empty()) return false; + size_t i = str.length() - 1, i2 = i; + int l = 2; + while(i != 0) { + i2 = str.rfind(_("to"), i - 1); + i = str.rfind("to", i - 1); + if(i2 != string::npos && (i == string::npos || i < i2)) {l = strlen(_("to")); i = i2;} + else l = 2; + if(i == string::npos) break; + if(((i > 0 && is_in(SPACES, str[i - 1])) || (allow_empty_from && i == 0)) && i + l < str.length() && is_in(SPACES, str[i + l])) { + to_str = str.substr(i + l , str.length() - i - l); + if(to_str.empty()) return false; + remove_blank_ends(to_str); + if(!to_str.empty()) { + if(to_str.rfind(SIGN_MINUS, 0) == 0) { + to_str.replace(0, strlen(SIGN_MINUS), MINUS); + } + if(!keep_modifiers && (to_str[0] == '0' || to_str[0] == '?' || to_str[0] == '+' || to_str[0] == '-')) { + to_str = to_str.substr(1, str.length() - 1); + remove_blank_ends(to_str); + } else if(!keep_modifiers && to_str.length() > 1 && to_str[1] == '?' && (to_str[0] == 'b' || to_str[0] == 'a' || to_str[0] == 'd')) { + to_str = to_str.substr(2, str.length() - 2); + remove_blank_ends(to_str); + } + } + str = str.substr(0, i); + return true; + } + } + return false; +} +bool Calculator::hasWhereExpression(const string &str, const EvaluationOptions &eo) const { + if(eo.parse_options.base == BASE_UNICODE || (eo.parse_options.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) return false; + if(str.empty()) return false; + size_t i = str.length() - 1, i2 = i; + int l = 2; + while(i != 0) { + //"where"-operator + i2 = str.rfind(_("where"), i - 1); + i = str.rfind("where", i - 1); + if(i2 != string::npos && (i == string::npos || i < i2)) {l = strlen(_("where")); i = i2;} + else l = 2; + if(i == string::npos) break; + if(i > 0 && is_in(SPACES, str[i - 1]) && i + l < str.length() && is_in(SPACES, str[i + l])) return true; + } + if((i = str.rfind("/.", str.length() - 2)) != string::npos && eo.parse_options.base >= 2 && eo.parse_options.base <= 10 && (str[i + 2] < '0' || str[i + 2] > '9')) return true; + return false; +} +bool Calculator::separateWhereExpression(string &str, string &to_str, const EvaluationOptions &eo) const { + if(eo.parse_options.base == BASE_UNICODE || (eo.parse_options.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) return false; + to_str = ""; + size_t i = 0; + if((i = str.rfind("/.", str.length() - 2)) != string::npos && i != str.length() - 2 && eo.parse_options.base >= 2 && eo.parse_options.base <= 10 && (str[i + 2] < '0' || str[i + 2] > '9')) { + to_str = str.substr(i + 2 , str.length() - i - 2); + } else { + i = str.length() - 1; + size_t i2 = i; + int l = 5; + while(i != 0) { + i2 = str.rfind(_("where"), i - 1); + i = str.rfind("where", i - 1); + if(i2 != string::npos && (i == string::npos || i < i2)) {l = strlen(_("where")); i = i2;} + else l = 5; + if(i == string::npos) break; + if(i > 0 && is_in(SPACES, str[i - 1]) && i + l < str.length() && is_in(SPACES, str[i + l])) { + to_str = str.substr(i + l , str.length() - i - l); + break; + } + } + } + if(!to_str.empty()) { + remove_blank_ends(to_str); + str = str.substr(0, i); + parseSigns(str); + if(str.find("&&") == string::npos) { + int par = 0; + int bra = 0; + for(size_t i = 0; i < str.length(); i++) { + switch(str[i]) { + case '(': {par++; break;} + case ')': {if(par > 0) par--; break;} + case '[': {bra++; break;} + case ']': {if(bra > 0) bra--; break;} + case COMMA_CH: { + if(par == 0 && bra == 0) { + str.replace(i, 1, LOGICAL_AND); + i++; + } + break; + } + default: {} + } + } + } + return true; + } + return false; +} +bool calculate_rand(MathStructure &mstruct, const EvaluationOptions &eo) { + if(mstruct.isFunction() && (mstruct.function()->id() == FUNCTION_ID_RAND || mstruct.function()->id() == FUNCTION_ID_RANDN || mstruct.function()->id() == FUNCTION_ID_RAND_POISSON)) { + mstruct.unformat(eo); + mstruct.calculateFunctions(eo, false); + return true; + } + bool ret = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(calculate_rand(mstruct[i], eo)) { + ret = true; + mstruct.childUpdated(i + 1); + } + } + return ret; +} +bool calculate_ans(MathStructure &mstruct, const EvaluationOptions &eo) { + if(mstruct.isFunction() && (mstruct.function()->hasName("answer") || mstruct.function()->hasName("expression"))) { + mstruct.unformat(eo); + mstruct.calculateFunctions(eo, false); + return true; + } else if(mstruct.isVariable() && mstruct.variable()->isKnown() && (mstruct.variable()->referenceName() == "ans" || (mstruct.variable()->referenceName().length() == 4 && mstruct.variable()->referenceName().substr(0, 3) == "ans" && is_in(NUMBERS, mstruct.variable()->referenceName()[3])))) { + mstruct.set(((KnownVariable*) mstruct.variable())->get(), true); + return true; + } + bool ret = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(calculate_ans(mstruct[i], eo)) { + mstruct.childUpdated(i + 1); + ret = true; + } + } + return ret; +} +bool handle_where_expression(MathStructure &m, MathStructure &mstruct, const EvaluationOptions &eo, vector& vars, vector& varms, bool empty_func, bool do_eval = true) { + if(m.isComparison()) { + if(m.comparisonType() == COMPARISON_EQUALS) { + // x=y + if(m[0].size() > 0 && do_eval) { + // not a single variable (or empty function) on the left side of the comparison: perform calculation + MathStructure m2(m); + MathStructure xvar = m[0].find_x_var(); + EvaluationOptions eo2 = eo; + eo2.isolate_x = true; + if(!xvar.isUndefined()) eo2.isolate_var = &xvar; + m2.eval(eo2); + if(m2.isComparison()) return handle_where_expression(m2, mstruct, eo, vars, varms, false, false); + } + if(m[0].isFunction() && m[1].isFunction() && (m[0].size() == 0 || (empty_func && m[0].function()->minargs() == 0)) && (m[1].size() == 0 || (empty_func && m[1].function()->minargs() == 0))) { + // if left value is a function without any arguments, do function replacement + if(!replace_function(mstruct, m[0].function(), m[1].function(), eo)) CALCULATOR->error(false, _("Original value (%s) was not found."), (m[0].function()->name() + "()").c_str(), NULL); + } else { + if(mstruct.countOccurrences(m[0]) > 1) { + + // make sure that only a single random value is used + calculate_rand(m[1], eo); + + if(m[1].containsInterval(true, false, false, 0, true)) { + // replace interval with variable if multiple occurrences if original value + MathStructure mv(m[1]); + replace_f_interval(mv, eo); + replace_intervals_f(mv); + if(!mstruct.replace(m[0], mv)) CALCULATOR->error(false, _("Original value (%s) was not found."), format_and_print(m[0]).c_str(), NULL); + } else { + if(!mstruct.replace(m[0], m[1])) CALCULATOR->error(false, _("Original value (%s) was not found."), format_and_print(m[0]).c_str(), NULL); + } + } else { + if(!mstruct.replace(m[0], m[1])) CALCULATOR->error(false, _("Original value (%s) was not found."), format_and_print(m[0]).c_str(), NULL); + } + } + return true; + } else if(m[0].isSymbolic() || (m[0].isVariable() && !m[0].variable()->isKnown())) { + // inequality found + // unknown variable range specification (e.g. x>0) + // right hand side value must be a non-complex number + if(!m[1].isNumber()) m[1].eval(eo); + if(m[1].isNumber() && !m[1].number().hasImaginaryPart()) { + Assumptions *ass = NULL; + // search for assumptions from previous "where" replacements + for(size_t i = 0; i < varms.size(); i++) { + if(varms[i] == m[0]) { + ass = vars[0]->assumptions(); + break; + } + } + // can only handle not equals if value is zero + if((m.comparisonType() != COMPARISON_NOT_EQUALS || (!ass && m[1].isZero()))) { + if(ass) { + // change existing assumptions + if(m.comparisonType() == COMPARISON_EQUALS_GREATER) { + if(!ass->min() || (*ass->min() < m[1].number())) { + ass->setMin(&m[1].number()); ass->setIncludeEqualsMin(true); + return true; + } else if(*ass->min() >= m[1].number()) { + return true; + } + } else if(m.comparisonType() == COMPARISON_EQUALS_LESS) { + if(!ass->max() || (*ass->max() > m[1].number())) { + ass->setMax(&m[1].number()); ass->setIncludeEqualsMax(true); + return true; + } else if(*ass->max() <= m[1].number()) { + return true; + } + } else if(m.comparisonType() == COMPARISON_GREATER) { + if(!ass->min() || (ass->includeEqualsMin() && *ass->min() <= m[1].number()) || (!ass->includeEqualsMin() && *ass->min() < m[1].number())) { + ass->setMin(&m[1].number()); ass->setIncludeEqualsMin(false); + return true; + } else if((ass->includeEqualsMin() && *ass->min() > m[1].number()) || (!ass->includeEqualsMin() && *ass->min() >= m[1].number())) { + return true; + } + } else if(m.comparisonType() == COMPARISON_LESS) { + if(!ass->max() || (ass->includeEqualsMax() && *ass->max() >= m[1].number()) || (!ass->includeEqualsMax() && *ass->max() > m[1].number())) { + ass->setMax(&m[1].number()); ass->setIncludeEqualsMax(false); + return true; + } else if((ass->includeEqualsMax() && *ass->max() < m[1].number()) || (!ass->includeEqualsMax() && *ass->max() <= m[1].number())) { + return true; + } + } + } else { + // create a new unknown variable and modify the assumptions + UnknownVariable *var = new UnknownVariable("", format_and_print(m[0])); + ass = new Assumptions(); + if(m[1].isZero()) { + if(m.comparisonType() == COMPARISON_EQUALS_GREATER) ass->setSign(ASSUMPTION_SIGN_NONNEGATIVE); + else if(m.comparisonType() == COMPARISON_EQUALS_LESS) ass->setSign(ASSUMPTION_SIGN_NONPOSITIVE); + else if(m.comparisonType() == COMPARISON_GREATER) ass->setSign(ASSUMPTION_SIGN_POSITIVE); + else if(m.comparisonType() == COMPARISON_LESS) ass->setSign(ASSUMPTION_SIGN_NEGATIVE); + else if(m.comparisonType() == COMPARISON_NOT_EQUALS) ass->setSign(ASSUMPTION_SIGN_NONZERO); + } else { + if(m.comparisonType() == COMPARISON_EQUALS_GREATER) {ass->setMin(&m[1].number()); ass->setIncludeEqualsMin(true);} + else if(m.comparisonType() == COMPARISON_EQUALS_LESS) {ass->setMax(&m[1].number()); ass->setIncludeEqualsMax(true);} + else if(m.comparisonType() == COMPARISON_GREATER) {ass->setMin(&m[1].number()); ass->setIncludeEqualsMin(false);} + else if(m.comparisonType() == COMPARISON_LESS) {ass->setMax(&m[1].number()); ass->setIncludeEqualsMax(false);} + } + var->setAssumptions(ass); + vars.push_back(var); + varms.push_back(m[0]); + MathStructure u_var(var); + if(!mstruct.replace(m[0], u_var)) CALCULATOR->error(false, _("Original value (%s) was not found."), format_and_print(m[0]).c_str(), NULL); + return true; + } + } + } + } else if(do_eval) { + // inequality without a single variable on the left side: calculate expression and try again + MathStructure xvar = m[0].find_x_var(); + EvaluationOptions eo2 = eo; + eo2.isolate_x = true; + if(!xvar.isUndefined()) eo2.isolate_var = &xvar; + m.eval(eo2); + return handle_where_expression(m, mstruct, eo, vars, varms, false, false); + } + } else if(m.isLogicalAnd()) { + // logical and (e.g. x=2&&y=3): perform multiple "where" replacments + bool ret = true; + for(size_t i = 0; i < m.size(); i++) { + if(!handle_where_expression(m[i], mstruct, eo, vars, varms, empty_func, do_eval)) ret = false; + } + return ret; + } + CALCULATOR->error(true, _("Unhandled \"where\" expression: %s"), format_and_print(m).c_str(), NULL); + return false; +} +MathStructure Calculator::calculate(string str, const EvaluationOptions &eo, MathStructure *parsed_struct, MathStructure *to_struct, bool make_to_division) { + + string str2, str_where; + + // retrieve expression after " to " and remove "to ..." from expression + if(make_to_division) separateToExpression(str, str2, eo, true); + + // retrieve expression after " where " (or "/.") and remove "to ..." from expression + separateWhereExpression(str, str_where, eo); + + // handle to expression provided as argument + Unit *u = NULL; + if(to_struct) { + // ignore if expression contains "to" expression + if(str2.empty()) { + if(to_struct->isSymbolic() && !to_struct->symbol().empty()) { + // if to_struct is symbol, treat as "to" string + str2 = to_struct->symbol(); + remove_blank_ends(str2); + } else if(to_struct->isUnit()) { + // if to_struct is unit, convert to this unit (later) + u = to_struct->unit(); + } + } + to_struct->setUndefined(); + } + + MathStructure mstruct; + current_stage = MESSAGE_STAGE_PARSING; + size_t n_messages = messages.size(); + + // perform expression parsing + parse(&mstruct, str, eo.parse_options); + if(parsed_struct) { + // set parsed_struct to parsed expression with preserved formatting + beginTemporaryStopMessages(); + ParseOptions po = eo.parse_options; + po.preserve_format = true; + parse(parsed_struct, str, po); + endTemporaryStopMessages(); + } + + // handle "where" expression + vector vars; + vector varms; + if(!str_where.empty()) { + + // parse "where" expression + MathStructure where_struct; + parse(&where_struct, str_where, eo.parse_options); + + current_stage = MESSAGE_STAGE_CALCULATION; + + // replace answer variables and functions in expression before performing any replacements from "where" epxression + calculate_ans(mstruct, eo); + + string str_test = str_where; + remove_blanks(str_test); + + // check if "where" expression includes function replacements + bool empty_func = str_test.find("()=") != string::npos; + + if(mstruct.isComparison() || (mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_SOLVE && mstruct.size() >= 1 && mstruct[0].isComparison())) { + beginTemporaryStopMessages(); + MathStructure mbak(mstruct); + if(handle_where_expression(where_struct, mstruct, eo, vars, varms, empty_func)) { + endTemporaryStopMessages(true); + } else { + endTemporaryStopMessages(); + mstruct = mbak; + // if where expression handling fails we can add the parsed "where" expression using logical and, + // if the original expression is an equation + if(mstruct.isComparison()) mstruct.transform(STRUCT_LOGICAL_AND, where_struct); + else {mstruct[0].transform(STRUCT_LOGICAL_AND, where_struct); mstruct.childUpdated(1);} + } + } else { + if(eo.approximation == APPROXIMATION_EXACT) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_TRY_EXACT; + handle_where_expression(where_struct, mstruct, eo2, vars, varms, empty_func); + } else { + handle_where_expression(where_struct, mstruct, eo, vars, varms, empty_func); + } + } + } + + current_stage = MESSAGE_STAGE_CALCULATION; + + // perform calculation + mstruct.eval(eo); + + current_stage = MESSAGE_STAGE_UNSET; + + if(!aborted()) { + // do unit conversion + bool b_units = mstruct.containsType(STRUCT_UNIT, true); + if(u) { + // convert to unit provided in to_struct + if(to_struct) to_struct->set(u); + if(b_units) { + current_stage = MESSAGE_STAGE_CONVERSION; + mstruct.set(convert(mstruct, u, eo, false, false)); + if(eo.mixed_units_conversion != MIXED_UNITS_CONVERSION_NONE) mstruct.set(convertToMixedUnits(mstruct, eo)); + } + } else if(!str2.empty()) { + // conversion using "to" expression + mstruct.set(convert(mstruct, str2, eo, to_struct)); + } else if(b_units) { + // do automatic conversion + current_stage = MESSAGE_STAGE_CONVERSION; + switch(eo.auto_post_conversion) { + case POST_CONVERSION_OPTIMAL: { + mstruct.set(convertToOptimalUnit(mstruct, eo, false)); + break; + } + case POST_CONVERSION_BASE: { + mstruct.set(convertToBaseUnits(mstruct, eo)); + break; + } + case POST_CONVERSION_OPTIMAL_SI: { + mstruct.set(convertToOptimalUnit(mstruct, eo, true)); + break; + } + default: {} + } + if(eo.mixed_units_conversion != MIXED_UNITS_CONVERSION_NONE) mstruct.set(convertToMixedUnits(mstruct, eo)); + } + } + + // clean up all new messages (removes "wide interval" warning if final value does not contains any wide interval) + cleanMessages(mstruct, n_messages + 1); + + current_stage = MESSAGE_STAGE_UNSET; + + // replace variables generated from "where" expression + for(size_t i = 0; i < vars.size(); i++) { + mstruct.replace(vars[i], varms[i]); + vars[i]->destroy(); + } + + return mstruct; + +} +MathStructure Calculator::calculate(const MathStructure &mstruct_to_calculate, const EvaluationOptions &eo, string to_str) { + + remove_blank_ends(to_str); + MathStructure mstruct(mstruct_to_calculate); + current_stage = MESSAGE_STAGE_CALCULATION; + size_t n_messages = messages.size(); + mstruct.eval(eo); + + current_stage = MESSAGE_STAGE_CONVERSION; + if(!to_str.empty()) { + mstruct.set(convert(mstruct, to_str, eo)); + } else { + switch(eo.auto_post_conversion) { + case POST_CONVERSION_OPTIMAL: { + mstruct.set(convertToOptimalUnit(mstruct, eo, false)); + break; + } + case POST_CONVERSION_BASE: { + mstruct.set(convertToBaseUnits(mstruct, eo)); + break; + } + case POST_CONVERSION_OPTIMAL_SI: { + mstruct.set(convertToOptimalUnit(mstruct, eo, true)); + break; + } + default: {} + } + if(eo.mixed_units_conversion != MIXED_UNITS_CONVERSION_NONE) mstruct.set(convertToMixedUnits(mstruct, eo)); + } + + cleanMessages(mstruct, n_messages + 1); + + current_stage = MESSAGE_STAGE_UNSET; + return mstruct; +} + +string Calculator::print(const MathStructure &mstruct, int msecs, const PrintOptions &po) { + startControl(msecs); + MathStructure mstruct2(mstruct); + mstruct2.format(po); + string print_result = mstruct2.print(po); + stopControl(); + return print_result; +} +string Calculator::printMathStructureTimeOut(const MathStructure &mstruct, int msecs, const PrintOptions &po) { + return print(mstruct, msecs, po); +} +int Calculator::testCondition(string expression) { + MathStructure mstruct = calculate(expression); + if(mstruct.isNumber()) { + if(mstruct.number().isPositive()) { + return 1; + } else { + return 0; + } + } + return -1; +} + +void Calculator::startPrintControl(int milli_timeout) { + startControl(milli_timeout); +} +void Calculator::abortPrint() { + abort(); +} +bool Calculator::printingAborted() { + return aborted(); +} +string Calculator::printingAbortedMessage() const { + return abortedMessage(); +} +string Calculator::timedOutString() const { + return _("timed out"); +} +bool Calculator::printingControlled() const { + return isControlled(); +} +void Calculator::stopPrintControl() { + stopControl(); +} + +void Calculator::startControl(int milli_timeout) { + b_controlled = true; + i_aborted = 0; + i_timeout = milli_timeout; + if(i_timeout > 0) { +#ifndef CLOCK_MONOTONIC + gettimeofday(&t_end, NULL); +#else + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + t_end.tv_sec = ts.tv_sec; + t_end.tv_usec = ts.tv_nsec / 1000; +#endif + long int usecs = t_end.tv_usec + (long int) milli_timeout * 1000; + t_end.tv_usec = usecs % 1000000; + t_end.tv_sec += usecs / 1000000; + } +} +bool Calculator::aborted() { + if(!b_controlled) return false; + if(i_aborted > 0) return true; + if(i_timeout > 0) { +#ifndef CLOCK_MONOTONIC + struct timeval tv; + gettimeofday(&tv, NULL); + if(tv.tv_sec > t_end.tv_sec || (tv.tv_sec == t_end.tv_sec && tv.tv_usec > t_end.tv_usec)) { +#else + struct timespec tv; + clock_gettime(CLOCK_MONOTONIC, &tv); + if(tv.tv_sec > t_end.tv_sec || (tv.tv_sec == t_end.tv_sec && tv.tv_nsec / 1000 > t_end.tv_usec)) { +#endif + i_aborted = 2; + return true; + } + } + return false; +} +string Calculator::abortedMessage() const { + if(i_aborted == 2) return _("timed out"); + return _("aborted"); +} +bool Calculator::isControlled() const { + return b_controlled; +} +void Calculator::stopControl() { + b_controlled = false; + i_aborted = 0; + i_timeout = 0; +} + diff -Nru libqalculate-3.6.0/libqalculate/Calculator.cc libqalculate-3.7.0/libqalculate/Calculator.cc --- libqalculate-3.6.0/libqalculate/Calculator.cc 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Calculator.cc 2020-01-21 22:54:40.000000000 +0000 @@ -25,87 +25,24 @@ #include "QalculateDateTime.h" #include -#include -#include #include #include #include -#include #include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_LIBCURL -# include -#endif #ifdef HAVE_ICU # include #endif -#if HAVE_UNORDERED_MAP -# include - using std::unordered_map; -#elif defined(__GNUC__) - -# ifndef __has_include -# define __has_include(x) 0 -# endif - -# if (defined(__clang__) && __has_include()) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 3) -# include - namespace Sgi = std; -# define unordered_map std::tr1::unordered_map -# else -# if __GNUC__ < 3 -# include - namespace Sgi { using ::hash_map; }; // inherit globals -# else -# include -# if __GNUC__ == 3 && __GNUC_MINOR__ == 0 - namespace Sgi = std; // GCC 3.0 -# else - namespace Sgi = ::__gnu_cxx; // GCC 3.1 and later -# endif -# endif -# define unordered_map Sgi::hash_map -# endif -#else // ... there are other compilers, right? - namespace Sgi = std; -# define unordered_map Sgi::hash_map -#endif +#include "MathStructure-support.h" using std::string; using std::cout; using std::vector; -using std::ostream; -using std::ofstream; using std::endl; -using std::ios; -using std::ifstream; using std::iterator; -using std::list; -using std::queue; -#define XML_GET_PREC_FROM_PROP(node, i) value = xmlGetProp(node, (xmlChar*) "precision"); if(value) {i = s2i((char*) value); xmlFree(value);} else {i = -1;} -#define XML_GET_APPROX_FROM_PROP(node, b) value = xmlGetProp(node, (xmlChar*) "approximate"); if(value) {b = !xmlStrcmp(value, (const xmlChar*) "true");} else {value = xmlGetProp(node, (xmlChar*) "precise"); if(value) {b = xmlStrcmp(value, (const xmlChar*) "true");} else {b = false;}} if(value) xmlFree(value); -#define XML_GET_FALSE_FROM_PROP(node, name, b) value = xmlGetProp(node, (xmlChar*) name); if(value && !xmlStrcmp(value, (const xmlChar*) "false")) {b = false;} else {b = true;} if(value) xmlFree(value); -#define XML_GET_TRUE_FROM_PROP(node, name, b) value = xmlGetProp(node, (xmlChar*) name); if(value && !xmlStrcmp(value, (const xmlChar*) "true")) {b = true;} else {b = false;} if(value) xmlFree(value); -#define XML_GET_BOOL_FROM_PROP(node, name, b) value = xmlGetProp(node, (xmlChar*) name); if(value && !xmlStrcmp(value, (const xmlChar*) "false")) {b = false;} else if(value && !xmlStrcmp(value, (const xmlChar*) "true")) {b = true;} if(value) xmlFree(value); -#define XML_GET_FALSE_FROM_TEXT(node, b) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if(value && !xmlStrcmp(value, (const xmlChar*) "false")) {b = false;} else {b = true;} if(value) xmlFree(value); -#define XML_GET_TRUE_FROM_TEXT(node, b) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if(value && !xmlStrcmp(value, (const xmlChar*) "true")) {b = true;} else {b = false;} if(value) xmlFree(value); -#define XML_GET_BOOL_FROM_TEXT(node, b) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if(value && !xmlStrcmp(value, (const xmlChar*) "false")) {b = false;} else if(value && !xmlStrcmp(value, (const xmlChar*) "true")) {b = true;} if(value) xmlFree(value); -#define XML_GET_STRING_FROM_PROP(node, name, str) value = xmlGetProp(node, (xmlChar*) name); if(value) {str = (char*) value; remove_blank_ends(str); xmlFree(value);} else str = ""; -#define XML_GET_STRING_FROM_TEXT(node, str) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if(value) {str = (char*) value; remove_blank_ends(str); xmlFree(value);} else str = ""; -#define XML_DO_FROM_PROP(node, name, action) value = xmlGetProp(node, (xmlChar*) name); if(value) action((char*) value); else action(""); if(value) xmlFree(value); -#define XML_DO_FROM_TEXT(node, action) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if(value) {action((char*) value); xmlFree(value);} else action(""); -#define XML_GET_INT_FROM_PROP(node, name, i) value = xmlGetProp(node, (xmlChar*) name); if(value) {i = s2i((char*) value); xmlFree(value);} -#define XML_GET_INT_FROM_TEXT(node, i) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if(value) {i = s2i((char*) value); xmlFree(value);} -#define XML_GET_LOCALE_STRING_FROM_TEXT(node, str, best, next_best) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); lang = xmlNodeGetLang(node); if(!best) {if(!lang) {if(!next_best) {if(value) {str = (char*) value; remove_blank_ends(str);} else str = ""; if(locale.empty()) {best = true;}}} else {if(locale == (char*) lang) {best = true; if(value) {str = (char*) value; remove_blank_ends(str);} else str = "";} else if(!next_best && strlen((char*) lang) >= 2 && fulfilled_translation == 0 && lang[0] == localebase[0] && lang[1] == localebase[1]) {next_best = true; if(value) {str = (char*) value; remove_blank_ends(str);} else str = "";} else if(!next_best && str.empty() && value) {str = (char*) value; remove_blank_ends(str);}}} if(value) xmlFree(value); if(lang) xmlFree(lang); -#define XML_GET_LOCALE_STRING_FROM_TEXT_REQ(node, str, best, next_best) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); lang = xmlNodeGetLang(node); if(!best) {if(!lang) {if(!next_best) {if(value) {str = (char*) value; remove_blank_ends(str);} else str = ""; if(locale.empty()) {best = true;}}} else {if(locale == (char*) lang) {best = true; if(value) {str = (char*) value; remove_blank_ends(str);} else str = "";} else if(!next_best && strlen((char*) lang) >= 2 && fulfilled_translation == 0 && lang[0] == localebase[0] && lang[1] == localebase[1]) {next_best = true; if(value) {str = (char*) value; remove_blank_ends(str);} else str = "";} else if(!next_best && str.empty() && value && !require_translation) {str = (char*) value; remove_blank_ends(str);}}} if(value) xmlFree(value); if(lang) xmlFree(lang); +#include "Calculator_p.h" PrintOptions::PrintOptions() : min_exp(EXP_PRECISION), base(BASE_DECIMAL), lower_case_numbers(false), lower_case_e(false), number_fraction_format(FRACTION_DECIMAL), indicate_infinite_series(false), show_ending_zeroes(true), abbreviate_names(true), use_reference_names(false), place_units_separately(true), use_unit_prefixes(true), use_prefixes_for_all_units(false), use_prefixes_for_currencies(false), use_all_prefixes(false), use_denominator_prefix(true), negative_exponents(false), short_multiplication(true), limit_implicit_multiplication(false), allow_non_usable(false), use_unicode_signs(false), multiplication_sign(MULTIPLICATION_SIGN_DOT), division_sign(DIVISION_SIGN_DIVISION_SLASH), spacious(true), excessive_parenthesis(false), halfexp_to_sqrt(true), min_decimals(0), max_decimals(-1), use_min_decimals(true), use_max_decimals(true), round_halfway_to_even(false), improve_division_multipliers(true), prefix(NULL), is_approximate(NULL), can_display_unicode_string_function(NULL), can_display_unicode_string_arg(NULL), hide_underscore_spaces(false), preserve_format(false), allow_factorization(false), spell_out_logical_operators(false), restrict_to_parent_precision(true), restrict_fraction_length(false), exp_to_root(false), preserve_precision(false), interval_display(INTERVAL_DISPLAY_INTERVAL), digit_grouping(DIGIT_GROUPING_NONE), date_time_format(DATE_TIME_FORMAT_ISO), time_zone(TIME_ZONE_LOCAL), custom_time_zone(0), twos_complement(true), hexadecimal_twos_complement(false), binary_bits(0) {} @@ -131,29 +68,6 @@ typedef void (*CREATEPLUG_PROC)(); -PlotParameters::PlotParameters() { - auto_y_min = true; - auto_x_min = true; - auto_y_max = true; - auto_x_max = true; - y_log = false; - x_log = false; - y_log_base = 10; - x_log_base = 10; - grid = false; - color = true; - linewidth = -1; - show_all_borders = false; - legend_placement = PLOT_LEGEND_TOP_RIGHT; -} -PlotDataParameters::PlotDataParameters() { - yaxis2 = false; - xaxis2 = false; - style = PLOT_STYLE_LINES; - smoothing = PLOT_SMOOTHING_NONE; - test_continuous = false; -} - CalculatorMessage::CalculatorMessage(string message_, MessageType type_, int cat_, int stage_) { mtype = type_; i_stage = stage_; @@ -222,144 +136,6 @@ extern UCaseMap *ucm; #endif - -enum { - PROC_RPN_ADD, - PROC_RPN_SET, - PROC_RPN_OPERATION_1, - PROC_RPN_OPERATION_2, - PROC_RPN_OPERATION_F, - PROC_NO_COMMAND -}; - -class CalculateThread : public Thread { - protected: - virtual void run(); -}; - - - -void autoConvert(const MathStructure &morig, MathStructure &mconv, const EvaluationOptions &eo) { - if(!morig.containsType(STRUCT_UNIT, true)) { - if(&mconv != &morig) mconv.set(morig); - return; - } - switch(eo.auto_post_conversion) { - case POST_CONVERSION_OPTIMAL: { - mconv.set(CALCULATOR->convertToOptimalUnit(morig, eo, false)); - break; - } - case POST_CONVERSION_BASE: { - mconv.set(CALCULATOR->convertToBaseUnits(morig, eo)); - break; - } - case POST_CONVERSION_OPTIMAL_SI: { - mconv.set(CALCULATOR->convertToOptimalUnit(morig, eo, true)); - break; - } - default: { - if(&mconv != &morig) mconv.set(morig); - } - } - if(eo.mixed_units_conversion != MIXED_UNITS_CONVERSION_NONE) mconv.set(CALCULATOR->convertToMixedUnits(mconv, eo)); -} - -void CalculateThread::run() { - enableAsynchronousCancel(); - while(true) { - bool b_parse = true; - if(!read(&b_parse)) break; - void *x = NULL; - if(!read(&x) || !x) break; - MathStructure *mstruct = (MathStructure*) x; - CALCULATOR->startControl(); - if(b_parse) { - mstruct->setAborted(); - if(CALCULATOR->tmp_parsedstruct) CALCULATOR->tmp_parsedstruct->setAborted(); - //if(CALCULATOR->tmp_tostruct) CALCULATOR->tmp_tostruct->setUndefined(); - mstruct->set(CALCULATOR->calculate(CALCULATOR->expression_to_calculate, CALCULATOR->tmp_evaluationoptions, CALCULATOR->tmp_parsedstruct, CALCULATOR->tmp_tostruct, CALCULATOR->tmp_maketodivision)); - } else { - MathStructure meval(*mstruct); - mstruct->setAborted(); - mstruct->set(CALCULATOR->calculate(meval, CALCULATOR->tmp_evaluationoptions)); - } - switch(CALCULATOR->tmp_proc_command) { - case PROC_RPN_ADD: { - CALCULATOR->RPNStackEnter(mstruct, false); - break; - } - case PROC_RPN_SET: { - CALCULATOR->setRPNRegister(CALCULATOR->tmp_rpnindex, mstruct, false); - break; - } - case PROC_RPN_OPERATION_1: { - if(CALCULATOR->RPNStackSize() > 0) { - CALCULATOR->setRPNRegister(1, mstruct, false); - } else { - CALCULATOR->RPNStackEnter(mstruct, false); - } - break; - } - case PROC_RPN_OPERATION_2: { - if(CALCULATOR->RPNStackSize() > 1) { - CALCULATOR->deleteRPNRegister(1); - } - if(CALCULATOR->RPNStackSize() > 0) { - CALCULATOR->setRPNRegister(1, mstruct, false); - } else { - CALCULATOR->RPNStackEnter(mstruct, false); - } - break; - } - case PROC_RPN_OPERATION_F: { - for(size_t i = 0; (CALCULATOR->tmp_proc_registers < 0 || (int) i < CALCULATOR->tmp_proc_registers - 1) && CALCULATOR->RPNStackSize() > 1; i++) { - CALCULATOR->deleteRPNRegister(1); - } - if(CALCULATOR->RPNStackSize() > 0 && CALCULATOR->tmp_proc_registers != 0) { - CALCULATOR->setRPNRegister(1, mstruct, false); - } else { - CALCULATOR->RPNStackEnter(mstruct, false); - } - break; - } - case PROC_NO_COMMAND: {} - } - CALCULATOR->stopControl(); - CALCULATOR->b_busy = false; - } -} - -class Calculator_p { - public: - unordered_map id_structs; - unordered_map ids_p; - vector freed_ids; - size_t ids_i; - Number custom_input_base, custom_output_base; - long int custom_input_base_i; - Unit *local_currency; - int use_binary_prefixes; - MathFunction *f_cis; -}; - -bool is_not_number(char c, int base) { - if(c >= '0' && c <= '9') return false; - if(base == -1) return false; - if(base == -12) return c != 'E' && c != 'X'; - if(base <= 10) return true; - if(base <= 36) { - if(c >= 'a' && c < 'a' + (base - 10)) return false; - if(c >= 'A' && c < 'A' + (base - 10)) return false; - return true; - } - if(base <= 62) { - if(c >= 'a' && c < 'a' + (base - 36)) return false; - if(c >= 'A' && c < 'Z') return false; - return true; - } - return false; -} - #define BITWISE_XOR "⊻" Calculator::Calculator() { @@ -404,11 +180,13 @@ srand(time(NULL)); exchange_rates_time[0] = 0; - exchange_rates_time[1] = 0; + exchange_rates_time[1] = (time_t) 438575L * (time_t) 3600; exchange_rates_time[2] = 0; + priv->exchange_rates_time2[0] = (time_t) 438575L * (time_t) 3600; exchange_rates_check_time[0] = 0; - exchange_rates_check_time[1] = 0; + exchange_rates_check_time[1] = (time_t) 438575L * (time_t) 3600; exchange_rates_check_time[2] = 0; + priv->exchange_rates_check_time2[0] = (time_t) 438575L * (time_t) 3600; b_exchange_rates_warning_enabled = true; b_exchange_rates_used = 0; @@ -630,11 +408,13 @@ srand(time(NULL)); exchange_rates_time[0] = 0; - exchange_rates_time[1] = 0; + exchange_rates_time[1] = (time_t) 438383L * (time_t) 3600; exchange_rates_time[2] = 0; + priv->exchange_rates_time2[0] = (time_t) 438383L * (time_t) 3600; exchange_rates_check_time[0] = 0; - exchange_rates_check_time[1] = 0; + exchange_rates_check_time[1] = (time_t) 438383L * (time_t) 3600; exchange_rates_check_time[2] = 0; + priv->exchange_rates_check_time2[0] = (time_t) 438383L * (time_t) 3600; b_exchange_rates_warning_enabled = true; b_exchange_rates_used = 0; @@ -1083,6 +863,8 @@ } return NULL; } +Prefix *Calculator::getDecimalNullPrefix() const {return decimal_null_prefix;} +Prefix *Calculator::getBinaryNullPrefix() const {return binary_null_prefix;} DecimalPrefix *Calculator::getExactDecimalPrefix(int exp10, int exp) const { for(size_t i = 0; i < decimal_prefixes.size(); i++) { if(decimal_prefixes[i]->exponent(exp) == exp10) { @@ -1623,86 +1405,6 @@ DOT_S = "."; } -size_t Calculator::addId(MathStructure *mstruct, bool persistent) { - size_t id = 0; - if(priv->freed_ids.size() > 0) { - id = priv->freed_ids.back(); - priv->freed_ids.pop_back(); - } else { - priv->ids_i++; - id = priv->ids_i; - } - priv->ids_p[id] = persistent; - priv->id_structs[id] = mstruct; - return id; -} -size_t Calculator::parseAddId(MathFunction *f, const string &str, const ParseOptions &po, bool persistent) { - size_t id = 0; - if(priv->freed_ids.size() > 0) { - id = priv->freed_ids.back(); - priv->freed_ids.pop_back(); - } else { - priv->ids_i++; - id = priv->ids_i; - } - priv->ids_p[id] = persistent; - priv->id_structs[id] = new MathStructure(); - f->parse(*priv->id_structs[id], str, po); - return id; -} -size_t Calculator::parseAddIdAppend(MathFunction *f, const MathStructure &append_mstruct, const string &str, const ParseOptions &po, bool persistent) { - size_t id = 0; - if(priv->freed_ids.size() > 0) { - id = priv->freed_ids.back(); - priv->freed_ids.pop_back(); - } else { - priv->ids_i++; - id = priv->ids_i; - } - priv->ids_p[id] = persistent; - priv->id_structs[id] = new MathStructure(); - f->parse(*priv->id_structs[id], str, po); - priv->id_structs[id]->addChild(append_mstruct); - return id; -} -size_t Calculator::parseAddVectorId(const string &str, const ParseOptions &po, bool persistent) { - size_t id = 0; - if(priv->freed_ids.size() > 0) { - id = priv->freed_ids.back(); - priv->freed_ids.pop_back(); - } else { - priv->ids_i++; - id = priv->ids_i; - } - priv->ids_p[id] = persistent; - priv->id_structs[id] = new MathStructure(); - f_vector->args(str, *priv->id_structs[id], po); - return id; -} -MathStructure *Calculator::getId(size_t id) { - if(priv->id_structs.find(id) != priv->id_structs.end()) { - if(priv->ids_p[id]) { - return new MathStructure(*priv->id_structs[id]); - } else { - MathStructure *mstruct = priv->id_structs[id]; - priv->freed_ids.push_back(id); - priv->id_structs.erase(id); - priv->ids_p.erase(id); - return mstruct; - } - } - return NULL; -} - -void Calculator::delId(size_t id) { - if(priv->ids_p.find(id) != priv->ids_p.end()) { - priv->freed_ids.push_back(id); - priv->id_structs[id]->unref(); - priv->id_structs.erase(id); - priv->ids_p.erase(id); - } -} - void Calculator::resetVariables() { variables.clear(); addBuiltinVariables(); @@ -1721,44 +1423,6 @@ resetUnits(); } -#ifdef __linux__ -# include -#endif - -#if defined __linux__ || defined _WIN32 -class UptimeVariable : public DynamicVariable { - private: - void calculate(MathStructure &m) const { - Number nr; -# ifdef __linux__ - std::ifstream proc_uptime("/proc/uptime", std::ios::in); - if(proc_uptime.is_open()) { - string s_uptime; - getline(proc_uptime, s_uptime, ' '); - nr.set(s_uptime); - } else { - struct sysinfo sf; - if(!sysinfo(&sf)) nr = (long int) sf.uptime; - } -# elif _WIN32 - ULONGLONG i_uptime = GetTickCount64(); - nr.set((long int) (i_uptime % 1000), 1000); - nr += (long int) (i_uptime / 1000); -# endif - m = nr; - Unit *u = CALCULATOR->getUnit("s"); - if(u) m *= u; - } - public: - UptimeVariable() : DynamicVariable("", "uptime") { - setApproximate(false); - always_recalculate = true; - } - UptimeVariable(const UptimeVariable *variable) {set(variable);} - ExpressionItem *copy() const {return new UptimeVariable(this);} -}; -#endif - void Calculator::addBuiltinVariables() { v_e = (KnownVariable*) addVariable(new EVariable()); @@ -1817,7 +1481,7 @@ f_elements = addFunction(new ElementsFunction()); f_element = addFunction(new ElementFunction()); f_transpose = addFunction(new TransposeFunction()); - f_identity = addFunction(new IdentityFunction()); + f_identity = addFunction(new IdentityMatrixFunction()); f_determinant = addFunction(new DeterminantFunction()); f_permanent = addFunction(new PermanentFunction()); f_adjoint = addFunction(new AdjointFunction()); @@ -1854,6 +1518,7 @@ f_frac = addFunction(new FracFunction()); f_rem = addFunction(new RemFunction()); f_mod = addFunction(new ModFunction()); + addFunction(new BernoulliFunction()); f_polynomial_unit = addFunction(new PolynomialUnitFunction()); f_polynomial_primpart = addFunction(new PolynomialPrimpartFunction()); @@ -1910,6 +1575,7 @@ f_besselj = addFunction(new BesseljFunction()); f_bessely = addFunction(new BesselyFunction()); f_erf = addFunction(new ErfFunction()); + priv->f_erfi = addFunction(new ErfiFunction()); f_erfc = addFunction(new ErfcFunction()); f_total = addFunction(new TotalFunction()); @@ -2005,6 +1671,8 @@ f_Ci = addFunction(new CiFunction()); f_Shi = addFunction(new ShiFunction()); f_Chi = addFunction(new ChiFunction()); + priv->f_fresnels = addFunction(new FresnelSFunction()); + priv->f_fresnelc = addFunction(new FresnelCFunction()); f_igamma = addFunction(new IGammaFunction()); if(canPlot()) f_plot = addFunction(new PlotFunction()); @@ -2025,10 +1693,14 @@ } void Calculator::addBuiltinUnits() { u_euro = addUnit(new Unit(_("Currency"), "EUR", "euros", "euro", "European Euros", false, true, true)); - u_btc = addUnit(new AliasUnit(_("Currency"), "BTC", "bitcoins", "bitcoin", "Bitcoins", u_euro, "6512.84", 1, "", false, true, true)); + u_btc = addUnit(new AliasUnit(_("Currency"), "BTC", "bitcoins", "bitcoin", "Bitcoins", u_euro, "7266.59", 1, "", false, true, true)); u_btc->setApproximate(); u_btc->setPrecision(-2); u_btc->setChanged(false); + priv->u_byn = addUnit(new AliasUnit(_("Currency"), "BYN", "", "", "Belarusian Ruble", u_euro, "2.23532", 1, "", false, true, true)); + priv->u_byn->setApproximate(); + priv->u_byn->setPrecision(-2); + priv->u_byn->setChanged(false); u_second = NULL; u_minute = NULL; u_hour = NULL; @@ -2192,60 +1864,6 @@ } deleteUnitName(name_, object); } -void Calculator::saveState() { -} -void Calculator::restoreState() { -} -void Calculator::clearBuffers() { - for(unordered_map::iterator it = priv->ids_p.begin(); it != priv->ids_p.end(); ++it) { - if(!it->second) { - priv->freed_ids.push_back(it->first); - priv->id_structs.erase(it->first); - priv->ids_p.erase(it); - } - } -} -bool Calculator::abort() { - i_aborted = 1; - if(!b_busy) return true; - if(!calculate_thread->running) { - b_busy = false; - } else { - int msecs = 5000; - while(b_busy && msecs > 0) { - sleep_ms(10); - msecs -= 10; - } - if(b_busy) { - calculate_thread->cancel(); - stopControl(); - stopped_messages_count.clear(); - stopped_warnings_count.clear(); - stopped_errors_count.clear(); - stopped_messages.clear(); - disable_errors_ref = 0; - if(tmp_rpn_mstruct) tmp_rpn_mstruct->unref(); - tmp_rpn_mstruct = NULL; - error(true, _("The calculation has been forcibly terminated. Please restart the application and report this as a bug."), NULL); - b_busy = false; - calculate_thread->start(); - return false; - } - } - return true; -} -bool Calculator::busy() { - return b_busy; -} -void Calculator::terminateThreads() { - if(calculate_thread->running) { - if(!calculate_thread->write(false) || !calculate_thread->write(NULL)) calculate_thread->cancel(); - for(size_t i = 0; i < 10 && calculate_thread->running; i++) { - sleep_ms(1); - } - if(calculate_thread->running) calculate_thread->cancel(); - } -} string Calculator::localizeExpression(string str, const ParseOptions &po) const { if((DOT_STR == DOT && COMMA_STR == COMMA && !po.comma_as_separator) || po.base == BASE_UNICODE || (po.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) return str; @@ -2450,10326 +2068,814 @@ return str; } -bool Calculator::calculateRPNRegister(size_t index, int msecs, const EvaluationOptions &eo) { - if(index <= 0 || index > rpn_stack.size()) return false; - return calculateRPN(new MathStructure(*rpn_stack[rpn_stack.size() - index]), PROC_RPN_SET, index, msecs, eo); -} - -bool Calculator::calculateRPN(MathStructure *mstruct, int command, size_t index, int msecs, const EvaluationOptions &eo, int function_arguments) { - b_busy = true; - if(!calculate_thread->running && !calculate_thread->start()) {mstruct->setAborted(); return false;} - bool had_msecs = msecs > 0; - tmp_evaluationoptions = eo; - tmp_proc_command = command; - tmp_rpnindex = index; - tmp_rpn_mstruct = mstruct; - tmp_proc_registers = function_arguments; - if(!calculate_thread->write(false)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} - if(!calculate_thread->write((void*) mstruct)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} - while(msecs > 0 && b_busy) { - sleep_ms(10); - msecs -= 10; - } - if(had_msecs && b_busy) { - abort(); - return false; +Unit* Calculator::addUnit(Unit *u, bool force, bool check_names) { + if(check_names) { + for(size_t i = 1; i <= u->countNames(); i++) { + u->setName(getName(u->getName(i).name, u, force), i); + } } - return true; -} -bool Calculator::calculateRPN(string str, int command, size_t index, int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct, MathStructure *to_struct, bool make_to_division, int function_arguments) { - MathStructure *mstruct = new MathStructure(); - b_busy = true; - if(!calculate_thread->running && !calculate_thread->start()) {mstruct->setAborted(); return false;} - bool had_msecs = msecs > 0; - expression_to_calculate = str; - tmp_evaluationoptions = eo; - tmp_proc_command = command; - tmp_rpnindex = index; - tmp_rpn_mstruct = mstruct; - tmp_parsedstruct = parsed_struct; - tmp_tostruct = to_struct; - tmp_maketodivision = make_to_division; - tmp_proc_registers = function_arguments; - if(!calculate_thread->write(true)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} - if(!calculate_thread->write((void*) mstruct)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} - while(msecs > 0 && b_busy) { - sleep_ms(10); - msecs -= 10; + if(!u->isLocal() && units.size() > 0 && units[units.size() - 1]->isLocal()) { + units.insert(units.begin(), u); + } else { + units.push_back(u); } - if(had_msecs && b_busy) { - abort(); - return false; + unitNameChanged(u, true); + for(vector::iterator it = deleted_units.begin(); it != deleted_units.end(); ++it) { + if(*it == u) { + deleted_units.erase(it); + break; + } } - return true; + u->setRegistered(true); + u->setChanged(false); + if(u->id() != 0) priv->id_units[u->id()] = u; + return u; } - -bool Calculator::calculateRPN(MathOperation op, int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct) { - MathStructure *mstruct; - if(rpn_stack.size() == 0) { - mstruct = new MathStructure(); - mstruct->add(m_zero, op); - if(parsed_struct) parsed_struct->clear(); - } else if(rpn_stack.size() == 1) { - if(parsed_struct) { - parsed_struct->set(*rpn_stack.back()); - if(op == OPERATION_SUBTRACT) { - parsed_struct->transform(STRUCT_NEGATE); - } else if(op == OPERATION_DIVIDE) { - parsed_struct->transform(STRUCT_INVERSE); - } else { - parsed_struct->add(*rpn_stack.back(), op); - } - } - if(op == OPERATION_SUBTRACT) { - mstruct = new MathStructure(); - } else if(op == OPERATION_DIVIDE) { - mstruct = new MathStructure(1, 1, 0); - } else { - mstruct = new MathStructure(*rpn_stack.back()); +void Calculator::delPrefixUFV(Prefix *object) { + int i = 0; + for(vector::iterator it = ufvl.begin(); ; ++it) { + del_ufvl: + if(it == ufvl.end()) { + break; } - mstruct->add(*rpn_stack.back(), op); - } else { - if(parsed_struct) { - parsed_struct->set(*rpn_stack[rpn_stack.size() - 2]); - if(op == OPERATION_SUBTRACT) { - parsed_struct->transform(STRUCT_ADDITION, *rpn_stack.back()); - (*parsed_struct)[1].transform(STRUCT_NEGATE); - } else if(op == OPERATION_DIVIDE) { - parsed_struct->transform(STRUCT_DIVISION, *rpn_stack.back()); - } else { - parsed_struct->add(*rpn_stack.back(), op); - } + if(*it == object) { + it = ufvl.erase(it); + ufvl_t.erase(ufvl_t.begin() + i); + ufvl_i.erase(ufvl_i.begin() + i); + if(it == ufvl.end()) break; + goto del_ufvl; } - mstruct = new MathStructure(*rpn_stack[rpn_stack.size() - 2]); - mstruct->add(*rpn_stack.back(), op); + i++; } - return calculateRPN(mstruct, PROC_RPN_OPERATION_2, 0, msecs, eo); -} -bool Calculator::calculateRPN(MathFunction *f, int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct) { - MathStructure *mstruct = new MathStructure(f, NULL); - int iregs = 0; - if(f->args() != 0) { - size_t i = f->minargs(); - bool fill_vector = (i > 0 && f->getArgumentDefinition(i) && f->getArgumentDefinition(i)->type() == ARGUMENT_TYPE_VECTOR); - if(fill_vector && rpn_stack.size() < i) fill_vector = false; - if(fill_vector && rpn_stack.size() > 0 && rpn_stack.back()->isVector()) fill_vector = false; - if(fill_vector) { - i = rpn_stack.size(); - } else if(i < 1) { - i = 1; - } - for(; i > 0; i--) { - if(i > rpn_stack.size()) { - error(false, _("Stack is empty. Filling remaining function arguments with zeroes."), NULL); - mstruct->addChild(m_zero); - } else { - if(fill_vector && rpn_stack.size() - i == (size_t) f->minargs() - 1) mstruct->addChild(m_empty_vector); - if(fill_vector && rpn_stack.size() - i >= (size_t) f->minargs() - 1) mstruct->getChild(f->minargs())->addChild(*rpn_stack[rpn_stack.size() - i]); - else mstruct->addChild(*rpn_stack[rpn_stack.size() - i]); - iregs++; - } - if(!fill_vector && f->getArgumentDefinition(i) && f->getArgumentDefinition(i)->type() == ARGUMENT_TYPE_ANGLE) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - (*mstruct)[i - 1].multiply(getDegUnit()); - break; - } - case ANGLE_UNIT_GRADIANS: { - (*mstruct)[i - 1].multiply(getGraUnit()); - break; - } - case ANGLE_UNIT_RADIANS: { - (*mstruct)[i - 1].multiply(getRadUnit()); - break; - } - default: {} - } + for(size_t i2 = 0; i2 < UFV_LENGTHS; i2++) { + i = 0; + for(vector::iterator it = ufv[0][i2].begin(); ; ++it) { + del_ufv: + if(it == ufv[0][i2].end()) { + break; + } + if(*it == object) { + it = ufv[0][i2].erase(it); + ufv_i[0][i2].erase(ufv_i[0][i2].begin() + i); + if(it == ufv[0][i2].end()) break; + goto del_ufv; } + i++; } - if(fill_vector) mstruct->childrenUpdated(); - f->appendDefaultValues(*mstruct); - } - if(parsed_struct) parsed_struct->set(*mstruct); - return calculateRPN(mstruct, PROC_RPN_OPERATION_F, 0, msecs, eo, iregs); -} -bool Calculator::calculateRPNBitwiseNot(int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct) { - MathStructure *mstruct; - if(rpn_stack.size() == 0) { - mstruct = new MathStructure(); - mstruct->setBitwiseNot(); - } else { - mstruct = new MathStructure(*rpn_stack.back()); - mstruct->setBitwiseNot(); } - if(parsed_struct) parsed_struct->set(*mstruct); - return calculateRPN(mstruct, PROC_RPN_OPERATION_1, 0, msecs, eo); } -bool Calculator::calculateRPNLogicalNot(int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct) { - MathStructure *mstruct; - if(rpn_stack.size() == 0) { - mstruct = new MathStructure(); - mstruct->setLogicalNot(); - } else { - mstruct = new MathStructure(*rpn_stack.back()); - mstruct->setLogicalNot(); - } - if(parsed_struct) parsed_struct->set(*rpn_stack.back()); - return calculateRPN(mstruct, PROC_RPN_OPERATION_1, 0, msecs, eo); -} -MathStructure *Calculator::calculateRPN(MathOperation op, const EvaluationOptions &eo, MathStructure *parsed_struct) { - current_stage = MESSAGE_STAGE_PARSING; - MathStructure *mstruct; - if(rpn_stack.size() == 0) { - mstruct = new MathStructure(); - mstruct->add(m_zero, op); - if(parsed_struct) parsed_struct->clear(); - } else if(rpn_stack.size() == 1) { - if(parsed_struct) { - parsed_struct->clear(); - if(op == OPERATION_SUBTRACT) { - parsed_struct->transform(STRUCT_ADDITION, *rpn_stack.back()); - (*parsed_struct)[1].transform(STRUCT_NEGATE); - } else if(op == OPERATION_DIVIDE) { - parsed_struct->transform(STRUCT_DIVISION, *rpn_stack.back()); - } else { - parsed_struct->add(*rpn_stack.back(), op); - } +void Calculator::delUFV(ExpressionItem *object) { + int i = 0; + for(vector::iterator it = ufvl.begin(); ; ++it) { + del_ufvl: + if(it == ufvl.end()) { + break; } - mstruct = new MathStructure(); - mstruct->add(*rpn_stack.back(), op); - } else { - if(parsed_struct) { - parsed_struct->set(*rpn_stack[rpn_stack.size() - 2]); - if(op == OPERATION_SUBTRACT) { - parsed_struct->transform(STRUCT_ADDITION, *rpn_stack.back()); - (*parsed_struct)[1].transform(STRUCT_NEGATE); - } else if(op == OPERATION_DIVIDE) { - parsed_struct->transform(STRUCT_DIVISION, *rpn_stack.back()); - } else { - parsed_struct->add(*rpn_stack.back(), op); - } + if(*it == object) { + it = ufvl.erase(it); + ufvl_t.erase(ufvl_t.begin() + i); + ufvl_i.erase(ufvl_i.begin() + i); + if(it == ufvl.end()) break; + goto del_ufvl; } - mstruct = new MathStructure(*rpn_stack[rpn_stack.size() - 2]); - mstruct->add(*rpn_stack.back(), op); + i++; } - current_stage = MESSAGE_STAGE_CALCULATION; - mstruct->eval(eo); - current_stage = MESSAGE_STAGE_CONVERSION; - autoConvert(*mstruct, *mstruct, eo); - current_stage = MESSAGE_STAGE_UNSET; - if(rpn_stack.size() > 1) { - rpn_stack.back()->unref(); - rpn_stack.erase(rpn_stack.begin() + (rpn_stack.size() - 1)); - } - if(rpn_stack.size() > 0) { - rpn_stack.back()->unref(); - rpn_stack.back() = mstruct; - } else { - rpn_stack.push_back(mstruct); + int i3 = 0; + switch(object->type()) { + case TYPE_FUNCTION: {i3 = 1; break;} + case TYPE_UNIT: {i3 = 2; break;} + case TYPE_VARIABLE: {i3 = 3; break;} } - return rpn_stack.back(); -} -MathStructure *Calculator::calculateRPN(MathFunction *f, const EvaluationOptions &eo, MathStructure *parsed_struct) { - current_stage = MESSAGE_STAGE_PARSING; - MathStructure *mstruct = new MathStructure(f, NULL); - size_t iregs = 0; - if(f->args() != 0) { - size_t i = f->minargs(); - bool fill_vector = (i > 0 && f->getArgumentDefinition(i) && f->getArgumentDefinition(i)->type() == ARGUMENT_TYPE_VECTOR); - if(fill_vector && rpn_stack.size() < i) fill_vector = false; - if(fill_vector && rpn_stack.size() > 0 && rpn_stack.back()->isVector()) fill_vector = false; - if(fill_vector) { - i = rpn_stack.size(); - } else if(i < 1) { - i = 1; - } - for(; i > 0; i--) { - if(i > rpn_stack.size()) { - error(false, _("Stack is empty. Filling remaining function arguments with zeroes."), NULL); - mstruct->addChild(m_zero); - } else { - if(fill_vector && rpn_stack.size() - i == (size_t) f->minargs() - 1) mstruct->addChild(m_empty_vector); - if(fill_vector && rpn_stack.size() - i >= (size_t) f->minargs() - 1) mstruct->getChild(f->minargs())->addChild(*rpn_stack[rpn_stack.size() - i]); - else mstruct->addChild(*rpn_stack[rpn_stack.size() - i]); - iregs++; - } - if(!fill_vector && f->getArgumentDefinition(i) && f->getArgumentDefinition(i)->type() == ARGUMENT_TYPE_ANGLE) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - (*mstruct)[i - 1].multiply(getDegUnit()); - break; - } - case ANGLE_UNIT_GRADIANS: { - (*mstruct)[i - 1].multiply(getGraUnit()); - break; - } - case ANGLE_UNIT_RADIANS: { - (*mstruct)[i - 1].multiply(getRadUnit()); - break; - } - default: {} - } + for(size_t i2 = 0; i2 < UFV_LENGTHS; i2++) { + i = 0; + for(vector::iterator it = ufv[i3][i2].begin(); ; ++it) { + del_ufv: + if(it == ufv[i3][i2].end()) { + break; + } + if(*it == object) { + it = ufv[i3][i2].erase(it); + ufv_i[i3][i2].erase(ufv_i[i3][i2].begin() + i); + if(it == ufv[i3][i2].end()) break; + goto del_ufv; } + i++; } - if(fill_vector) mstruct->childrenUpdated(); - f->appendDefaultValues(*mstruct); - } - if(parsed_struct) parsed_struct->set(*mstruct); - current_stage = MESSAGE_STAGE_CALCULATION; - mstruct->eval(eo); - current_stage = MESSAGE_STAGE_CONVERSION; - autoConvert(*mstruct, *mstruct, eo); - current_stage = MESSAGE_STAGE_UNSET; - if(iregs == 0) { - rpn_stack.push_back(mstruct); - } else { - for(size_t i = 0; i < iregs - 1 && rpn_stack.size() > 1; i++) { - rpn_stack.back()->unref(); - rpn_stack.pop_back(); - deleteRPNRegister(1); - } - rpn_stack.back()->unref(); - rpn_stack.back() = mstruct; - } - return rpn_stack.back(); -} -MathStructure *Calculator::calculateRPNBitwiseNot(const EvaluationOptions &eo, MathStructure *parsed_struct) { - current_stage = MESSAGE_STAGE_PARSING; - MathStructure *mstruct; - if(rpn_stack.size() == 0) { - mstruct = new MathStructure(); - mstruct->setBitwiseNot(); - } else { - mstruct = new MathStructure(*rpn_stack.back()); - mstruct->setBitwiseNot(); - } - if(parsed_struct) parsed_struct->set(*mstruct); - current_stage = MESSAGE_STAGE_CALCULATION; - mstruct->eval(eo); - current_stage = MESSAGE_STAGE_CONVERSION; - autoConvert(*mstruct, *mstruct, eo); - current_stage = MESSAGE_STAGE_UNSET; - if(rpn_stack.size() == 0) { - rpn_stack.push_back(mstruct); - } else { - rpn_stack.back()->unref(); - rpn_stack.back() = mstruct; } - return rpn_stack.back(); } -MathStructure *Calculator::calculateRPNLogicalNot(const EvaluationOptions &eo, MathStructure *parsed_struct) { - current_stage = MESSAGE_STAGE_PARSING; - MathStructure *mstruct; - if(rpn_stack.size() == 0) { - mstruct = new MathStructure(); - mstruct->setLogicalNot(); - } else { - mstruct = new MathStructure(*rpn_stack.back()); - mstruct->setLogicalNot(); - } - if(parsed_struct) parsed_struct->set(*mstruct); - current_stage = MESSAGE_STAGE_CALCULATION; - mstruct->eval(eo); - current_stage = MESSAGE_STAGE_CONVERSION; - autoConvert(*mstruct, *mstruct, eo); - current_stage = MESSAGE_STAGE_UNSET; - if(rpn_stack.size() == 0) { - rpn_stack.push_back(mstruct); - } else { - rpn_stack.back()->unref(); - rpn_stack.back() = mstruct; +Unit* Calculator::getUnit(string name_) { + if(name_.empty()) return NULL; + for(size_t i = 0; i < units.size(); i++) { + if(units[i]->subtype() != SUBTYPE_COMPOSITE_UNIT && (units[i]->hasName(name_))) { + return units[i]; + } } - return rpn_stack.back(); -} -bool Calculator::RPNStackEnter(MathStructure *mstruct, int msecs, const EvaluationOptions &eo) { - return calculateRPN(mstruct, PROC_RPN_ADD, 0, msecs, eo); + return NULL; } -bool Calculator::RPNStackEnter(string str, int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct, MathStructure *to_struct, bool make_to_division) { - remove_blank_ends(str); - if(str.empty() && rpn_stack.size() > 0) { - rpn_stack.push_back(new MathStructure(*rpn_stack.back())); - return true; - } - return calculateRPN(str, PROC_RPN_ADD, 0, msecs, eo, parsed_struct, to_struct, make_to_division); +Unit* Calculator::getUnitById(int id) const { + switch(id) { + case UNIT_ID_EURO: {return u_euro;} + case UNIT_ID_BYN: {return priv->u_byn;} + case UNIT_ID_BTC: {return u_btc;} + case UNIT_ID_SECOND: {return u_second;} + case UNIT_ID_MINUTE: {return u_minute;} + case UNIT_ID_HOUR: {return u_hour;} + case UNIT_ID_DAY: {return u_day;} + case UNIT_ID_MONTH: {return u_month;} + case UNIT_ID_YEAR: {return u_year;} + } + unordered_map::iterator it = priv->id_units.find(id); + if(it == priv->id_units.end()) return NULL; + return it->second; } -void Calculator::RPNStackEnter(MathStructure *mstruct, bool eval, const EvaluationOptions &eo) { - if(eval) { - current_stage = MESSAGE_STAGE_CALCULATION; - mstruct->eval(eo); - current_stage = MESSAGE_STAGE_CONVERSION; - autoConvert(*mstruct, *mstruct, eo); - current_stage = MESSAGE_STAGE_UNSET; - } - rpn_stack.push_back(mstruct); -} -void Calculator::RPNStackEnter(string str, const EvaluationOptions &eo, MathStructure *parsed_struct, MathStructure *to_struct, bool make_to_division) { - remove_blank_ends(str); - if(str.empty() && rpn_stack.size() > 0) rpn_stack.push_back(new MathStructure(*rpn_stack.back())); - else rpn_stack.push_back(new MathStructure(calculate(str, eo, parsed_struct, to_struct, make_to_division))); -} -bool Calculator::setRPNRegister(size_t index, MathStructure *mstruct, int msecs, const EvaluationOptions &eo) { - if(mstruct == NULL) { - deleteRPNRegister(index); - return true; +Unit* Calculator::getActiveUnit(string name_) { + if(name_.empty()) return NULL; + for(size_t i = 0; i < units.size(); i++) { + if(units[i]->isActive() && units[i]->subtype() != SUBTYPE_COMPOSITE_UNIT && units[i]->hasName(name_)) { + return units[i]; + } } - if(index <= 0 || index > rpn_stack.size()) return false; - return calculateRPN(mstruct, PROC_RPN_SET, index, msecs, eo); + return NULL; } -bool Calculator::setRPNRegister(size_t index, string str, int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct, MathStructure *to_struct, bool make_to_division) { - if(index <= 0 || index > rpn_stack.size()) return false; - return calculateRPN(str, PROC_RPN_SET, index, msecs, eo, parsed_struct, to_struct, make_to_division); -} -void Calculator::setRPNRegister(size_t index, MathStructure *mstruct, bool eval, const EvaluationOptions &eo) { - if(mstruct == NULL) { - deleteRPNRegister(index); - return; - } - if(eval) { - current_stage = MESSAGE_STAGE_CALCULATION; - mstruct->eval(eo); - current_stage = MESSAGE_STAGE_CONVERSION; - autoConvert(*mstruct, *mstruct, eo); - current_stage = MESSAGE_STAGE_UNSET; - } - if(index <= 0 || index > rpn_stack.size()) return; - index = rpn_stack.size() - index; - rpn_stack[index]->unref(); - rpn_stack[index] = mstruct; -} -void Calculator::setRPNRegister(size_t index, string str, const EvaluationOptions &eo, MathStructure *parsed_struct, MathStructure *to_struct, bool make_to_division) { - if(index <= 0 || index > rpn_stack.size()) return; - index = rpn_stack.size() - index; - MathStructure *mstruct = new MathStructure(calculate(str, eo, parsed_struct, to_struct, make_to_division)); - rpn_stack[index]->unref(); - rpn_stack[index] = mstruct; -} -void Calculator::deleteRPNRegister(size_t index) { - if(index <= 0 || index > rpn_stack.size()) return; - index = rpn_stack.size() - index; - rpn_stack[index]->unref(); - rpn_stack.erase(rpn_stack.begin() + index); -} -MathStructure *Calculator::getRPNRegister(size_t index) const { - if(index > 0 && index <= rpn_stack.size()) { - index = rpn_stack.size() - index; - return rpn_stack[index]; +Unit* Calculator::getLocalCurrency() { + if(priv->local_currency) return priv->local_currency; + struct lconv *lc = localeconv(); + if(lc) { + string local_currency = lc->int_curr_symbol; + remove_blank_ends(local_currency); + if(!local_currency.empty()) { + if(local_currency.length() > 3) local_currency = local_currency.substr(0, 3); + return getActiveUnit(local_currency); + } } return NULL; } -size_t Calculator::RPNStackSize() const { - return rpn_stack.size(); -} -void Calculator::clearRPNStack() { - for(size_t i = 0; i < rpn_stack.size(); i++) { - rpn_stack[i]->unref(); - } - rpn_stack.clear(); -} -void Calculator::moveRPNRegister(size_t old_index, size_t new_index) { - if(old_index == new_index) return; - if(old_index > 0 && old_index <= rpn_stack.size()) { - old_index = rpn_stack.size() - old_index; - MathStructure *mstruct = rpn_stack[old_index]; - if(new_index > rpn_stack.size()) { - new_index = 0; - } else if(new_index <= 1) { - rpn_stack.push_back(mstruct); - rpn_stack.erase(rpn_stack.begin() + old_index); - return; - } else { - new_index = rpn_stack.size() - new_index; - } - if(new_index > old_index) { - rpn_stack.erase(rpn_stack.begin() + old_index); - rpn_stack.insert(rpn_stack.begin() + new_index, mstruct); - } else if(new_index < old_index) { - rpn_stack.insert(rpn_stack.begin() + new_index, mstruct); - rpn_stack.erase(rpn_stack.begin() + (old_index + 1)); - } - } -} -void Calculator::moveRPNRegisterUp(size_t index) { - if(index > 1 && index <= rpn_stack.size()) { - index = rpn_stack.size() - index; - MathStructure *mstruct = rpn_stack[index]; - rpn_stack.erase(rpn_stack.begin() + index); - index++; - if(index == rpn_stack.size()) rpn_stack.push_back(mstruct); - else rpn_stack.insert(rpn_stack.begin() + index, mstruct); - } -} -void Calculator::moveRPNRegisterDown(size_t index) { - if(index > 0 && index < rpn_stack.size()) { - index = rpn_stack.size() - index; - MathStructure *mstruct = rpn_stack[index]; - rpn_stack.erase(rpn_stack.begin() + index); - index--; - rpn_stack.insert(rpn_stack.begin() + index, mstruct); - } +void Calculator::setLocalCurrency(Unit *u) { + priv->local_currency = u; } - -int has_information_unit(const MathStructure &m, bool top = true) { - if(m.isUnit_exp()) { - if(m.isUnit()) { - if(m.unit()->baseUnit()->referenceName() == "bit") return 1; - } else { - if(m[0].unit()->baseUnit()->referenceName() == "bit") { - if(m[1].isInteger() && m[1].number().isPositive()) return 1; - return 2; - } - } - return 0; - } - for(size_t i = 0; i < m.size(); i++) { - int ret = has_information_unit(m[i], false); - if(ret > 0) { - if(ret == 1 && top && m.isMultiplication() && m[0].isNumber() && m[0].number().isFraction()) return 2; - return ret; +Unit* Calculator::getCompositeUnit(string internal_name_) { + if(internal_name_.empty()) return NULL; + for(size_t i = 0; i < units.size(); i++) { + if(units[i]->subtype() == SUBTYPE_COMPOSITE_UNIT && units[i]->hasName(internal_name_)) { + return units[i]; } } - return 0; + return NULL; } -#define EQUALS_IGNORECASE_AND_LOCAL(x,y,z) (equalsIgnoreCase(x, y) || equalsIgnoreCase(x, z)) -string Calculator::calculateAndPrint(string str, int msecs, const EvaluationOptions &eo, const PrintOptions &po) { - if(msecs > 0) startControl(msecs); - PrintOptions printops = po; - EvaluationOptions evalops = eo; - MathStructure mstruct; - bool do_bases = false, do_factors = false, do_fraction = false, do_pfe = false, do_calendars = false, do_expand = false, do_binary_prefixes = false, complex_angle_form = false; - string from_str = str, to_str; - Number base_save; - if(printops.base == BASE_CUSTOM) base_save = customOutputBase(); - int save_bin = priv->use_binary_prefixes; - if(separateToExpression(from_str, to_str, evalops, true)) { - remove_duplicate_blanks(to_str); - string to_str1, to_str2; - size_t ispace = to_str.find_first_of(SPACES); - if(ispace != string::npos) { - to_str1 = to_str.substr(0, ispace); - remove_blank_ends(to_str1); - to_str2 = to_str.substr(ispace + 1); - remove_blank_ends(to_str2); - } - if(equalsIgnoreCase(to_str, "hex") || EQUALS_IGNORECASE_AND_LOCAL(to_str, "hexadecimal", _("hexadecimal"))) { - str = from_str; - printops.base = BASE_HEXADECIMAL; - } else if(equalsIgnoreCase(to_str, "bin") || EQUALS_IGNORECASE_AND_LOCAL(to_str, "binary", _("binary"))) { - str = from_str; - printops.base = BASE_BINARY; - } else if(equalsIgnoreCase(to_str, "dec") || EQUALS_IGNORECASE_AND_LOCAL(to_str, "decimal", _("decimal"))) { - str = from_str; - printops.base = BASE_DECIMAL; - } else if(equalsIgnoreCase(to_str, "oct") || EQUALS_IGNORECASE_AND_LOCAL(to_str, "octal", _("octal"))) { - str = from_str; - printops.base = BASE_OCTAL; - } else if(equalsIgnoreCase(to_str, "duo") || EQUALS_IGNORECASE_AND_LOCAL(to_str, "duodecimal", _("duodecimal"))) { - str = from_str; - printops.base = BASE_DUODECIMAL; - } else if(equalsIgnoreCase(to_str, "roman") || equalsIgnoreCase(to_str, _("roman"))) { - str = from_str; - printops.base = BASE_ROMAN_NUMERALS; - } else if(equalsIgnoreCase(to_str, "bijective") || equalsIgnoreCase(to_str, _("bijective"))) { - str = from_str; - printops.base = BASE_BIJECTIVE_26; - } else if(equalsIgnoreCase(to_str, "sexa") || equalsIgnoreCase(to_str, "sexagesimal") || equalsIgnoreCase(to_str, _("sexagesimal"))) { - str = from_str; - printops.base = BASE_SEXAGESIMAL; - } else if(equalsIgnoreCase(to_str, "time") || equalsIgnoreCase(to_str, _("time"))) { - str = from_str; - printops.base = BASE_TIME; - } else if(equalsIgnoreCase(to_str, "unicode")) { - str = from_str; - printops.base = BASE_UNICODE; - } else if(equalsIgnoreCase(to_str, "utc") || equalsIgnoreCase(to_str, "gmt")) { - str = from_str; - printops.time_zone = TIME_ZONE_UTC; - } else if(to_str.length() > 3 && (equalsIgnoreCase(to_str.substr(0, 3), "utc") || equalsIgnoreCase(to_str.substr(0, 3), "gmt"))) { - to_str = to_str.substr(3); - remove_blanks(to_str); - bool b_minus = false; - if(to_str[0] == '+') { - to_str.erase(0, 1); - } else if(to_str[0] == '-') { - b_minus = true; - to_str.erase(0, 1); - } else if(to_str.find(SIGN_MINUS) == 0) { - b_minus = true; - to_str.erase(0, strlen(SIGN_MINUS)); - } - unsigned int tzh = 0, tzm = 0; - int itz = 0; - if(!to_str.empty() && sscanf(to_str.c_str(), "%2u:%2u", &tzh, &tzm) > 0) { - itz = tzh * 60 + tzm; - if(b_minus) itz = -itz; - } else { - error(true, _("Time zone parsing failed."), NULL); - } - printops.time_zone = TIME_ZONE_CUSTOM; - printops.custom_time_zone = itz; - str = from_str; - } else if(to_str == "CET") { - printops.time_zone = TIME_ZONE_CUSTOM; - printops.custom_time_zone = 60; - str = from_str; - } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "rectangular", _("rectangular")) || EQUALS_IGNORECASE_AND_LOCAL(to_str, "cartesian", _("cartesian")) || str == "rect") { - str = from_str; - evalops.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; - } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "exponential", _("exponential")) || to_str == "exp") { - str = from_str; - evalops.complex_number_form = COMPLEX_NUMBER_FORM_EXPONENTIAL; - } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "polar", _("polar"))) { - str = from_str; - evalops.complex_number_form = COMPLEX_NUMBER_FORM_POLAR; - } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "angle", _("angle")) || EQUALS_IGNORECASE_AND_LOCAL(to_str, "phasor", _("phasor"))) { - str = from_str; - evalops.complex_number_form = COMPLEX_NUMBER_FORM_CIS; - complex_angle_form = true; - } else if(to_str == "cis") { - str = from_str; - evalops.complex_number_form = COMPLEX_NUMBER_FORM_CIS; - } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "fraction", _("fraction"))) { - str = from_str; - do_fraction = true; - } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "factors", _("factors")) || equalsIgnoreCase(to_str, "factor")) { - str = from_str; - evalops.structuring = STRUCTURING_FACTORIZE; - do_factors = true; - } else if(equalsIgnoreCase(to_str, "partial fraction") || equalsIgnoreCase(to_str, _("partial fraction"))) { - str = from_str; - do_pfe = true; - } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "bases", _("bases"))) { - do_bases = true; - str = from_str; - } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "calendars", _("calendars"))) { - do_calendars = true; - str = from_str; - } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "optimal", _("optimal"))) { - str = from_str; - evalops.parse_options.units_enabled = true; - evalops.auto_post_conversion = POST_CONVERSION_OPTIMAL_SI; - } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "base", _("base"))) { - str = from_str; - evalops.parse_options.units_enabled = true; - evalops.auto_post_conversion = POST_CONVERSION_BASE; - } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str1, "base", _("base"))) { - str = from_str; - if(to_str2 == "b26" || to_str2 == "B26") printops.base = BASE_BIJECTIVE_26; - else if(equalsIgnoreCase(to_str2, "golden") || equalsIgnoreCase(to_str2, "golden ratio") || to_str2 == "φ") printops.base = BASE_GOLDEN_RATIO; - else if(equalsIgnoreCase(to_str2, "unicode")) printops.base = BASE_UNICODE; - else if(equalsIgnoreCase(to_str2, "supergolden") || equalsIgnoreCase(to_str2, "supergolden ratio") || to_str2 == "ψ") printops.base = BASE_SUPER_GOLDEN_RATIO; - else if(equalsIgnoreCase(to_str2, "pi") || to_str2 == "π") printops.base = BASE_PI; - else if(to_str2 == "e") printops.base = BASE_E; - else if(to_str2 == "sqrt(2)" || to_str2 == "sqrt 2" || to_str2 == "sqrt2" || to_str2 == "√2") printops.base = BASE_SQRT2; - else { - EvaluationOptions eo = evalops; - eo.parse_options.base = 10; - MathStructure m = calculate(to_str2, eo); - if(m.isInteger() && m.number() >= 2 && m.number() <= 36) { - printops.base = m.number().intValue(); - } else { - printops.base = BASE_CUSTOM; - base_save = customOutputBase(); - setCustomOutputBase(m.number()); - } - } - } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "mixed", _("mixed"))) { - str = from_str; - evalops.parse_options.units_enabled = true; - evalops.auto_post_conversion = POST_CONVERSION_NONE; - evalops.mixed_units_conversion = MIXED_UNITS_CONVERSION_FORCE_INTEGER; - } else { - evalops.parse_options.units_enabled = true; - if(to_str[0] == '?' || (to_str.length() > 1 && to_str[1] == '?' && (to_str[0] == 'a' || to_str[0] == 'd'))) { - printops.use_unit_prefixes = true; - printops.use_prefixes_for_currencies = true; - printops.use_prefixes_for_all_units = true; - if(to_str[0] == 'a') printops.use_all_prefixes = true; - else if(to_str[0] == 'd') priv->use_binary_prefixes = 0; - } else if(to_str.length() > 1 && to_str[1] == '?' && to_str[0] == 'b') { - do_binary_prefixes = true; - } - } - } else { - size_t i = str.find_first_of(SPACES LEFT_PARENTHESIS); - if(i != string::npos) { - to_str = str.substr(0, i); - if(to_str == "factor" || EQUALS_IGNORECASE_AND_LOCAL(to_str, "factorize", _("factorize"))) { - str = str.substr(i + 1); - do_factors = true; - evalops.structuring = STRUCTURING_FACTORIZE; - } else if(EQUALS_IGNORECASE_AND_LOCAL(to_str, "expand", _("expand"))) { - str = str.substr(i + 1); - evalops.structuring = STRUCTURING_SIMPLIFY; - do_expand = true; - } - } - } - - mstruct = calculate(str, evalops); - - if(do_factors) { - mstruct.integerFactorize(); - } else if(do_expand) { - mstruct.expand(evalops, false); - } - if(do_pfe) mstruct.expandPartialFractions(evalops); - - printops.allow_factorization = printops.allow_factorization || evalops.structuring == STRUCTURING_FACTORIZE || do_factors; - - if(do_calendars && mstruct.isDateTime()) { - str = ""; - bool b_fail; - long int y, m, d; -#define PRINT_CALENDAR(x, c) if(!str.empty()) {str += "\n";} str += x; str += " "; b_fail = !dateToCalendar(*mstruct.datetime(), y, m, d, c); if(b_fail) {str += _("failed");} else {str += i2s(d); str += " "; str += monthName(m, c, true); str += " "; str += i2s(y);} - PRINT_CALENDAR(string(_("Gregorian:")), CALENDAR_GREGORIAN); - PRINT_CALENDAR(string(_("Hebrew:")), CALENDAR_HEBREW); - PRINT_CALENDAR(string(_("Islamic:")), CALENDAR_ISLAMIC); - PRINT_CALENDAR(string(_("Persian:")), CALENDAR_PERSIAN); - PRINT_CALENDAR(string(_("Indian national:")), CALENDAR_INDIAN); - PRINT_CALENDAR(string(_("Chinese:")), CALENDAR_CHINESE); - long int cy, yc, st, br; - chineseYearInfo(y, cy, yc, st, br); - if(!b_fail) {str += " ("; str += chineseStemName(st); str += string(" "); str += chineseBranchName(br); str += ")";} - PRINT_CALENDAR(string(_("Julian:")), CALENDAR_JULIAN); - PRINT_CALENDAR(string(_("Revised julian:")), CALENDAR_MILANKOVIC); - PRINT_CALENDAR(string(_("Coptic:")), CALENDAR_COPTIC); - PRINT_CALENDAR(string(_("Ethiopian:")), CALENDAR_ETHIOPIAN); - stopControl(); - return str; - } else if(do_bases) { - printops.base = BASE_BINARY; - str = print(mstruct, 0, printops); - str += " = "; - printops.base = BASE_OCTAL; - str += print(mstruct, 0, printops); - str += " = "; - printops.base = BASE_DECIMAL; - str += print(mstruct, 0, printops); - str += " = "; - printops.base = BASE_HEXADECIMAL; - str += print(mstruct, 0, printops); - stopControl(); - return str; - } else if(do_fraction) { - if(mstruct.isNumber()) printops.number_fraction_format = FRACTION_COMBINED; - else printops.number_fraction_format = FRACTION_FRACTIONAL; - } else if(do_binary_prefixes) { - int i = has_information_unit(mstruct); - printops.use_unit_prefixes = true; - priv->use_binary_prefixes = (i > 0 ? 1 : 2); - if(i == 1) { - printops.use_denominator_prefix = false; - } else if(i > 1) { - printops.use_denominator_prefix = true; - } else { - printops.use_prefixes_for_currencies = true; - printops.use_prefixes_for_all_units = true; +Variable* Calculator::addVariable(Variable *v, bool force, bool check_names) { + if(check_names) { + for(size_t i = 1; i <= v->countNames(); i++) { + v->setName(getName(v->getName(i).name, v, force), i); } } - mstruct.removeDefaultAngleUnit(evalops); - mstruct.format(printops); - str = mstruct.print(printops); - if(complex_angle_form) gsub(" cis ", "∠", str); - stopControl(); - if(printops.base == BASE_CUSTOM) setCustomOutputBase(base_save); - priv->use_binary_prefixes = save_bin; - return str; -} -bool Calculator::calculate(MathStructure *mstruct, string str, int msecs, const EvaluationOptions &eo, MathStructure *parsed_struct, MathStructure *to_struct, bool make_to_division) { - mstruct->set(string(_("calculating...")), false, true); - b_busy = true; - if(!calculate_thread->running && !calculate_thread->start()) {mstruct->setAborted(); return false;} - bool had_msecs = msecs > 0; - expression_to_calculate = str; - tmp_evaluationoptions = eo; - tmp_proc_command = PROC_NO_COMMAND; - tmp_rpn_mstruct = NULL; - tmp_parsedstruct = parsed_struct; - tmp_tostruct = to_struct; - tmp_maketodivision = make_to_division; - if(!calculate_thread->write(true)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} - if(!calculate_thread->write((void*) mstruct)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} - while(msecs > 0 && b_busy) { - sleep_ms(10); - msecs -= 10; - } - if(had_msecs && b_busy) { - if(!abort()) mstruct->setAborted(); - return false; - } - return true; -} -bool Calculator::calculate(MathStructure *mstruct, int msecs, const EvaluationOptions &eo, string to_str) { - b_busy = true; - if(!calculate_thread->running && !calculate_thread->start()) {mstruct->setAborted(); return false;} - bool had_msecs = msecs > 0; - expression_to_calculate = ""; - tmp_evaluationoptions = eo; - tmp_proc_command = PROC_NO_COMMAND; - tmp_rpn_mstruct = NULL; - tmp_parsedstruct = NULL; - if(!to_str.empty()) tmp_tostruct = new MathStructure(to_str); - else tmp_tostruct = NULL; - tmp_tostruct = NULL; - tmp_maketodivision = false; - if(!calculate_thread->write(false)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} - if(!calculate_thread->write((void*) mstruct)) {calculate_thread->cancel(); mstruct->setAborted(); return false;} - while(msecs > 0 && b_busy) { - sleep_ms(10); - msecs -= 10; + if(!v->isLocal() && variables.size() > 0 && variables[variables.size() - 1]->isLocal()) { + variables.insert(variables.begin(), v); + } else { + variables.push_back(v); } - if(had_msecs && b_busy) { - if(!abort()) mstruct->setAborted(); - return false; + variableNameChanged(v, true); + for(vector::iterator it = deleted_variables.begin(); it != deleted_variables.end(); ++it) { + if(*it == v) { + deleted_variables.erase(it); + break; + } } - return true; + v->setRegistered(true); + v->setChanged(false); + if(v->id() != 0) priv->id_variables[v->id()] = v; + return v; } -bool Calculator::hasToExpression(const string &str, bool allow_empty_from) const { - if(str.empty()) return false; - size_t i = str.length() - 1, i2 = i; - int l = 2; - while(i != 0) { - i2 = str.rfind(_("to"), i - 1); - i = str.rfind("to", i - 1); - if(i2 != string::npos && (i == string::npos || i < i2)) {l = strlen(_("to")); i = i2;} - else l = 2; - if(i == string::npos) break; - if(((i > 0 && is_in(SPACES, str[i - 1])) || (allow_empty_from && i == 0)) && i + l < str.length() && is_in(SPACES, str[i + l])) return true; - } - return false; +void Calculator::expressionItemDeactivated(ExpressionItem *item) { + delUFV(item); } -bool Calculator::hasToExpression(const string &str, bool allow_empty_from, const EvaluationOptions &eo) const { - if(eo.parse_options.base == BASE_UNICODE || (eo.parse_options.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) return false; - if(str.empty()) return false; - size_t i = str.length() - 1, i2 = i; - int l = 2; - while(i != 0) { - i2 = str.rfind(_("to"), i - 1); - i = str.rfind("to", i - 1); - if(i2 != string::npos && (i == string::npos || i < i2)) {l = strlen(_("to")); i = i2;} - else l = 2; - if(i == string::npos) break; - if(((i > 0 && is_in(SPACES, str[i - 1])) || (allow_empty_from && i == 0)) && i + l < str.length() && is_in(SPACES, str[i + l])) return true; +void Calculator::expressionItemActivated(ExpressionItem *item) { + ExpressionItem *item2 = getActiveExpressionItem(item); + if(item2) { + item2->setActive(false); } - return false; + nameChanged(item); } -bool Calculator::separateToExpression(string &str, string &to_str, const EvaluationOptions &eo, bool keep_modifiers, bool allow_empty_from) const { - if(eo.parse_options.base == BASE_UNICODE || (eo.parse_options.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) return false; - to_str = ""; - if(str.empty()) return false; - size_t i = str.length() - 1, i2 = i; - int l = 2; - while(i != 0) { - i2 = str.rfind(_("to"), i - 1); - i = str.rfind("to", i - 1); - if(i2 != string::npos && (i == string::npos || i < i2)) {l = strlen(_("to")); i = i2;} - else l = 2; - if(i == string::npos) break; - if(((i > 0 && is_in(SPACES, str[i - 1])) || (allow_empty_from && i == 0)) && i + l < str.length() && is_in(SPACES, str[i + l])) { - to_str = str.substr(i + l , str.length() - i - l); - if(to_str.empty()) return false; - remove_blank_ends(to_str); - if(!to_str.empty()) { - if(to_str.rfind(SIGN_MINUS, 0) == 0) { - to_str.replace(0, strlen(SIGN_MINUS), MINUS); - } - if(!keep_modifiers && (to_str[0] == '0' || to_str[0] == '?' || to_str[0] == '+' || to_str[0] == '-')) { - to_str = to_str.substr(1, str.length() - 1); - remove_blank_ends(to_str); - } else if(!keep_modifiers && to_str.length() > 1 && to_str[1] == '?' && (to_str[0] == 'b' || to_str[0] == 'a' || to_str[0] == 'd')) { - to_str = to_str.substr(2, str.length() - 2); - remove_blank_ends(to_str); +void Calculator::expressionItemDeleted(ExpressionItem *item) { + switch(item->type()) { + case TYPE_VARIABLE: { + for(vector::iterator it = variables.begin(); it != variables.end(); ++it) { + if(*it == item) { + variables.erase(it); + deleted_variables.push_back((Variable*) item); + break; } } - str = str.substr(0, i); - return true; + break; } - } - return false; -} -bool Calculator::hasWhereExpression(const string &str, const EvaluationOptions &eo) const { - if(eo.parse_options.base == BASE_UNICODE || (eo.parse_options.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) return false; - if(str.empty()) return false; - size_t i = str.length() - 1, i2 = i; - int l = 2; - while(i != 0) { - //"where"-operator - i2 = str.rfind(_("where"), i - 1); - i = str.rfind("where", i - 1); - if(i2 != string::npos && (i == string::npos || i < i2)) {l = strlen(_("where")); i = i2;} - else l = 2; - if(i == string::npos) break; - if(i > 0 && is_in(SPACES, str[i - 1]) && i + l < str.length() && is_in(SPACES, str[i + l])) return true; - } - if((i = str.rfind("/.", str.length() - 2)) != string::npos && eo.parse_options.base >= 2 && eo.parse_options.base <= 10 && (str[i + 2] < '0' || str[i + 2] > '9')) return true; - return false; -} -bool Calculator::separateWhereExpression(string &str, string &to_str, const EvaluationOptions &eo) const { - if(eo.parse_options.base == BASE_UNICODE || (eo.parse_options.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) return false; - to_str = ""; - size_t i = 0; - if((i = str.rfind("/.", str.length() - 2)) != string::npos && i != str.length() - 2 && eo.parse_options.base >= 2 && eo.parse_options.base <= 10 && (str[i + 2] < '0' || str[i + 2] > '9')) { - to_str = str.substr(i + 2 , str.length() - i - 2); - } else { - i = str.length() - 1; - size_t i2 = i; - int l = 5; - while(i != 0) { - i2 = str.rfind(_("where"), i - 1); - i = str.rfind("where", i - 1); - if(i2 != string::npos && (i == string::npos || i < i2)) {l = strlen(_("where")); i = i2;} - else l = 5; - if(i == string::npos) break; - if(i > 0 && is_in(SPACES, str[i - 1]) && i + l < str.length() && is_in(SPACES, str[i + l])) { - to_str = str.substr(i + l , str.length() - i - l); - break; + case TYPE_FUNCTION: { + for(vector::iterator it = functions.begin(); it != functions.end(); ++it) { + if(*it == item) { + functions.erase(it); + deleted_functions.push_back((MathFunction*) item); + break; + } } - } - } - if(!to_str.empty()) { - remove_blank_ends(to_str); - str = str.substr(0, i); - parseSigns(str); - if(str.find("&&") == string::npos) { - int par = 0; - int bra = 0; - for(size_t i = 0; i < str.length(); i++) { - switch(str[i]) { - case '(': {par++; break;} - case ')': {if(par > 0) par--; break;} - case '[': {bra++; break;} - case ']': {if(bra > 0) bra--; break;} - case COMMA_CH: { - if(par == 0 && bra == 0) { - str.replace(i, 1, LOGICAL_AND); - i++; - } + if(item->subtype() == SUBTYPE_DATA_SET) { + for(vector::iterator it = data_sets.begin(); it != data_sets.end(); ++it) { + if(*it == item) { + data_sets.erase(it); break; } - default: {} } } + break; } - return true; - } - return false; -} -extern string format_and_print(const MathStructure &mstruct); -extern bool replace_function(MathStructure &m, MathFunction *f1, MathFunction *f2, const EvaluationOptions &eo); -extern bool replace_intervals_f(MathStructure &mstruct); -extern bool replace_f_interval(MathStructure &mstruct, const EvaluationOptions &eo); - -bool calculate_rand(MathStructure &mstruct, const EvaluationOptions &eo) { - if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_rand) { - mstruct.unformat(eo); - mstruct.calculateFunctions(eo, false); - return true; - } - bool ret = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(calculate_rand(mstruct[i], eo)) { - ret = true; - mstruct.childUpdated(i + 1); + case TYPE_UNIT: { + for(vector::iterator it = units.begin(); it != units.end(); ++it) { + if(*it == item) { + units.erase(it); + deleted_units.push_back((Unit*) item); + break; + } + } + break; } } - return ret; -} -bool calculate_ans(MathStructure &mstruct, const EvaluationOptions &eo) { - if(mstruct.isFunction() && (mstruct.function()->hasName("answer") || mstruct.function()->hasName("expression"))) { - mstruct.unformat(eo); - mstruct.calculateFunctions(eo, false); - return true; - } else if(mstruct.isVariable() && mstruct.variable()->isKnown() && (mstruct.variable()->referenceName() == "ans" || (mstruct.variable()->referenceName().length() == 4 && mstruct.variable()->referenceName().substr(0, 3) == "ans" && is_in(NUMBERS, mstruct.variable()->referenceName()[3])))) { - mstruct.set(((KnownVariable*) mstruct.variable())->get(), true); - return true; - } - bool ret = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(calculate_ans(mstruct[i], eo)) { - mstruct.childUpdated(i + 1); - ret = true; + for(size_t i2 = 1; i2 <= item->countNames(); i2++) { + if(item->type() == TYPE_VARIABLE || item->type() == TYPE_UNIT) { + for(size_t i = 0; i < variables.size(); i++) { + if(!variables[i]->isLocal() && !variables[i]->isActive() && variables[i]->hasName(item->getName(i2).name, item->getName(i2).case_sensitive) && !getActiveExpressionItem(variables[i])) {variables[i]->setActive(true);} + } + for(size_t i = 0; i < units.size(); i++) { + if(!units[i]->isLocal() && !units[i]->isActive() && units[i]->hasName(item->getName(i2).name, item->getName(i2).case_sensitive) && !getActiveExpressionItem(units[i])) units[i]->setActive(true); + } + } else { + for(size_t i = 0; i < functions.size(); i++) { + if(!functions[i]->isLocal() && !functions[i]->isActive() && functions[i]->hasName(item->getName(i2).name, item->getName(i2).case_sensitive) && !getActiveExpressionItem(functions[i])) functions[i]->setActive(true); + } } } - return ret; + delUFV(item); } -bool handle_where_expression(MathStructure &m, MathStructure &mstruct, const EvaluationOptions &eo, vector& vars, vector& varms, bool empty_func, bool do_eval = true) { - if(m.isComparison()) { - if(m.comparisonType() == COMPARISON_EQUALS) { - if(m[0].size() > 0 && do_eval) { - MathStructure m2(m); - MathStructure xvar = m[0].find_x_var(); - EvaluationOptions eo2 = eo; - eo2.isolate_x = true; - if(!xvar.isUndefined()) eo2.isolate_var = &xvar; - m2.eval(eo2); - if(m2.isComparison()) return handle_where_expression(m2, mstruct, eo, vars, varms, false, false); - } - if(m[0].isFunction() && m[1].isFunction() && (m[0].size() == 0 || (empty_func && m[0].function()->minargs() == 0)) && (m[1].size() == 0 || (empty_func && m[1].function()->minargs() == 0))) { - if(!replace_function(mstruct, m[0].function(), m[1].function(), eo)) CALCULATOR->error(false, _("Original value (%s) was not found."), (m[0].function()->name() + "()").c_str(), NULL); - } else { - calculate_rand(m[1], eo); - if(mstruct.countOccurrences(m[0]) > 1 && m[1].containsInterval(true, false, false, 0, true)) { - MathStructure mv(m[1]); - replace_f_interval(mv, eo); - replace_intervals_f(mv); - if(!mstruct.replace(m[0], mv)) CALCULATOR->error(false, _("Original value (%s) was not found."), format_and_print(m[0]).c_str(), NULL); - } else { - if(!mstruct.replace(m[0], m[1])) CALCULATOR->error(false, _("Original value (%s) was not found."), format_and_print(m[0]).c_str(), NULL); +void Calculator::nameChanged(ExpressionItem *item, bool new_item) { + if(!item->isActive() || item->countNames() == 0) return; + if(item->type() == TYPE_UNIT && ((Unit*) item)->subtype() == SUBTYPE_COMPOSITE_UNIT) { + return; + } + size_t l2; + if(!new_item) delUFV(item); + for(size_t i2 = 1; i2 <= item->countNames(); i2++) { + l2 = item->getName(i2).name.length(); + if(l2 > UFV_LENGTHS) { + size_t i = 0, l = 0; + for(vector::iterator it = ufvl.begin(); ; ++it) { + if(it != ufvl.end()) { + if(ufvl_t[i] == 'v') + l = ((Variable*) (*it))->getName(ufvl_i[i]).name.length(); + else if(ufvl_t[i] == 'f') + l = ((MathFunction*) (*it))->getName(ufvl_i[i]).name.length(); + else if(ufvl_t[i] == 'u') + l = ((Unit*) (*it))->getName(ufvl_i[i]).name.length(); + else if(ufvl_t[i] == 'p') + l = ((Prefix*) (*it))->shortName(false).length(); + else if(ufvl_t[i] == 'P') + l = ((Prefix*) (*it))->longName(false).length(); + else if(ufvl_t[i] == 'q') + l = ((Prefix*) (*it))->unicodeName(false).length(); } - } - return true; - } else if(m[0].isSymbolic() || (m[0].isVariable() && !m[0].variable()->isKnown())) { - if(!m[1].isNumber()) m[1].eval(eo); - if(m[1].isNumber() && !m[1].number().hasImaginaryPart()) { - Assumptions *ass = NULL; - for(size_t i = 0; i < varms.size(); i++) { - if(varms[i] == m[0]) { - ass = vars[0]->assumptions(); - break; + if(it == ufvl.end()) { + ufvl.push_back((void*) item); + switch(item->type()) { + case TYPE_VARIABLE: {ufvl_t.push_back('v'); break;} + case TYPE_FUNCTION: {ufvl_t.push_back('f'); break;} + case TYPE_UNIT: {ufvl_t.push_back('u'); break;} } - } - if((m.comparisonType() != COMPARISON_NOT_EQUALS || (!ass && m[1].isZero()))) { - if(ass) { - if(m.comparisonType() == COMPARISON_EQUALS_GREATER) { - if(!ass->min() || (*ass->min() < m[1].number())) { - ass->setMin(&m[1].number()); ass->setIncludeEqualsMin(true); - return true; - } else if(*ass->min() >= m[1].number()) { - return true; - } - } else if(m.comparisonType() == COMPARISON_EQUALS_LESS) { - if(!ass->max() || (*ass->max() > m[1].number())) { - ass->setMax(&m[1].number()); ass->setIncludeEqualsMax(true); - return true; - } else if(*ass->max() <= m[1].number()) { - return true; - } - } else if(m.comparisonType() == COMPARISON_GREATER) { - if(!ass->min() || (ass->includeEqualsMin() && *ass->min() <= m[1].number()) || (!ass->includeEqualsMin() && *ass->min() < m[1].number())) { - ass->setMin(&m[1].number()); ass->setIncludeEqualsMin(false); - return true; - } else if((ass->includeEqualsMin() && *ass->min() > m[1].number()) || (!ass->includeEqualsMin() && *ass->min() >= m[1].number())) { - return true; - } - } else if(m.comparisonType() == COMPARISON_LESS) { - if(!ass->max() || (ass->includeEqualsMax() && *ass->max() >= m[1].number()) || (!ass->includeEqualsMax() && *ass->max() > m[1].number())) { - ass->setMax(&m[1].number()); ass->setIncludeEqualsMax(false); - return true; - } else if((ass->includeEqualsMax() && *ass->max() < m[1].number()) || (!ass->includeEqualsMax() && *ass->max() <= m[1].number())) { - return true; - } - } - } else { - UnknownVariable *var = new UnknownVariable("", format_and_print(m[0])); - ass = new Assumptions(); - if(m[1].isZero()) { - if(m.comparisonType() == COMPARISON_EQUALS_GREATER) ass->setSign(ASSUMPTION_SIGN_NONNEGATIVE); - else if(m.comparisonType() == COMPARISON_EQUALS_LESS) ass->setSign(ASSUMPTION_SIGN_NONPOSITIVE); - else if(m.comparisonType() == COMPARISON_GREATER) ass->setSign(ASSUMPTION_SIGN_POSITIVE); - else if(m.comparisonType() == COMPARISON_LESS) ass->setSign(ASSUMPTION_SIGN_NEGATIVE); - else if(m.comparisonType() == COMPARISON_NOT_EQUALS) ass->setSign(ASSUMPTION_SIGN_NONZERO); - } else { - if(m.comparisonType() == COMPARISON_EQUALS_GREATER) {ass->setMin(&m[1].number()); ass->setIncludeEqualsMin(true);} - else if(m.comparisonType() == COMPARISON_EQUALS_LESS) {ass->setMax(&m[1].number()); ass->setIncludeEqualsMax(true);} - else if(m.comparisonType() == COMPARISON_GREATER) {ass->setMin(&m[1].number()); ass->setIncludeEqualsMin(false);} - else if(m.comparisonType() == COMPARISON_LESS) {ass->setMax(&m[1].number()); ass->setIncludeEqualsMax(false);} + ufvl_i.push_back(i2); + break; + } else { + if(l < l2 + || (item->type() == TYPE_VARIABLE && l == l2 && ufvl_t[i] == 'v') + || (item->type() == TYPE_FUNCTION && l == l2 && (ufvl_t[i] != 'p' && ufvl_t[i] != 'P' && ufvl_t[i] != 'q')) + || (item->type() == TYPE_UNIT && l == l2 && (ufvl_t[i] != 'p' && ufvl_t[i] != 'P' && ufvl_t[i] != 'q' && ufvl_t[i] != 'f')) + ) { + ufvl.insert(it, (void*) item); + switch(item->type()) { + case TYPE_VARIABLE: {ufvl_t.insert(ufvl_t.begin() + i, 'v'); break;} + case TYPE_FUNCTION: {ufvl_t.insert(ufvl_t.begin() + i, 'f'); break;} + case TYPE_UNIT: {ufvl_t.insert(ufvl_t.begin() + i, 'u'); break;} } - var->setAssumptions(ass); - vars.push_back(var); - varms.push_back(m[0]); - MathStructure u_var(var); - if(!mstruct.replace(m[0], u_var)) CALCULATOR->error(false, _("Original value (%s) was not found."), format_and_print(m[0]).c_str(), NULL); - return true; + ufvl_i.insert(ufvl_i.begin() + i, i2); + break; } } + i++; } - } else if(do_eval) { - MathStructure xvar = m[0].find_x_var(); - EvaluationOptions eo2 = eo; - eo2.isolate_x = true; - if(!xvar.isUndefined()) eo2.isolate_var = &xvar; - m.eval(eo2); - return handle_where_expression(m, mstruct, eo, vars, varms, false, false); - } - } else if(m.isLogicalAnd()) { - bool ret = true; - for(size_t i = 0; i < m.size(); i++) { - if(!handle_where_expression(m[i], mstruct, eo, vars, varms, empty_func, do_eval)) ret = false; - } - return ret; - } - CALCULATOR->error(true, _("Unhandled \"where\" expression: %s"), format_and_print(m).c_str(), NULL); - return false; -} -MathStructure Calculator::calculate(string str, const EvaluationOptions &eo, MathStructure *parsed_struct, MathStructure *to_struct, bool make_to_division) { - - string str2, str_where; - - if(make_to_division) separateToExpression(str, str2, eo, true); - separateWhereExpression(str, str_where, eo); - - Unit *u = NULL; - if(to_struct) { - if(str2.empty()) { - if(to_struct->isSymbolic() && !to_struct->symbol().empty()) { - str2 = to_struct->symbol(); - remove_blank_ends(str2); - } else if(to_struct->isUnit()) { - u = to_struct->unit(); - } - } - to_struct->setUndefined(); - } - - MathStructure mstruct; - current_stage = MESSAGE_STAGE_PARSING; - size_t n_messages = messages.size(); - parse(&mstruct, str, eo.parse_options); - if(parsed_struct) { - beginTemporaryStopMessages(); - ParseOptions po = eo.parse_options; - po.preserve_format = true; - parse(parsed_struct, str, po); - endTemporaryStopMessages(); - } - - vector vars; - vector varms; - if(!str_where.empty()) { - MathStructure where_struct; - parse(&where_struct, str_where, eo.parse_options); - current_stage = MESSAGE_STAGE_CALCULATION; - calculate_ans(mstruct, eo); - string str_test = str_where; - remove_blanks(str_test); - bool empty_func = str_test.find("()=") != string::npos; - if(mstruct.isComparison() || (mstruct.isFunction() && mstruct.function() == CALCULATOR->f_solve && mstruct.size() >= 1 && mstruct[0].isComparison())) { - beginTemporaryStopMessages(); - MathStructure mbak(mstruct); - if(handle_where_expression(where_struct, mstruct, eo, vars, varms, empty_func)) { - endTemporaryStopMessages(true); - } else { - endTemporaryStopMessages(); - mstruct = mbak; - if(mstruct.isComparison()) mstruct.transform(STRUCT_LOGICAL_AND, where_struct); - else {mstruct[0].transform(STRUCT_LOGICAL_AND, where_struct); mstruct.childUpdated(1);} - } - } else { - if(eo.approximation == APPROXIMATION_EXACT) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_TRY_EXACT; - handle_where_expression(where_struct, mstruct, eo2, vars, varms, empty_func); - } else { - handle_where_expression(where_struct, mstruct, eo, vars, varms, empty_func); - } - } - } - - current_stage = MESSAGE_STAGE_CALCULATION; - - mstruct.eval(eo); - - current_stage = MESSAGE_STAGE_UNSET; - - if(!aborted()) { - bool b_units = mstruct.containsType(STRUCT_UNIT, true); - if(b_units && u) { - current_stage = MESSAGE_STAGE_CONVERSION; - if(to_struct) to_struct->set(u); - mstruct.set(convert(mstruct, u, eo, false, false)); - if(eo.mixed_units_conversion != MIXED_UNITS_CONVERSION_NONE) mstruct.set(convertToMixedUnits(mstruct, eo)); - } else if(!str2.empty()) { - mstruct.set(convert(mstruct, str2, eo)); - } else if(b_units) { - current_stage = MESSAGE_STAGE_CONVERSION; - switch(eo.auto_post_conversion) { - case POST_CONVERSION_OPTIMAL: { - mstruct.set(convertToOptimalUnit(mstruct, eo, false)); + } else if(l2 > 0) { + l2--; + switch(item->type()) { + case TYPE_VARIABLE: { + ufv[3][l2].push_back((void*) item); + ufv_i[3][l2].push_back(i2); break; } - case POST_CONVERSION_BASE: { - mstruct.set(convertToBaseUnits(mstruct, eo)); + case TYPE_FUNCTION: { + ufv[1][l2].push_back((void*) item); + ufv_i[1][l2].push_back(i2); break; } - case POST_CONVERSION_OPTIMAL_SI: { - mstruct.set(convertToOptimalUnit(mstruct, eo, true)); + case TYPE_UNIT: { + ufv[2][l2].push_back((void*) item); + ufv_i[2][l2].push_back(i2); break; } - default: {} } - if(eo.mixed_units_conversion != MIXED_UNITS_CONVERSION_NONE) mstruct.set(convertToMixedUnits(mstruct, eo)); } } +} +void Calculator::variableNameChanged(Variable *v, bool new_item) { + nameChanged(v, new_item); +} +void Calculator::functionNameChanged(MathFunction *f, bool new_item) { + nameChanged(f, new_item); +} +void Calculator::unitNameChanged(Unit *u, bool new_item) { + nameChanged(u, new_item); +} - cleanMessages(mstruct, n_messages + 1); - - current_stage = MESSAGE_STAGE_UNSET; - - for(size_t i = 0; i < vars.size(); i++) { - mstruct.replace(vars[i], varms[i]); - vars[i]->destroy(); +Variable* Calculator::getVariable(string name_) { + if(name_.empty()) return NULL; + for(size_t i = 0; i < variables.size(); i++) { + if(variables[i]->hasName(name_)) { + return variables[i]; + } } - - return mstruct; - + return NULL; } -MathStructure Calculator::calculate(const MathStructure &mstruct_to_calculate, const EvaluationOptions &eo, string to_str) { - - remove_blank_ends(to_str); - MathStructure mstruct(mstruct_to_calculate); - current_stage = MESSAGE_STAGE_CALCULATION; - size_t n_messages = messages.size(); - mstruct.eval(eo); - - current_stage = MESSAGE_STAGE_CONVERSION; - if(!to_str.empty()) { - mstruct.set(convert(mstruct, to_str, eo)); - } else { - switch(eo.auto_post_conversion) { - case POST_CONVERSION_OPTIMAL: { - mstruct.set(convertToOptimalUnit(mstruct, eo, false)); - break; - } - case POST_CONVERSION_BASE: { - mstruct.set(convertToBaseUnits(mstruct, eo)); - break; - } - case POST_CONVERSION_OPTIMAL_SI: { - mstruct.set(convertToOptimalUnit(mstruct, eo, true)); - break; - } - default: {} - } - if(eo.mixed_units_conversion != MIXED_UNITS_CONVERSION_NONE) mstruct.set(convertToMixedUnits(mstruct, eo)); - } - - cleanMessages(mstruct, n_messages + 1); - - current_stage = MESSAGE_STAGE_UNSET; - return mstruct; -} - -string Calculator::print(const MathStructure &mstruct, int msecs, const PrintOptions &po) { - startControl(msecs); - MathStructure mstruct2(mstruct); - mstruct2.format(po); - string print_result = mstruct2.print(po); - stopControl(); - return print_result; -} -string Calculator::printMathStructureTimeOut(const MathStructure &mstruct, int msecs, const PrintOptions &po) { - return print(mstruct, msecs, po); -} - -MathStructure Calculator::convertToMixedUnits(const MathStructure &mstruct, const EvaluationOptions &eo) { - if(eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_NONE) return mstruct; - if(!mstruct.isMultiplication()) return mstruct; - if(mstruct.size() != 2) return mstruct; - size_t n_messages = messages.size(); - if(mstruct[1].isUnit() && (!mstruct[1].prefix() || mstruct[1].prefix() == decimal_null_prefix) && mstruct[0].isNumber()) { - Prefix *p = mstruct[1].prefix(); - MathStructure mstruct_new(mstruct); - Unit *u = mstruct[1].unit(); - Number nr = mstruct[0].number(); - if(!nr.isReal()) return mstruct; - if(nr.isOne()) return mstruct; - if(u->subtype() == SUBTYPE_COMPOSITE_UNIT) return mstruct; - bool negated = false; - if(nr.isNegative()) { - nr.negate(); - negated = true; - } - bool accept_obsolete = (u->subtype() == SUBTYPE_ALIAS_UNIT && abs(((AliasUnit*) u)->mixWithBase()) > 1); - Unit *original_u = u; - Unit *last_nonobsolete_u = u; - Number last_nonobsolete_nr = nr; - Number nr_one(1, 1); - Number nr_ten(10, 1); - while(eo.mixed_units_conversion > MIXED_UNITS_CONVERSION_DOWNWARDS && nr.isGreaterThan(nr_one)) { - Unit *best_u = NULL; - Number best_nr; - int best_priority = 0; - for(size_t i = 0; i < units.size(); i++) { - Unit *ui = units[i]; - if(ui->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) ui)->firstBaseUnit() == u && ((AliasUnit*) ui)->firstBaseExponent() == 1) { - AliasUnit *aui = (AliasUnit*) ui; - int priority_i = aui->mixWithBase(); - if(((priority_i > 0 && (!best_u || priority_i <= best_priority)) || (best_priority == 0 && priority_i == 0 && ((eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_FORCE_INTEGER && aui->expression().find_first_not_of(NUMBERS) == string::npos) || eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_FORCE_ALL))) && (aui->mixWithBaseMinimum() <= 1 || nr.isGreaterThanOrEqualTo(aui->mixWithBaseMinimum()))) { - MathStructure mstruct_nr(nr); - MathStructure m_exp(m_one); - aui->convertFromFirstBaseUnit(mstruct_nr, m_exp); - mstruct_nr.eval(eo); - if(mstruct_nr.isNumber() && m_exp.isOne() && mstruct_nr.number().isLessThan(nr) && mstruct_nr.number().isGreaterThanOrEqualTo(nr_one) && (!best_u || mstruct_nr.number().isLessThan(best_nr))) { - best_u = ui; - best_nr = mstruct_nr.number(); - best_priority = priority_i; - } - } - } - } - if(!best_u) break; - u = best_u; - nr = best_nr; - if(accept_obsolete || best_priority <= 1) { - last_nonobsolete_u = u; - last_nonobsolete_nr = nr; - } - } - u = last_nonobsolete_u; - nr = last_nonobsolete_nr; - if(u != original_u) { - if(negated) last_nonobsolete_nr.negate(); - mstruct_new[0].set(last_nonobsolete_nr); - mstruct_new[1].set(u, p); - } - while(u->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) u)->firstBaseUnit()->subtype() != SUBTYPE_COMPOSITE_UNIT && ((AliasUnit*) u)->firstBaseExponent() == 1 && (((AliasUnit*) u)->mixWithBase() != 0 || eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_FORCE_ALL || (eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_FORCE_INTEGER && ((AliasUnit*) u)->expression().find_first_not_of(NUMBERS) == string::npos)) && !nr.isInteger() && !nr.isZero()) { - Number int_nr(nr); - int_nr.trunc(); - if(eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_DOWNWARDS_KEEP && int_nr.isZero()) break; - nr -= int_nr; - MathStructure mstruct_nr(nr); - MathStructure m_exp(m_one); - ((AliasUnit*) u)->convertToFirstBaseUnit(mstruct_nr, m_exp); - mstruct_nr.eval(eo); - while(!accept_obsolete && ((AliasUnit*) u)->firstBaseUnit()->subtype() == SUBTYPE_ALIAS_UNIT && abs(((AliasUnit*) ((AliasUnit*) u)->firstBaseUnit())->mixWithBase()) > 1) { - u = ((AliasUnit*) u)->firstBaseUnit(); - if(((AliasUnit*) u)->firstBaseExponent() == 1 && (((AliasUnit*) u)->mixWithBase() != 0 || eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_FORCE_ALL || (eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_FORCE_INTEGER && ((AliasUnit*) u)->expression().find_first_not_of(NUMBERS) == string::npos))) { - ((AliasUnit*) u)->convertToFirstBaseUnit(mstruct_nr, m_exp); - mstruct_nr.eval(eo); - if(!mstruct_nr.isNumber() || !m_exp.isOne()) break; - } else { - mstruct_nr.setUndefined(); - break; - } - } - if(!mstruct_nr.isNumber() || !m_exp.isOne()) break; - if(eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_FORCE_ALL && mstruct_nr.number().isLessThanOrEqualTo(nr)) break; - u = ((AliasUnit*) u)->firstBaseUnit(); - nr = mstruct_nr.number(); - MathStructure mstruct_term; - if(negated) { - Number pos_nr(nr); - pos_nr.negate(); - mstruct_term.set(pos_nr); - } else { - mstruct_term.set(nr); - } - mstruct_term *= MathStructure(u, p); - if(int_nr.isZero()) { - if(mstruct_new.isAddition()) mstruct_new[mstruct_new.size() - 1].set(mstruct_term); - else mstruct_new.set(mstruct_term); - } else { - if(negated) int_nr.negate(); - if(mstruct_new.isAddition()) mstruct_new[mstruct_new.size() - 1][0].set(int_nr); - else mstruct_new[0].set(int_nr); - mstruct_new.add(mstruct_term, true); - } - } - cleanMessages(mstruct_new, n_messages + 1); - return mstruct_new; - } - return mstruct; -} - -MathStructure Calculator::convert(double value, Unit *from_unit, Unit *to_unit, const EvaluationOptions &eo) { - size_t n_messages = messages.size(); - MathStructure mstruct(value); - mstruct *= from_unit; - mstruct.eval(eo); - if(eo.approximation == APPROXIMATION_EXACT) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_TRY_EXACT; - mstruct.convert(to_unit, true, NULL, false, eo2); - } else { - mstruct.convert(to_unit, true, NULL, false, eo); - } - mstruct.divide(to_unit, true); - mstruct.eval(eo); - cleanMessages(mstruct, n_messages + 1); - return mstruct; - -} -MathStructure Calculator::convert(string str, Unit *from_unit, Unit *to_unit, int msecs, const EvaluationOptions &eo) { - return convertTimeOut(str, from_unit, to_unit, msecs, eo); -} -MathStructure Calculator::convertTimeOut(string str, Unit *from_unit, Unit *to_unit, int msecs, const EvaluationOptions &eo) { - MathStructure mstruct; - parse(&mstruct, str, eo.parse_options); - mstruct *= from_unit; - b_busy = true; - if(!calculate_thread->running && !calculate_thread->start()) return mstruct; - bool had_msecs = msecs > 0; - tmp_evaluationoptions = eo; - tmp_proc_command = PROC_NO_COMMAND; - bool b_parse = false; - if(!calculate_thread->write(b_parse)) {calculate_thread->cancel(); return mstruct;} - void *x = (void*) &mstruct; - if(!calculate_thread->write(x)) {calculate_thread->cancel(); return mstruct;} - while(msecs > 0 && b_busy) { - sleep_ms(10); - msecs -= 10; - } - if(had_msecs && b_busy) { - abort(); - mstruct.setAborted(); - return mstruct; - } - if(eo.approximation == APPROXIMATION_EXACT) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_TRY_EXACT; - mstruct.convert(to_unit, true, NULL, false, eo2); - } else { - mstruct.convert(to_unit, true, NULL, false, eo); - } - mstruct.divide(to_unit, true); - b_busy = true; - if(!calculate_thread->write(b_parse)) {calculate_thread->cancel(); return mstruct;} - x = (void*) &mstruct; - if(!calculate_thread->write(x)) {calculate_thread->cancel(); return mstruct;} - while(msecs > 0 && b_busy) { - sleep_ms(10); - msecs -= 10; - } - if(had_msecs && b_busy) { - abort(); - mstruct.setAborted(); - } - return mstruct; -} -MathStructure Calculator::convert(string str, Unit *from_unit, Unit *to_unit, const EvaluationOptions &eo) { - size_t n_messages = messages.size(); - MathStructure mstruct; - parse(&mstruct, str, eo.parse_options); - mstruct *= from_unit; - mstruct.eval(eo); - if(eo.approximation == APPROXIMATION_EXACT) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_TRY_EXACT; - mstruct.convert(to_unit, true, NULL, false, eo2); - } else { - mstruct.convert(to_unit, true, NULL, false, eo); - } - mstruct.divide(to_unit, true); - mstruct.eval(eo); - cleanMessages(mstruct, n_messages + 1); - return mstruct; -} -MathStructure Calculator::convert(const MathStructure &mstruct, KnownVariable *to_var, const EvaluationOptions &eo) { - if(mstruct.contains(to_var, true) > 0) return mstruct; - size_t n_messages = messages.size(); - if(b_var_units && !to_var->unit().empty() && to_var->isExpression()) { - CompositeUnit cu("", "temporary_composite_convert", "", to_var->unit()); - if(cu.countUnits() > 0) { - AliasUnit au("", "temporary_alias_convert", "", "", "", &cu, to_var->expression()); - bool unc_rel = false; - if(!to_var->uncertainty(&unc_rel).empty()) au.setUncertainty(to_var->uncertainty(), unc_rel); - au.setApproximate(to_var->isApproximate()); - au.setPrecision(to_var->precision()); - MathStructure mstruct_new(convert(mstruct, &au, eo, false, false)); - if(mstruct_new.contains(&au)) { - mstruct_new.replace(&au, to_var); - return mstruct_new; - } - } - } - MathStructure mstruct_new(mstruct); - mstruct_new /= to_var->get(); - mstruct_new.eval(eo); - mstruct_new *= to_var; - cleanMessages(mstruct, n_messages + 1); - return mstruct_new; -} -MathStructure Calculator::convert(const MathStructure &mstruct, Unit *to_unit, const EvaluationOptions &eo, bool always_convert, bool convert_to_mixed_units) { - if(!mstruct.containsType(STRUCT_UNIT, true)) return mstruct; - CompositeUnit *cu = NULL; - if(to_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) cu = (CompositeUnit*) to_unit; - if(cu && cu->countUnits() == 0) return mstruct; - MathStructure mstruct_new(mstruct); - size_t n_messages = messages.size(); - if(to_unit->hasNonlinearRelationTo(to_unit->baseUnit()) && to_unit->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { - mstruct_new = convert(mstruct, to_unit->baseUnit(), eo, always_convert, convert_to_mixed_units); - mstruct_new.calculateDivide(((CompositeUnit*) to_unit->baseUnit())->generateMathStructure(false, eo.keep_prefixes), eo); - to_unit->convertFromBaseUnit(mstruct_new); - mstruct_new.eval(eo); - mstruct_new.multiply(MathStructure(to_unit, eo.keep_prefixes ? decimal_null_prefix : NULL)); - EvaluationOptions eo2 = eo; - eo2.sync_units = false; - eo2.keep_prefixes = true; - mstruct_new.eval(eo2); - cleanMessages(mstruct, n_messages + 1); - return mstruct_new; - } - //bool b_simple = !cu && (to_unit->subtype() != SUBTYPE_ALIAS_UNIT || (((AliasUnit*) to_unit)->baseUnit()->subtype() != SUBTYPE_COMPOSITE_UNIT && ((AliasUnit*) to_unit)->baseExponent() == 1)); - - bool b_changed = false; - if(mstruct_new.isAddition()) { - if(aborted()) return mstruct; - mstruct_new.factorizeUnits(); - if(!b_changed && !mstruct_new.equals(mstruct, true, true)) b_changed = true; - } - - if(!mstruct_new.isPower() && !mstruct_new.isUnit() && !mstruct_new.isMultiplication()) { - if(mstruct_new.size() > 0) { - for(size_t i = 0; i < mstruct_new.size(); i++) { - if(aborted()) return mstruct; - if(!mstruct_new.isFunction() || !mstruct_new.function()->getArgumentDefinition(i + 1) || mstruct_new.function()->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) { - mstruct_new[i] = convert(mstruct_new[i], to_unit, eo, false, convert_to_mixed_units); - if(!b_changed && !mstruct_new.equals(mstruct[i], true, true)) b_changed = true; - } - } - if(b_changed) { - mstruct_new.childrenUpdated(); - EvaluationOptions eo2 = eo; - //eo2.calculate_functions = false; - eo2.sync_units = false; - eo2.keep_prefixes = true; - mstruct_new.eval(eo2); - cleanMessages(mstruct, n_messages + 1); - } - return mstruct_new; - } - } else { - EvaluationOptions eo2 = eo; - eo2.keep_prefixes = true; - bool b = false; - if(eo.approximation == APPROXIMATION_EXACT) eo2.approximation = APPROXIMATION_TRY_EXACT; - if(mstruct_new.convert(to_unit, true, NULL, false, eo2, eo.keep_prefixes ? decimal_null_prefix : NULL) || always_convert) { - b = true; - } else { - CompositeUnit *cu2 = cu; - if(to_unit->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) to_unit)->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { - cu2 = (CompositeUnit*) ((AliasUnit*) to_unit)->baseUnit(); - } - if(cu2) { - switch(mstruct_new.type()) { - case STRUCT_UNIT: { - if(cu2->containsRelativeTo(mstruct_new.unit())) { - b = true; - } - break; - } - case STRUCT_MULTIPLICATION: { - for(size_t i = 1; i <= mstruct_new.countChildren(); i++) { - if(aborted()) return mstruct; - if(mstruct_new.getChild(i)->isUnit() && cu2->containsRelativeTo(mstruct_new.getChild(i)->unit())) { - b = true; - } - if(mstruct_new.getChild(i)->isPower() && mstruct_new.getChild(i)->base()->isUnit() && cu2->containsRelativeTo(mstruct_new.getChild(i)->base()->unit())) { - b = true; - } - } - break; - } - case STRUCT_POWER: { - if(mstruct_new.base()->isUnit() && cu2->containsRelativeTo(mstruct_new.base()->unit())) { - b = true; - } - break; - } - default: {} - } - } - } - if(b) { - eo2.approximation = eo.approximation; - eo2.sync_units = true; - eo2.keep_prefixes = false; - MathStructure mbak(mstruct_new); - mstruct_new.divide(MathStructure(to_unit, NULL)); - mstruct_new.eval(eo2); - if(mstruct_new.containsType(STRUCT_UNIT)) { - mbak.inverse(); - mbak.divide(MathStructure(to_unit, NULL)); - mbak.eval(eo2); - if(!mbak.containsType(STRUCT_UNIT)) mstruct_new = mbak; - } - - if(cu) { - MathStructure mstruct_cu(cu->generateMathStructure(false, eo.keep_prefixes)); - Prefix *p = NULL; - size_t i = 1; - Unit *u = cu->get(i, NULL, &p); - while(u) { - mstruct_new.setPrefixForUnit(u, p); - i++; - u = cu->get(i, NULL, &p); - } - mstruct_new.multiply(mstruct_cu); - } else { - mstruct_new.multiply(MathStructure(to_unit, eo.keep_prefixes ? decimal_null_prefix : NULL)); - } - - eo2.sync_units = false; - eo2.keep_prefixes = true; - mstruct_new.eval(eo2); - - cleanMessages(mstruct, n_messages + 1); - - if(convert_to_mixed_units && eo2.mixed_units_conversion != MIXED_UNITS_CONVERSION_NONE) { - eo2.mixed_units_conversion = MIXED_UNITS_CONVERSION_DOWNWARDS_KEEP; - return convertToMixedUnits(mstruct_new, eo2); - } else { - return mstruct_new; - } - } - } - - return mstruct; - -} -MathStructure Calculator::convertToBaseUnits(const MathStructure &mstruct, const EvaluationOptions &eo) { - if(!mstruct.containsType(STRUCT_UNIT, true)) return mstruct; - size_t n_messages = messages.size(); - MathStructure mstruct_new(mstruct); - mstruct_new.convertToBaseUnits(true, NULL, true, eo); - if(!mstruct_new.equals(mstruct, true, true)) { - EvaluationOptions eo2 = eo; - eo2.approximation = eo.approximation; - eo2.keep_prefixes = false; - eo2.isolate_x = false; - eo2.test_comparisons = false; - //eo2.calculate_functions = false; - mstruct_new.eval(eo2); - cleanMessages(mstruct, n_messages + 1); - } - return mstruct_new; -} -Unit *Calculator::findMatchingUnit(const MathStructure &mstruct) { - switch(mstruct.type()) { - case STRUCT_POWER: { - if(mstruct.base()->isUnit() && mstruct.exponent()->isNumber() && mstruct.exponent()->number().isInteger() && mstruct.exponent()->number() < 10 && mstruct.exponent()->number() > -10) { - Unit *u_base = mstruct.base()->unit(); - int exp = mstruct.exponent()->number().intValue(); - if(u_base->subtype() == SUBTYPE_ALIAS_UNIT) { - u_base = u_base->baseUnit(); - exp *= ((AliasUnit*) u_base)->baseExponent(); - } - for(size_t i = 0; i < units.size(); i++) { - Unit *u = units[i]; - if(u->subtype() == SUBTYPE_ALIAS_UNIT && u->baseUnit() == u_base && ((AliasUnit*) u)->baseExponent() == exp) { - return u; - } - } - CompositeUnit *cu = new CompositeUnit("", "temporary_find_matching_unit"); - cu->add(u_base, exp); - Unit *u = getOptimalUnit(cu); - if(u != cu && !u->isRegistered()) { - delete u; - } else if(u != cu) { - MathStructure mtest(mstruct); - mtest.divide(u); - mtest.eval(); - if(mtest.isNumber()) { - delete cu; - return u; - } - } - delete cu; - } - return findMatchingUnit(mstruct[0]); - } - case STRUCT_UNIT: { - return mstruct.unit(); - } - case STRUCT_MULTIPLICATION: { - if(mstruct.size() == 2 && !mstruct[0].isUnit_exp()) { - return findMatchingUnit(mstruct[1]); - } - CompositeUnit *cu = new CompositeUnit("", "temporary_find_matching_unit"); - for(size_t i = 1; i <= mstruct.countChildren(); i++) { - if(mstruct.getChild(i)->isUnit()) { - cu->add(mstruct.getChild(i)->unit()->baseUnit()); - } else if(mstruct.getChild(i)->isPower() && mstruct.getChild(i)->base()->isUnit() && mstruct.getChild(i)->exponent()->isNumber() && mstruct.getChild(i)->exponent()->number().isInteger()) { - cu->add(mstruct.getChild(i)->base()->unit()->baseUnit(), mstruct.getChild(i)->exponent()->number().intValue()); - } - } - if(cu->countUnits() == 1) { - int exp = 1; - Unit *u_base = cu->get(1, &exp); - if(exp == 1) return u_base; - for(size_t i = 0; i < units.size(); i++) { - Unit *u = units[i]; - if(u->subtype() == SUBTYPE_ALIAS_UNIT && u->baseUnit() == u_base && ((AliasUnit*) u)->baseExponent() == exp) { - return u; - } - } - } - if(cu->countUnits() > 1) { - for(size_t i = 0; i < units.size(); i++) { - Unit *u = units[i]; - if(u->subtype() == SUBTYPE_COMPOSITE_UNIT) { - if(((CompositeUnit*) u)->countUnits() == cu->countUnits()) { - bool b = true; - for(size_t i2 = 1; i2 <= cu->countUnits(); i2++) { - int exp1 = 1, exp2 = 1; - Unit *ui1 = cu->get(i2, &exp1); - b = false; - for(size_t i3 = 1; i3 <= cu->countUnits(); i3++) { - Unit *ui2 = ((CompositeUnit*) u)->get(i3, &exp2); - if(ui1 == ui2->baseUnit()) { - b = (exp1 == exp2); - break; - } - } - if(!b) break; - } - if(b) { - delete cu; - return u; - } - } - } - } - } - Unit *u = getOptimalUnit(cu); - if(u != cu && !u->isRegistered()) { - if(cu->countUnits() > 1 && u->subtype() == SUBTYPE_COMPOSITE_UNIT) { - MathStructure m_u = ((CompositeUnit*) u)->generateMathStructure(); - if(m_u != cu->generateMathStructure()) { - Unit *u2 = findMatchingUnit(m_u); - if(u2) { - MathStructure mtest(mstruct); - mtest.divide(u2); - mtest.eval(); - if(mtest.isNumber()) { - delete cu; - delete u; - return u2; - } - } - } - } - delete u; - } else if(u != cu) { - MathStructure mtest(mstruct); - mtest.divide(u); - mtest.eval(); - if(mtest.isNumber()) { - delete cu; - return u; - } - } - delete cu; - break; - } - default: { - for(size_t i = 0; i < mstruct.size(); i++) { - if(aborted()) return NULL; - if(!mstruct.isFunction() || !mstruct.function()->getArgumentDefinition(i + 1) || mstruct.function()->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) { - Unit *u = findMatchingUnit(mstruct[i]); - if(u) return u; - } - } - break; - } - } - return NULL; -} -Unit *Calculator::getBestUnit(Unit *u, bool allow_only_div, bool convert_to_local_currency) {return getOptimalUnit(u, allow_only_div, convert_to_local_currency);} -Unit *Calculator::getOptimalUnit(Unit *u, bool allow_only_div, bool convert_to_local_currency) { - switch(u->subtype()) { - case SUBTYPE_BASE_UNIT: { - if(convert_to_local_currency && u->isCurrency()) { - Unit *u_local_currency = getLocalCurrency(); - if(u_local_currency) return u_local_currency; - } - return u; - } - case SUBTYPE_ALIAS_UNIT: { - AliasUnit *au = (AliasUnit*) u; - if(au->baseExponent() == 1 && au->baseUnit()->subtype() == SUBTYPE_BASE_UNIT) { - if(au->isCurrency()) { - if(!convert_to_local_currency) return u; - Unit *u_local_currency = getLocalCurrency(); - if(u_local_currency) return u_local_currency; - } - return (Unit*) au->baseUnit(); - } else if(au->isSIUnit() && (au->firstBaseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT || au->firstBaseExponent() != 1)) { - return u; - } else { - return getOptimalUnit((Unit*) au->firstBaseUnit()); - } - } - case SUBTYPE_COMPOSITE_UNIT: { - CompositeUnit *cu = (CompositeUnit*) u; - int exp, b_exp; - int points = 0; - bool minus = false; - bool has_positive = false; - int new_points; - int new_points_m; - int max_points = 0; - for(size_t i = 1; i <= cu->countUnits(); i++) { - cu->get(i, &exp); - if(exp < 0) { - max_points -= exp; - } else { - max_points += exp; - has_positive = true; - } - } - for(size_t i = 0; i < units.size(); i++) { - if(units[i]->subtype() == SUBTYPE_COMPOSITE_UNIT) { - CompositeUnit *cu2 = (CompositeUnit*) units[i]; - if(cu == cu2 && !cu2->isHidden()) { - points = max_points - 1; - } else if(!cu2->isHidden() && cu2->isSIUnit() && cu2->countUnits() == cu->countUnits()) { - bool b_match = true; - for(size_t i2 = 1; i2 <= cu->countUnits(); i2++) { - int exp2; - if(cu->get(i2, &exp) != cu2->get(i2, &exp2) || exp != exp2) { - b_match = false; - break; - } - } - if(b_match) { - points = max_points - 1; - break; - } - } - } - } - Unit *best_u = NULL; - Unit *bu, *u2; - AliasUnit *au; - for(size_t i = 0; i < units.size(); i++) { - u2 = units[i]; - if(u2->subtype() == SUBTYPE_BASE_UNIT && (points == 0 || (points == 1 && minus))) { - for(size_t i2 = 1; i2 <= cu->countUnits(); i2++) { - if(cu->get(i2, &exp)->baseUnit() == u2 && !cu->get(i2)->hasNonlinearRelationTo(u2)) { - points = 1; - best_u = u2; - minus = !has_positive && (exp < 0); - break; - } - } - } else if(!u2->isSIUnit()) { - } else if(u2->subtype() == SUBTYPE_ALIAS_UNIT) { - au = (AliasUnit*) u2; - bu = (Unit*) au->baseUnit(); - b_exp = au->baseExponent(); - new_points = 0; - new_points_m = 0; - if((b_exp != 1 || bu->subtype() == SUBTYPE_COMPOSITE_UNIT) && !au->hasNonlinearRelationTo(bu)) { - if(bu->subtype() == SUBTYPE_BASE_UNIT) { - for(size_t i2 = 1; i2 <= cu->countUnits(); i2++) { - if(cu->get(i2, &exp) == bu) { - bool m = false; - if(b_exp < 0 && exp < 0) { - b_exp = -b_exp; - exp = -exp; - } else if(b_exp < 0) { - b_exp = -b_exp; - m = true; - } else if(exp < 0) { - exp = -exp; - m = true; - } - new_points = exp - b_exp; - if(new_points < 0) { - new_points = -new_points; - } - new_points = exp - new_points; - if(!allow_only_div && m && new_points >= max_points) { - new_points = -1; - } - if(new_points > points || (!m && minus && new_points == points)) { - points = new_points; - minus = m; - best_u = au; - } - break; - } - } - } else if(au->firstBaseExponent() != 1 || au->firstBaseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { - MathStructure cu_mstruct = ((CompositeUnit*) bu)->generateMathStructure(); - if(b_exp != 1) { - if(cu_mstruct.isMultiplication()) { - for(size_t i2 = 0; i2 < cu_mstruct.size(); i2++) { - if(cu_mstruct[i2].isPower()) cu_mstruct[i2][1].number() *= b_exp; - else cu_mstruct[i2].raise(b_exp); - } - } else if(cu_mstruct.isPower()) { - cu_mstruct[1].number() *= b_exp; - } else { - cu_mstruct.raise(b_exp); - } - } - cu_mstruct = convertToBaseUnits(cu_mstruct); - if(cu_mstruct.isMultiplication()) { - for(size_t i2 = 1; i2 <= cu_mstruct.countChildren(); i2++) { - bu = NULL; - if(cu_mstruct.getChild(i2)->isUnit()) { - bu = cu_mstruct.getChild(i2)->unit(); - b_exp = 1; - } else if(cu_mstruct.getChild(i2)->isPower() && cu_mstruct.getChild(i2)->base()->isUnit() && cu_mstruct.getChild(i2)->exponent()->isNumber() && cu_mstruct.getChild(i2)->exponent()->number().isInteger()) { - bu = cu_mstruct.getChild(i2)->base()->unit(); - b_exp = cu_mstruct.getChild(i2)->exponent()->number().intValue(); - } - if(bu) { - bool b = false; - for(size_t i3 = 1; i3 <= cu->countUnits(); i3++) { - if(cu->get(i3, &exp) == bu) { - b = true; - bool m = false; - if(exp < 0 && b_exp > 0) { - new_points -= b_exp; - exp = -exp; - m = true; - } else if(exp > 0 && b_exp < 0) { - new_points += b_exp; - b_exp = -b_exp; - m = true; - } else { - if(b_exp < 0) new_points_m += b_exp; - else new_points_m -= b_exp; - } - if(exp < 0) { - exp = -exp; - b_exp = -b_exp; - } - if(exp >= b_exp) { - if(m) new_points_m += exp - (exp - b_exp); - else new_points += exp - (exp - b_exp); - } else { - if(m) new_points_m += exp - (b_exp - exp); - else new_points += exp - (b_exp - exp); - } - break; - } - } - if(!b) { - if(b_exp < 0) b_exp = -b_exp; - new_points -= b_exp; - new_points_m -= b_exp; - } - } - } - if(!allow_only_div && new_points_m >= max_points) { - new_points_m = -1; - } - if(new_points > points && new_points >= new_points_m) { - minus = false; - points = new_points; - best_u = au; - } else if(new_points_m > points || (new_points_m == points && minus)) { - minus = true; - points = new_points_m; - best_u = au; - } - } - } - } - } - if(points >= max_points && !minus) break; - } - if(!best_u) return u; - best_u = getOptimalUnit(best_u, false, convert_to_local_currency); - if(points > 1 && points < max_points - 1) { - CompositeUnit *cu_new = new CompositeUnit("", "temporary_composite_convert"); - bool return_cu = minus; - if(minus) { - cu_new->add(best_u, -1); - } else { - cu_new->add(best_u); - } - MathStructure cu_mstruct = ((CompositeUnit*) u)->generateMathStructure(); - if(minus) cu_mstruct *= best_u; - else cu_mstruct /= best_u; - cu_mstruct = convertToBaseUnits(cu_mstruct); - CompositeUnit *cu2 = new CompositeUnit("", "temporary_composite_convert_to_optimal_unit"); - bool b = false; - for(size_t i = 1; i <= cu_mstruct.countChildren(); i++) { - if(cu_mstruct.getChild(i)->isUnit()) { - b = true; - cu2->add(cu_mstruct.getChild(i)->unit()); - } else if(cu_mstruct.getChild(i)->isPower() && cu_mstruct.getChild(i)->base()->isUnit() && cu_mstruct.getChild(i)->exponent()->isNumber() && cu_mstruct.getChild(i)->exponent()->number().isInteger()) { - if(cu_mstruct.getChild(i)->exponent()->number().isGreaterThan(10) || cu_mstruct.getChild(i)->exponent()->number().isLessThan(-10)) { - if(aborted() || cu_mstruct.getChild(i)->exponent()->number().isGreaterThan(1000) || cu_mstruct.getChild(i)->exponent()->number().isLessThan(-1000)) { - b = false; - break; - } - } - b = true; - cu2->add(cu_mstruct.getChild(i)->base()->unit(), cu_mstruct.getChild(i)->exponent()->number().intValue()); - } - } - if(b) { - Unit *u2 = getOptimalUnit(cu2, true, convert_to_local_currency); - b = false; - if(u2->subtype() == SUBTYPE_COMPOSITE_UNIT) { - for(size_t i3 = 1; i3 <= ((CompositeUnit*) u2)->countUnits(); i3++) { - Unit *cu_unit = ((CompositeUnit*) u2)->get(i3, &exp); - for(size_t i4 = 1; i4 <= cu_new->countUnits(); i4++) { - if(cu_new->get(i4, &b_exp) == cu_unit) { - b = true; - cu_new->setExponent(i4, b_exp + exp); - break; - } - } - if(!b) cu_new->add(cu_unit, exp); - } - return_cu = true; - } else if(u2->subtype() == SUBTYPE_ALIAS_UNIT) { - return_cu = true; - for(size_t i3 = 1; i3 <= cu_new->countUnits(); i3++) { - if(cu_new->get(i3, &exp) == u2) { - b = true; - cu_new->setExponent(i3, exp + 1); - break; - } - } - if(!b) cu_new->add(u2); - } - if(!u2->isRegistered() && u2 != cu2) delete u2; - } - delete cu2; - if(return_cu) { - return cu_new; - } else { - delete cu_new; - return best_u; - } - } - if(minus) { - CompositeUnit *cu_new = new CompositeUnit("", "temporary_composite_convert"); - cu_new->add(best_u, -1); - return cu_new; - } else { - return best_u; - } - } - } - return u; -} -MathStructure Calculator::convertToBestUnit(const MathStructure &mstruct, const EvaluationOptions &eo, bool convert_to_si_units) {return convertToOptimalUnit(mstruct, eo, convert_to_si_units);} -MathStructure Calculator::convertToOptimalUnit(const MathStructure &mstruct, const EvaluationOptions &eo, bool convert_to_si_units) { - EvaluationOptions eo2 = eo; - //eo2.calculate_functions = false; - eo2.sync_units = false; - eo2.isolate_x = false; - eo2.test_comparisons = false; - switch(mstruct.type()) { - case STRUCT_POWER: { - if(mstruct.base()->isUnit() && mstruct.exponent()->isNumber() && mstruct.exponent()->number().isRational() && !mstruct.exponent()->number().isZero()) { - MathStructure mstruct_new(mstruct); - int old_points = 0; - bool overflow = false; - if(mstruct_new.exponent()->isInteger()) old_points = mstruct_new.exponent()->number().intValue(&overflow); - else old_points = mstruct_new.exponent()->number().numerator().intValue(&overflow) + mstruct_new.exponent()->number().denominator().intValue() * (mstruct_new.exponent()->number().isNegative() ? -1 : 1); - if(overflow) return mstruct_new; - bool old_minus = false; - if(old_points < 0) { - old_points = -old_points; - old_minus = true; - } - bool is_si_units = mstruct_new.base()->unit()->isSIUnit(); - if(mstruct_new.base()->unit()->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { - mstruct_new.convertToBaseUnits(true, NULL, true, eo2, true); - if(mstruct_new.equals(mstruct, true, true)) { - return mstruct_new; - } else { - mstruct_new.eval(eo2); - } - mstruct_new = convertToOptimalUnit(mstruct_new, eo, convert_to_si_units); - if(mstruct_new.equals(mstruct, true, true)) return mstruct_new; - } else { - CompositeUnit *cu = new CompositeUnit("", "temporary_composite_convert_to_optimal_unit"); - cu->add(mstruct_new.base()->unit(), mstruct_new.exponent()->number().numerator().intValue()); - Unit *u = getOptimalUnit(cu, false, eo.local_currency_conversion); - if(u == cu) { - delete cu; - return mstruct_new; - } - if(eo.approximation == APPROXIMATION_EXACT && cu->hasApproximateRelationTo(u, true)) { - if(!u->isRegistered()) delete u; - delete cu; - return mstruct_new; - } - delete cu; - mstruct_new = convert(mstruct_new, u, eo, true); - if(!u->isRegistered()) delete u; - } - int new_points = 0; - bool new_is_si_units = true; - bool new_minus = true; - bool is_currency = false; - if(mstruct_new.isMultiplication()) { - for(size_t i = 1; i <= mstruct_new.countChildren(); i++) { - if(mstruct_new.getChild(i)->isUnit()) { - if(new_is_si_units && !mstruct_new.getChild(i)->unit()->isSIUnit()) new_is_si_units = false; - is_currency = mstruct_new.getChild(i)->unit()->isCurrency(); - new_points++; - new_minus = false; - } else if(mstruct_new.getChild(i)->isPower() && mstruct_new.getChild(i)->base()->isUnit() && mstruct_new.getChild(i)->exponent()->isNumber() && mstruct_new.getChild(i)->exponent()->number().isRational()) { - int points = 0; - if(mstruct_new.getChild(i)->exponent()->isInteger()) points = mstruct_new.getChild(i)->exponent()->number().intValue(); - else points = mstruct_new.getChild(i)->exponent()->number().numerator().intValue() + mstruct_new.getChild(i)->exponent()->number().denominator().intValue() * (mstruct_new.getChild(i)->exponent()->number().isNegative() ? -1 : 1); - if(new_is_si_units && !mstruct_new.getChild(i)->base()->unit()->isSIUnit()) new_is_si_units = false; - is_currency = mstruct_new.getChild(i)->base()->unit()->isCurrency(); - if(points < 0) { - new_points -= points; - } else { - new_points += points; - new_minus = false; - } - - } - } - } else if(mstruct_new.isPower() && mstruct_new.base()->isUnit() && mstruct_new.exponent()->isNumber() && mstruct_new.exponent()->number().isRational()) { - int points = 0; - if(mstruct_new.exponent()->isInteger()) points = mstruct_new.exponent()->number().intValue(); - else points = mstruct_new.exponent()->number().numerator().intValue() + mstruct_new.exponent()->number().denominator().intValue() * (mstruct_new.exponent()->number().isNegative() ? -1 : 1); - if(new_is_si_units && !mstruct_new.base()->unit()->isSIUnit()) new_is_si_units = false; - is_currency = mstruct_new.base()->unit()->isCurrency(); - if(points < 0) { - new_points = -points; - } else { - new_points = points; - new_minus = false; - } - } else if(mstruct_new.isUnit()) { - if(!mstruct_new.unit()->isSIUnit()) new_is_si_units = false; - is_currency = mstruct_new.unit()->isCurrency(); - new_points = 1; - new_minus = false; - } - if(new_points == 0) return mstruct; - if((new_points > old_points && (!convert_to_si_units || is_si_units || !new_is_si_units)) || (new_points == old_points && (new_minus || !old_minus) && (!is_currency || !eo.local_currency_conversion) && (!convert_to_si_units || !new_is_si_units))) return mstruct; - return mstruct_new; - } - } - case STRUCT_BITWISE_XOR: {} - case STRUCT_BITWISE_OR: {} - case STRUCT_BITWISE_AND: {} - case STRUCT_BITWISE_NOT: {} - case STRUCT_LOGICAL_XOR: {} - case STRUCT_LOGICAL_OR: {} - case STRUCT_LOGICAL_AND: {} - case STRUCT_LOGICAL_NOT: {} - case STRUCT_COMPARISON: {} - case STRUCT_FUNCTION: {} - case STRUCT_VECTOR: {} - case STRUCT_ADDITION: { - if(!mstruct.containsType(STRUCT_UNIT, true)) return mstruct; - MathStructure mstruct_new(mstruct); - bool b = false; - for(size_t i = 0; i < mstruct_new.size(); i++) { - if(aborted()) return mstruct; - if(!mstruct_new.isFunction() || !mstruct_new.function()->getArgumentDefinition(i + 1) || mstruct_new.function()->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) { - mstruct_new[i] = convertToOptimalUnit(mstruct_new[i], eo, convert_to_si_units); - if(!b && !mstruct_new[i].equals(mstruct[i], true, true)) b = true; - } - } - if(b) { - mstruct_new.childrenUpdated(); - if(mstruct.isAddition()) mstruct_new.eval(eo2); - } - return mstruct_new; - } - case STRUCT_UNIT: { - if((!mstruct.unit()->isCurrency() || !eo.local_currency_conversion) && (!convert_to_si_units || mstruct.unit()->isSIUnit())) return mstruct; - Unit *u = getOptimalUnit(mstruct.unit(), false, eo.local_currency_conversion); - if(u != mstruct.unit()) { - if((u->isSIUnit() || (u->isCurrency() && eo.local_currency_conversion)) && (eo.approximation != APPROXIMATION_EXACT || !mstruct.unit()->hasApproximateRelationTo(u, true))) { - MathStructure mstruct_new = convert(mstruct, u, eo, true); - if(!u->isRegistered()) delete u; - return mstruct_new; - } - if(!u->isRegistered()) delete u; - } - break; - } - case STRUCT_MULTIPLICATION: { - if(!mstruct.containsType(STRUCT_UNIT, true)) return mstruct; - int old_points = 0; - bool old_minus = true; - bool is_si_units = true; - bool is_currency = false; - bool child_updated = false; - MathStructure mstruct_old(mstruct); - for(size_t i = 1; i <= mstruct_old.countChildren(); i++) { - if(aborted()) return mstruct_old; - if(mstruct_old.getChild(i)->isUnit()) { - if(is_si_units && !mstruct_old.getChild(i)->unit()->isSIUnit()) is_si_units = false; - is_currency = mstruct_old.getChild(i)->unit()->isCurrency(); - old_points++; - old_minus = false; - } else if(mstruct_old.getChild(i)->isPower() && mstruct_old.getChild(i)->base()->isUnit() && mstruct_old.getChild(i)->exponent()->isNumber() && mstruct_old.getChild(i)->exponent()->number().isRational()) { - int points = 0; - if(mstruct_old.getChild(i)->exponent()->number().isInteger()) points = mstruct_old.getChild(i)->exponent()->number().intValue(); - else points = mstruct_old.getChild(i)->exponent()->number().numerator().intValue() + mstruct_old.getChild(i)->exponent()->number().denominator().intValue() * (mstruct_old.getChild(i)->exponent()->number().isNegative() ? -1 : 1);; - if(is_si_units && !mstruct_old.getChild(i)->base()->unit()->isSIUnit()) is_si_units = false; - is_currency = mstruct_old.getChild(i)->base()->unit()->isCurrency(); - if(points < 0) { - old_points -= points; - } else { - old_points += points; - old_minus = false; - } - } else if(mstruct_old.getChild(i)->size() > 0 && !aborted()) { - mstruct_old[i - 1] = convertToOptimalUnit(mstruct_old[i - 1], eo, convert_to_si_units); - mstruct_old.childUpdated(i); - if(!mstruct_old[i - 1].equals(mstruct[i - 1], true, true)) child_updated = true; - } - } - if(child_updated) mstruct_old.eval(eo2); - if((!is_currency || !eo.local_currency_conversion) && (!convert_to_si_units || is_si_units) && old_points <= 1 && !old_minus) { - return mstruct_old; - } - MathStructure mstruct_new(mstruct_old); - mstruct_new.convertToBaseUnits(true, NULL, true, eo2, true); - if(!mstruct_new.equals(mstruct, true, true)) { - mstruct_new.eval(eo2); - } - if(mstruct_new.type() != STRUCT_MULTIPLICATION) { - if(!mstruct_new.containsInterval(true, true, false, 1, true) && !aborted()) mstruct_new = convertToOptimalUnit(mstruct_new, eo, convert_to_si_units); - } else { - CompositeUnit *cu = new CompositeUnit("", "temporary_composite_convert_to_optimal_unit"); - bool b = false; - child_updated = false; - for(size_t i = 1; i <= mstruct_new.countChildren(); i++) { - if(aborted()) return mstruct_old; - if(mstruct_new.getChild(i)->isUnit()) { - b = true; - cu->add(mstruct_new.getChild(i)->unit()); - } else if(mstruct_new.getChild(i)->isPower() && mstruct_new.getChild(i)->base()->isUnit() && mstruct_new.getChild(i)->exponent()->isNumber() && mstruct_new.getChild(i)->exponent()->number().isInteger()) { - b = true; - cu->add(mstruct_new.getChild(i)->base()->unit(), mstruct_new.getChild(i)->exponent()->number().intValue()); - } else if(mstruct_new.getChild(i)->size() > 0 && !mstruct_new.getChild(i)->containsInterval(true, true, false, 1, true) && !aborted()) { - MathStructure m_i_old(mstruct_new[i - 1]); - mstruct_new[i - 1] = convertToOptimalUnit(mstruct_new[i - 1], eo, convert_to_si_units); - mstruct_new.childUpdated(i); - if(!mstruct_new[i - 1].equals(m_i_old, true, true)) child_updated = true; - } - } - bool is_converted = false; - if(b) { - Unit *u = getOptimalUnit(cu, false, eo.local_currency_conversion); - if(u != cu) { - if(eo.approximation != APPROXIMATION_EXACT || !cu->hasApproximateRelationTo(u, true)) { - mstruct_new = convert(mstruct_new, u, eo, true); - is_converted = true; - } - if(!u->isRegistered()) delete u; - } - } - delete cu; - if((!b || !is_converted) && (!convert_to_si_units || is_si_units)) { - return mstruct_old; - } - if(child_updated) mstruct_new.eval(eo2); - } - if((eo.approximation == APPROXIMATION_EXACT && !mstruct_old.isApproximate()) && (mstruct_new.isApproximate() || (mstruct_old.containsInterval(true, true, false, 0, true) <= 0 && mstruct_new.containsInterval(true, true, false, 0, true) > 0))) return mstruct_old; - if(mstruct_new.equals(mstruct_old, true, true)) return mstruct_old; - int new_points = 0; - bool new_minus = true; - bool new_is_si_units = true; - bool new_is_currency = false; - if(mstruct_new.isMultiplication()) { - for(size_t i = 1; i <= mstruct_new.countChildren(); i++) { - if(aborted()) return mstruct_old; - if(mstruct_new.getChild(i)->isUnit()) { - if(new_is_si_units && !mstruct_new.getChild(i)->unit()->isSIUnit()) new_is_si_units = false; - new_is_currency = mstruct_new.getChild(i)->unit()->isCurrency(); - new_points++; - new_minus = false; - } else if(mstruct_new.getChild(i)->isPower() && mstruct_new.getChild(i)->base()->isUnit() && mstruct_new.getChild(i)->exponent()->isNumber() && mstruct_new.getChild(i)->exponent()->number().isRational()) { - int points = 0; - if(mstruct_new.getChild(i)->exponent()->number().isInteger()) points = mstruct_new.getChild(i)->exponent()->number().intValue(); - else points = mstruct_new.getChild(i)->exponent()->number().numerator().intValue() + mstruct_new.getChild(i)->exponent()->number().denominator().intValue() * (mstruct_new.getChild(i)->exponent()->number().isNegative() ? -1 : 1); - if(new_is_si_units && !mstruct_new.getChild(i)->base()->unit()->isSIUnit()) new_is_si_units = false; - new_is_currency = mstruct_new.getChild(i)->base()->unit()->isCurrency(); - if(points < 0) { - new_points -= points; - } else { - new_points += points; - new_minus = false; - } - } - } - } else if(mstruct_new.isPower() && mstruct_new.base()->isUnit() && mstruct_new.exponent()->isNumber() && mstruct_new.exponent()->number().isRational()) { - int points = 0; - if(mstruct_new.exponent()->number().isInteger()) points = mstruct_new.exponent()->number().intValue(); - else points = mstruct_new.exponent()->number().numerator().intValue() + mstruct_new.exponent()->number().denominator().intValue() * (mstruct_new.exponent()->number().isNegative() ? -1 : 1); - if(new_is_si_units && !mstruct_new.base()->unit()->isSIUnit()) new_is_si_units = false; - new_is_currency = mstruct_new.base()->unit()->isCurrency(); - if(points < 0) { - new_points = -points; - } else { - new_points = points; - new_minus = false; - } - } else if(mstruct_new.isUnit()) { - if(!mstruct_new.unit()->isSIUnit()) new_is_si_units = false; - new_is_currency = mstruct_new.unit()->isCurrency(); - new_points = 1; - new_minus = false; - } - if(new_points == 0) return mstruct_old; - if((new_points > old_points && (!convert_to_si_units || is_si_units || !new_is_si_units)) || (new_points == old_points && (new_minus || !old_minus) && (!new_is_currency || !eo.local_currency_conversion) && (!convert_to_si_units || !new_is_si_units))) return mstruct_old; - return mstruct_new; - } - default: {} - } - return mstruct; -} -MathStructure Calculator::convertToCompositeUnit(const MathStructure &mstruct, CompositeUnit *cu, const EvaluationOptions &eo, bool always_convert) { - return convert(mstruct, cu, eo, always_convert); -} -MathStructure Calculator::convert(const MathStructure &mstruct_to_convert, string str2, const EvaluationOptions &eo, MathStructure *to_struct) { - if(to_struct) to_struct->setUndefined(); - remove_blank_ends(str2); - if(str2.empty()) return mstruct_to_convert; - current_stage = MESSAGE_STAGE_CONVERSION; - int do_prefix = 0; - if(str2.length() > 1 && str2[1] == '?' && (str2[0] == 'b' || str2[0] == 'a' || str2[0] == 'd')) { - do_prefix = 2; - } else if(str2[0] == '?') { - do_prefix = 1; - } - EvaluationOptions eo2 = eo; - eo2.keep_prefixes = !do_prefix; - if(str2[0] == '-') eo2.mixed_units_conversion = MIXED_UNITS_CONVERSION_NONE; - else if(str2[0] == '+') eo2.mixed_units_conversion = MIXED_UNITS_CONVERSION_FORCE_INTEGER; - else if(eo2.mixed_units_conversion != MIXED_UNITS_CONVERSION_NONE) eo2.mixed_units_conversion = MIXED_UNITS_CONVERSION_DOWNWARDS_KEEP; - if(do_prefix || str2[0] == '0' || str2[0] == '+' || str2[0] == '-') { - str2 = str2.substr(do_prefix > 1 ? 2 : 1, str2.length() - (do_prefix > 1 ? 2 : 1)); - remove_blank_ends(str2); - if(str2.empty()) { - current_stage = MESSAGE_STAGE_UNSET; - return convertToMixedUnits(mstruct_to_convert, eo2); - } - } - MathStructure mstruct; - bool b = false; - Unit *u = getUnit(str2); - if(!u) u = getCompositeUnit(str2); - Variable *v = NULL; - if(!u) v = getVariable(str2); - if(!u && !v) { - for(size_t i = 0; i < signs.size(); i++) { - if(str2 == signs[i]) { - u = getUnit(real_signs[i]); - if(!u) v = getVariable(real_signs[i]); - break; - } - } - } - if(v && !v->isKnown()) v = NULL; - if(u) { - if(to_struct) to_struct->set(u); - mstruct.set(convert(mstruct_to_convert, u, eo2, false, false)); - b = true; - } else if(v) { - if(to_struct) to_struct->set(v); - mstruct.set(convert(mstruct_to_convert, (KnownVariable*) v, eo2)); - b = true; - } else { - current_stage = MESSAGE_STAGE_CONVERSION_PARSING; - CompositeUnit cu("", "temporary_composite_convert", "", str2); - if(cu.countUnits() == 2 && cu.get(1)->referenceName() == "g" && cu.get(2)->referenceName() == "m" && str2.substr(0, 2) == "kg") { - int exp; Prefix *p; - if(cu.get(1, &exp, &p) && exp == 1 && p && p->value() == 1000 && cu.get(2, &exp, &p) && exp == -2) { - Unit *u = getUnit("pond"); - if(u) { - MathStructure mtest(convertToBaseUnits(mstruct_to_convert, eo)); - mtest.sort(); - if(mtest.isMultiplication() && mtest.size() >= 3 && mtest[mtest.size() - 3].isUnit() && mtest[mtest.size() - 3].unit()->referenceName() == "g" && mtest[mtest.size() - 2].isPower() && mtest[mtest.size() - 2][1].isMinusOne() && mtest[mtest.size() - 2][0].isUnit() && mtest[mtest.size() - 2][0].unit()->referenceName() == "m" && mtest[mtest.size() - 1].isPower() && mtest[mtest.size() - 1][1] == Number(-2, 1) && mtest[mtest.size() - 1][0].isUnit() && mtest[mtest.size() - 1][0].unit()->referenceName() == "s") { - str2.replace(1, 2, "pond"); - cu.setBaseExpression(str2); - } - } - } - } - current_stage = MESSAGE_STAGE_CONVERSION; - if(to_struct) to_struct->set(cu.generateMathStructure()); - if(cu.countUnits() > 0) { - mstruct.set(convert(mstruct_to_convert, &cu, eo2, false, false)); - b = true; - } - } - if(!b) return mstruct_to_convert; - if(!v && eo2.mixed_units_conversion != MIXED_UNITS_CONVERSION_NONE) mstruct.set(convertToMixedUnits(mstruct, eo2)); - current_stage = MESSAGE_STAGE_UNSET; - return mstruct; -} -Unit* Calculator::addUnit(Unit *u, bool force, bool check_names) { - if(check_names) { - for(size_t i = 1; i <= u->countNames(); i++) { - u->setName(getName(u->getName(i).name, u, force), i); - } - } - if(!u->isLocal() && units.size() > 0 && units[units.size() - 1]->isLocal()) { - units.insert(units.begin(), u); - } else { - units.push_back(u); - } - unitNameChanged(u, true); - for(vector::iterator it = deleted_units.begin(); it != deleted_units.end(); ++it) { - if(*it == u) { - deleted_units.erase(it); - break; - } - } - u->setRegistered(true); - u->setChanged(false); - return u; -} -void Calculator::delPrefixUFV(Prefix *object) { - int i = 0; - for(vector::iterator it = ufvl.begin(); ; ++it) { - del_ufvl: - if(it == ufvl.end()) { - break; - } - if(*it == object) { - it = ufvl.erase(it); - ufvl_t.erase(ufvl_t.begin() + i); - ufvl_i.erase(ufvl_i.begin() + i); - if(it == ufvl.end()) break; - goto del_ufvl; - } - i++; - } - for(size_t i2 = 0; i2 < UFV_LENGTHS; i2++) { - i = 0; - for(vector::iterator it = ufv[0][i2].begin(); ; ++it) { - del_ufv: - if(it == ufv[0][i2].end()) { - break; - } - if(*it == object) { - it = ufv[0][i2].erase(it); - ufv_i[0][i2].erase(ufv_i[0][i2].begin() + i); - if(it == ufv[0][i2].end()) break; - goto del_ufv; - } - i++; - } - } -} -void Calculator::delUFV(ExpressionItem *object) { - int i = 0; - for(vector::iterator it = ufvl.begin(); ; ++it) { - del_ufvl: - if(it == ufvl.end()) { - break; - } - if(*it == object) { - it = ufvl.erase(it); - ufvl_t.erase(ufvl_t.begin() + i); - ufvl_i.erase(ufvl_i.begin() + i); - if(it == ufvl.end()) break; - goto del_ufvl; - } - i++; - } - int i3 = 0; - switch(object->type()) { - case TYPE_FUNCTION: {i3 = 1; break;} - case TYPE_UNIT: {i3 = 2; break;} - case TYPE_VARIABLE: {i3 = 3; break;} - } - for(size_t i2 = 0; i2 < UFV_LENGTHS; i2++) { - i = 0; - for(vector::iterator it = ufv[i3][i2].begin(); ; ++it) { - del_ufv: - if(it == ufv[i3][i2].end()) { - break; - } - if(*it == object) { - it = ufv[i3][i2].erase(it); - ufv_i[i3][i2].erase(ufv_i[i3][i2].begin() + i); - if(it == ufv[i3][i2].end()) break; - goto del_ufv; - } - i++; - } - } -} -Unit* Calculator::getUnit(string name_) { - if(name_.empty()) return NULL; - for(size_t i = 0; i < units.size(); i++) { - if(units[i]->subtype() != SUBTYPE_COMPOSITE_UNIT && (units[i]->hasName(name_))) { - return units[i]; - } - } - return NULL; -} -Unit* Calculator::getActiveUnit(string name_) { - if(name_.empty()) return NULL; - for(size_t i = 0; i < units.size(); i++) { - if(units[i]->isActive() && units[i]->subtype() != SUBTYPE_COMPOSITE_UNIT && units[i]->hasName(name_)) { - return units[i]; - } - } - return NULL; -} -Unit* Calculator::getLocalCurrency() { - if(priv->local_currency) return priv->local_currency; - struct lconv *lc = localeconv(); - if(lc) { - string local_currency = lc->int_curr_symbol; - remove_blank_ends(local_currency); - if(!local_currency.empty()) { - if(local_currency.length() > 3) local_currency = local_currency.substr(0, 3); - return getActiveUnit(local_currency); - } - } - return NULL; -} -void Calculator::setLocalCurrency(Unit *u) { - priv->local_currency = u; -} -Unit* Calculator::getCompositeUnit(string internal_name_) { - if(internal_name_.empty()) return NULL; - for(size_t i = 0; i < units.size(); i++) { - if(units[i]->subtype() == SUBTYPE_COMPOSITE_UNIT && units[i]->hasName(internal_name_)) { - return units[i]; - } - } - return NULL; -} - -Variable* Calculator::addVariable(Variable *v, bool force, bool check_names) { - if(check_names) { - for(size_t i = 1; i <= v->countNames(); i++) { - v->setName(getName(v->getName(i).name, v, force), i); - } - } - if(!v->isLocal() && variables.size() > 0 && variables[variables.size() - 1]->isLocal()) { - variables.insert(variables.begin(), v); - } else { - variables.push_back(v); - } - variableNameChanged(v, true); - for(vector::iterator it = deleted_variables.begin(); it != deleted_variables.end(); ++it) { - if(*it == v) { - deleted_variables.erase(it); - break; - } - } - v->setRegistered(true); - v->setChanged(false); - return v; -} -void Calculator::expressionItemDeactivated(ExpressionItem *item) { - delUFV(item); -} -void Calculator::expressionItemActivated(ExpressionItem *item) { - ExpressionItem *item2 = getActiveExpressionItem(item); - if(item2) { - item2->setActive(false); - } - nameChanged(item); -} -void Calculator::expressionItemDeleted(ExpressionItem *item) { - switch(item->type()) { - case TYPE_VARIABLE: { - for(vector::iterator it = variables.begin(); it != variables.end(); ++it) { - if(*it == item) { - variables.erase(it); - deleted_variables.push_back((Variable*) item); - break; - } - } - break; - } - case TYPE_FUNCTION: { - for(vector::iterator it = functions.begin(); it != functions.end(); ++it) { - if(*it == item) { - functions.erase(it); - deleted_functions.push_back((MathFunction*) item); - break; - } - } - if(item->subtype() == SUBTYPE_DATA_SET) { - for(vector::iterator it = data_sets.begin(); it != data_sets.end(); ++it) { - if(*it == item) { - data_sets.erase(it); - break; - } - } - } - break; - } - case TYPE_UNIT: { - for(vector::iterator it = units.begin(); it != units.end(); ++it) { - if(*it == item) { - units.erase(it); - deleted_units.push_back((Unit*) item); - break; - } - } - break; - } - } - for(size_t i2 = 1; i2 <= item->countNames(); i2++) { - if(item->type() == TYPE_VARIABLE || item->type() == TYPE_UNIT) { - for(size_t i = 0; i < variables.size(); i++) { - if(!variables[i]->isLocal() && !variables[i]->isActive() && variables[i]->hasName(item->getName(i2).name, item->getName(i2).case_sensitive) && !getActiveExpressionItem(variables[i])) {variables[i]->setActive(true);} - } - for(size_t i = 0; i < units.size(); i++) { - if(!units[i]->isLocal() && !units[i]->isActive() && units[i]->hasName(item->getName(i2).name, item->getName(i2).case_sensitive) && !getActiveExpressionItem(units[i])) units[i]->setActive(true); - } - } else { - for(size_t i = 0; i < functions.size(); i++) { - if(!functions[i]->isLocal() && !functions[i]->isActive() && functions[i]->hasName(item->getName(i2).name, item->getName(i2).case_sensitive) && !getActiveExpressionItem(functions[i])) functions[i]->setActive(true); - } - } - } - delUFV(item); -} -void Calculator::nameChanged(ExpressionItem *item, bool new_item) { - if(!item->isActive() || item->countNames() == 0) return; - if(item->type() == TYPE_UNIT && ((Unit*) item)->subtype() == SUBTYPE_COMPOSITE_UNIT) { - return; - } - size_t l2; - if(!new_item) delUFV(item); - for(size_t i2 = 1; i2 <= item->countNames(); i2++) { - l2 = item->getName(i2).name.length(); - if(l2 > UFV_LENGTHS) { - size_t i = 0, l = 0; - for(vector::iterator it = ufvl.begin(); ; ++it) { - if(it != ufvl.end()) { - if(ufvl_t[i] == 'v') - l = ((Variable*) (*it))->getName(ufvl_i[i]).name.length(); - else if(ufvl_t[i] == 'f') - l = ((MathFunction*) (*it))->getName(ufvl_i[i]).name.length(); - else if(ufvl_t[i] == 'u') - l = ((Unit*) (*it))->getName(ufvl_i[i]).name.length(); - else if(ufvl_t[i] == 'p') - l = ((Prefix*) (*it))->shortName(false).length(); - else if(ufvl_t[i] == 'P') - l = ((Prefix*) (*it))->longName(false).length(); - else if(ufvl_t[i] == 'q') - l = ((Prefix*) (*it))->unicodeName(false).length(); - } - if(it == ufvl.end()) { - ufvl.push_back((void*) item); - switch(item->type()) { - case TYPE_VARIABLE: {ufvl_t.push_back('v'); break;} - case TYPE_FUNCTION: {ufvl_t.push_back('f'); break;} - case TYPE_UNIT: {ufvl_t.push_back('u'); break;} - } - ufvl_i.push_back(i2); - break; - } else { - if(l < l2 - || (item->type() == TYPE_VARIABLE && l == l2 && ufvl_t[i] == 'v') - || (item->type() == TYPE_FUNCTION && l == l2 && (ufvl_t[i] != 'p' && ufvl_t[i] != 'P' && ufvl_t[i] != 'q')) - || (item->type() == TYPE_UNIT && l == l2 && (ufvl_t[i] != 'p' && ufvl_t[i] != 'P' && ufvl_t[i] != 'q' && ufvl_t[i] != 'f')) - ) { - ufvl.insert(it, (void*) item); - switch(item->type()) { - case TYPE_VARIABLE: {ufvl_t.insert(ufvl_t.begin() + i, 'v'); break;} - case TYPE_FUNCTION: {ufvl_t.insert(ufvl_t.begin() + i, 'f'); break;} - case TYPE_UNIT: {ufvl_t.insert(ufvl_t.begin() + i, 'u'); break;} - } - ufvl_i.insert(ufvl_i.begin() + i, i2); - break; - } - } - i++; - } - } else if(l2 > 0) { - l2--; - switch(item->type()) { - case TYPE_VARIABLE: { - ufv[3][l2].push_back((void*) item); - ufv_i[3][l2].push_back(i2); - break; - } - case TYPE_FUNCTION: { - ufv[1][l2].push_back((void*) item); - ufv_i[1][l2].push_back(i2); - break; - } - case TYPE_UNIT: { - ufv[2][l2].push_back((void*) item); - ufv_i[2][l2].push_back(i2); - break; - } - } - } - } -} -void Calculator::variableNameChanged(Variable *v, bool new_item) { - nameChanged(v, new_item); -} -void Calculator::functionNameChanged(MathFunction *f, bool new_item) { - nameChanged(f, new_item); -} -void Calculator::unitNameChanged(Unit *u, bool new_item) { - nameChanged(u, new_item); -} - -Variable* Calculator::getVariable(string name_) { - if(name_.empty()) return NULL; - for(size_t i = 0; i < variables.size(); i++) { - if(variables[i]->hasName(name_)) { - return variables[i]; - } - } - return NULL; -} -Variable* Calculator::getActiveVariable(string name_) { - if(name_.empty()) return NULL; - for(size_t i = 0; i < variables.size(); i++) { - if(variables[i]->isActive() && variables[i]->hasName(name_)) { - return variables[i]; - } - } - return NULL; -} -ExpressionItem* Calculator::addExpressionItem(ExpressionItem *item, bool force) { - switch(item->type()) { - case TYPE_VARIABLE: { - return addVariable((Variable*) item, force); - } - case TYPE_FUNCTION: { - if(item->subtype() == SUBTYPE_DATA_SET) return addDataSet((DataSet*) item, force); - else return addFunction((MathFunction*) item, force); - } - case TYPE_UNIT: { - return addUnit((Unit*) item, force); - } - } - return NULL; -} -MathFunction* Calculator::addFunction(MathFunction *f, bool force, bool check_names) { - if(check_names) { - for(size_t i = 1; i <= f->countNames(); i++) { - f->setName(getName(f->getName(i).name, f, force), i); - } - } - if(!f->isLocal() && functions.size() > 0 && functions[functions.size() - 1]->isLocal()) { - functions.insert(functions.begin(), f); - } else { - functions.push_back(f); - } - functionNameChanged(f, true); - for(vector::iterator it = deleted_functions.begin(); it != deleted_functions.end(); ++it) { - if(*it == f) { - deleted_functions.erase(it); - break; - } - } - f->setRegistered(true); - f->setChanged(false); - return f; -} -DataSet* Calculator::addDataSet(DataSet *dc, bool force, bool check_names) { - addFunction(dc, force, check_names); - data_sets.push_back(dc); - return dc; -} -DataSet* Calculator::getDataSet(size_t index) { - if(index > 0 && index <= data_sets.size()) { - return data_sets[index - 1]; - } - return 0; -} -DataSet* Calculator::getDataSet(string name) { - if(name.empty()) return NULL; - for(size_t i = 0; i < data_sets.size(); i++) { - if(data_sets[i]->hasName(name)) { - return data_sets[i]; - } - } - return NULL; -} -MathFunction* Calculator::getFunction(string name_) { - if(name_.empty()) return NULL; - for(size_t i = 0; i < functions.size(); i++) { - if(functions[i]->hasName(name_)) { - return functions[i]; - } - } - return NULL; -} -MathFunction* Calculator::getActiveFunction(string name_) { - if(name_.empty()) return NULL; - for(size_t i = 0; i < functions.size(); i++) { - if(functions[i]->isActive() && functions[i]->hasName(name_)) { - return functions[i]; - } - } - return NULL; -} -bool Calculator::variableNameIsValid(const string &name_) { - return !name_.empty() && name_.find_first_of(ILLEGAL_IN_NAMES) == string::npos && is_not_in(NUMBERS, name_[0]); -} -bool Calculator::functionNameIsValid(const string &name_) { - return !name_.empty() && name_.find_first_of(ILLEGAL_IN_NAMES) == string::npos && is_not_in(NUMBERS, name_[0]); -} -bool Calculator::unitNameIsValid(const string &name_) { - return !name_.empty() && name_.find_first_of(ILLEGAL_IN_UNITNAMES) == string::npos; -} -bool Calculator::variableNameIsValid(const char *name_) { - if(strlen(name_) == 0) return false; - if(is_in(NUMBERS, name_[0])) return false; - for(size_t i = 0; name_[i] != '\0'; i++) { - if(is_in(ILLEGAL_IN_NAMES, name_[i])) return false; - } - return true; -} -bool Calculator::functionNameIsValid(const char *name_) { - if(strlen(name_) == 0) return false; - if(is_in(NUMBERS, name_[0])) return false; - for(size_t i = 0; name_[i] != '\0'; i++) { - if(is_in(ILLEGAL_IN_NAMES, name_[i])) return false; - } - return true; -} -bool Calculator::unitNameIsValid(const char *name_) { - if(strlen(name_) == 0) return false; - for(size_t i = 0; name_[i] != '\0'; i++) { - if(is_in(ILLEGAL_IN_UNITNAMES, name_[i])) return false; - } - return true; -} -#define VERSION_BEFORE(i1, i2, i3) (version_numbers[0] < i1 || (version_numbers[0] == i1 && (version_numbers[1] < i2 || (version_numbers[1] == i2 && version_numbers[2] < i3)))) -bool Calculator::variableNameIsValid(const string &name_, int version_numbers[3], bool is_user_defs) { - return variableNameIsValid(name_.c_str(), version_numbers, is_user_defs); -} -bool Calculator::functionNameIsValid(const string &name_, int version_numbers[3], bool is_user_defs) { - return functionNameIsValid(name_.c_str(), version_numbers, is_user_defs); -} -bool Calculator::unitNameIsValid(const string &name_, int version_numbers[3], bool is_user_defs) { - return unitNameIsValid(name_.c_str(), version_numbers, is_user_defs); -} -bool Calculator::variableNameIsValid(const char *name_, int version_numbers[3], bool is_user_defs) { - if(strlen(name_) == 0) return false; - if(is_in(NUMBERS, name_[0])) return false; - bool b = false; - for(size_t i = 0; name_[i] != '\0'; i++) { - if(is_in(ILLEGAL_IN_NAMES, name_[i])) { - if(is_user_defs && VERSION_BEFORE(0, 8, 1) && name_[i] == BITWISE_NOT_CH) { - b = true; - } else { - return false; - } - } - } - if(b) { - error(true, _("\"%s\" is not allowed in names anymore. Please change the name of \"%s\", or the variable will be lost."), BITWISE_NOT, name_, NULL); - } - return true; -} -bool Calculator::functionNameIsValid(const char *name_, int version_numbers[3], bool is_user_defs) { - if(strlen(name_) == 0) return false; - if(is_in(NUMBERS, name_[0])) return false; - bool b = false; - for(size_t i = 0; name_[i] != '\0'; i++) { - if(is_in(ILLEGAL_IN_NAMES, name_[i])) { - if(is_user_defs && VERSION_BEFORE(0, 8, 1) && name_[i] == BITWISE_NOT_CH) { - b = true; - } else { - return false; - } - } - } - if(b) { - error(true, _("\"%s\" is not allowed in names anymore. Please change the name \"%s\", or the function will be lost."), BITWISE_NOT, name_, NULL); - } - return true; -} -bool Calculator::unitNameIsValid(const char *name_, int version_numbers[3], bool is_user_defs) { - if(strlen(name_) == 0) return false; - bool b = false; - for(size_t i = 0; name_[i] != '\0'; i++) { - if(is_in(ILLEGAL_IN_UNITNAMES, name_[i])) { - if(is_user_defs && VERSION_BEFORE(0, 8, 1) && name_[i] == BITWISE_NOT_CH) { - b = true; - } else { - return false; - } - } - } - if(b) { - error(true, _("\"%s\" is not allowed in names anymore. Please change the name \"%s\", or the unit will be lost."), BITWISE_NOT, name_, NULL); - } - return true; -} -string Calculator::convertToValidVariableName(string name_) { - if(name_.empty()) return "var_1"; - size_t i = 0; - while(true) { - i = name_.find_first_of(ILLEGAL_IN_NAMES_MINUS_SPACE_STR, i); - if(i == string::npos) - break; - name_.erase(name_.begin() + i); - } - gsub(SPACE, UNDERSCORE, name_); - while(is_in(NUMBERS, name_[0])) { - name_.erase(name_.begin()); - } - return name_; -} -string Calculator::convertToValidFunctionName(string name_) { - if(name_.empty()) return "func_1"; - return convertToValidVariableName(name_); -} -string Calculator::convertToValidUnitName(string name_) { - if(name_.empty()) return "new_unit"; - size_t i = 0; - string stmp = ILLEGAL_IN_NAMES_MINUS_SPACE_STR + NUMBERS; - while(true) { - i = name_.find_first_of(stmp, i); - if(i == string::npos) - break; - name_.erase(name_.begin() + i); - } - gsub(SPACE, UNDERSCORE, name_); - return name_; -} -bool Calculator::nameTaken(string name, ExpressionItem *object) { - if(name.empty()) return false; - if(object) { - switch(object->type()) { - case TYPE_VARIABLE: {} - case TYPE_UNIT: { - for(size_t index = 0; index < variables.size(); index++) { - if(variables[index]->isActive() && variables[index]->hasName(name)) { - return variables[index] != object; - } - } - for(size_t i = 0; i < units.size(); i++) { - if(units[i]->isActive() && units[i]->hasName(name)) { - return units[i] != object; - } - } - break; - } - case TYPE_FUNCTION: { - for(size_t index = 0; index < functions.size(); index++) { - if(functions[index]->isActive() && functions[index]->hasName(name)) { - return functions[index] != object; - } - } - break; - } - } - } else { - return getActiveExpressionItem(name) != NULL; - } - return false; -} -bool Calculator::variableNameTaken(string name, Variable *object) { - if(name.empty()) return false; - for(size_t index = 0; index < variables.size(); index++) { - if(variables[index]->isActive() && variables[index]->hasName(name)) { - return variables[index] != object; - } - } - - for(size_t i = 0; i < units.size(); i++) { - if(units[i]->isActive() && units[i]->hasName(name)) { - return true; - } - } - return false; -} -bool Calculator::unitNameTaken(string name, Unit *object) { - if(name.empty()) return false; - for(size_t index = 0; index < variables.size(); index++) { - if(variables[index]->isActive() && variables[index]->hasName(name)) { - return true; - } - } - - for(size_t i = 0; i < units.size(); i++) { - if(units[i]->isActive() && units[i]->hasName(name)) { - return units[i] == object; - } - } - return false; -} -bool Calculator::functionNameTaken(string name, MathFunction *object) { - if(name.empty()) return false; - for(size_t index = 0; index < functions.size(); index++) { - if(functions[index]->isActive() && functions[index]->hasName(name)) { - return functions[index] != object; - } - } - return false; -} -bool Calculator::unitIsUsedByOtherUnits(const Unit *u) const { - const Unit *u2; - for(size_t i = 0; i < units.size(); i++) { - if(units[i] != u) { - u2 = units[i]; - while(u2->subtype() == SUBTYPE_ALIAS_UNIT) { - u2 = ((AliasUnit*) u2)->firstBaseUnit(); - if(u2 == u) { - return true; - } - } - } - } - return false; -} - -bool compare_name(const string &name, const string &str, const size_t &name_length, const size_t &str_index, int base) { - if(name_length == 0) return false; - if(name[0] != str[str_index]) return false; - if(name_length == 1) { - if(base < 2 || base > 10) return is_not_number(str[str_index], base); - return true; - } - for(size_t i = 1; i < name_length; i++) { - if(name[i] != str[str_index + i]) return false; - } - if(base < 2 || base > 10) { - for(size_t i = 0; i < name_length; i++) { - if(is_not_number(str[str_index + i], base)) return true; - } - return false; - } - return true; -} -size_t compare_name_no_case(const string &name, const string &str, const size_t &name_length, const size_t &str_index, int base) { - if(name_length == 0) return 0; - size_t is = str_index; - for(size_t i = 0; i < name_length; i++, is++) { - if(is >= str.length()) return 0; - if((name[i] < 0 && i + 1 < name_length) || (str[is] < 0 && is + 1 < str.length())) { - size_t i2 = 1, is2 = 1; - if(name[i] < 0) { - while(i2 + i < name_length && name[i2 + i] < 0) { - i2++; - } - } - if(str[is] < 0) { - while(is2 + is < str.length() && str[is2 + is] < 0) { - is2++; - } - } - bool isequal = (i2 == is2); - if(isequal) { - for(size_t i3 = 0; i3 < i2; i3++) { - if(str[is + i3] != name[i + i3]) { - isequal = false; - break; - } - } - } - if(!isequal) { - char *gstr1 = utf8_strdown(name.c_str() + (sizeof(char) * i), i2); - char *gstr2 = utf8_strdown(str.c_str() + (sizeof(char) * (is)), is2); - if(!gstr1 || !gstr2) return 0; - if(strcmp(gstr1, gstr2) != 0) {free(gstr1); free(gstr2); return 0;} - free(gstr1); free(gstr2); - } - i += i2 - 1; - is += is2 - 1; - } else if(name[i] != str[is] && !((name[i] >= 'a' && name[i] <= 'z') && name[i] - 32 == str[is]) && !((name[i] <= 'Z' && name[i] >= 'A') && name[i] + 32 == str[is])) { - return 0; - } - } - if(base < 2 || base > 10) { - for(size_t i = str_index; i < is; i++) { - if(is_not_number(str[i], base)) return is - str_index; - } - return 0; - } - return is - str_index; -} - -const char *internal_signs[] = {SIGN_PLUSMINUS, "\b", "+/-", "\b", "⊻", "\a", "∠", "\x1c"}; -#define INTERNAL_SIGNS_COUNT 8 -#define INTERNAL_NUMBER_CHARS "\b" -#define INTERNAL_OPERATORS "\a\b%\x1c" -#define DUODECIMAL_CHARS "EX" - -void Calculator::parseSigns(string &str, bool convert_to_internal_representation) const { - vector q_begin; - vector q_end; - size_t quote_index = 0; - while(true) { - quote_index = str.find_first_of("\"\'", quote_index); - if(quote_index == string::npos) { - break; - } - q_begin.push_back(quote_index); - quote_index = str.find(str[quote_index], quote_index + 1); - if(quote_index == string::npos) { - q_end.push_back(str.length() - 1); - break; - } - q_end.push_back(quote_index); - quote_index++; - } - for(size_t i = 0; i < signs.size(); i++) { - size_t ui = str.find(signs[i]); - size_t ui2 = 0; - while(ui != string::npos) { - for(size_t ui2 = 0; ui2 < q_end.size(); ui2++) { - if(ui >= q_begin[ui2]) { - if(ui <= q_end[ui2]) { - ui = str.find(signs[i], q_end[ui2] + 1); - if(ui == string::npos) break; - } - } else { - break; - } - } - if(ui == string::npos) break; - int index_shift = real_signs[i].length() - signs[i].length(); - for(size_t ui3 = ui2; ui3 < q_begin.size(); ui3++) { - q_begin[ui3] += index_shift; - q_end[ui3] += index_shift; - } - str.replace(ui, signs[i].length(), real_signs[i]); - ui = str.find(signs[i], ui + real_signs[i].length()); - } - } - - size_t prev_ui = string::npos, space_n = 0; - while(true) { - size_t ui = str.find("\xe2\x81", prev_ui == string::npos ? 0 : prev_ui); - if(ui != string::npos && (ui == str.length() - 2 || (str[ui + 2] != -80 && (str[ui + 2] < -76 || str[ui + 2] > -71)))) ui = string::npos; - size_t ui2 = str.find('\xc2', prev_ui == string::npos ? 0 : prev_ui); - if(ui2 != string::npos && (ui2 == str.length() - 1 || (str[ui2 + 1] != -71 && str[ui2 + 1] != -77 && str[ui2 + 1] != -78))) ui2 = string::npos; - if(ui2 != string::npos && (ui == string::npos || ui2 < ui)) ui = ui2; - if(ui != string::npos) { - for(size_t ui3 = 0; ui3 < q_end.size(); ui3++) { - if(ui <= q_end[ui3] && ui >= q_begin[ui3]) { - ui = str.find("\xe2\x81", q_end[ui3] + 1); - if(ui != string::npos && (ui == str.length() - 2 || (str[ui + 2] != -80 && (str[ui + 2] < -76 || str[ui + 2] > -71)))) ui = string::npos; - ui2 = str.find('\xc2', q_end[ui3] + 1); - if(ui2 != string::npos && (ui2 == str.length() - 1 || (str[ui2 + 1] != -71 && str[ui2 + 1] != -77 && str[ui2 + 1] != -78))) ui2 = string::npos; - if(ui2 != string::npos && (ui == string::npos || ui2 < ui)) ui = ui2; - if(ui == string::npos) break; - } - } - } - if(ui == string::npos) break; - int index_shift = (str[ui] == '\xc2' ? -2 : -3); - if(ui == prev_ui) index_shift += 1; - else index_shift += 4; - for(size_t ui3 = 0; ui3 < q_begin.size(); ui3++) { - if(q_begin[ui3] >= ui) { - q_begin[ui3] += index_shift; - q_end[ui3] += index_shift; - } - } - if(str[ui] == '\xc2') { - if(str[ui + 1] == -71) str.replace(ui, 2, ui == prev_ui ? "1)" : "^(1)"); - else if(str[ui + 1] == -78) str.replace(ui, 2, ui == prev_ui ? "2)" : "^(2)"); - else if(str[ui + 1] == -77) str.replace(ui, 2, ui == prev_ui ? "3)" : "^(3)"); - } else { - if(str[ui + 2] == -80) str.replace(ui, 3, ui == prev_ui ? "0)" : "^(0)"); - else if(str[ui + 2] == -76) str.replace(ui, 3, ui == prev_ui ? "4)" : "^(4)"); - else if(str[ui + 2] == -75) str.replace(ui, 3, ui == prev_ui ? "5)" : "^(5)"); - else if(str[ui + 2] == -74) str.replace(ui, 3, ui == prev_ui ? "6)" : "^(6)"); - else if(str[ui + 2] == -73) str.replace(ui, 3, ui == prev_ui ? "7)" : "^(7)"); - else if(str[ui + 2] == -72) str.replace(ui, 3, ui == prev_ui ? "8)" : "^(8)"); - else if(str[ui + 2] == -71) str.replace(ui, 3, ui == prev_ui ? "9)" : "^(9)"); - } - if(ui == prev_ui) { - str.erase(prev_ui - space_n - 1, 1); - prev_ui = ui + 1; - } else { - prev_ui = ui + 4; - } - space_n = 0; - while(prev_ui + 1 < str.length() && str[prev_ui] == SPACE_CH) { - space_n++; - prev_ui++; - } - } - prev_ui = string::npos; - while(true) { - size_t ui = str.find("\xe2\x85", prev_ui == string::npos ? 0 : prev_ui); - if(ui != string::npos && (ui == str.length() - 2 || str[ui + 2] < -112 || str[ui + 2] > -98)) ui = string::npos; - if(ui != string::npos) { - for(size_t ui3 = 0; ui3 < q_end.size(); ui3++) { - if(ui <= q_end[ui3] && ui >= q_begin[ui3]) { - ui = str.find("\xe2\x85", q_end[ui3] + 1); - if(ui != string::npos && (ui == str.length() - 2 || str[ui + 2] < -112 || str[ui + 2] > -98)) ui = string::npos; - if(ui == string::npos) break; - } - } - } - if(ui == string::npos) break; - space_n = 0; - while(ui > 0 && ui - 1 - space_n != 0 && str[ui - 1 - space_n] == SPACE_CH) space_n++; - bool b_add = (ui > 0 && is_in(NUMBER_ELEMENTS, str[ui - 1 - space_n])); - int index_shift = (b_add ? 6 : 5) - 3; - if(str[ui + 2] == -110) index_shift++; - for(size_t ui2 = 0; ui2 < q_begin.size(); ui2++) { - if(q_begin[ui2] >= ui) { - q_begin[ui2] += index_shift; - q_end[ui2] += index_shift; - } - } - if(str[ui + 2] == -98) str.replace(ui, 3, b_add ? "+(7/8)" : "(7/8)"); - else if(str[ui + 2] == -99) str.replace(ui, 3, b_add ? "+(5/8)" : "(5/8)"); - else if(str[ui + 2] == -100) str.replace(ui, 3, b_add ? "+(3/8)" : "(3/8)"); - else if(str[ui + 2] == -101) str.replace(ui, 3, b_add ? "+(1/8)" : "(1/8)"); - else if(str[ui + 2] == -102) str.replace(ui, 3, b_add ? "+(5/6)" : "(5/6)"); - else if(str[ui + 2] == -103) str.replace(ui, 3, b_add ? "+(1/6)" : "(1/6)"); - else if(str[ui + 2] == -104) str.replace(ui, 3, b_add ? "+(4/5)" : "(4/5)"); - else if(str[ui + 2] == -105) str.replace(ui, 3, b_add ? "+(3/5)" : "(3/5)"); - else if(str[ui + 2] == -106) str.replace(ui, 3, b_add ? "+(2/5)" : "(2/5)"); - else if(str[ui + 2] == -107) str.replace(ui, 3, b_add ? "+(1/5)" : "(1/5)"); - else if(str[ui + 2] == -108) str.replace(ui, 3, b_add ? "+(2/3)" : "(2/3)"); - else if(str[ui + 2] == -109) str.replace(ui, 3, b_add ? "+(1/3)" : "(1/3)"); - else if(str[ui + 2] == -110) {str.replace(ui, 3, b_add ? "+(1/10)" : "(1/10)"); ui++;} - else if(str[ui + 2] == -111) str.replace(ui, 3, b_add ? "+(1/9)" : "(1/9)"); - else if(str[ui + 2] == -112) str.replace(ui, 3, b_add ? "+(1/7)" : "(1/7)"); - if(b_add) prev_ui = ui + 6; - else prev_ui = ui + 5; - } - prev_ui = string::npos; - while(true) { - size_t ui = str.find('\xc2', prev_ui == string::npos ? 0 : prev_ui); - if(ui != string::npos && (ui == str.length() - 1 || (str[ui + 1] != -66 && str[ui + 1] != -67 && str[ui + 1] != -68))) ui = string::npos; - if(ui != string::npos) { - for(size_t ui3 = 0; ui3 < q_end.size(); ui3++) { - if(ui <= q_end[ui3] && ui >= q_begin[ui3]) { - ui = str.find('\xc2', q_end[ui3] + 1); - if(ui != string::npos && (ui == str.length() - 1 || (str[ui + 1] != -66 && str[ui + 1] != -67 && str[ui + 1] != -68))) ui = string::npos; - if(ui == string::npos) break; - } - } - } - if(ui == string::npos) break; - space_n = 0; - while(ui > 0 && ui - 1 - space_n != 0 && str[ui - 1 - space_n] == SPACE_CH) space_n++; - bool b_add = (ui > 0 && is_in(NUMBER_ELEMENTS, str[ui - 1 - space_n])); - int index_shift = (b_add ? 6 : 5) - 2; - for(size_t ui2 = 0; ui2 < q_begin.size(); ui2++) { - if(q_begin[ui2] >= ui) { - q_begin[ui2] += index_shift; - q_end[ui2] += index_shift; - } - } - if(str[ui + 1] == -66) str.replace(ui, 2, b_add ? "+(3/4)" : "(3/4)"); - else if(str[ui + 1] == -67) str.replace(ui, 2, b_add ? "+(1/2)" : "(1/2)"); - else if(str[ui + 1] == -68) str.replace(ui, 2, b_add ? "+(1/4)" : "(1/4)"); - if(b_add) prev_ui = ui + 6; - else prev_ui = ui + 5; - } - if(convert_to_internal_representation) { - remove_blank_ends(str); - remove_duplicate_blanks(str); - for(size_t i = 0; i < INTERNAL_SIGNS_COUNT; i += 2) { - size_t ui = str.find(internal_signs[i]); - size_t ui2 = 0; - while(ui != string::npos) { - for(; ui2 < q_end.size(); ui2++) { - if(ui >= q_begin[ui2]) { - if(ui <= q_end[ui2]) { - ui = str.find(internal_signs[i], q_end[ui2] + 1); - if(ui == string::npos) break; - } - } else { - break; - } - } - if(ui == string::npos) break; - int index_shift = strlen(internal_signs[i + 1]) - strlen(internal_signs[i]); - for(size_t ui3 = ui2; ui3 < q_begin.size(); ui3++) { - q_begin[ui3] += index_shift; - q_end[ui3] += index_shift; - } - str.replace(ui, strlen(internal_signs[i]), internal_signs[i + 1]); - ui = str.find(internal_signs[i], ui + strlen(internal_signs[i + 1])); - } - } - } -} - - -MathStructure Calculator::parse(string str, const ParseOptions &po) { - - MathStructure mstruct; - parse(&mstruct, str, po); - return mstruct; - -} - -void Calculator::parse(MathStructure *mstruct, string str, const ParseOptions &parseoptions) { - - ParseOptions po = parseoptions; - MathStructure *unended_function = po.unended_function; - po.unended_function = NULL; - - if(po.base == BASE_UNICODE || (po.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) { - mstruct->set(Number(str, po)); - return; - } - int base = po.base; - if(base == BASE_CUSTOM) { - base = (int) priv->custom_input_base_i; - } else if(base == BASE_GOLDEN_RATIO || base == BASE_SUPER_GOLDEN_RATIO || base == BASE_SQRT2) { - base = 2; - } else if(base == BASE_PI) { - base = 4; - } else if(base == BASE_E) { - base = 3; - } else if(base == BASE_DUODECIMAL) { - base = -12; - } else if(base < 2 || base > 36) { - base = -1; - } - - mstruct->clear(); - - const string *name = NULL; - string stmp, stmp2; - - bool b_prime_quote = true; - - size_t i_degree = str.find(SIGN_DEGREE); - if(i_degree != string::npos && i_degree < str.length() - strlen(SIGN_DEGREE) && is_not_in(NOT_IN_NAMES INTERNAL_OPERATORS NUMBER_ELEMENTS, str[i_degree + strlen(SIGN_DEGREE)])) i_degree = string::npos; - - if(base != -1 && base <= BASE_HEXADECIMAL) { - if(i_degree == string::npos) { - size_t i_quote = str.find('\'', 0); - size_t i_dquote = str.find('\"', 0); - if(i_quote == 0 || i_dquote == 0) { - b_prime_quote = false; - } else if((i_quote != string::npos && i_quote < str.length() - 1 && str.find('\'', i_quote + 1) != string::npos) || (i_quote != string::npos && i_dquote == i_quote + 1) || (i_dquote != string::npos && i_dquote < str.length() - 1 && str.find('\"', i_dquote + 1) != string::npos)) { - b_prime_quote = false; - while(i_dquote != string::npos) { - i_quote = str.rfind('\'', i_dquote - 1); - if(i_quote != string::npos) { - size_t i_prev = str.find_last_not_of(SPACES, i_quote - 1); - if(i_prev != string::npos && is_in(NUMBER_ELEMENTS, str[i_prev])) { - if(is_in(NUMBER_ELEMENTS, str[str.find_first_not_of(SPACES, i_quote + 1)]) && str.find_first_not_of(SPACES NUMBER_ELEMENTS, i_quote + 1) == i_dquote) { - if(i_prev == 0) { - b_prime_quote = true; - break; - } else { - i_prev = str.find_last_not_of(NUMBER_ELEMENTS, i_prev - 1); - if(i_prev == string::npos || (str[i_prev] != '\"' && str[i_prev] != '\'')) { - b_prime_quote = true; - break; - } - } - } - } - } - i_dquote = str.find('\"', i_dquote + 2); - } - } - } - if(b_prime_quote) { - gsub("\'", "′", str); - gsub("\"", "″", str); - } - } - - parseSigns(str, true); - - for(size_t str_index = 0; str_index < str.length(); str_index++) { - if(str[str_index] == '\"' || str[str_index] == '\'') { - if(str_index == str.length() - 1) { - str.erase(str_index, 1); - } else { - size_t i = str.find(str[str_index], str_index + 1); - size_t name_length; - if(i == string::npos) { - i = str.length(); - name_length = i - str_index; - } else { - name_length = i - str_index + 1; - } - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - MathStructure *mstruct = new MathStructure(str.substr(str_index + 1, i - str_index - 1)); - stmp += i2s(addId(mstruct)); - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - str.replace(str_index, name_length, stmp); - str_index += stmp.length() - 1; - } - } - } - - - if(po.brackets_as_parentheses) { - gsub(LEFT_VECTOR_WRAP, LEFT_PARENTHESIS, str); - gsub(RIGHT_VECTOR_WRAP, RIGHT_PARENTHESIS, str); - } - - - size_t isave = 0; - if((isave = str.find(":=", 1)) != string::npos) { - string name = str.substr(0, isave); - string value = str.substr(isave + 2, str.length() - (isave + 2)); - str = value; - str += COMMA; - str += name; - f_save->parse(*mstruct, str, po); - return; - } - - if(po.default_dataset != NULL && str.length() > 1) { - size_t str_index = str.find(DOT_CH, 1); - while(str_index != string::npos) { - if(str_index + 1 < str.length() && ((is_not_number(str[str_index + 1], base) && is_not_in(INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index + 1]) && is_not_in(INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index - 1])) || (is_not_in(INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index + 1]) && is_not_number(str[str_index - 1], base) && is_not_in(INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index - 1])))) { - size_t dot_index = str.find_first_of(NOT_IN_NAMES INTERNAL_OPERATORS DOT, str_index + 1); - if(dot_index != string::npos && str[dot_index] == DOT_CH) { - str_index = dot_index; - } else { - size_t property_index = str.find_last_of(NOT_IN_NAMES INTERNAL_OPERATORS, str_index - 1); - if(property_index == string::npos) { - str.insert(0, 1, '.'); - str.insert(0, po.default_dataset->referenceName()); - str_index += po.default_dataset->referenceName().length() + 1; - } else { - str.insert(property_index + 1, 1, '.'); - str.insert(property_index + 1, po.default_dataset->referenceName()); - str_index += po.default_dataset->referenceName().length() + 1; - } - } - } - str_index = str.find(DOT_CH, str_index + 1); - } - } - - //remove spaces in numbers - size_t space_i = 0; - if(!po.rpn) { - space_i = str.find(SPACE_CH, 0); - while(space_i != string::npos) { - if(is_in(NUMBERS INTERNAL_NUMBER_CHARS DOT, str[space_i + 1]) && is_in(NUMBERS INTERNAL_NUMBER_CHARS DOT, str[space_i - 1])) { - str.erase(space_i, 1); - space_i--; - } - space_i = str.find(SPACE_CH, space_i + 1); - } - } - - if(base != -1 && base <= BASE_HEXADECIMAL) { - bool b_degree = (i_degree != string::npos); - size_t i_quote = str.find("′"); - size_t i_dquote = str.find("″"); - while(i_quote != string::npos || i_dquote != string::npos) { - size_t i_op = 0; - if(i_quote == string::npos || i_dquote < i_quote) { - bool b = false; - if(b_degree) { - i_degree = str.rfind(SIGN_DEGREE, i_dquote - 1); - if(i_degree != string::npos && i_degree > 0 && i_degree < i_dquote) { - size_t i_op = str.find_first_not_of(SPACE, i_degree + strlen(SIGN_DEGREE)); - if(i_op != string::npos) { - i_op = str.find_first_not_of(SPACE, i_degree + strlen(SIGN_DEGREE)); - if(is_in(NUMBER_ELEMENTS, str[i_op])) i_op = str.find_first_not_of(NUMBER_ELEMENTS SPACE, i_op); - else i_op = 0; - } - size_t i_prev = string::npos; - if(i_op == i_dquote) { - i_prev = str.find_last_not_of(SPACE, i_degree - 1); - if(i_prev != string::npos) { - if(is_in(NUMBER_ELEMENTS, str[i_prev])) { - i_prev = str.find_last_not_of(NUMBER_ELEMENTS SPACE, i_prev); - if(i_prev == string::npos) i_prev = 0; - else i_prev++; - } else { - i_prev = string::npos; - } - } - } - if(i_prev != string::npos) { - str.insert(i_prev, LEFT_PARENTHESIS); - i_degree++; - i_op++; - str.replace(i_op, strlen("″"), "arcsec" RIGHT_PARENTHESIS); - str.replace(i_degree, strlen(SIGN_DEGREE), "deg" PLUS); - b = true; - } - } - } - if(!b) { - if(str.length() >= i_dquote + strlen("″") && is_in(NUMBERS, str[i_dquote + strlen("″")])) str.insert(i_dquote + strlen("″"), " "); - str.replace(i_dquote, strlen("″"), b_degree ? "arcsec" : "in"); - i_op = i_dquote; - } - } else { - bool b = false; - if(b_degree) { - i_degree = str.rfind(SIGN_DEGREE, i_quote - 1); - if(i_degree != string::npos && i_degree > 0 && i_degree < i_quote) { - size_t i_op = str.find_first_not_of(SPACE, i_degree + strlen(SIGN_DEGREE)); - if(i_op != string::npos) { - i_op = str.find_first_not_of(SPACE, i_degree + strlen(SIGN_DEGREE)); - if(is_in(NUMBER_ELEMENTS, str[i_op])) i_op = str.find_first_not_of(NUMBER_ELEMENTS SPACE, i_op); - else i_op = 0; - } - size_t i_prev = string::npos; - if(i_op == i_quote) { - i_prev = str.find_last_not_of(SPACE, i_degree - 1); - if(i_prev != string::npos) { - if(is_in(NUMBER_ELEMENTS, str[i_prev])) { - i_prev = str.find_last_not_of(NUMBER_ELEMENTS SPACE, i_prev); - if(i_prev == string::npos) i_prev = 0; - else i_prev++; - } else { - i_prev = string::npos; - } - } - } - if(i_prev != string::npos) { - str.insert(i_prev, LEFT_PARENTHESIS); - i_degree++; - i_quote++; - i_op++; - if(i_dquote != string::npos) { - i_dquote++; - size_t i_op2 = str.find_first_not_of(SPACE, i_quote + strlen("′")); - if(i_op2 != string::npos && is_in(NUMBER_ELEMENTS, str[i_op2])) i_op2 = str.find_first_not_of(NUMBER_ELEMENTS SPACE, i_op2); - else i_op2 = 0; - if(i_op2 == i_dquote) { - str.replace(i_dquote, strlen("″"), "arcsec" RIGHT_PARENTHESIS); - i_op = i_op2; - } - } - str.replace(i_quote, strlen("′"), i_op == i_quote ? "arcmin" RIGHT_PARENTHESIS : "arcmin" PLUS); - str.replace(i_degree, strlen(SIGN_DEGREE), "deg" PLUS); - b = true; - } - } - } - if(!b) { - i_op = str.find_first_not_of(SPACE, i_quote + strlen("′")); - if(i_op != string::npos && is_in(NUMBER_ELEMENTS, str[i_op])) i_op = str.find_first_not_of(NUMBER_ELEMENTS SPACE, i_op); - else i_op = 0; - size_t i_prev = string::npos; - if(((!b_degree && i_op == string::npos) || i_op == i_dquote) && i_quote != 0) { - i_prev = str.find_last_not_of(SPACE, i_quote - 1); - if(i_prev != string::npos) { - if(is_in(NUMBER_ELEMENTS, str[i_prev])) { - i_prev = str.find_last_not_of(NUMBER_ELEMENTS SPACE, i_prev); - if(i_prev == string::npos) i_prev = 0; - else i_prev++; - } else { - i_prev = string::npos; - } - } - } - if(i_prev != string::npos) { - str.insert(i_prev, LEFT_PARENTHESIS); - i_quote++; - if(i_op == string::npos) str += b_degree ? "arcsec" RIGHT_PARENTHESIS : "in" RIGHT_PARENTHESIS; - else str.replace(i_op + 1, strlen("″"), b_degree ? "arcsec" RIGHT_PARENTHESIS : "in" RIGHT_PARENTHESIS); - str.replace(i_quote, strlen("′"), b_degree ? "arcmin" PLUS : "ft" PLUS); - if(i_op == string::npos) break; - i_op++; - } else { - if(str.length() >= i_quote + strlen("′") && is_in(NUMBERS, str[i_quote + strlen("′")])) str.insert(i_quote + strlen("′"), " "); - str.replace(i_quote, strlen("′"), b_degree ? "arcmin" : "ft"); - i_op = i_quote; - } - } - } - if(i_dquote != string::npos) i_dquote = str.find("″", i_op); - if(i_quote != string::npos) i_quote = str.find("′", i_op); - } - } - - size_t i_mod = str.find("%"); - if(i_mod != string::npos && !v_percent->hasName("%")) i_mod = string::npos; - while(i_mod != string::npos) { - if(po.rpn) { - if(i_mod == 0 || is_not_in(OPERATORS "\\" INTERNAL_OPERATORS SPACE, str[i_mod - 1])) { - str.replace(i_mod, 1, v_percent->referenceName()); - i_mod += v_percent->referenceName().length() - 1; - } - } else if(i_mod == 0 || i_mod == str.length() - 1 || (is_in(RIGHT_PARENTHESIS RIGHT_VECTOR_WRAP COMMA OPERATORS "%\a\b", str[i_mod + 1]) && str[i_mod + 1] != BITWISE_NOT_CH && str[i_mod + 1] != NOT_CH) || is_in(LEFT_PARENTHESIS LEFT_VECTOR_WRAP COMMA OPERATORS "\a\b", str[i_mod - 1])) { - str.replace(i_mod, 1, v_percent->referenceName()); - i_mod += v_percent->referenceName().length() - 1; - } - i_mod = str.find("%", i_mod + 1); - } - - if(po.rpn) { - gsub("&&", "& &", str); - gsub("||", "| |", str); - gsub("\%\%", "\% \%", str); - } - - for(size_t str_index = 0; str_index < str.length(); str_index++) { - if(str[str_index] == LEFT_VECTOR_WRAP_CH) { - int i4 = 1; - size_t i3 = str_index; - while(true) { - i3 = str.find_first_of(LEFT_VECTOR_WRAP RIGHT_VECTOR_WRAP, i3 + 1); - if(i3 == string::npos) { - for(; i4 > 0; i4--) { - str += RIGHT_VECTOR_WRAP; - } - i3 = str.length() - 1; - } else if(str[i3] == LEFT_VECTOR_WRAP_CH) { - i4++; - } else if(str[i3] == RIGHT_VECTOR_WRAP_CH) { - i4--; - if(i4 > 0) { - size_t i5 = str.find_first_not_of(SPACE, i3 + 1); - if(i5 != string::npos && str[i5] == LEFT_VECTOR_WRAP_CH) { - str.insert(i5, COMMA); - } - } - } - if(i4 == 0) { - stmp2 = str.substr(str_index + 1, i3 - str_index - 1); - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - stmp += i2s(parseAddVectorId(stmp2, po)); - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - str.replace(str_index, i3 + 1 - str_index, stmp); - str_index += stmp.length() - 1; - break; - } - } - } else if(str[str_index] == '\\' && str_index + 1 < str.length() && (is_not_in(NOT_IN_NAMES INTERNAL_OPERATORS NUMBERS, str[str_index + 1]) || (!po.rpn && str_index > 0 && is_in(NUMBERS SPACE PLUS MINUS BITWISE_NOT NOT LEFT_PARENTHESIS, str[str_index + 1])))) { - if(is_in(NUMBERS SPACE PLUS MINUS BITWISE_NOT NOT LEFT_PARENTHESIS, str[str_index + 1])) { - str.replace(str_index, 1, "//"); - str_index++; - } else { - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - size_t l = 1; - if(str[str_index + l] < 0) { - do { - l++; - } while(str_index + l < str.length() && str[str_index + l] < 0 && (unsigned char) str[str_index + l] < 0xC0); - l--; - } - MathStructure *mstruct = new MathStructure(str.substr(str_index + 1, l)); - stmp += i2s(addId(mstruct)); - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - str.replace(str_index, l + 1, stmp); - str_index += stmp.length() - l; - } - } else if(str[str_index] == '!' && po.functions_enabled) { - if(str_index > 0 && (str.length() - str_index == 1 || str[str_index + 1] != EQUALS_CH)) { - stmp2 = ""; - size_t i5 = str.find_last_not_of(SPACE, str_index - 1); - size_t i3; - if(i5 == string::npos) { - } else if(str[i5] == RIGHT_PARENTHESIS_CH) { - if(i5 == 0) { - stmp2 = str.substr(0, i5 + 1); - } else { - i3 = i5 - 1; - size_t i4 = 1; - while(true) { - i3 = str.find_last_of(LEFT_PARENTHESIS RIGHT_PARENTHESIS, i3); - if(i3 == string::npos) { - stmp2 = str.substr(0, i5 + 1); - break; - } - if(str[i3] == RIGHT_PARENTHESIS_CH) { - i4++; - } else { - i4--; - if(i4 == 0) { - stmp2 = str.substr(i3, i5 + 1 - i3); - break; - } - } - if(i3 == 0) { - stmp2 = str.substr(0, i5 + 1); - break; - } - i3--; - } - } - } else if(str[i5] == ID_WRAP_RIGHT_CH && (i3 = str.find_last_of(ID_WRAP_LEFT, i5 - 1)) != string::npos) { - stmp2 = str.substr(i3, i5 + 1 - i3); - } else if(is_not_in(RESERVED OPERATORS INTERNAL_OPERATORS SPACES VECTOR_WRAPS PARENTHESISS COMMAS, str[i5])) { - i3 = str.find_last_of(RESERVED OPERATORS INTERNAL_OPERATORS SPACES VECTOR_WRAPS PARENTHESISS COMMAS, i5); - if(i3 == string::npos) { - stmp2 = str.substr(0, i5 + 1); - } else { - stmp2 = str.substr(i3 + 1, i5 - i3); - } - } - if(!stmp2.empty()) { - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - int ifac = 1; - i3 = str_index + 1; - size_t i4 = i3; - while((i3 = str.find_first_not_of(SPACE, i3)) != string::npos && str[i3] == '!') { - ifac++; - i3++; - i4 = i3; - } - if(ifac == 2) stmp += i2s(parseAddId(f_factorial2, stmp2, po)); - else if(ifac == 1) stmp += i2s(parseAddId(f_factorial, stmp2, po)); - else stmp += i2s(parseAddIdAppend(f_multifactorial, MathStructure(ifac, 1, 0), stmp2, po)); - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - str.replace(i5 - stmp2.length() + 1, stmp2.length() + i4 - i5 - 1, stmp); - str_index = stmp.length() + i5 - stmp2.length(); - } - } - } else if(!po.rpn && (str[str_index] == 'c' || str[str_index] == 'C') && str.length() > str_index + 6 && str[str_index + 5] == SPACE_CH && (str_index == 0 || is_in(OPERATORS INTERNAL_OPERATORS PARENTHESISS, str[str_index - 1])) && compare_name_no_case("compl", str, 5, str_index, base)) { - str.replace(str_index, 6, BITWISE_NOT); - } else if(str[str_index] == SPACE_CH) { - size_t i = str.find(SPACE, str_index + 1); - if(po.rpn && i == string::npos) i = str.length(); - if(i != string::npos) { - i -= str_index + 1; - size_t il = 0; - if(i == per_str_len && (il = compare_name_no_case(per_str, str, per_str_len, str_index + 1, base))) { - str.replace(str_index + 1, il, DIVISION); - str_index++; - } else if(i == times_str_len && (il = compare_name_no_case(times_str, str, times_str_len, str_index + 1, base))) { - str.replace(str_index + 1, il, MULTIPLICATION); - str_index++; - } else if(i == plus_str_len && (il = compare_name_no_case(plus_str, str, plus_str_len, str_index + 1, base))) { - str.replace(str_index + 1, il, PLUS); - str_index++; - } else if(i == minus_str_len && (il = compare_name_no_case(minus_str, str, minus_str_len, str_index + 1, base))) { - str.replace(str_index + 1, il, MINUS); - str_index++; - } else if(and_str_len > 0 && i == and_str_len && (il = compare_name_no_case(and_str, str, and_str_len, str_index + 1, base))) { - str.replace(str_index + 1, il, LOGICAL_AND); - str_index += 2; - } else if(i == AND_str_len && (il = compare_name_no_case(AND_str, str, AND_str_len, str_index + 1, base))) { - str.replace(str_index + 1, il, LOGICAL_AND); - str_index += 2; - } else if(or_str_len > 0 && i == or_str_len && (il = compare_name_no_case(or_str, str, or_str_len, str_index + 1, base))) { - str.replace(str_index + 1, il, LOGICAL_OR); - str_index += 2; - } else if(i == OR_str_len && (il = compare_name_no_case(OR_str, str, OR_str_len, str_index + 1, base))) { - str.replace(str_index + 1, il, LOGICAL_OR); - str_index += 2; - } else if(i == XOR_str_len && (il = compare_name_no_case(XOR_str, str, XOR_str_len, str_index + 1, base))) { - str.replace(str_index + 1, il, "\a"); - str_index++; - } else if(i == 5 && (il = compare_name_no_case("bitor", str, 5, str_index + 1, base))) { - str.replace(str_index + 1, il, BITWISE_OR); - str_index++; - } else if(i == 6 && (il = compare_name_no_case("bitand", str, 6, str_index + 1, base))) { - str.replace(str_index + 1, il, BITWISE_AND); - str_index++; - } else if(i == 3 && (il = compare_name_no_case("mod", str, 3, str_index + 1, base))) { - str.replace(str_index + 1, il, "\%\%"); - str_index += 2; - } else if(i == 3 && (il = compare_name_no_case("rem", str, 3, str_index + 1, base))) { - str.replace(str_index + 1, il, "%"); - str_index++; - } else if(i == 3 && (il = compare_name_no_case("div", str, 3, str_index + 1, base))) { - if(po.rpn) { - str.replace(str_index + 1, il, "\\"); - str_index++; - } else { - str.replace(str_index + 1, il, "//"); - str_index += 2; - } - } - } - } else if(str_index > 0 && base >= 2 && base <= 10 && is_in(EXPS, str[str_index]) && str_index + 1 < str.length() && (is_in(NUMBER_ELEMENTS, str[str_index + 1]) || (is_in(PLUS MINUS, str[str_index + 1]) && str_index + 2 < str.length() && is_in(NUMBER_ELEMENTS, str[str_index + 2]))) && is_in(NUMBER_ELEMENTS, str[str_index - 1])) { - //don't do anything when e is used instead of E for EXP - } else if(base <= 33 && str[str_index] == '0' && (str_index == 0 || is_in(NOT_IN_NAMES INTERNAL_OPERATORS, str[str_index - 1]))) { - if(str_index + 2 < str.length() && (str[str_index + 1] == 'x' || str[str_index + 1] == 'X') && is_in(NUMBER_ELEMENTS "abcdefABCDEF", str[str_index + 2])) { - //hexadecimal number 0x... - if(po.base == BASE_HEXADECIMAL) { - str.erase(str_index, 2); - } else { - size_t i; - if(po.rpn) i = str.find_first_not_of(NUMBER_ELEMENTS "abcdefABCDEF", str_index + 2); - else i = str.find_first_not_of(SPACE NUMBER_ELEMENTS "abcdefABCDEF", str_index + 2); - size_t name_length; - if(i == string::npos) i = str.length(); - while(str[i - 1] == SPACE_CH) i--; - name_length = i - str_index; - ParseOptions po_hex = po; - po_hex.base = BASE_HEXADECIMAL; - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - MathStructure *mstruct = new MathStructure(Number(str.substr(str_index, i - str_index), po_hex)); - stmp += i2s(addId(mstruct)); - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - str.replace(str_index, name_length, stmp); - str_index += stmp.length() - 1; - } - - } else if(base <= 12 && str_index + 2 < str.length() && (str[str_index + 1] == 'b' || str[str_index + 1] == 'B') && is_in("01", str[str_index + 2])) { - //binary number 0b... - if(po.base == BASE_BINARY) { - str.erase(str_index, 2); - } else { - size_t i; - if(po.rpn) i = str.find_first_not_of(NUMBER_ELEMENTS, str_index + 2); - else i = str.find_first_not_of(SPACE NUMBER_ELEMENTS, str_index + 2); - size_t name_length; - if(i == string::npos) i = str.length(); - while(str[i - 1] == SPACE_CH) i--; - name_length = i - str_index; - ParseOptions po_bin = po; - po_bin.base = BASE_BINARY; - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - MathStructure *mstruct = new MathStructure(Number(str.substr(str_index, i - str_index), po_bin)); - stmp += i2s(addId(mstruct)); - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - str.replace(str_index, name_length, stmp); - str_index += stmp.length() - 1; - } - } else if(base <= 24 && str_index + 2 < str.length() && (str[str_index + 1] == 'o' || str[str_index + 1] == 'O') && is_in(NUMBERS, str[str_index + 2])) { - //octal number 0o... - if(po.base == BASE_OCTAL) { - str.erase(str_index, 2); - } else { - size_t i; - if(po.rpn) i = str.find_first_not_of(NUMBER_ELEMENTS, str_index + 2); - else i = str.find_first_not_of(SPACE NUMBER_ELEMENTS, str_index + 2); - size_t name_length; - if(i == string::npos) i = str.length(); - while(str[i - 1] == SPACE_CH) i--; - name_length = i - str_index; - ParseOptions po_oct = po; - po_oct.base = BASE_OCTAL; - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - MathStructure *mstruct = new MathStructure(Number(str.substr(str_index, i - str_index), po_oct)); - stmp += i2s(addId(mstruct)); - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - str.replace(str_index, name_length, stmp); - str_index += stmp.length() - 1; - } - } - } else if(is_not_in(NUMBERS INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index])) { - bool p_mode = false; - void *best_p_object = NULL; - Prefix *best_p = NULL; - size_t best_pl = 0; - size_t best_pnl = 0; - bool moved_forward = false; - const string *found_function_name = NULL; - bool case_sensitive = false; - size_t found_function_name_length = 0; - void *found_function = NULL, *object = NULL; - int vt2 = -1; - size_t ufv_index; - size_t name_length; - size_t vt3 = 0; - char ufvt = 0; - size_t last_name_char = str.find_first_of(NOT_IN_NAMES INTERNAL_OPERATORS, str_index + 1); - if(last_name_char == string::npos) { - last_name_char = str.length() - 1; - } else { - last_name_char--; - } - size_t last_unit_char = str.find_last_not_of(NUMBERS, last_name_char); - size_t name_chars_left = last_name_char - str_index + 1; - size_t unit_chars_left = last_unit_char - str_index + 1; - if(name_chars_left <= UFV_LENGTHS) { - ufv_index = name_chars_left - 1; - vt2 = 0; - } else { - ufv_index = 0; - } - Prefix *p = NULL; - while(vt2 < 4) { - name = NULL; - p = NULL; - switch(vt2) { - case -1: { - if(ufv_index < ufvl.size()) { - switch(ufvl_t[ufv_index]) { - case 'v': { - if(po.variables_enabled && !p_mode) { - name = &((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).name; - case_sensitive = ((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).case_sensitive; - name_length = name->length(); - if(name_length < found_function_name_length) { - name = NULL; - } else if(po.limit_implicit_multiplication) { - if(name_length != name_chars_left && name_length != unit_chars_left) name = NULL; - } else if(name_length > name_chars_left) { - name = NULL; - } - } - break; - } - case 'f': { - if(po.functions_enabled && !found_function_name && !p_mode) { - name = &((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).name; - case_sensitive = ((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).case_sensitive; - name_length = name->length(); - if(po.limit_implicit_multiplication) { - if(name_length != name_chars_left && name_length != unit_chars_left) name = NULL; - } else if(name_length > name_chars_left || name_length < found_function_name_length) { - name = NULL; - } - } - break; - } - case 'u': { - if(po.units_enabled && !p_mode) { - name = &((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).name; - case_sensitive = ((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).case_sensitive; - name_length = name->length(); - if(name_length < found_function_name_length) { - name = NULL; - } else if(po.limit_implicit_multiplication || ((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).plural) { - if(name_length != unit_chars_left) name = NULL; - } else if(name_length > unit_chars_left) { - name = NULL; - } - } - break; - } - case 'p': { - if(!p && po.units_enabled) { - name = &((Prefix*) ufvl[ufv_index])->shortName(); - name_length = name->length(); - if(name_length >= unit_chars_left || name_length < found_function_name_length) { - name = NULL; - } - } - case_sensitive = true; - break; - } - case 'P': { - if(!p && po.units_enabled) { - name = &((Prefix*) ufvl[ufv_index])->longName(); - name_length = name->length(); - if(name_length >= unit_chars_left || name_length < found_function_name_length) { - name = NULL; - } - } - case_sensitive = false; - break; - } - case 'q': { - if(!p && po.units_enabled) { - name = &((Prefix*) ufvl[ufv_index])->unicodeName(); - name_length = name->length(); - if(name_length >= unit_chars_left || name_length < found_function_name_length) { - name = NULL; - } - } - case_sensitive = true; - break; - } - } - ufvt = ufvl_t[ufv_index]; - object = ufvl[ufv_index]; - ufv_index++; - break; - } else { - if(found_function_name) { - vt2 = 4; - break; - } - vt2 = 0; - vt3 = 0; - if(po.limit_implicit_multiplication && unit_chars_left <= UFV_LENGTHS) { - ufv_index = unit_chars_left - 1; - } else { - ufv_index = UFV_LENGTHS - 1; - } - } - } - case 0: { - if(po.units_enabled && ufv_index < unit_chars_left - 1 && vt3 < ufv[vt2][ufv_index].size()) { - object = ufv[vt2][ufv_index][vt3]; - switch(ufv_i[vt2][ufv_index][vt3]) { - case 1: { - ufvt = 'P'; - name = &((Prefix*) object)->longName(); - name_length = name->length(); - case_sensitive = false; - break; - } - case 2: { - ufvt = 'p'; - name = &((Prefix*) object)->shortName(); - name_length = name->length(); - case_sensitive = true; - break; - } - case 3: { - ufvt = 'q'; - name = &((Prefix*) object)->unicodeName(); - name_length = name->length(); - case_sensitive = true; - break; - } - } - vt3++; - break; - } - vt2 = 1; - vt3 = 0; - } - case 1: { - if(!found_function_name && po.functions_enabled && !p_mode && (!po.limit_implicit_multiplication || ufv_index + 1 == unit_chars_left || ufv_index + 1 == name_chars_left) && vt3 < ufv[vt2][ufv_index].size()) { - object = ufv[vt2][ufv_index][vt3]; - ufvt = 'f'; - name = &((MathFunction*) object)->getName(ufv_i[vt2][ufv_index][vt3]).name; - name_length = name->length(); - case_sensitive = ((MathFunction*) object)->getName(ufv_i[vt2][ufv_index][vt3]).case_sensitive; - vt3++; - break; - } - vt2 = 2; - vt3 = 0; - } - case 2: { - if(po.units_enabled && !p_mode && (!po.limit_implicit_multiplication || ufv_index + 1 == unit_chars_left) && ufv_index < unit_chars_left && vt3 < ufv[vt2][ufv_index].size()) { - object = ufv[vt2][ufv_index][vt3]; - if(ufv_index + 1 == unit_chars_left || !((Unit*) object)->getName(ufv_i[vt2][ufv_index][vt3]).plural) { - ufvt = 'u'; - name = &((Unit*) object)->getName(ufv_i[vt2][ufv_index][vt3]).name; - name_length = name->length(); - case_sensitive = ((Unit*) object)->getName(ufv_i[vt2][ufv_index][vt3]).case_sensitive; - } - vt3++; - break; - } - vt2 = 3; - vt3 = 0; - } - case 3: { - if(po.variables_enabled && !p_mode && (!po.limit_implicit_multiplication || ufv_index + 1 == unit_chars_left || ufv_index + 1 == name_chars_left) && vt3 < ufv[vt2][ufv_index].size()) { - object = ufv[vt2][ufv_index][vt3]; - ufvt = 'v'; - name = &((Variable*) object)->getName(ufv_i[vt2][ufv_index][vt3]).name; - name_length = name->length(); - case_sensitive = ((Variable*) object)->getName(ufv_i[vt2][ufv_index][vt3]).case_sensitive; - vt3++; - break; - } - if(ufv_index == 0 || found_function_name) { - vt2 = 4; - } else { - ufv_index--; - vt3 = 0; - vt2 = 0; - } - } - } - if(name && name_length >= found_function_name_length && ((case_sensitive && compare_name(*name, str, name_length, str_index, base)) || (!case_sensitive && (name_length = compare_name_no_case(*name, str, name_length, str_index, base))))) { - moved_forward = false; - switch(ufvt) { - case 'v': { - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - stmp += i2s(addId(new MathStructure((Variable*) object))); - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - str.replace(str_index, name_length, stmp); - str_index += stmp.length(); - moved_forward = true; - break; - } - case 'f': { - if(((ExpressionItem*) object)->subtype() == SUBTYPE_DATA_SET && str[str_index + name_length] == DOT_CH) { - str[str_index + name_length] = LEFT_PARENTHESIS_CH; - size_t dot2_index = str.find(DOT_CH, str_index + name_length + 1); - str[dot2_index] = COMMA_CH; - size_t end_index = str.find_first_of(NOT_IN_NAMES INTERNAL_OPERATORS, dot2_index + 1); - if(end_index == string::npos) str += RIGHT_PARENTHESIS_CH; - else str.insert(end_index, 1, RIGHT_PARENTHESIS_CH); - } - size_t not_space_index; - if((not_space_index = str.find_first_not_of(SPACES, str_index + name_length)) == string::npos || str[not_space_index] != LEFT_PARENTHESIS_CH) { - found_function = object; - found_function_name = name; - found_function_name_length = name_length; - break; - } - set_function: - MathFunction *f = (MathFunction*) object; - int i4 = -1; - size_t i6; - if(f->args() == 0) { - size_t i7 = str.find_first_not_of(SPACES, str_index + name_length); - if(i7 != string::npos && str[i7] == LEFT_PARENTHESIS_CH) { - i7 = str.find_first_not_of(SPACES, i7 + 1); - if(i7 != string::npos && str[i7] == RIGHT_PARENTHESIS_CH) { - i4 = i7 - str_index + 1; - } - } - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - stmp += i2s(parseAddId(f, empty_string, po)); - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - if(i4 < 0) i4 = name_length; - } else if(po.rpn && f->args() == 1 && str_index > 0 && str[str_index - 1] != LEFT_PARENTHESIS_CH && (str_index + name_length >= str.length() || str[str_index + name_length] != LEFT_PARENTHESIS_CH) && (i6 = str.find_last_not_of(SPACE, str_index - 1)) != string::npos) { - size_t i7 = i6; - int nr_of_p = 0, nr_of_op = 0; - bool b_started = false; - while(i7 != 0) { - if(nr_of_p > 0) { - if(str[i7] == LEFT_PARENTHESIS_CH) { - nr_of_p--; - if(nr_of_p == 0 && nr_of_op == 0) break; - } else if(str[i7] == RIGHT_PARENTHESIS_CH) { - nr_of_p++; - } - } else if(nr_of_p == 0 && is_in(OPERATORS INTERNAL_OPERATORS SPACE RIGHT_PARENTHESIS, str[i7])) { - if(nr_of_op == 0 && b_started) { - i7++; - break; - } else { - if(is_in(OPERATORS INTERNAL_OPERATORS, str[i7])) { - nr_of_op++; - b_started = false; - } else if(str[i7] == RIGHT_PARENTHESIS_CH) { - nr_of_p++; - b_started = true; - } else if(b_started) { - nr_of_op--; - b_started = false; - } - } - } else { - b_started = true; - } - i7--; - } - stmp2 = str.substr(i7, i6 - i7 + 1); - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - if(f == f_vector) stmp += i2s(parseAddVectorId(stmp2, po)); - else stmp += i2s(parseAddId(f, stmp2, po)); - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - str.replace(i7, str_index + name_length - i7, stmp); - str_index += name_length; - moved_forward = true; - } else { - bool b = false, b_unended_function = false, b_comma_before = false, b_power_before = false; - //bool b_space_first = false; - size_t i5 = 1; - int arg_i = f->args(); - i6 = 0; - while(!b) { - if(i6 + str_index + name_length >= str.length()) { - b = true; - i5 = 2; - i6++; - b_unended_function = true; - break; - } else { - char c = str[str_index + name_length + i6]; - if(c == LEFT_PARENTHESIS_CH) { - if(i5 < 2) b = true; - else if(i5 == 2 && po.parsing_mode == PARSING_MODE_CONVENTIONAL && !b_power_before) b = true; - else i5++; - } else if(c == RIGHT_PARENTHESIS_CH) { - if(i5 <= 2) b = true; - else i5--; - } else if(c == POWER_CH) { - if(i5 < 2) i5 = 2; - b_power_before = true; - } else if(!b_comma_before && !b_power_before && c == ' ' && arg_i <= 1) { - //if(i5 < 2) b_space_first = true; - if(i5 == 2) b = true; - } else if(!b_comma_before && i5 == 2 && arg_i <= 1 && is_in(OPERATORS INTERNAL_OPERATORS, c) && c != POWER_CH) { - b = true; - } else if(c == COMMA_CH) { - if(i5 == 2) arg_i--; - b_comma_before = true; - if(i5 < 2) i5 = 2; - } else if(i5 < 2) { - i5 = 2; - } - if(c != COMMA_CH && c != ' ') b_comma_before = false; - if(c != POWER_CH && c != ' ') b_power_before = false; - } - i6++; - } - if(b && i5 >= 2) { - stmp2 = str.substr(str_index + name_length, i6 - 1); - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - if(b_unended_function && unended_function) { - po.unended_function = unended_function; - } - if(f == f_vector) { - stmp += i2s(parseAddVectorId(stmp2, po)); - } else if((f == f_interval || f == f_uncertainty) && po.read_precision != DONT_READ_PRECISION) { - ParseOptions po2 = po; - po2.read_precision = DONT_READ_PRECISION; - stmp += i2s(parseAddId(f, stmp2, po2)); - } else { - stmp += i2s(parseAddId(f, stmp2, po)); - } - po.unended_function = NULL; - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - i4 = i6 + 1 + name_length - 2; - b = false; - } - size_t i9 = i6; - if(b) { - b = false; - i6 = i6 + 1 + str_index + name_length; - size_t i7 = i6 - 1; - size_t i8 = i7; - while(true) { - i5 = str.find(RIGHT_PARENTHESIS_CH, i7); - if(i5 == string::npos) { - b_unended_function = true; - //str.append(1, RIGHT_PARENTHESIS_CH); - //i5 = str.length() - 1; - i5 = str.length(); - } - if(i5 < (i6 = str.find(LEFT_PARENTHESIS_CH, i8)) || i6 == string::npos) { - i6 = i5; - b = true; - break; - } - i7 = i5 + 1; - i8 = i6 + 1; - } - if(!b) { - b_unended_function = false; - } - } - if(b) { - stmp2 = str.substr(str_index + name_length + i9, i6 - (str_index + name_length + i9)); - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - if(b_unended_function && unended_function) { - po.unended_function = unended_function; - } - if(f == f_vector) { - stmp += i2s(parseAddVectorId(stmp2, po)); - } else if((f == f_interval || f == f_uncertainty) && po.read_precision != DONT_READ_PRECISION) { - ParseOptions po2 = po; - po2.read_precision = DONT_READ_PRECISION; - stmp += i2s(parseAddId(f, stmp2, po2)); - } else { - stmp += i2s(parseAddId(f, stmp2, po)); - } - po.unended_function = NULL; - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - i4 = i6 + 1 - str_index; - } - } - if(i4 > 0) { - str.replace(str_index, i4, stmp); - str_index += stmp.length(); - moved_forward = true; - } - break; - } - case 'u': { - replace_text_by_unit_place: - if(str.length() > str_index + name_length && is_in("23", str[str_index + name_length]) && (str.length() == str_index + name_length + 1 || is_not_in(NUMBER_ELEMENTS, str[str_index + name_length + 1])) && *name != SIGN_DEGREE && !((Unit*) object)->isCurrency()) { - str.insert(str_index + name_length, 1, POWER_CH); - } - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - stmp += i2s(addId(new MathStructure((Unit*) object, p))); - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - str.replace(str_index, name_length, stmp); - str_index += stmp.length(); - moved_forward = true; - p = NULL; - break; - } - case 'p': {} - case 'q': {} - case 'P': { - if(str_index + name_length == str.length() || is_in(NOT_IN_NAMES INTERNAL_OPERATORS, str[str_index + name_length])) { - break; - } - p = (Prefix*) object; - str_index += name_length; - unit_chars_left = last_unit_char - str_index + 1; - size_t name_length_old = name_length; - int index = 0; - if(unit_chars_left > UFV_LENGTHS) { - for(size_t ufv_index2 = 0; ufv_index2 < ufvl.size(); ufv_index2++) { - name = NULL; - switch(ufvl_t[ufv_index2]) { - case 'u': { - name = &((Unit*) ufvl[ufv_index2])->getName(ufvl_i[ufv_index2]).name; - case_sensitive = ((Unit*) ufvl[ufv_index2])->getName(ufvl_i[ufv_index2]).case_sensitive; - name_length = name->length(); - if(po.limit_implicit_multiplication || ((Unit*) ufvl[ufv_index2])->getName(ufvl_i[ufv_index2]).plural) { - if(name_length != unit_chars_left) name = NULL; - } else if(name_length > unit_chars_left) { - name = NULL; - } - break; - } - } - if(name && ((case_sensitive && compare_name(*name, str, name_length, str_index, base)) || (!case_sensitive && (name_length = compare_name_no_case(*name, str, name_length, str_index, base))))) { - if((!p_mode && name_length_old > 1) || (p_mode && (name_length + name_length_old > best_pl || ((ufvt != 'P' || !((Unit*) ufvl[ufv_index2])->getName(ufvl_i[ufv_index2]).abbreviation) && name_length + name_length_old == best_pl)))) { - p_mode = true; - best_p = p; - best_p_object = ufvl[ufv_index2]; - best_pl = name_length + name_length_old; - best_pnl = name_length_old; - index = -1; - break; - } - if(!p_mode) { - str.erase(str_index - name_length_old, name_length_old); - str_index -= name_length_old; - object = ufvl[ufv_index2]; - goto replace_text_by_unit_place; - } - } - } - } - if(index < 0) { - } else if(UFV_LENGTHS >= unit_chars_left) { - index = unit_chars_left - 1; - } else if(po.limit_implicit_multiplication) { - index = -1; - } else { - index = UFV_LENGTHS - 1; - } - for(; index >= 0; index--) { - for(size_t ufv_index2 = 0; ufv_index2 < ufv[2][index].size(); ufv_index2++) { - name = &((Unit*) ufv[2][index][ufv_index2])->getName(ufv_i[2][index][ufv_index2]).name; - case_sensitive = ((Unit*) ufv[2][index][ufv_index2])->getName(ufv_i[2][index][ufv_index2]).case_sensitive; - name_length = name->length(); - if(index + 1 == (int) unit_chars_left || !((Unit*) ufv[2][index][ufv_index2])->getName(ufv_i[2][index][ufv_index2]).plural) { - if(name_length <= unit_chars_left && ((case_sensitive && compare_name(*name, str, name_length, str_index, base)) || (!case_sensitive && (name_length = compare_name_no_case(*name, str, name_length, str_index, base))))) { - if((!p_mode && name_length_old > 1) || (p_mode && (name_length + name_length_old > best_pl || ((ufvt != 'P' || !((Unit*) ufv[2][index][ufv_index2])->getName(ufv_i[2][index][ufv_index2]).abbreviation) && name_length + name_length_old == best_pl)))) { - p_mode = true; - best_p = p; - best_p_object = ufv[2][index][ufv_index2]; - best_pl = name_length + name_length_old; - best_pnl = name_length_old; - index = -1; - } - if(!p_mode) { - str.erase(str_index - name_length_old, name_length_old); - str_index -= name_length_old; - object = ufv[2][index][ufv_index2]; - goto replace_text_by_unit_place; - } - } - } - } - if(po.limit_implicit_multiplication || (p_mode && index + 1 + name_length_old < best_pl)) { - break; - } - } - str_index -= name_length_old; - unit_chars_left = last_unit_char - str_index + 1; - break; - } - } - if(moved_forward) { - str_index--; - break; - } - } - } - if(!moved_forward && p_mode) { - object = best_p_object; - p = best_p; - str.erase(str_index, best_pnl); - name_length = best_pl - best_pnl; - goto replace_text_by_unit_place; - } else if(!moved_forward && found_function) { - object = found_function; - name = found_function_name; - name_length = found_function_name_length; - goto set_function; - } - if(!moved_forward) { - bool b = po.unknowns_enabled && is_not_number(str[str_index], base) && !(str_index > 0 && is_in(EXPS, str[str_index]) && str_index + 1 < str.length() && (is_in(NUMBER_ELEMENTS, str[str_index + 1]) || (is_in(PLUS MINUS, str[str_index + 1]) && str_index + 2 < str.length() && is_in(NUMBER_ELEMENTS, str[str_index + 2]))) && is_in(NUMBER_ELEMENTS, str[str_index - 1])); - if(po.limit_implicit_multiplication) { - if(b) { - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - stmp += i2s(addId(new MathStructure(str.substr(str_index, unit_chars_left)))); - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - str.replace(str_index, unit_chars_left, stmp); - str_index += stmp.length() - 1; - } else { - str_index += unit_chars_left - 1; - } - } else if(b) { - size_t i = 1; - if(str[str_index + 1] < 0) { - i++; - while(i <= unit_chars_left && (unsigned char) str[str_index + i] >= 0x80 && (unsigned char) str[str_index + i] <= 0xBF) { - i++; - } - } - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - stmp += i2s(addId(new MathStructure(str.substr(str_index, i)))); - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - str.replace(str_index, i, stmp); - str_index += stmp.length() - 1; - } - } - } - } - - size_t comma_i = str.find(COMMA, 0); - while(comma_i != string::npos) { - int i3 = 1; - size_t left_par_i = comma_i; - while(left_par_i > 0) { - left_par_i = str.find_last_of(LEFT_PARENTHESIS RIGHT_PARENTHESIS, left_par_i - 1); - if(left_par_i == string::npos) break; - if(str[left_par_i] == LEFT_PARENTHESIS_CH) { - i3--; - if(i3 == 0) break; - } else if(str[left_par_i] == RIGHT_PARENTHESIS_CH) { - i3++; - } - } - if(i3 > 0) { - str.insert(0, i3, LEFT_PARENTHESIS_CH); - comma_i += i3; - i3 = 0; - left_par_i = 0; - } - if(i3 == 0) { - i3 = 1; - size_t right_par_i = comma_i; - while(true) { - right_par_i = str.find_first_of(LEFT_PARENTHESIS RIGHT_PARENTHESIS, right_par_i + 1); - if(right_par_i == string::npos) { - for(; i3 > 0; i3--) { - str += RIGHT_PARENTHESIS; - } - right_par_i = str.length() - 1; - } else if(str[right_par_i] == LEFT_PARENTHESIS_CH) { - i3++; - } else if(str[right_par_i] == RIGHT_PARENTHESIS_CH) { - i3--; - } - if(i3 == 0) { - stmp2 = str.substr(left_par_i + 1, right_par_i - left_par_i - 1); - stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; - stmp += i2s(parseAddVectorId(stmp2, po)); - stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; - str.replace(left_par_i, right_par_i + 1 - left_par_i, stmp); - comma_i = left_par_i + stmp.length() - 1; - break; - } - } - } - comma_i = str.find(COMMA, comma_i + 1); - } - - if(po.rpn) { - size_t rpn_i = str.find(SPACE, 0); - while(rpn_i != string::npos) { - if(rpn_i == 0 || rpn_i + 1 == str.length() || is_in("~+-*/^\a\b\\\x1c", str[rpn_i - 1]) || (is_in("%&|", str[rpn_i - 1]) && str[rpn_i + 1] != str[rpn_i - 1]) || (is_in("!><=", str[rpn_i - 1]) && is_not_in("=<>", str[rpn_i + 1])) || (is_in(SPACE OPERATORS INTERNAL_OPERATORS, str[rpn_i + 1]) && (str[rpn_i - 1] == SPACE_CH || (str[rpn_i - 1] != str[rpn_i + 1] && is_not_in("!><=", str[rpn_i - 1]))))) { - str.erase(rpn_i, 1); - } else { - rpn_i++; - } - rpn_i = str.find(SPACE, rpn_i); - } - } else if(po.parsing_mode != PARSING_MODE_ADAPTIVE) { - remove_blanks(str); - } else { - //remove spaces between next to operators (except '/') and before/after parentheses - space_i = str.find(SPACE_CH, 0); - while(space_i != string::npos) { - if((str[space_i + 1] != DIVISION_CH && is_in(OPERATORS INTERNAL_OPERATORS RIGHT_PARENTHESIS, str[space_i + 1])) || (str[space_i - 1] != DIVISION_CH && is_in(OPERATORS INTERNAL_OPERATORS LEFT_PARENTHESIS, str[space_i - 1]))) { - str.erase(space_i, 1); - space_i--; - } - space_i = str.find(SPACE_CH, space_i + 1); - } - } - - parseOperators(mstruct, str, po); - -} - -#define BASE_2_10 ((po.base >= 2 && po.base <= 10) || (po.base < BASE_CUSTOM && po.base != BASE_UNICODE && po.base != BASE_BIJECTIVE_26) || (po.base == BASE_CUSTOM && priv->custom_input_base_i <= 10)) - -bool Calculator::parseNumber(MathStructure *mstruct, string str, const ParseOptions &po) { - mstruct->clear(); - if(str.empty()) return false; - if(str.find_first_not_of(OPERATORS "\a%\x1c" SPACE) == string::npos && (po.base != BASE_ROMAN_NUMERALS || str.find("|") == string::npos)) { - gsub("\a", str.find_first_of("%" OPERATORS) != string::npos ? " xor " : "xor", str); - gsub("\x1c", "∠", str); - error(false, _("Misplaced operator(s) \"%s\" ignored"), str.c_str(), NULL); - return false; - } - int minus_count = 0; - bool has_sign = false, had_non_sign = false, b_dot = false, b_exp = false, after_sign_e = false; - int i_colon = 0; - size_t i = 0; - - while(i < str.length()) { - if(!had_non_sign && str[i] == MINUS_CH) { - has_sign = true; - minus_count++; - str.erase(i, 1); - } else if(!had_non_sign && str[i] == PLUS_CH) { - has_sign = true; - str.erase(i, 1); - } else if(str[i] == SPACE_CH) { - str.erase(i, 1); - } else if(!b_exp && BASE_2_10 && (str[i] == EXP_CH || str[i] == EXP2_CH)) { - b_exp = true; - had_non_sign = true; - after_sign_e = true; - i++; - } else if(after_sign_e && (str[i] == MINUS_CH || str[i] == PLUS_CH)) { - after_sign_e = false; - i++; - } else if(po.preserve_format && str[i] == DOT_CH) { - b_dot = true; - had_non_sign = true; - after_sign_e = false; - i++; - } else if(po.preserve_format && (!b_dot || i_colon > 0) && str[i] == ':') { - i_colon++; - had_non_sign = true; - after_sign_e = false; - i++; - } else if(str[i] == COMMA_CH && DOT_S == ".") { - str.erase(i, 1); - after_sign_e = false; - had_non_sign = true; - } else if(is_in(OPERATORS, str[i]) && (po.base != BASE_ROMAN_NUMERALS || (str[i] != '(' && str[i] != ')' && str[i] != '|'))) { - error(false, _("Misplaced '%c' ignored"), str[i], NULL); - str.erase(i, 1); - } else if(str[i] == '\a') { - error(false, _("Misplaced operator(s) \"%s\" ignored"), "xor", NULL); - str.erase(i, 1); - } else if(str[i] == '\x1c') { - error(false, _("Misplaced operator(s) \"%s\" ignored"), "∠", NULL); - str.erase(i, 1); - } else if(str[i] == '\b') { - b_exp = false; - had_non_sign = false; - after_sign_e = false; - i++; - } else { - had_non_sign = true; - after_sign_e = false; - i++; - } - } - if(str.empty()) { - if(minus_count % 2 == 1 && !po.preserve_format) { - mstruct->set(-1, 1, 0); - } else if(has_sign) { - mstruct->set(1, 1, 0); - if(po.preserve_format) { - while(minus_count > 0) { - mstruct->transform(STRUCT_NEGATE); - minus_count--; - } - } - } - return false; - } - if(str[0] == ID_WRAP_LEFT_CH && str.length() > 2 && str[str.length() - 1] == ID_WRAP_RIGHT_CH) { - int id = s2i(str.substr(1, str.length() - 2)); - MathStructure *m_temp = getId((size_t) id); - if(!m_temp) { - mstruct->setUndefined(); - error(true, _("Internal id %s does not exist."), i2s(id).c_str(), NULL); - return true; - } - mstruct->set_nocopy(*m_temp); - m_temp->unref(); - if(po.preserve_format) { - while(minus_count > 0) { - mstruct->transform(STRUCT_NEGATE); - minus_count--; - } - } else if(minus_count % 2 == 1) { - mstruct->negate(); - } - return true; - } - size_t itmp; - if((BASE_2_10 || po.base == BASE_DUODECIMAL) && (itmp = str.find_first_not_of(po.base == BASE_DUODECIMAL ? NUMBER_ELEMENTS INTERNAL_NUMBER_CHARS MINUS DUODECIMAL_CHARS : NUMBER_ELEMENTS INTERNAL_NUMBER_CHARS EXPS MINUS, 0)) != string::npos) { - if(itmp == 0) { - error(true, _("\"%s\" is not a valid variable/function/unit."), str.c_str(), NULL); - if(minus_count % 2 == 1 && !po.preserve_format) { - mstruct->set(-1, 1, 0); - } else if(has_sign) { - mstruct->set(1, 1, 0); - if(po.preserve_format) { - while(minus_count > 0) { - mstruct->transform(STRUCT_NEGATE); - minus_count--; - } - } - } - return false; - } else { - string stmp = str.substr(itmp, str.length() - itmp); - error(true, _("Trailing characters \"%s\" (not a valid variable/function/unit) in number \"%s\" was ignored."), stmp.c_str(), str.c_str(), NULL); - str.erase(itmp, str.length() - itmp); - } - } - gsub("\b", "±", str); - Number nr(str, po); - if(!po.preserve_format && minus_count % 2 == 1) { - nr.negate(); - } - if(i_colon && nr.isRational() && !nr.isInteger()) { - Number nr_num(nr.numerator()), nr_den(1, 1, 0); - while(i_colon) { - nr_den *= 60; - i_colon--; - } - nr_num *= nr_den; - nr_num /= nr.denominator(); - mstruct->set(nr_num); - mstruct->transform(STRUCT_DIVISION, nr_den); - } else { - mstruct->set(nr); - } - if(po.preserve_format) { - while(minus_count > 0) { - mstruct->transform(STRUCT_NEGATE); - minus_count--; - } - } - return true; - -} - -bool Calculator::parseAdd(string &str, MathStructure *mstruct, const ParseOptions &po) { - if(str.length() > 0) { - size_t i; - if(BASE_2_10) { - i = str.find_first_of(SPACE MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS EXPS ID_WRAP_LEFT, 1); - } else { - i = str.find_first_of(SPACE MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS ID_WRAP_LEFT, 1); - } - if(i == string::npos && str[0] != LOGICAL_NOT_CH && str[0] != BITWISE_NOT_CH && !(str[0] == ID_WRAP_LEFT_CH && str.find(ID_WRAP_RIGHT) < str.length() - 1)) { - return parseNumber(mstruct, str, po); - } else { - return parseOperators(mstruct, str, po); - } - } - return false; -} -bool Calculator::parseAdd(string &str, MathStructure *mstruct, const ParseOptions &po, MathOperation s, bool append) { - if(str.length() > 0) { - size_t i; - if(BASE_2_10) { - i = str.find_first_of(SPACE MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS EXPS ID_WRAP_LEFT, 1); - } else { - i = str.find_first_of(SPACE MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS ID_WRAP_LEFT, 1); - } - if(i == string::npos && str[0] != LOGICAL_NOT_CH && str[0] != BITWISE_NOT_CH && !(str[0] == ID_WRAP_LEFT_CH && str.find(ID_WRAP_RIGHT) < str.length() - 1)) { - if(s == OPERATION_EXP10 && po.read_precision == ALWAYS_READ_PRECISION) { - ParseOptions po2 = po; - po2.read_precision = READ_PRECISION_WHEN_DECIMALS; - MathStructure *mstruct2 = new MathStructure(); - if(!parseNumber(mstruct2, str, po2)) { - mstruct2->unref(); - return false; - } - mstruct->add_nocopy(mstruct2, s, append); - } else { - MathStructure *mstruct2 = new MathStructure(); - if(!parseNumber(mstruct2, str, po)) { - mstruct2->unref(); - return false; - } - if(s == OPERATION_EXP10 && !po.preserve_format && mstruct->isNumber() && mstruct2->isNumber()) { - mstruct->number().exp10(mstruct2->number()); - mstruct->numberUpdated(); - mstruct->mergePrecision(*mstruct2); - } else if(s == OPERATION_DIVIDE && po.preserve_format) { - mstruct->transform_nocopy(STRUCT_DIVISION, mstruct2); - } else if(s == OPERATION_SUBTRACT && po.preserve_format) { - mstruct2->transform(STRUCT_NEGATE); - mstruct->add_nocopy(mstruct2, OPERATION_ADD, append); - } else { - mstruct->add_nocopy(mstruct2, s, append); - } - } - } else { - MathStructure *mstruct2 = new MathStructure(); - if(!parseOperators(mstruct2, str, po)) { - mstruct2->unref(); - return false; - } - if(s == OPERATION_DIVIDE && po.preserve_format) { - mstruct->transform_nocopy(STRUCT_DIVISION, mstruct2); - } else if(s == OPERATION_SUBTRACT && po.preserve_format) { - mstruct2->transform(STRUCT_NEGATE); - mstruct->add_nocopy(mstruct2, OPERATION_ADD, append); - } else { - mstruct->add_nocopy(mstruct2, s, append); - } - } - } - return true; -} - -MathStructure *get_out_of_negate(MathStructure &mstruct, int *i_neg) { - if(mstruct.isNegate() || (mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isMinusOne())) { - (*i_neg)++; - return get_out_of_negate(mstruct.last(), i_neg); - } - return &mstruct; -} - -bool Calculator::parseOperators(MathStructure *mstruct, string str, const ParseOptions &po) { - string save_str = str; - mstruct->clear(); - size_t i = 0, i2 = 0, i3 = 0; - string str2, str3; - bool extended_roman = (po.base == BASE_ROMAN_NUMERALS && (i = str.find("|")) != string::npos && i + 1 < str.length() && str[i + 1] == RIGHT_PARENTHESIS_CH); - while(!extended_roman) { - //find first right parenthesis and then the last left parenthesis before - i2 = str.find(RIGHT_PARENTHESIS_CH); - if(i2 == string::npos) { - i = str.rfind(LEFT_PARENTHESIS_CH); - if(i == string::npos) { - //if no parenthesis break - break; - } else { - //right parenthesis missing -- append - str += RIGHT_PARENTHESIS_CH; - i2 = str.length() - 1; - } - } else { - if(i2 > 0) { - i = str.rfind(LEFT_PARENTHESIS_CH, i2 - 1); - } else { - i = string::npos; - } - if(i == string::npos) { - //left parenthesis missing -- prepend - str.insert(str.begin(), 1, LEFT_PARENTHESIS_CH); - i = 0; - i2++; - } - } - while(true) { - //remove unnecessary double parenthesis and the found parenthesis - if(i > 0 && i2 + 1 < str.length() && str[i - 1] == LEFT_PARENTHESIS_CH && str[i2 + 1] == RIGHT_PARENTHESIS_CH) { - str.erase(str.begin() + (i - 1)); - i--; i2--; - str.erase(str.begin() + (i2 + 1)); - } else { - break; - } - } - if(i > 0 && is_not_in(MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS SPACE, str[i - 1]) && (!BASE_2_10 || (str[i - 1] != EXP_CH && str[i - 1] != EXP2_CH))) { - if(po.rpn) { - str.insert(i2 + 1, MULTIPLICATION); - str.insert(i, SPACE); - i++; - i2++; - } - } - if(i2 + 1 < str.length() && is_not_in(MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS SPACE, str[i2 + 1]) && (!BASE_2_10 || (str[i2 + 1] != EXP_CH && str[i2 + 1] != EXP2_CH))) { - if(po.rpn) { - i3 = str.find(SPACE, i2 + 1); - if(i3 == string::npos) { - str += MULTIPLICATION; - } else { - str.replace(i3, 1, MULTIPLICATION); - } - str.insert(i2 + 1, SPACE); - } - } - if(po.rpn && i > 0 && i2 + 1 == str.length() && is_not_in(PARENTHESISS SPACE, str[i - 1])) { - str += MULTIPLICATION_CH; - } - str2 = str.substr(i + 1, i2 - (i + 1)); - MathStructure *mstruct2 = new MathStructure(); - if(str2.empty()) { - error(false, "Empty expression in parentheses interpreted as zero.", NULL); - } else { - parseOperators(mstruct2, str2, po); - } - mstruct2->setInParentheses(true); - str2 = ID_WRAP_LEFT; - str2 += i2s(addId(mstruct2)); - str2 += ID_WRAP_RIGHT; - str.replace(i, i2 - i + 1, str2); - mstruct->clear(); - } - bool b_abs_or = false, b_bit_or = false; - i = 0; - if(!po.rpn) { - while(po.base != BASE_ROMAN_NUMERALS && (i = str.find('|', i)) != string::npos) { - if(i == 0 || i == str.length() - 1 || is_in(OPERATORS INTERNAL_OPERATORS SPACE, str[i - 1])) {b_abs_or = true; break;} - if(str[i + 1] == '|') { - if(i == str.length() - 2) {b_abs_or = true; break;} - if(b_bit_or) { - b_abs_or = true; - break; - } - i += 2; - } else { - b_bit_or = true; - i++; - } - } - } - if(b_abs_or) { - while((i = str.find('|', 0)) != string::npos && i + 1 != str.length()) { - if(str[i + 1] == '|') { - size_t depth = 1; - i2 = i; - while((i2 = str.find("||", i2 + 2)) != string::npos) { - if(is_in(OPERATORS INTERNAL_OPERATORS, str[i2 - 1])) depth++; - else depth--; - if(depth == 0) break; - } - if(i2 == string::npos) str2 = str.substr(i + 2); - else str2 = str.substr(i + 2, i2 - (i + 2)); - str3 = ID_WRAP_LEFT; - str3 += i2s(parseAddId(f_magnitude, str2, po)); - str3 += ID_WRAP_RIGHT; - if(i2 == string::npos) str.replace(i, str.length() - i, str3); - else str.replace(i, i2 - i + 2, str3); - } else { - size_t depth = 1; - i2 = i; - while((i2 = str.find('|', i2 + 1)) != string::npos) { - if(is_in(OPERATORS INTERNAL_OPERATORS, str[i2 - 1])) depth++; - else depth--; - if(depth == 0) break; - } - if(i2 == string::npos) str2 = str.substr(i + 1); - else str2 = str.substr(i + 1, i2 - (i + 1)); - str3 = ID_WRAP_LEFT; - str3 += i2s(parseAddId(f_abs, str2, po)); - str3 += ID_WRAP_RIGHT; - if(i2 == string::npos) str.replace(i, str.length() - i, str3); - else str.replace(i, i2 - i + 1, str3); - } - } - } - if(po.rpn) { - i = 0; - i3 = 0; - ParseOptions po2 = po; - po2.rpn = false; - vector mstack; - bool b = false; - char last_operator = 0; - char last_operator2 = 0; - while(true) { - i = str.find_first_of(OPERATORS "\a%\x1c" SPACE "\\", i3 + 1); - if(i == string::npos) { - if(!b) { - parseAdd(str, mstruct, po2); - return true; - } - if(i3 != 0) { - str2 = str.substr(i3 + 1, str.length() - i3 - 1); - } else { - str2 = str.substr(i3, str.length() - i3); - } - remove_blank_ends(str2); - if(!str2.empty()) { - error(false, _("RPN syntax error. Values left at the end of the RPN expression."), NULL); - } else if(mstack.size() > 1) { - if(last_operator == 0 && mstack.size() > 1) { - error(false, _("Unused stack values."), NULL); - } else { - while(mstack.size() > 1) { - switch(last_operator) { - case PLUS_CH: { - mstack[mstack.size() - 2]->add_nocopy(mstack.back()); - mstack.pop_back(); - break; - } - case MINUS_CH: { - if(po.preserve_format) { - mstack.back()->transform(STRUCT_NEGATE); - mstack[mstack.size() - 2]->add_nocopy(mstack.back()); - } else { - mstack[mstack.size() - 2]->subtract_nocopy(mstack.back()); - } - mstack.pop_back(); - break; - } - case MULTIPLICATION_CH: { - mstack[mstack.size() - 2]->multiply_nocopy(mstack.back()); - mstack.pop_back(); - break; - } - case DIVISION_CH: { - if(po.preserve_format) { - mstack[mstack.size() - 2]->transform_nocopy(STRUCT_DIVISION, mstack.back()); - } else { - mstack[mstack.size() - 2]->divide_nocopy(mstack.back()); - } - mstack.pop_back(); - break; - } - case POWER_CH: { - mstack[mstack.size() - 2]->raise_nocopy(mstack.back()); - mstack.pop_back(); - break; - } - case AND_CH: { - mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_AND, mstack.back()); - mstack.pop_back(); - break; - } - case OR_CH: { - mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_OR, mstack.back()); - mstack.pop_back(); - break; - } - case GREATER_CH: { - if(last_operator2 == GREATER_CH) { - if(po.preserve_format) mstack.back()->transform(STRUCT_NEGATE); - else mstack.back()->negate(); - mstack[mstack.size() - 2]->transform(CALCULATOR->f_shift); - mstack[mstack.size() - 2]->addChild_nocopy(mstack.back()); - mstack[mstack.size() - 2]->addChild(m_one); - } else if(last_operator2 == EQUALS_CH) { - mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS_GREATER); - } else { - mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_GREATER); - } - mstack.pop_back(); - break; - } - case LESS_CH: { - if(last_operator2 == LESS_CH) { - mstack[mstack.size() - 2]->transform(CALCULATOR->f_shift); - mstack[mstack.size() - 2]->addChild_nocopy(mstack.back()); - mstack[mstack.size() - 2]->addChild(m_one); - } else if(last_operator2 == EQUALS_CH) { - mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS_LESS); - } else { - mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_LESS); - } - mstack.pop_back(); - break; - } - case NOT_CH: { - mstack.back()->transform(STRUCT_LOGICAL_NOT); - break; - } - case EQUALS_CH: { - if(last_operator2 == NOT_CH) { - mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_NOT_EQUALS); - } else { - mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS); - } - mstack.pop_back(); - break; - } - case BITWISE_NOT_CH: { - mstack.back()->transform(STRUCT_BITWISE_NOT); - error(false, _("Unused stack values."), NULL); - break; - } - case '\x1c': { - if(po.angle_unit != ANGLE_UNIT_NONE && po.angle_unit != ANGLE_UNIT_RADIANS && mstack.back()->contains(getRadUnit(), false, true, true) <= 0 && mstack.back()->contains(getGraUnit(), false, true, true) <= 0 && mstack.back()->contains(getDegUnit(), false, true, true) <= 0) { - switch(po.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstack.back()->multiply(getDegUnit()); break;} - case ANGLE_UNIT_GRADIANS: {mstack.back()->multiply(getGraUnit()); break;} - default: {} - } - } - mstack.back()->transform(priv->f_cis); - mstack[mstack.size() - 2]->transform_nocopy(STRUCT_MULTIPLICATION, mstack.back()); - mstack.pop_back(); - break; - } - case '\a': { - mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_XOR, mstack.back()); - mstack.pop_back(); - break; - } - case '%': { - if(last_operator2 == '%') { - mstack[mstack.size() - 2]->transform(f_mod); - } else { - mstack[mstack.size() - 2]->transform(f_rem); - } - mstack[mstack.size() - 2]->addChild_nocopy(mstack.back()); - mstack.pop_back(); - break; - } - case '\\': { - if(po.preserve_format) { - mstack[mstack.size() - 2]->transform_nocopy(STRUCT_DIVISION, mstack.back()); - } else { - mstack[mstack.size() - 2]->divide_nocopy(mstack.back()); - } - mstack[mstack.size() - 2]->transform(f_trunc); - mstack.pop_back(); - break; - } - default: { - error(true, _("RPN syntax error. Operator '%c' not supported."), last_operator, NULL); - mstack.pop_back(); - break; - } - } - if(last_operator == NOT_CH || last_operator == BITWISE_NOT_CH) break; - } - } - } else if(mstack.size() == 1) { - if(last_operator == NOT_CH) { - mstack.back()->transform(STRUCT_LOGICAL_NOT); - } else if(last_operator == BITWISE_NOT_CH) { - mstack.back()->transform(STRUCT_BITWISE_NOT); - } - } - mstruct->set_nocopy(*mstack.back()); - while(!mstack.empty()) { - mstack.back()->unref(); - mstack.pop_back(); - } - return true; - } - b = true; - if(i3 != 0) { - str2 = str.substr(i3 + 1, i - i3 - 1); - } else { - str2 = str.substr(i3, i - i3); - } - remove_blank_ends(str2); - if(!str2.empty()) { - mstack.push_back(new MathStructure()); - if((str[i] == GREATER_CH || str[i] == LESS_CH) && po2.base < 10 && po2.base >= 2 && i + 1 < str.length() && str[i + 1] == str[i] && str2.find_first_not_of(NUMBERS SPACE PLUS MINUS) == string::npos) { - for(i = 0; i < str2.size(); i++) { - if(str2[i] >= '0' && str2[i] <= '9' && po.base <= str2[i] - '0') { - po2.base = BASE_DECIMAL; - break; - } - } - parseAdd(str2, mstack.back(), po2); - po2.base = po.base; - } else { - parseAdd(str2, mstack.back(), po2); - } - } - if(str[i] != SPACE_CH) { - if(mstack.size() < 1) { - error(true, _("RPN syntax error. Stack is empty."), NULL); - } else if(mstack.size() < 2) { - if(str[i] == NOT_CH) { - mstack.back()->transform(STRUCT_LOGICAL_NOT); - } else if(str[i] == MINUS_CH) { - if(po.preserve_format) mstack.back()->transform(STRUCT_NEGATE); - else mstack.back()->negate(); - } else if(str[i] == BITWISE_NOT_CH) { - mstack.back()->transform(STRUCT_BITWISE_NOT); - } else if(str[i] == '\x1c') { - if(po.angle_unit != ANGLE_UNIT_NONE && po.angle_unit != ANGLE_UNIT_RADIANS && mstack.back()->contains(getRadUnit(), false, true, true) <= 0 && mstack.back()->contains(getGraUnit(), false, true, true) <= 0 && mstack.back()->contains(getDegUnit(), false, true, true) <= 0) { - switch(po.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstack.back()->multiply(getDegUnit()); break;} - case ANGLE_UNIT_GRADIANS: {mstack.back()->multiply(getGraUnit()); break;} - default: {} - } - } - mstack.back()->transform(priv->f_cis); - mstack.back()->multiply(m_one); - if(po.preserve_format) mstack.back()->swapChildren(1, 2); - } else { - error(false, _("RPN syntax error. Operator ignored as there where only one stack value."), NULL); - } - } else { - switch(str[i]) { - case PLUS_CH: { - mstack[mstack.size() - 2]->add_nocopy(mstack.back()); - mstack.pop_back(); - break; - } - case MINUS_CH: { - if(po.preserve_format) { - mstack.back()->transform(STRUCT_NEGATE); - mstack[mstack.size() - 2]->add_nocopy(mstack.back()); - } else { - mstack[mstack.size() - 2]->subtract_nocopy(mstack.back()); - } - mstack.pop_back(); - break; - } - case MULTIPLICATION_CH: { - mstack[mstack.size() - 2]->multiply_nocopy(mstack.back()); - mstack.pop_back(); - break; - } - case DIVISION_CH: { - if(po.preserve_format) { - mstack[mstack.size() - 2]->transform_nocopy(STRUCT_DIVISION, mstack.back()); - } else { - mstack[mstack.size() - 2]->divide_nocopy(mstack.back()); - } - mstack.pop_back(); - break; - } - case POWER_CH: { - mstack[mstack.size() - 2]->raise_nocopy(mstack.back()); - mstack.pop_back(); - break; - } - case AND_CH: { - if(i + 1 < str.length() && str[i + 1] == AND_CH) { - mstack[mstack.size() - 2]->transform_nocopy(STRUCT_LOGICAL_AND, mstack.back()); - } else { - mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_AND, mstack.back()); - } - mstack.pop_back(); - break; - } - case OR_CH: { - if(i + 1 < str.length() && str[i + 1] == OR_CH) { - mstack[mstack.size() - 2]->transform_nocopy(STRUCT_LOGICAL_OR, mstack.back()); - } else { - mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_OR, mstack.back()); - } - mstack.pop_back(); - break; - } - case GREATER_CH: { - if(i + 1 < str.length() && str[i + 1] == GREATER_CH) { - if(po.preserve_format) mstack.back()->transform(STRUCT_NEGATE); - else mstack.back()->negate(); - mstack[mstack.size() - 2]->transform(CALCULATOR->f_shift); - mstack[mstack.size() - 2]->addChild_nocopy(mstack.back()); - mstack[mstack.size() - 2]->addChild(m_one); - } else if(i + 1 < str.length() && str[i + 1] == EQUALS_CH) { - mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS_GREATER); - } else { - mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_GREATER); - } - mstack.pop_back(); - break; - } - case LESS_CH: { - if(i + 1 < str.length() && str[i + 1] == LESS_CH) { - mstack[mstack.size() - 2]->transform(CALCULATOR->f_shift); - mstack[mstack.size() - 2]->addChild_nocopy(mstack.back()); - mstack[mstack.size() - 2]->addChild(m_one); - } else if(i + 1 < str.length() && str[i + 1] == EQUALS_CH) { - mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS_LESS); - } else { - mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_LESS); - } - mstack.pop_back(); - break; - } - case NOT_CH: { - mstack.back()->transform(STRUCT_LOGICAL_NOT); - break; - } - case EQUALS_CH: { - if(i + 1 < str.length() && str[i + 1] == NOT_CH) { - mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_NOT_EQUALS); - mstack.pop_back(); - } else { - mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS); - } - mstack.pop_back(); - break; - } - case BITWISE_NOT_CH: { - mstack.back()->transform(STRUCT_BITWISE_NOT); - break; - } - case '\x1c': { - if(po.angle_unit != ANGLE_UNIT_NONE && po.angle_unit != ANGLE_UNIT_RADIANS && mstack.back()->contains(getRadUnit(), false, true, true) <= 0 && mstack.back()->contains(getGraUnit(), false, true, true) <= 0 && mstack.back()->contains(getDegUnit(), false, true, true) <= 0) { - switch(po.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstack.back()->multiply(getDegUnit()); break;} - case ANGLE_UNIT_GRADIANS: {mstack.back()->multiply(getGraUnit()); break;} - default: {} - } - } - mstack.back()->transform(priv->f_cis); - mstack[mstack.size() - 2]->transform_nocopy(STRUCT_MULTIPLICATION, mstack.back()); - mstack.pop_back(); - break; - } - case '\a': { - mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_XOR, mstack.back()); - mstack.pop_back(); - break; - } - case '%': { - if(i + 1 < str.length() && str[i + 1] == '%') { - mstack[mstack.size() - 2]->transform(f_mod); - } else { - mstack[mstack.size() - 2]->transform(f_rem); - } - mstack[mstack.size() - 2]->addChild_nocopy(mstack.back()); - mstack.pop_back(); - break; - } - case '\\': { - if(po.preserve_format) { - mstack[mstack.size() - 2]->transform_nocopy(STRUCT_DIVISION, mstack.back()); - } else { - mstack[mstack.size() - 2]->divide_nocopy(mstack.back()); - } - mstack[mstack.size() - 2]->transform(f_trunc); - mstack.pop_back(); - break; - } - default: { - error(true, _("RPN syntax error. Operator '%c' not supported."), str[i], NULL); - mstack.pop_back(); - break; - } - } - last_operator = str[i]; - if(i + 1 < str.length()) last_operator2 = str[i + 1]; - else last_operator2 = 0; - if((last_operator2 == EQUALS_CH && (last_operator == GREATER_CH || last_operator == LESS_CH || last_operator == EQUALS_CH)) || (last_operator2 == NOT_CH && last_operator == EQUALS_CH) || (last_operator == last_operator2 && (last_operator == GREATER_CH || last_operator == LESS_CH || last_operator == '%' || last_operator == AND_CH || last_operator == OR_CH))) { - i++; - } - } - } - i3 = i; - } - } - if(po.rpn) remove_blanks(str); - i = 0; - i3 = 0; - if((i = str.find(LOGICAL_AND, 1)) != string::npos && i + 2 != str.length()) { - bool b = false, append = false; - while(i != string::npos && i + 2 != str.length()) { - str2 = str.substr(0, i); - str = str.substr(i + 2, str.length() - (i + 2)); - if(b) { - parseAdd(str2, mstruct, po, OPERATION_LOGICAL_AND, append); - append = true; - } else { - parseAdd(str2, mstruct, po); - b = true; - } - i = str.find(LOGICAL_AND, 1); - } - if(b) { - parseAdd(str, mstruct, po, OPERATION_LOGICAL_AND, append); - } else { - parseAdd(str, mstruct, po); - } - return true; - } - if(po.base != BASE_ROMAN_NUMERALS && (i = str.find(LOGICAL_OR, 1)) != string::npos && i + 2 != str.length()) { - bool b = false, append = false; - while(i != string::npos && i + 2 != str.length()) { - str2 = str.substr(0, i); - str = str.substr(i + 2, str.length() - (i + 2)); - if(b) { - parseAdd(str2, mstruct, po, OPERATION_LOGICAL_OR, append); - append = true; - } else { - parseAdd(str2, mstruct, po); - b = true; - } - i = str.find(LOGICAL_OR, 1); - } - if(b) { - parseAdd(str, mstruct, po, OPERATION_LOGICAL_OR, append); - } else { - parseAdd(str, mstruct, po); - } - return true; - } - /*if((i = str.find(LOGICAL_XOR, 1)) != string::npos && i + strlen(LOGICAL_XOR) != str.length()) { - str2 = str.substr(0, i); - str = str.substr(i + strlen(LOGICAL_XOR), str.length() - (i + strlen(LOGICAL_XOR))); - parseAdd(str2, mstruct, po); - parseAdd(str, mstruct, po, OPERATION_LOGICAL_XOR); - return true; - }*/ - if(po.base != BASE_ROMAN_NUMERALS && (i = str.find(BITWISE_OR, 1)) != string::npos && i + 1 != str.length()) { - bool b = false, append = false; - while(i != string::npos && i + 1 != str.length()) { - str2 = str.substr(0, i); - str = str.substr(i + 1, str.length() - (i + 1)); - if(b) { - parseAdd(str2, mstruct, po, OPERATION_BITWISE_OR, append); - append = true; - } else { - parseAdd(str2, mstruct, po); - b = true; - } - i = str.find(BITWISE_OR, 1); - } - if(b) { - parseAdd(str, mstruct, po, OPERATION_BITWISE_OR, append); - } else { - parseAdd(str, mstruct, po); - } - return true; - } - if((i = str.find('\a', 1)) != string::npos && i + 1 != str.length()) { - str2 = str.substr(0, i); - str = str.substr(i + 1, str.length() - (i + 1)); - parseAdd(str2, mstruct, po); - parseAdd(str, mstruct, po, OPERATION_BITWISE_XOR); - return true; - } - if((i = str.find(BITWISE_AND, 1)) != string::npos && i + 1 != str.length()) { - bool b = false, append = false; - while(i != string::npos && i + 1 != str.length()) { - str2 = str.substr(0, i); - str = str.substr(i + 1, str.length() - (i + 1)); - if(b) { - parseAdd(str2, mstruct, po, OPERATION_BITWISE_AND, append); - append = true; - } else { - parseAdd(str2, mstruct, po); - b = true; - } - i = str.find(BITWISE_AND, 1); - } - if(b) { - parseAdd(str, mstruct, po, OPERATION_BITWISE_AND, append); - } else { - parseAdd(str, mstruct, po); - } - return true; - } - if((i = str.find_first_of(LESS GREATER EQUALS NOT, 0)) != string::npos) { - while(i != string::npos && ((str[i] == LOGICAL_NOT_CH && (i + 1 >= str.length() || str[i + 1] != EQUALS_CH)) || (str[i] == LESS_CH && i + 1 < str.length() && str[i + 1] == LESS_CH) || (str[i] == GREATER_CH && i + 1 < str.length() && str[i + 1] == GREATER_CH))) { - i = str.find_first_of(LESS GREATER NOT EQUALS, i + 2); - } - } - if(i != string::npos) { - bool b = false; - bool c = false; - while(i != string::npos && str[i] == NOT_CH && str.length() > i + 1 && str[i + 1] == NOT_CH) { - i++; - if(i + 1 == str.length()) { - c = true; - } - } - MathOperation s = OPERATION_ADD; - while(!c) { - while(i != string::npos && ((str[i] == LOGICAL_NOT_CH && (i + 1 >= str.length() || str[i + 1] != EQUALS_CH)) || (str[i] == LESS_CH && i + 1 < str.length() && str[i + 1] == LESS_CH) || (str[i] == GREATER_CH && i + 1 < str.length() && str[i + 1] == GREATER_CH))) { - i = str.find_first_of(LESS GREATER NOT EQUALS, i + 2); - while(i != string::npos && str[i] == NOT_CH && str.length() > i + 1 && str[i + 1] == NOT_CH) { - i++; - if(i + 1 == str.length()) { - i = string::npos; - } - } - } - if(i == string::npos) { - str2 = str.substr(0, str.length()); - } else { - str2 = str.substr(0, i); - } - if(b) { - switch(i3) { - case EQUALS_CH: {s = OPERATION_EQUALS; break;} - case GREATER_CH: {s = OPERATION_GREATER; break;} - case LESS_CH: {s = OPERATION_LESS; break;} - case GREATER_CH * EQUALS_CH: {s = OPERATION_EQUALS_GREATER; break;} - case LESS_CH * EQUALS_CH: {s = OPERATION_EQUALS_LESS; break;} - case GREATER_CH * LESS_CH: {s = OPERATION_NOT_EQUALS; break;} - } - parseAdd(str2, mstruct, po, s); - } - if(i == string::npos) { - return true; - } - if(!b) { - parseAdd(str2, mstruct, po); - b = true; - } - if(str.length() > i + 1 && is_in(LESS GREATER NOT EQUALS, str[i + 1])) { - if(str[i] == str[i + 1]) { - i3 = str[i]; - } else { - i3 = str[i] * str[i + 1]; - if(i3 == NOT_CH * EQUALS_CH) { - i3 = GREATER_CH * LESS_CH; - } else if(i3 == NOT_CH * LESS_CH) { - i3 = GREATER_CH; - } else if(i3 == NOT_CH * GREATER_CH) { - i3 = LESS_CH; - } - } - i++; - } else { - i3 = str[i]; - } - str = str.substr(i + 1, str.length() - (i + 1)); - i = str.find_first_of(LESS GREATER NOT EQUALS, 0); - while(i != string::npos && str[i] == NOT_CH && str.length() > i + 1 && str[i + 1] == NOT_CH) { - i++; - if(i + 1 == str.length()) { - i = string::npos; - } - } - } - } - i = str.find(SHIFT_LEFT, 1); - i2 = str.find(SHIFT_RIGHT, 1); - if(i2 != string::npos && (i == string::npos || i2 < i)) i = i2; - if(i != string::npos && i + 2 != str.length()) { - MathStructure mstruct1, mstruct2; - bool b_neg = (str[i] == '>'); - str2 = str.substr(0, i); - str = str.substr(i + 2, str.length() - (i + 2)); - parseAdd(str2, &mstruct1, po); - if(po.base < 10 && po.base >= 2 && str.find_first_not_of(NUMBERS SPACE PLUS MINUS) == string::npos) { - for(i = 0; i < str.size(); i++) { - if(str[i] >= '0' && str[i] <= '9' && po.base <= str[i] - '0') { - ParseOptions po2 = po; - po2.base = BASE_DECIMAL; - parseAdd(str, &mstruct2, po2); - if(b_neg) { - if(po.preserve_format) mstruct2.transform(STRUCT_NEGATE); - else mstruct2.negate(); - } - mstruct->set(f_shift, &mstruct1, &mstruct2, &m_one, NULL); - return true; - } - } - } - parseAdd(str, &mstruct2, po); - if(b_neg) { - if(po.preserve_format) mstruct2.transform(STRUCT_NEGATE); - else mstruct2.negate(); - } - mstruct->set(f_shift, &mstruct1, &mstruct2, &m_one, NULL); - return true; - } - - if((i = str.find_first_of(PLUS MINUS, 1)) != string::npos && i + 1 != str.length()) { - bool b = false, c = false, append = false; - bool min = false; - while(i != string::npos && i + 1 != str.length()) { - if(is_not_in(MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS EXPS, str[i - 1])) { - str2 = str.substr(0, i); - if(!c && b) { - bool b_add; - if(min) { - b_add = parseAdd(str2, mstruct, po, OPERATION_SUBTRACT, append) && mstruct->isAddition(); - } else { - b_add = parseAdd(str2, mstruct, po, OPERATION_ADD, append) && mstruct->isAddition(); - } - append = true; - if(b_add) { - int i_neg = 0; - MathStructure *mstruct_a = get_out_of_negate(mstruct->last(), &i_neg); - MathStructure *mstruct_b = mstruct_a; - if(mstruct_a->isMultiplication() && mstruct_a->size() >= 2) mstruct_b = &mstruct_a->last(); - if(mstruct_b->isVariable() && (mstruct_b->variable() == v_percent || mstruct_b->variable() == v_permille || mstruct_b->variable() == v_permyriad)) { - Variable *v = mstruct_b->variable(); - bool b_neg = (i_neg % 2 == 1); - while(i_neg > 0) { - mstruct->last().setToChild(mstruct->last().size()); - i_neg--; - } - if(mstruct->last().isVariable()) { - mstruct->last().multiply(m_one); - mstruct->last().swapChildren(1, 2); - } - if(mstruct->last().size() > 2) { - mstruct->last().delChild(mstruct->last().size()); - mstruct->last().multiply(v); - } - if(mstruct->last()[0].isNumber()) { - if(b_neg) mstruct->last()[0].number().negate(); - if(v == v_percent) mstruct->last()[0].number().add(100); - else if(v == v_permille) mstruct->last()[0].number().add(1000); - else mstruct->last()[0].number().add(10000); - } else { - if(b_neg && po.preserve_format) mstruct->last()[0].transform(STRUCT_NEGATE); - else if(b_neg) mstruct->last()[0].negate(); - if(v == v_percent) mstruct->last()[0] += Number(100, 1); - else if(v == v_permille) mstruct->last()[0] += Number(1000, 1); - else mstruct->last()[0] += Number(10000, 1); - mstruct->last()[0].swapChildren(1, 2); - } - if(mstruct->size() == 2) { - mstruct->setType(STRUCT_MULTIPLICATION); - } else { - MathStructure *mpercent = &mstruct->last(); - mpercent->ref(); - mstruct->delChild(mstruct->size()); - mstruct->multiply_nocopy(mpercent); - } - } - } - } else { - if(!b && str2.empty()) { - c = true; - } else { - parseAdd(str2, mstruct, po); - if(c && min) { - if(po.preserve_format) mstruct->transform(STRUCT_NEGATE); - else mstruct->negate(); - } - c = false; - } - b = true; - } - min = str[i] == MINUS_CH; - str = str.substr(i + 1, str.length() - (i + 1)); - i = str.find_first_of(PLUS MINUS, 1); - } else { - i = str.find_first_of(PLUS MINUS, i + 1); - } - } - if(b) { - if(c) { - b = parseAdd(str, mstruct, po); - if(min) { - if(po.preserve_format) mstruct->transform(STRUCT_NEGATE); - else mstruct->negate(); - } - return b; - } else { - bool b_add; - if(min) { - b_add = parseAdd(str, mstruct, po, OPERATION_SUBTRACT, append) && mstruct->isAddition(); - } else { - b_add = parseAdd(str, mstruct, po, OPERATION_ADD, append) && mstruct->isAddition(); - } - if(b_add) { - int i_neg = 0; - MathStructure *mstruct_a = get_out_of_negate(mstruct->last(), &i_neg); - MathStructure *mstruct_b = mstruct_a; - if(mstruct_a->isMultiplication() && mstruct_a->size() >= 2) mstruct_b = &mstruct_a->last(); - if(mstruct_b->isVariable() && (mstruct_b->variable() == v_percent || mstruct_b->variable() == v_permille || mstruct_b->variable() == v_permyriad)) { - Variable *v = mstruct_b->variable(); - bool b_neg = (i_neg % 2 == 1); - while(i_neg > 0) { - mstruct->last().setToChild(mstruct->last().size()); - i_neg--; - } - if(mstruct->last().isVariable()) { - mstruct->last().multiply(m_one); - mstruct->last().swapChildren(1, 2); - } - if(mstruct->last().size() > 2) { - mstruct->last().delChild(mstruct->last().size()); - mstruct->last().multiply(v); - } - if(mstruct->last()[0].isNumber()) { - if(b_neg) mstruct->last()[0].number().negate(); - if(v == v_percent) mstruct->last()[0].number().add(100); - else if(v == v_permille) mstruct->last()[0].number().add(1000); - else mstruct->last()[0].number().add(10000); - } else { - if(b_neg && po.preserve_format) mstruct->last()[0].transform(STRUCT_NEGATE); - else if(b_neg) mstruct->last()[0].negate(); - if(v == v_percent) mstruct->last()[0] += Number(100, 1); - else if(v == v_permille) mstruct->last()[0] += Number(1000, 1); - else mstruct->last()[0] += Number(10000, 1); - mstruct->last()[0].swapChildren(1, 2); - } - if(mstruct->size() == 2) { - mstruct->setType(STRUCT_MULTIPLICATION); - } else { - MathStructure *mpercent = &mstruct->last(); - mpercent->ref(); - mstruct->delChild(mstruct->size()); - mstruct->multiply_nocopy(mpercent); - } - } - } - } - return true; - } - } - if(!po.rpn && po.parsing_mode == PARSING_MODE_ADAPTIVE && (i = str.find(DIVISION_CH, 1)) != string::npos && i + 1 != str.length()) { - while(i != string::npos && i + 1 != str.length()) { - bool b = false; - if(i > 2 && i < str.length() - 3 && str[i + 1] == ID_WRAP_LEFT_CH) { - i2 = i; - b = true; - bool had_unit = false, had_nonunit = false; - MathStructure *m_temp = NULL, *m_temp2 = NULL; - while(b) { - b = false; - size_t i4 = i2; - if(i2 > 2 && str[i2 - 1] == ID_WRAP_RIGHT_CH) { - b = true; - } else if(i2 > 4 && str[i2 - 3] == ID_WRAP_RIGHT_CH && str[i2 - 2] == POWER_CH && is_in(NUMBERS, str[i2 - 1])) { - b = true; - i4 -= 2; - } - if(!b) { - if((i2 > 1 && is_not_in(OPERATORS INTERNAL_OPERATORS MULTIPLICATION_2, str[i2 - 1])) || (i2 > 2 && str[i2 - 1] == MULTIPLICATION_2_CH && is_not_in(OPERATORS INTERNAL_OPERATORS, str[i2 - 2]))) had_nonunit = true; - break; - } - i2 = str.rfind(ID_WRAP_LEFT_CH, i4 - 2); - m_temp = NULL; - if(i2 != string::npos) { - int id = s2i(str.substr(i2 + 1, (i4 - 1) - (i2 + 1))); - if(priv->id_structs.find(id) != priv->id_structs.end()) m_temp = priv->id_structs[id]; - } - if(!m_temp || !m_temp->isUnit()) { - had_nonunit = true; - break; - } - had_unit = true; - } - i3 = i; - b = had_unit && had_nonunit; - had_unit = false; - while(b) { - size_t i4 = i3; - i3 = str.find(ID_WRAP_RIGHT_CH, i4 + 2); - m_temp2 = NULL; - if(i3 != string::npos) { - int id = s2i(str.substr(i4 + 2, (i3 - 1) - (i4 + 1))); - if(priv->id_structs.find(id) != priv->id_structs.end()) m_temp2 = priv->id_structs[id]; - } - if(!m_temp2 || !m_temp2->isUnit()) { - b = false; - break; - } - had_unit = true; - b = false; - if(i3 < str.length() - 3 && str[i3 + 1] == ID_WRAP_LEFT_CH) { - b = true; - } else if(i3 < str.length() - 5 && str[i3 + 3] == ID_WRAP_LEFT_CH && str[i3 + 1] == POWER_CH && is_in(NUMBERS, str[i3 + 2])) { - b = true; - i3 += 2; - } - } - b = had_unit; - if(b) { - if(i3 < str.length() - 2 && str[i3 + 1] == POWER_CH && is_in(NUMBERS, str[i3 + 2])) { - i3 += 2; - while(i3 < str.length() - 1 && is_in(NUMBERS, str[i3 + 1])) i3++; - } - if(i3 == str.length() - 1 || (str[i3 + 1] != POWER_CH && str[i3 + 1] != DIVISION_CH)) { - MathStructure *mstruct2 = new MathStructure(); - str2 = str.substr(i2, i - i2); - parseAdd(str2, mstruct2, po); - str2 = str.substr(i + 1, i3 - i); - parseAdd(str2, mstruct2, po, OPERATION_DIVIDE); - str2 = ID_WRAP_LEFT; - str2 += i2s(addId(mstruct2)); - str2 += ID_WRAP_RIGHT; - str.replace(i2, i3 - i2 + 1, str2); - } else { - b = false; - } - } - } - if(!b) { - i2 = str.find_last_not_of(NUMBERS INTERNAL_NUMBER_CHARS PLUS MINUS EXPS, i - 1); - if(i2 == string::npos || (i2 != i - 1 && str[i2] == MULTIPLICATION_2_CH)) b = true; - i2 = str.rfind(MULTIPLICATION_2_CH, i - 1); - if(i2 == string::npos) b = true; - if(b) { - i3 = str.find_first_of(MULTIPLICATION_2 "%" MULTIPLICATION DIVISION, i + 1); - if(i3 == string::npos || i3 == i + 1 || str[i3] != MULTIPLICATION_2_CH) b = false; - if(i3 < str.length() + 1 && (str[i3 + 1] == '%' || str[i3 + 1] == DIVISION_CH || str[i3 + 1] == MULTIPLICATION_CH || str[i3 + 1] == POWER_CH)) b = false; - } - if(b) { - if(i3 != string::npos) str[i3] = MULTIPLICATION_CH; - if(i2 != string::npos) str[i2] = MULTIPLICATION_CH; - } else { - if(str[i + 1] == MULTIPLICATION_2_CH) { - str.erase(i + 1, 1); - } - if(str[i - 1] == MULTIPLICATION_2_CH) { - str.erase(i - 1, 1); - i--; - } - } - } - i = str.find(DIVISION_CH, i + 1); - } - } - if(po.parsing_mode == PARSING_MODE_ADAPTIVE && !po.rpn) remove_blanks(str); - if(po.parsing_mode == PARSING_MODE_CONVENTIONAL) { - if((i = str.find(ID_WRAP_RIGHT_CH, 1)) != string::npos && i + 1 != str.length()) { - while(i != string::npos && i + 1 != str.length()) { - if(is_in(NUMBERS ID_WRAP_LEFT, str[i + 1])) { - str.insert(i + 1, 1, MULTIPLICATION_CH); - i++; - } - i = str.find(ID_WRAP_RIGHT_CH, i + 1); - } - } - if((i = str.find(ID_WRAP_LEFT_CH, 1)) != string::npos) { - while(i != string::npos) { - if(is_in(NUMBERS, str[i - 1])) { - str.insert(i, 1, MULTIPLICATION_CH); - i++; - } - i = str.find(ID_WRAP_LEFT_CH, i + 1); - } - } - } - if((i = str.find_first_of(MULTIPLICATION DIVISION "%", 0)) != string::npos && i + 1 != str.length()) { - bool b = false, append = false; - int type = 0; - while(i != string::npos && i + 1 != str.length()) { - if(i < 1) { - if(i < 1 && str.find_first_not_of(MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS EXPS) == string::npos) { - gsub("\a", str.find_first_of(OPERATORS "%") != string::npos ? " xor " : "xor", str); - error(false, _("Misplaced operator(s) \"%s\" ignored"), str.c_str(), NULL); - return b; - } - i = 1; - while(i < str.length() && is_in(MULTIPLICATION DIVISION "%", str[i])) { - i++; - } - string errstr = str.substr(0, i); - gsub("\a", str.find_first_of(OPERATORS "%") != string::npos ? " xor " : "xor", errstr); - error(false, _("Misplaced operator(s) \"%s\" ignored"), errstr.c_str(), NULL); - str = str.substr(i, str.length() - i); - i = str.find_first_of(MULTIPLICATION DIVISION "%", 0); - } else { - str2 = str.substr(0, i); - if(b) { - switch(type) { - case 1: { - parseAdd(str2, mstruct, po, OPERATION_DIVIDE, append); - break; - } - case 2: { - MathStructure *mstruct2 = new MathStructure(); - parseAdd(str2, mstruct2, po); - mstruct->transform(f_rem); - mstruct->addChild_nocopy(mstruct2); - break; - } - case 3: { - parseAdd(str2, mstruct, po, OPERATION_DIVIDE, append); - mstruct->transform(f_trunc); - break; - } - case 4: { - MathStructure *mstruct2 = new MathStructure(); - parseAdd(str2, mstruct2, po); - mstruct->transform(f_mod); - mstruct->addChild_nocopy(mstruct2); - break; - } - default: { - parseAdd(str2, mstruct, po, OPERATION_MULTIPLY, append); - } - } - append = true; - } else { - parseAdd(str2, mstruct, po); - b = true; - } - if(str[i] == DIVISION_CH) { - if(str[i + 1] == DIVISION_CH) {type = 3; i++;} - else type = 1; - } else if(str[i] == '%') { - if(str[i + 1] == '%') {type = 4; i++;} - else type = 2; - } else { - type = 0; - } - if(is_in(MULTIPLICATION DIVISION "%", str[i + 1])) { - i2 = 1; - while(i2 + i + 1 != str.length() && is_in(MULTIPLICATION DIVISION "%", str[i2 + i + 1])) { - i2++; - } - string errstr = str.substr(i, i2); - gsub("\a", str.find_first_of(OPERATORS "%") != string::npos ? " xor " : "xor", errstr); - error(false, _("Misplaced operator(s) \"%s\" ignored"), errstr.c_str(), NULL); - i += i2; - } - str = str.substr(i + 1, str.length() - (i + 1)); - i = str.find_first_of(MULTIPLICATION DIVISION "%", 0); - } - } - if(b) { - switch(type) { - case 1: { - parseAdd(str, mstruct, po, OPERATION_DIVIDE, append); - break; - } - case 2: { - MathStructure *mstruct2 = new MathStructure(); - parseAdd(str, mstruct2, po); - mstruct->transform(f_rem); - mstruct->addChild_nocopy(mstruct2); - break; - } - case 3: { - parseAdd(str, mstruct, po, OPERATION_DIVIDE, append); - mstruct->transform(f_trunc); - break; - } - case 4: { - MathStructure *mstruct2 = new MathStructure(); - parseAdd(str, mstruct2, po); - mstruct->transform(f_mod); - mstruct->addChild_nocopy(mstruct2); - break; - } - default: { - parseAdd(str, mstruct, po, OPERATION_MULTIPLY, append); - } - } - return true; - } - } - - if((i = str.find('\x1c', 0)) != string::npos && i + 1 != str.length()) { - if(i != 0) str2 = str.substr(0, i); - str = str.substr(i + 1, str.length() - (i + 1)); - if(i != 0) parseAdd(str2, mstruct, po); - else mstruct->set(1, 1, 0); - if(parseAdd(str, mstruct, po, OPERATION_MULTIPLY)) { - if(po.angle_unit != ANGLE_UNIT_NONE && po.angle_unit != ANGLE_UNIT_RADIANS && mstruct->last().contains(getRadUnit(), false, true, true) <= 0 && mstruct->last().contains(getGraUnit(), false, true, true) <= 0 && mstruct->last().contains(getDegUnit(), false, true, true) <= 0) { - switch(po.angle_unit) { - case ANGLE_UNIT_DEGREES: {mstruct->last().multiply(getDegUnit()); break;} - case ANGLE_UNIT_GRADIANS: {mstruct->last().multiply(getGraUnit()); break;} - default: {} - } - } - mstruct->last().transform(priv->f_cis); - } - return true; - } - - if(str.empty()) return false; - if(str.find_first_not_of(OPERATORS INTERNAL_OPERATORS SPACE) == string::npos && (po.base != BASE_ROMAN_NUMERALS || str.find_first_of("(|)") == string::npos)) { - gsub("\a", str.find_first_of(OPERATORS "%") != string::npos ? " xor " : "xor", str); - gsub("\x1c", "∠", str); - error(false, _("Misplaced operator(s) \"%s\" ignored"), str.c_str(), NULL); - return false; - } - - i = 0; - bool ret = true; - bool has_sign = false; - int minus_count = 0; - while(i < str.length()) { - if(str[i] == MINUS_CH) { - has_sign = true; - minus_count++; - str.erase(i, 1); - } else if(str[i] == PLUS_CH) { - has_sign = true; - str.erase(i, 1); - } else if(str[i] == SPACE_CH) { - str.erase(i, 1); - } else if(str[i] == BITWISE_NOT_CH || str[i] == LOGICAL_NOT_CH) { - break; - } else if(is_in(OPERATORS INTERNAL_OPERATORS, str[i]) && (po.base != BASE_ROMAN_NUMERALS || (str[i] != '(' && str[i] != ')' && str[i] != '|'))) { - if(str[i] == '\a') error(false, _("Misplaced operator(s) \"%s\" ignored"), "xor", NULL); - else if(str[i] == '\x1c') error(false, _("Misplaced operator(s) \"%s\" ignored"), "∠", NULL); - else error(false, _("Misplaced '%c' ignored"), str[i], NULL); - str.erase(i, 1); - } else { - break; - } - } - - if(!str.empty() && (str[0] == BITWISE_NOT_CH || str[0] == LOGICAL_NOT_CH)) { - bool bit = (str[0] == BITWISE_NOT_CH); - str.erase(0, 1); - parseAdd(str, mstruct, po); - if(bit) mstruct->setBitwiseNot(); - else mstruct->setLogicalNot(); - if(po.preserve_format) { - while(minus_count > 0) { - mstruct->transform(STRUCT_NEGATE); - minus_count--; - } - } else if(minus_count % 2 == 1) { - mstruct->negate(); - } - return true; - } - - if(str.empty()) { - if(minus_count % 2 == 1 && !po.preserve_format) { - mstruct->set(-1, 1, 0); - } else if(has_sign) { - mstruct->set(1, 1, 0); - if(po.preserve_format) { - while(minus_count > 0) { - mstruct->transform(STRUCT_NEGATE); - minus_count--; - } - } - } - return false; - } - if((i = str.find(ID_WRAP_RIGHT_CH, 1)) != string::npos && i + 1 != str.length()) { - bool b = false, append = false; - while(i != string::npos && i + 1 != str.length()) { - if(str[i + 1] != POWER_CH && str[i + 1] != '\b') { - str2 = str.substr(0, i + 1); - str = str.substr(i + 1, str.length() - (i + 1)); - if(b) { - parseAdd(str2, mstruct, po, OPERATION_MULTIPLY, append); - append = true; - } else { - parseAdd(str2, mstruct, po); - b = true; - } - i = str.find(ID_WRAP_RIGHT_CH, 1); - } else { - i = str.find(ID_WRAP_RIGHT_CH, i + 1); - } - } - if(b) { - parseAdd(str, mstruct, po, OPERATION_MULTIPLY, append); - if(po.parsing_mode == PARSING_MODE_ADAPTIVE && mstruct->isMultiplication() && mstruct->size() >= 2 && !(*mstruct)[0].inParentheses()) { - Unit *u1 = NULL; Prefix *p1 = NULL; - bool b_plus = false; - if((*mstruct)[0].isMultiplication() && (*mstruct)[0].size() == 2 && (*mstruct)[0][0].isNumber() && (*mstruct)[0][1].isUnit()) {u1 = (*mstruct)[0][1].unit(); p1 = (*mstruct)[0][1].prefix();} - if(u1 && u1->subtype() == SUBTYPE_BASE_UNIT && (u1->referenceName() == "m" || (!p1 && u1->referenceName() == "L")) && (!p1 || (p1->type() == PREFIX_DECIMAL && ((DecimalPrefix*) p1)->exponent() <= 3 && ((DecimalPrefix*) p1)->exponent() > -3))) { - b_plus = true; - for(size_t i2 = 1; i2 < mstruct->size(); i2++) { - if(!(*mstruct)[i2].inParentheses() && (*mstruct)[i2].isMultiplication() && (*mstruct)[i2].size() == 2 && (*mstruct)[i2][0].isNumber() && (*mstruct)[i2][1].isUnit() && (*mstruct)[i2][1].unit() == u1) { - Prefix *p2 = (*mstruct)[i2][1].prefix(); - if(p1 && p2) b_plus = p1->type() == PREFIX_DECIMAL && p2->type() == PREFIX_DECIMAL && ((DecimalPrefix*) p1)->exponent() > ((DecimalPrefix*) p2)->exponent() && ((DecimalPrefix*) p2)->exponent() >= -3; - else if(p2) b_plus = p2->type() == PREFIX_DECIMAL && ((DecimalPrefix*) p2)->exponent() < 0 && ((DecimalPrefix*) p2)->exponent() >= -3; - else if(p1) b_plus = p1->type() == PREFIX_DECIMAL && ((DecimalPrefix*) p1)->exponent() > 1; - else b_plus = false; - if(!b_plus) break; - p1 = p2; - } else { - b_plus = false; - break; - } - } - } else if(u1 && !p1 && u1->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) u1)->mixWithBase()) { - b_plus = true; - for(size_t i2 = 1; i2 < mstruct->size(); i2++) { - if(!(*mstruct)[i2].inParentheses() && (*mstruct)[i2].isMultiplication() && (*mstruct)[i2].size() == 2 && (*mstruct)[i2][0].isNumber() && (*mstruct)[i2][1].isUnit() && u1->isChildOf((*mstruct)[i2][1].unit()) && !(*mstruct)[i2][1].prefix() && (i2 == mstruct->size() - 1 || ((*mstruct)[i2][1].unit()->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) (*mstruct)[i2][1].unit())->mixWithBase()))) { - while(((AliasUnit*) u1)->firstBaseUnit() != (*mstruct)[i2][1].unit()) { - u1 = ((AliasUnit*) u1)->firstBaseUnit(); - if(u1->subtype() != SUBTYPE_ALIAS_UNIT || !((AliasUnit*) u1)->mixWithBase()) { - b_plus = false; - break; - } - } - if(!b_plus) break; - u1 = (*mstruct)[i2][1].unit(); - } else { - b_plus = false; - break; - } - } - } - if(b_plus) mstruct->setType(STRUCT_ADDITION); - } - if(po.preserve_format) { - while(minus_count > 0) { - mstruct->transform(STRUCT_NEGATE); - minus_count--; - } - } else if(minus_count % 2 == 1) { - mstruct->negate(); - } - return true; - } - } - if((i = str.find(ID_WRAP_LEFT_CH, 1)) != string::npos) { - bool b = false, append = false; - while(i != string::npos) { - if(str[i - 1] != POWER_CH && (i < 2 || str[i - 1] != MINUS_CH || str[i - 2] != POWER_CH) && str[i - 1] != '\b') { - str2 = str.substr(0, i); - str = str.substr(i, str.length() - i); - if(b) { - parseAdd(str2, mstruct, po, OPERATION_MULTIPLY, append); - append = true; - } else { - parseAdd(str2, mstruct, po); - b = true; - } - i = str.find(ID_WRAP_LEFT_CH, 1); - } else { - i = str.find(ID_WRAP_LEFT_CH, i + 1); - } - } - if(b) { - parseAdd(str, mstruct, po, OPERATION_MULTIPLY, append); - if(po.preserve_format) { - while(minus_count > 0) { - mstruct->transform(STRUCT_NEGATE); - minus_count--; - } - } else if(minus_count % 2 == 1) { - mstruct->negate(); - } - return true; - } - } - if((i = str.find(POWER_CH, 1)) != string::npos && i + 1 != str.length()) { - str2 = str.substr(0, i); - str = str.substr(i + 1, str.length() - (i + 1)); - parseAdd(str2, mstruct, po); - parseAdd(str, mstruct, po, OPERATION_RAISE); - } else if((i = str.find("\b", 1)) != string::npos && i + 1 != str.length()) { - str2 = str.substr(0, i); - str = str.substr(i + 1, str.length() - (i + 1)); - MathStructure *mstruct2 = new MathStructure; - if(po.read_precision != DONT_READ_PRECISION) { - ParseOptions po2 = po; - po2.read_precision = DONT_READ_PRECISION; - parseAdd(str2, mstruct, po2); - parseAdd(str, mstruct2, po2); - } else { - parseAdd(str2, mstruct, po); - parseAdd(str, mstruct2, po); - } - mstruct->transform(f_uncertainty); - mstruct->addChild_nocopy(mstruct2); - mstruct->addChild(m_zero); - } else if(BASE_2_10 && (i = str.find_first_of(EXPS, 1)) != string::npos && i + 1 != str.length() && str.find("\b") == string::npos) { - str2 = str.substr(0, i); - str = str.substr(i + 1, str.length() - (i + 1)); - parseAdd(str2, mstruct, po); - parseAdd(str, mstruct, po, OPERATION_EXP10); - } else if((i = str.find(ID_WRAP_LEFT_CH, 1)) != string::npos && i + 1 != str.length() && str.find(ID_WRAP_RIGHT_CH, i + 1) && str.find_first_not_of(PLUS MINUS, 0) != i) { - str2 = str.substr(0, i); - str = str.substr(i, str.length() - i); - parseAdd(str2, mstruct, po); - parseAdd(str, mstruct, po, OPERATION_MULTIPLY); - } else if(str.length() > 0 && str[0] == ID_WRAP_LEFT_CH && (i = str.find(ID_WRAP_RIGHT_CH, 1)) != string::npos && i + 1 != str.length()) { - str2 = str.substr(0, i + 1); - str = str.substr(i + 1, str.length() - (i + 1)); - parseAdd(str2, mstruct, po); - parseAdd(str, mstruct, po, OPERATION_MULTIPLY); - } else { - ret = parseNumber(mstruct, str, po); - } - if(po.preserve_format) { - while(minus_count > 0) { - mstruct->transform(STRUCT_NEGATE); - minus_count--; - } - } else if(minus_count % 2 == 1) { - mstruct->negate(); - } - return ret; -} - -string Calculator::getName(string name, ExpressionItem *object, bool force, bool always_append) { - ExpressionItem *item = NULL; - if(!object) { - } else if(object->type() == TYPE_FUNCTION) { - item = getActiveFunction(name); - } else { - item = getActiveVariable(name); - if(!item) { - item = getActiveUnit(name); - } - if(!item) { - item = getCompositeUnit(name); - } - } - if(item && force && !name.empty() && item != object && object) { - if(!item->isLocal()) { - bool b = item->hasChanged(); - if(object->isActive()) { - item->setActive(false); - } - if(!object->isLocal()) { - item->setChanged(b); - } - } else { - if(object->isActive()) { - item->destroy(); - } - } - return name; - } - int i2 = 1; - bool changed = false; - if(name.empty()) { - name = "var"; - always_append = true; - item = NULL; - changed = true; - } - string stmp = name; - if(always_append) { - stmp += NAME_NUMBER_PRE_STR; - stmp += "1"; - } - if(changed || (item && item != object)) { - if(item) { - i2++; - stmp = name; - stmp += NAME_NUMBER_PRE_STR; - stmp += i2s(i2); - } - while(true) { - if(!object) { - item = getActiveFunction(stmp); - if(!item) { - item = getActiveVariable(stmp); - } - if(!item) { - item = getActiveUnit(stmp); - } - if(!item) { - item = getCompositeUnit(stmp); - } - } else if(object->type() == TYPE_FUNCTION) { - item = getActiveFunction(stmp); - } else { - item = getActiveVariable(stmp); - if(!item) { - item = getActiveUnit(stmp); - } - if(!item) { - item = getCompositeUnit(stmp); - } - } - if(item && item != object) { - i2++; - stmp = name; - stmp += NAME_NUMBER_PRE_STR; - stmp += i2s(i2); - } else { - break; - } - } - } - if(i2 > 1 && !always_append) { - error(false, _("Name \"%s\" is in use. Replacing with \"%s\"."), name.c_str(), stmp.c_str(), NULL); - } - return stmp; -} - -bool Calculator::loadGlobalDefinitions() { - bool b = true; - if(!loadDefinitions(buildPath(getGlobalDefinitionsDir(), "prefixes.xml").c_str(), false)) b = false; - if(!loadDefinitions(buildPath(getGlobalDefinitionsDir(), "currencies.xml").c_str(), false)) b = false; - if(!loadDefinitions(buildPath(getGlobalDefinitionsDir(), "units.xml").c_str(), false)) b = false; - if(!loadDefinitions(buildPath(getGlobalDefinitionsDir(), "functions.xml").c_str(), false)) b = false; - if(!loadDefinitions(buildPath(getGlobalDefinitionsDir(), "datasets.xml").c_str(), false)) b = false; - if(!loadDefinitions(buildPath(getGlobalDefinitionsDir(), "variables.xml").c_str(), false)) b = false; - return b; -} -bool Calculator::loadGlobalDefinitions(string filename) { - return loadDefinitions(buildPath(getGlobalDefinitionsDir(), filename).c_str(), false); -} -bool Calculator::loadGlobalPrefixes() { - return loadGlobalDefinitions("prefixes.xml"); -} -bool Calculator::loadGlobalCurrencies() { - return loadGlobalDefinitions("currencies.xml"); -} -bool Calculator::loadGlobalUnits() { - bool b = loadGlobalDefinitions("currencies.xml"); - return loadGlobalDefinitions("units.xml") && b; -} -bool Calculator::loadGlobalVariables() { - return loadGlobalDefinitions("variables.xml"); -} -bool Calculator::loadGlobalFunctions() { - return loadGlobalDefinitions("functions.xml"); -} -bool Calculator::loadGlobalDataSets() { - return loadGlobalDefinitions("datasets.xml"); -} -bool Calculator::loadLocalDefinitions() { - string homedir = buildPath(getLocalDataDir(), "definitions"); - if(!dirExists(homedir)) { - string homedir_old = buildPath(getOldLocalDir(), "definitions"); - if(dirExists(homedir)) { - if(!dirExists(getLocalDataDir())) { - recursiveMakeDir(getLocalDataDir()); - } - if(makeDir(homedir)) { - list eps_old; - struct dirent *ep_old; - DIR *dp_old = opendir(homedir_old.c_str()); - if(dp_old) { - while((ep_old = readdir(dp_old))) { -#ifdef _DIRENT_HAVE_D_TYPE - if(ep_old->d_type != DT_DIR) { -#endif - if(strcmp(ep_old->d_name, "..") != 0 && strcmp(ep_old->d_name, ".") != 0 && strcmp(ep_old->d_name, "datasets") != 0) { - eps_old.push_back(ep_old->d_name); - } -#ifdef _DIRENT_HAVE_D_TYPE - } -#endif - } - closedir(dp_old); - } - for(list::iterator it = eps_old.begin(); it != eps_old.end(); ++it) { - move_file(buildPath(homedir_old, *it).c_str(), buildPath(homedir, *it).c_str()); - } - if(removeDir(homedir_old)) { - removeDir(getOldLocalDir()); - } - } - } - } - list eps; - struct dirent *ep; - DIR *dp = opendir(homedir.c_str()); - if(dp) { - while((ep = readdir(dp))) { -#ifdef _DIRENT_HAVE_D_TYPE - if(ep->d_type != DT_DIR) { -#endif - if(strcmp(ep->d_name, "..") != 0 && strcmp(ep->d_name, ".") != 0 && strcmp(ep->d_name, "datasets") != 0) { - eps.push_back(ep->d_name); - } -#ifdef _DIRENT_HAVE_D_TYPE - } -#endif - } - closedir(dp); - } - eps.sort(); - for(list::iterator it = eps.begin(); it != eps.end(); ++it) { - loadDefinitions(buildPath(homedir, *it).c_str(), (*it) == "functions.xml" || (*it) == "variables.xml" || (*it) == "units.xml" || (*it) == "datasets.xml", true); - } - for(size_t i = 0; i < variables.size(); i++) { - if(!variables[i]->isLocal() && !variables[i]->isActive() && !getActiveExpressionItem(variables[i])) variables[i]->setActive(true); - } - for(size_t i = 0; i < units.size(); i++) { - if(!units[i]->isLocal() && !units[i]->isActive() && !getActiveExpressionItem(units[i])) units[i]->setActive(true); - } - for(size_t i = 0; i < functions.size(); i++) { - if(!functions[i]->isLocal() && !functions[i]->isActive() && !getActiveExpressionItem(functions[i])) functions[i]->setActive(true); - } - return true; -} - -#define ITEM_SAVE_BUILTIN_NAMES\ - if(!is_user_defs) {item->setRegistered(false);} \ - for(size_t i = 1; i <= item->countNames(); i++) { \ - if(item->getName(i).reference) { \ - for(size_t i2 = 0; i2 < 10; i2++) { \ - if(ref_names[i2].name.empty()) { \ - ref_names[i2] = item->getName(i); \ - break; \ - } \ - } \ - } \ - } \ - item->clearNames(); - -#define ITEM_SET_BEST_NAMES(validation) \ - size_t names_i = 0, i2 = 0; \ - string *str_names; \ - if(best_names == "-") {best_names = ""; nextbest_names = "";} \ - if(!best_names.empty()) {str_names = &best_names;} \ - else if(!nextbest_names.empty()) {str_names = &nextbest_names;} \ - else {str_names = &default_names;} \ - if(!str_names->empty() && (*str_names)[0] == '!') { \ - names_i = str_names->find('!', 1) + 1; \ - } \ - while(true) { \ - size_t i3 = names_i; \ - names_i = str_names->find(",", i3); \ - if(i2 == 0) { \ - i2 = str_names->find(":", i3); \ - } \ - bool case_set = false; \ - ename.unicode = false; \ - ename.abbreviation = false; \ - ename.case_sensitive = false; \ - ename.suffix = false; \ - ename.avoid_input = false; \ - ename.completion_only = false; \ - ename.reference = false; \ - ename.plural = false; \ - if(i2 < names_i) { \ - bool b = true; \ - for(; i3 < i2; i3++) { \ - switch((*str_names)[i3]) { \ - case '-': {b = false; break;} \ - case 'a': {ename.abbreviation = b; b = true; break;} \ - case 'c': {ename.case_sensitive = b; b = true; case_set = true; break;} \ - case 'i': {ename.avoid_input = b; b = true; break;} \ - case 'p': {ename.plural = b; b = true; break;} \ - case 'r': {ename.reference = b; b = true; break;} \ - case 's': {ename.suffix = b; b = true; break;} \ - case 'u': {ename.unicode = b; b = true; break;} \ - case 'o': {ename.completion_only = b; b = true; break;} \ - } \ - } \ - i3++; \ - i2 = 0; \ - } \ - if(names_i == string::npos) {ename.name = str_names->substr(i3, str_names->length() - i3);} \ - else {ename.name = str_names->substr(i3, names_i - i3);} \ - remove_blank_ends(ename.name); \ - if(!ename.name.empty() && validation(ename.name, version_numbers, is_user_defs)) { \ - if(!case_set) { \ - ename.case_sensitive = ename.abbreviation || text_length_is_one(ename.name); \ - } \ - item->addName(ename); \ - } \ - if(names_i == string::npos) {break;} \ - names_i++; \ - } - -#define ITEM_SET_BUILTIN_NAMES \ - for(size_t i = 0; i < 10; i++) { \ - if(ref_names[i].name.empty()) { \ - break; \ - } else { \ - size_t i4 = item->hasName(ref_names[i].name, ref_names[i].case_sensitive); \ - if(i4 > 0) { \ - const ExpressionName *enameptr = &item->getName(i4); \ - ref_names[i].case_sensitive = enameptr->case_sensitive; \ - ref_names[i].abbreviation = enameptr->abbreviation; \ - ref_names[i].avoid_input = enameptr->avoid_input; \ - ref_names[i].completion_only = enameptr->completion_only; \ - ref_names[i].plural = enameptr->plural; \ - ref_names[i].suffix = enameptr->suffix; \ - item->setName(ref_names[i], i4); \ - } else { \ - item->addName(ref_names[i]); \ - } \ - ref_names[i].name = ""; \ - } \ - } \ - if(!is_user_defs) { \ - item->setRegistered(true); \ - nameChanged(item); \ - } - -#define ITEM_SET_REFERENCE_NAMES(validation) \ - if(str_names != &default_names && !default_names.empty()) { \ - if(default_names[0] == '!') { \ - names_i = default_names.find('!', 1) + 1; \ - } else { \ - names_i = 0; \ - } \ - i2 = 0; \ - while(true) { \ - size_t i3 = names_i; \ - names_i = default_names.find(",", i3); \ - if(i2 == 0) { \ - i2 = default_names.find(":", i3); \ - } \ - bool case_set = false; \ - ename.unicode = false; \ - ename.abbreviation = false; \ - ename.case_sensitive = false; \ - ename.suffix = false; \ - ename.avoid_input = false; \ - ename.completion_only = false; \ - ename.reference = false; \ - ename.plural = false; \ - if(i2 < names_i) { \ - bool b = true; \ - for(; i3 < i2; i3++) { \ - switch(default_names[i3]) { \ - case '-': {b = false; break;} \ - case 'a': {ename.abbreviation = b; b = true; break;} \ - case 'c': {ename.case_sensitive = b; b = true; case_set = true; break;} \ - case 'i': {ename.avoid_input = b; b = true; break;} \ - case 'p': {ename.plural = b; b = true; break;} \ - case 'r': {ename.reference = b; b = true; break;} \ - case 's': {ename.suffix = b; b = true; break;} \ - case 'u': {ename.unicode = b; b = true; break;} \ - case 'o': {ename.completion_only = b; b = true; break;} \ - } \ - } \ - i3++; \ - i2 = 0; \ - } \ - if(ename.reference) { \ - if(names_i == string::npos) {ename.name = default_names.substr(i3, default_names.length() - i3);} \ - else {ename.name = default_names.substr(i3, names_i - i3);} \ - remove_blank_ends(ename.name); \ - size_t i4 = item->hasName(ename.name, ename.case_sensitive); \ - if(i4 > 0) { \ - const ExpressionName *enameptr = &item->getName(i4); \ - ename.suffix = enameptr->suffix; \ - ename.abbreviation = enameptr->abbreviation; \ - ename.avoid_input = enameptr->avoid_input; \ - ename.completion_only = enameptr->completion_only; \ - ename.plural = enameptr->plural; \ - ename.case_sensitive = enameptr->case_sensitive; \ - item->setName(ename, i4); \ - } else if(!ename.name.empty() && validation(ename.name, version_numbers, is_user_defs)) { \ - if(!case_set) { \ - ename.case_sensitive = ename.abbreviation || text_length_is_one(ename.name); \ - } \ - item->addName(ename); \ - } \ - } \ - if(names_i == string::npos) {break;} \ - names_i++; \ - } \ - } - - -#define ITEM_READ_NAME(validation)\ - if(!new_names && (!xmlStrcmp(child->name, (const xmlChar*) "name") || !xmlStrcmp(child->name, (const xmlChar*) "abbreviation") || !xmlStrcmp(child->name, (const xmlChar*) "plural"))) {\ - name_index = 1;\ - XML_GET_INT_FROM_PROP(child, "index", name_index)\ - if(name_index > 0 && name_index <= 10) {\ - name_index--;\ - names[name_index] = empty_expression_name;\ - ref_names[name_index] = empty_expression_name;\ - value2 = NULL;\ - bool case_set = false;\ - if(child->name[0] == 'a') {\ - names[name_index].abbreviation = true;\ - ref_names[name_index].abbreviation = true;\ - } else if(child->name[0] == 'p') {\ - names[name_index].plural = true;\ - ref_names[name_index].plural = true;\ - }\ - child2 = child->xmlChildrenNode;\ - while(child2 != NULL) {\ - if((!best_name[name_index] || (ref_names[name_index].name.empty() && !locale.empty())) && !xmlStrcmp(child2->name, (const xmlChar*) "name")) {\ - lang = xmlNodeGetLang(child2);\ - if(!lang) {\ - value2 = xmlNodeListGetString(doc, child2->xmlChildrenNode, 1);\ - if(!value2 || validation((char*) value2, version_numbers, is_user_defs)) {\ - if(locale.empty()) {\ - best_name[name_index] = true;\ - if(value2) names[name_index].name = (char*) value2;\ - else names[name_index].name = "";\ - } else if(!require_translation) {\ - if(!best_name[name_index] && !nextbest_name[name_index]) {\ - if(value2) names[name_index].name = (char*) value2;\ - else names[name_index].name = "";\ - }\ - if(value2) ref_names[name_index].name = (char*) value2;\ - else ref_names[name_index].name = "";\ - }\ - }\ - } else if(!best_name[name_index] && !locale.empty()) {\ - if(locale == (char*) lang) {\ - value2 = xmlNodeListGetString(doc, child2->xmlChildrenNode, 1);\ - if(!value2 || validation((char*) value2, version_numbers, is_user_defs)) {\ - best_name[name_index] = true;\ - if(value2) names[name_index].name = (char*) value2;\ - else names[name_index].name = "";\ - }\ - } else if(!nextbest_name[name_index] && strlen((char*) lang) >= 2 && fulfilled_translation == 0 && lang[0] == localebase[0] && lang[1] == localebase[1]) {\ - value2 = xmlNodeListGetString(doc, child2->xmlChildrenNode, 1);\ - if(!value2 || validation((char*) value2, version_numbers, is_user_defs)) {\ - nextbest_name[name_index] = true; \ - if(value2) names[name_index].name = (char*) value2;\ - else names[name_index].name = "";\ - }\ - }\ - }\ - if(value2) xmlFree(value2);\ - if(lang) xmlFree(lang);\ - value2 = NULL; lang = NULL;\ - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "unicode")) {\ - XML_GET_BOOL_FROM_TEXT(child2, names[name_index].unicode)\ - ref_names[name_index].unicode = names[name_index].unicode;\ - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "reference")) {\ - XML_GET_BOOL_FROM_TEXT(child2, names[name_index].reference)\ - ref_names[name_index].reference = names[name_index].reference;\ - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "suffix")) {\ - XML_GET_BOOL_FROM_TEXT(child2, names[name_index].suffix)\ - ref_names[name_index].suffix = names[name_index].suffix;\ - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "avoid_input")) {\ - XML_GET_BOOL_FROM_TEXT(child2, names[name_index].avoid_input)\ - ref_names[name_index].avoid_input = names[name_index].avoid_input;\ - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "completion_only")) {\ - XML_GET_BOOL_FROM_TEXT(child2, names[name_index].completion_only)\ - ref_names[name_index].completion_only = names[name_index].completion_only;\ - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "plural")) {\ - XML_GET_BOOL_FROM_TEXT(child2, names[name_index].plural)\ - ref_names[name_index].plural = names[name_index].plural;\ - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "abbreviation")) {\ - XML_GET_BOOL_FROM_TEXT(child2, names[name_index].abbreviation)\ - ref_names[name_index].abbreviation = names[name_index].abbreviation;\ - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "case_sensitive")) {\ - XML_GET_BOOL_FROM_TEXT(child2, names[name_index].case_sensitive)\ - ref_names[name_index].case_sensitive = names[name_index].case_sensitive;\ - case_set = true;\ - }\ - child2 = child2->next;\ - }\ - if(!case_set) {\ - ref_names[name_index].case_sensitive = ref_names[name_index].abbreviation || text_length_is_one(ref_names[name_index].name);\ - names[name_index].case_sensitive = names[name_index].abbreviation || text_length_is_one(names[name_index].name);\ - }\ - if(names[name_index].reference) {\ - if(!ref_names[name_index].name.empty()) {\ - if(ref_names[name_index].name == names[name_index].name) {\ - ref_names[name_index].name = "";\ - } else {\ - names[name_index].reference = false;\ - }\ - }\ - } else if(!ref_names[name_index].name.empty()) {\ - ref_names[name_index].name = "";\ - }\ - }\ - } - -#define ITEM_READ_DTH \ - if(!xmlStrcmp(child->name, (const xmlChar*) "description")) {\ - XML_GET_LOCALE_STRING_FROM_TEXT(child, description, best_description, next_best_description)\ - } else if(!xmlStrcmp(child->name, (const xmlChar*) "title")) {\ - XML_GET_LOCALE_STRING_FROM_TEXT_REQ(child, title, best_title, next_best_title)\ - } else if(!xmlStrcmp(child->name, (const xmlChar*) "hidden")) {\ - XML_GET_TRUE_FROM_TEXT(child, hidden);\ - } - -#define ITEM_READ_NAMES \ - if(new_names && ((best_names.empty() && fulfilled_translation != 2) || default_names.empty()) && !xmlStrcmp(child->name, (const xmlChar*) "names")) {\ - value = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);\ - lang = xmlNodeGetLang(child);\ - if(!lang) {\ - if(default_names.empty()) {\ - if(value) {\ - default_names = (char*) value;\ - remove_blank_ends(default_names);\ - } else {\ - default_names = "";\ - }\ - }\ - } else if(best_names.empty()) {\ - if(locale == (char*) lang) {\ - if(value) {\ - best_names = (char*) value;\ - remove_blank_ends(best_names);\ - } else {\ - best_names = " ";\ - }\ - } else if(nextbest_names.empty() && strlen((char*) lang) >= 2 && fulfilled_translation == 0 && lang[0] == localebase[0] && lang[1] == localebase[1]) {\ - if(value) {\ - nextbest_names = (char*) value;\ - remove_blank_ends(nextbest_names);\ - } else {\ - nextbest_names = " ";\ - }\ - } else if(nextbest_names.empty() && default_names.empty() && value && !require_translation) {\ - nextbest_names = (char*) value;\ - remove_blank_ends(nextbest_names);\ - }\ - }\ - if(value) xmlFree(value);\ - if(lang) xmlFree(lang);\ - } - -#define ITEM_INIT_DTH \ - hidden = false;\ - title = ""; best_title = false; next_best_title = false;\ - description = ""; best_description = false; next_best_description = false;\ - if(fulfilled_translation > 0) require_translation = false; \ - else {XML_GET_TRUE_FROM_PROP(cur, "require_translation", require_translation)} - -#define ITEM_INIT_NAME \ - if(new_names) {\ - best_names = "";\ - nextbest_names = "";\ - default_names = "";\ - } else {\ - for(size_t i = 0; i < 10; i++) {\ - best_name[i] = false;\ - nextbest_name[i] = false;\ - }\ - } - - -#define ITEM_SET_NAME_1(validation)\ - if(!name.empty() && validation(name, version_numbers, is_user_defs)) {\ - ename.name = name;\ - ename.unicode = false;\ - ename.abbreviation = false;\ - ename.case_sensitive = text_length_is_one(ename.name);\ - ename.suffix = false;\ - ename.avoid_input = false;\ - ename.completion_only = false;\ - ename.reference = true;\ - ename.plural = false;\ - item->addName(ename);\ - } - -#define ITEM_SET_NAME_2\ - for(size_t i = 0; i < 10; i++) {\ - if(!names[i].name.empty()) {\ - item->addName(names[i], i + 1);\ - names[i].name = "";\ - } else if(!ref_names[i].name.empty()) {\ - item->addName(ref_names[i], i + 1);\ - ref_names[i].name = "";\ - }\ - } - -#define ITEM_SET_NAME_3\ - for(size_t i = 0; i < 10; i++) {\ - if(!ref_names[i].name.empty()) {\ - item->addName(ref_names[i]);\ - ref_names[i].name = "";\ - }\ - } - -#define ITEM_SET_DTH\ - item->setDescription(description);\ - if(!title.empty() && title[0] == '!') {\ - size_t i = title.find('!', 1);\ - if(i == string::npos) {\ - item->setTitle(title);\ - } else if(i + 1 == title.length()) {\ - item->setTitle("");\ - } else {\ - item->setTitle(title.substr(i + 1, title.length() - (i + 1)));\ - }\ - } else {\ - item->setTitle(title);\ - }\ - item->setHidden(hidden); - -#define ITEM_SET_SHORT_NAME\ - if(!name.empty() && unitNameIsValid(name, version_numbers, is_user_defs)) {\ - ename.name = name;\ - ename.unicode = false;\ - ename.abbreviation = true;\ - ename.case_sensitive = true;\ - ename.suffix = false;\ - ename.avoid_input = false;\ - ename.completion_only = false;\ - ename.reference = true;\ - ename.plural = false;\ - item->addName(ename);\ - } - -#define ITEM_SET_SINGULAR\ - if(!singular.empty()) {\ - ename.name = singular;\ - ename.unicode = false;\ - ename.abbreviation = false;\ - ename.case_sensitive = text_length_is_one(ename.name);\ - ename.suffix = false;\ - ename.avoid_input = false;\ - ename.completion_only = false;\ - ename.reference = false;\ - ename.plural = false;\ - item->addName(ename);\ - } - -#define ITEM_SET_PLURAL\ - if(!plural.empty()) {\ - ename.name = plural;\ - ename.unicode = false;\ - ename.abbreviation = false;\ - ename.case_sensitive = text_length_is_one(ename.name);\ - ename.suffix = false;\ - ename.avoid_input = false;\ - ename.completion_only = false;\ - ename.reference = false;\ - ename.plural = true;\ - item->addName(ename);\ - } - -#define BUILTIN_NAMES_1\ - if(!is_user_defs) item->setRegistered(false);\ - bool has_ref_name;\ - for(size_t i = 1; i <= item->countNames(); i++) {\ - if(item->getName(i).reference) {\ - has_ref_name = false;\ - for(size_t i2 = 0; i2 < 10; i2++) {\ - if(names[i2].name == item->getName(i).name || ref_names[i2].name == item->getName(i).name) {\ - has_ref_name = true;\ - break;\ - }\ - }\ - if(!has_ref_name) {\ - for(int i2 = 9; i2 >= 0; i2--) {\ - if(ref_names[i2].name.empty()) {\ - ref_names[i2] = item->getName(i);\ - break;\ - }\ - }\ - }\ - }\ - }\ - item->clearNames(); - -#define BUILTIN_UNIT_NAMES_1\ - if(!is_user_defs) item->setRegistered(false);\ - bool has_ref_name;\ - for(size_t i = 1; i <= item->countNames(); i++) {\ - if(item->getName(i).reference) {\ - has_ref_name = item->getName(i).name == singular || item->getName(i).name == plural;\ - for(size_t i2 = 0; !has_ref_name && i2 < 10; i2++) {\ - if(names[i2].name == item->getName(i).name || ref_names[i2].name == item->getName(i).name) {\ - has_ref_name = true;\ - break;\ - }\ - }\ - if(!has_ref_name) {\ - for(int i2 = 9; i2 >= 0; i2--) {\ - if(ref_names[i2].name.empty()) {\ - ref_names[i2] = item->getName(i);\ - break;\ - }\ - }\ - }\ - }\ - }\ - item->clearNames(); - -#define BUILTIN_NAMES_2\ - if(!is_user_defs) {\ - item->setRegistered(true);\ - nameChanged(item);\ - } - -#define ITEM_CLEAR_NAMES\ - for(size_t i = 0; i < 10; i++) {\ - if(!names[i].name.empty()) {\ - names[i].name = "";\ - }\ - if(!ref_names[i].name.empty()) {\ - ref_names[i].name = "";\ - }\ - } - -int Calculator::loadDefinitions(const char* file_name, bool is_user_defs, bool check_duplicates) { - - xmlDocPtr doc; - xmlNodePtr cur, child, child2, child3; - string version, stmp, name, uname, type, svalue, sexp, plural, countries, singular, category_title, category, description, title, inverse, suncertainty, base, argname, usystem; - bool unc_rel; - bool best_title, next_best_title, best_category_title, next_best_category_title, best_description, next_best_description; - bool best_plural, next_best_plural, best_singular, next_best_singular, best_argname, next_best_argname, best_countries, next_best_countries; - bool best_proptitle, next_best_proptitle, best_propdescr, next_best_propdescr; - string proptitle, propdescr; - ExpressionName names[10]; - ExpressionName ref_names[10]; - string prop_names[10]; - string ref_prop_names[10]; - bool best_name[10]; - bool nextbest_name[10]; - string best_names, nextbest_names, default_names; - string best_prop_names, nextbest_prop_names, default_prop_names; - int name_index, prec; - ExpressionName ename; - - string locale; -#ifdef _WIN32 - WCHAR wlocale[LOCALE_NAME_MAX_LENGTH]; - if(LCIDToLocaleName(LOCALE_USER_DEFAULT, wlocale, LOCALE_NAME_MAX_LENGTH, 0) != 0) locale = utf8_encode(wlocale); - gsub("-", "_", locale); -#else - char *clocale = setlocale(LC_MESSAGES, NULL); - if(clocale) locale = clocale; -#endif - - if(b_ignore_locale || locale == "POSIX" || locale == "C") { - locale = ""; - } else { - size_t i = locale.find('.'); - if(i != string::npos) locale = locale.substr(0, i); - } - - int fulfilled_translation = 0; - string localebase; - if(locale.length() > 2) { - localebase = locale.substr(0, 2); - if(locale == "en_US") { - fulfilled_translation = 2; - } else if(localebase == "en") { - fulfilled_translation = 1; - } - } else { - localebase = locale; - if(locale == "en") { - fulfilled_translation = 2; - } - } - while(localebase.length() < 2) { - localebase += " "; - fulfilled_translation = 2; - } - - int exponent = 1, litmp = 0, mix_priority = 0, mix_min = 0; - bool active = false, hidden = false, b = false, require_translation = false, use_with_prefixes = false, use_with_prefixes_set = false; - Number nr; - ExpressionItem *item; - MathFunction *f; - Variable *v; - Unit *u; - AliasUnit *au; - CompositeUnit *cu; - Prefix *p; - Argument *arg; - DataSet *dc; - DataProperty *dp; - int itmp; - IntegerArgument *iarg; - NumberArgument *farg; - xmlChar *value, *lang, *value2; - int in_unfinished = 0; - bool done_something = false; - doc = xmlParseFile(file_name); - if(doc == NULL) { - return false; - } - cur = xmlDocGetRootElement(doc); - if(cur == NULL) { - xmlFreeDoc(doc); - return false; - } - while(cur != NULL) { - if(!xmlStrcmp(cur->name, (const xmlChar*) "QALCULATE")) { - XML_GET_STRING_FROM_PROP(cur, "version", version) - break; - } - cur = cur->next; - } - if(cur == NULL) { - error(true, _("File not identified as Qalculate! definitions file: %s."), file_name, NULL); - xmlFreeDoc(doc); - return false; - } - int version_numbers[] = {3, 6, 0}; - parse_qalculate_version(version, version_numbers); - - bool new_names = version_numbers[0] > 0 || version_numbers[1] > 9 || (version_numbers[1] == 9 && version_numbers[2] >= 4); - - ParseOptions po; - - vector unfinished_nodes; - vector unfinished_cats; - queue sub_items; - vector > nodes; - - category = ""; - nodes.resize(1); - - Unit *u_usd = getUnit("USD"); - - while(true) { - if(!in_unfinished) { - category_title = ""; best_category_title = false; next_best_category_title = false; - child = cur->xmlChildrenNode; - while(child != NULL) { - if(!xmlStrcmp(child->name, (const xmlChar*) "title")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child, category_title, best_category_title, next_best_category_title) - } else if(!xmlStrcmp(child->name, (const xmlChar*) "category")) { - nodes.back().push(child); - } else { - sub_items.push(child); - } - child = child->next; - } - if(!category.empty()) { - category += "/"; - } - if(!category_title.empty() && category_title[0] == '!') {\ - size_t i = category_title.find('!', 1); - if(i == string::npos) { - category += category_title; - } else if(i + 1 < category_title.length()) { - category += category_title.substr(i + 1, category_title.length() - (i + 1)); - } - } else { - category += category_title; - } - } - while(!sub_items.empty() || (in_unfinished && cur)) { - if(!in_unfinished) { - cur = sub_items.front(); - sub_items.pop(); - } - if(!xmlStrcmp(cur->name, (const xmlChar*) "activate")) { - XML_GET_STRING_FROM_TEXT(cur, name) - ExpressionItem *item = getInactiveExpressionItem(name); - if(item && !item->isLocal()) { - item->setActive(true); - done_something = true; - } - } else if(!xmlStrcmp(cur->name, (const xmlChar*) "deactivate")) { - XML_GET_STRING_FROM_TEXT(cur, name) - ExpressionItem *item = getActiveExpressionItem(name); - if(item && !item->isLocal()) { - item->setActive(false); - done_something = true; - } - } else if(!xmlStrcmp(cur->name, (const xmlChar*) "function")) { - if(VERSION_BEFORE(0, 6, 3)) { - XML_GET_STRING_FROM_PROP(cur, "name", name) - } else { - name = ""; - } - XML_GET_FALSE_FROM_PROP(cur, "active", active) - f = new UserFunction(category, "", "", is_user_defs, 0, "", "", 0, active); - item = f; - done_something = true; - child = cur->xmlChildrenNode; - ITEM_INIT_DTH - ITEM_INIT_NAME - while(child != NULL) { - if(!xmlStrcmp(child->name, (const xmlChar*) "expression")) { - XML_DO_FROM_TEXT(child, ((UserFunction*) f)->setFormula); - XML_GET_PREC_FROM_PROP(child, prec) - f->setPrecision(prec); - XML_GET_APPROX_FROM_PROP(child, b) - f->setApproximate(b); - } else if(!xmlStrcmp(child->name, (const xmlChar*) "condition")) { - XML_DO_FROM_TEXT(child, f->setCondition); - } else if(!xmlStrcmp(child->name, (const xmlChar*) "subfunction")) { - XML_GET_FALSE_FROM_PROP(child, "precalculate", b); - value = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - if(value) ((UserFunction*) f)->addSubfunction((char*) value, b); - else ((UserFunction*) f)->addSubfunction("", true); - if(value) xmlFree(value); - } else if(!xmlStrcmp(child->name, (const xmlChar*) "argument")) { - farg = NULL; iarg = NULL; - XML_GET_STRING_FROM_PROP(child, "type", type); - if(type == "text") { - arg = new TextArgument(); - } else if(type == "symbol") { - arg = new SymbolicArgument(); - } else if(type == "date") { - arg = new DateArgument(); - } else if(type == "integer") { - iarg = new IntegerArgument(); - arg = iarg; - } else if(type == "number") { - farg = new NumberArgument(); - arg = farg; - } else if(type == "vector") { - arg = new VectorArgument(); - } else if(type == "matrix") { - arg = new MatrixArgument(); - } else if(type == "boolean") { - arg = new BooleanArgument(); - } else if(type == "function") { - arg = new FunctionArgument(); - } else if(type == "unit") { - arg = new UnitArgument(); - } else if(type == "variable") { - arg = new VariableArgument(); - } else if(type == "object") { - arg = new ExpressionItemArgument(); - } else if(type == "angle") { - arg = new AngleArgument(); - } else if(type == "data-object") { - arg = new DataObjectArgument(NULL, ""); - } else if(type == "data-property") { - arg = new DataPropertyArgument(NULL, ""); - } else { - arg = new Argument(); - } - child2 = child->xmlChildrenNode; - argname = ""; best_argname = false; next_best_argname = false; - while(child2 != NULL) { - if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname) - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "min")) { - if(farg) { - XML_DO_FROM_TEXT(child2, nr.set); - farg->setMin(&nr); - XML_GET_FALSE_FROM_PROP(child, "include_equals", b) - farg->setIncludeEqualsMin(b); - } else if(iarg) { - XML_GET_STRING_FROM_TEXT(child2, stmp); - Number integ(stmp); - iarg->setMin(&integ); - } - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "max")) { - if(farg) { - XML_DO_FROM_TEXT(child2, nr.set); - farg->setMax(&nr); - XML_GET_FALSE_FROM_PROP(child, "include_equals", b) - farg->setIncludeEqualsMax(b); - } else if(iarg) { - XML_GET_STRING_FROM_TEXT(child2, stmp); - Number integ(stmp); - iarg->setMax(&integ); - } - } else if(farg && !xmlStrcmp(child2->name, (const xmlChar*) "complex_allowed")) { - XML_GET_FALSE_FROM_TEXT(child2, b); - farg->setComplexAllowed(b); - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "condition")) { - XML_DO_FROM_TEXT(child2, arg->setCustomCondition); - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "matrix_allowed")) { - XML_GET_TRUE_FROM_TEXT(child2, b); - arg->setMatrixAllowed(b); - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "zero_forbidden")) { - XML_GET_TRUE_FROM_TEXT(child2, b); - arg->setZeroForbidden(b); - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "test")) { - XML_GET_FALSE_FROM_TEXT(child2, b); - arg->setTests(b); - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "handle_vector")) { - XML_GET_FALSE_FROM_TEXT(child2, b); - arg->setHandleVector(b); - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "alert")) { - XML_GET_FALSE_FROM_TEXT(child2, b); - arg->setAlerts(b); - } - child2 = child2->next; - } - if(!argname.empty() && argname[0] == '!') { - size_t i = argname.find('!', 1); - if(i == string::npos) { - arg->setName(argname); - } else if(i + 1 < argname.length()) { - arg->setName(argname.substr(i + 1, argname.length() - (i + 1))); - } - } else { - arg->setName(argname); - } - itmp = 1; - XML_GET_INT_FROM_PROP(child, "index", itmp); - f->setArgumentDefinition(itmp, arg); - } else if(!xmlStrcmp(child->name, (const xmlChar*) "example")) { - XML_DO_FROM_TEXT(child, f->setExample); - } else ITEM_READ_NAME(functionNameIsValid) - else ITEM_READ_DTH - else { - ITEM_READ_NAMES - } - child = child->next; - } - if(new_names) { - ITEM_SET_BEST_NAMES(functionNameIsValid) - ITEM_SET_REFERENCE_NAMES(functionNameIsValid) - } else { - ITEM_SET_NAME_1(functionNameIsValid) - ITEM_SET_NAME_2 - ITEM_SET_NAME_3 - } - ITEM_SET_DTH - if(check_duplicates && !is_user_defs) { - for(size_t i = 1; i <= f->countNames();) { - if(getActiveFunction(f->getName(i).name)) f->removeName(i); - else i++; - } - } - if(f->countNames() == 0) { - f->destroy(); - f = NULL; - } else { - f->setChanged(false); - addFunction(f, true, is_user_defs); - } - } else if(!xmlStrcmp(cur->name, (const xmlChar*) "dataset") || !xmlStrcmp(cur->name, (const xmlChar*) "builtin_dataset")) { - bool builtin = !xmlStrcmp(cur->name, (const xmlChar*) "builtin_dataset"); - XML_GET_FALSE_FROM_PROP(cur, "active", active) - if(builtin) { - XML_GET_STRING_FROM_PROP(cur, "name", name) - dc = getDataSet(name); - if(!dc) { - goto after_load_object; - } - dc->setCategory(category); - } else { - dc = new DataSet(category, "", "", "", "", is_user_defs); - } - item = dc; - done_something = true; - child = cur->xmlChildrenNode; - ITEM_INIT_DTH - ITEM_INIT_NAME - while(child != NULL) { - if(!xmlStrcmp(child->name, (const xmlChar*) "property")) { - dp = new DataProperty(dc); - child2 = child->xmlChildrenNode; - if(new_names) { - default_prop_names = ""; best_prop_names = ""; nextbest_prop_names = ""; - } else { - for(size_t i = 0; i < 10; i++) { - best_name[i] = false; - nextbest_name[i] = false; - } - } - proptitle = ""; best_proptitle = false; next_best_proptitle = false; - propdescr = ""; best_propdescr = false; next_best_propdescr = false; - while(child2 != NULL) { - if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child2, proptitle, best_proptitle, next_best_proptitle) - } else if(!new_names && !xmlStrcmp(child2->name, (const xmlChar*) "name")) { - name_index = 1; - XML_GET_INT_FROM_PROP(child2, "index", name_index) - if(name_index > 0 && name_index <= 10) { - name_index--; - prop_names[name_index] = ""; - ref_prop_names[name_index] = ""; - value2 = NULL; - child3 = child2->xmlChildrenNode; - while(child3 != NULL) { - if((!best_name[name_index] || (ref_prop_names[name_index].empty() && !locale.empty())) && !xmlStrcmp(child3->name, (const xmlChar*) "name")) { - lang = xmlNodeGetLang(child3); - if(!lang) { - value2 = xmlNodeListGetString(doc, child3->xmlChildrenNode, 1); - if(locale.empty()) { - best_name[name_index] = true; - if(value2) prop_names[name_index] = (char*) value2; - else prop_names[name_index] = ""; - } else { - if(!best_name[name_index] && !nextbest_name[name_index]) { - if(value2) prop_names[name_index] = (char*) value2; - else prop_names[name_index] = ""; - } - if(value2) ref_prop_names[name_index] = (char*) value2; - else ref_prop_names[name_index] = ""; - } - } else if(!best_name[name_index] && !locale.empty()) { - if(locale == (char*) lang) { - value2 = xmlNodeListGetString(doc, child3->xmlChildrenNode, 1); - best_name[name_index] = true; - if(value2) prop_names[name_index] = (char*) value2; - else prop_names[name_index] = ""; - } else if(!nextbest_name[name_index] && strlen((char*) lang) >= 2 && fulfilled_translation == 0 && lang[0] == localebase[0] && lang[1] == localebase[1]) { - value2 = xmlNodeListGetString(doc, child3->xmlChildrenNode, 1); - nextbest_name[name_index] = true; - if(value2) prop_names[name_index] = (char*) value2; - else prop_names[name_index] = ""; - } - } - if(value2) xmlFree(value2); - if(lang) xmlFree(lang); - value2 = NULL; lang = NULL; - } - child3 = child3->next; - } - if(!ref_prop_names[name_index].empty() && ref_prop_names[name_index] == prop_names[name_index]) { - ref_prop_names[name_index] = ""; - } - } - } else if(new_names && !xmlStrcmp(child2->name, (const xmlChar*) "names") && ((best_prop_names.empty() && fulfilled_translation != 2) || default_prop_names.empty())) { - value2 = xmlNodeListGetString(doc, child2->xmlChildrenNode, 1); - lang = xmlNodeGetLang(child2); - if(!lang) { - if(default_prop_names.empty()) { - if(value2) { - default_prop_names = (char*) value2; - remove_blank_ends(default_prop_names); - } else { - default_prop_names = ""; - } - } - } else { - if(locale == (char*) lang) { - if(value2) { - best_prop_names = (char*) value2; - remove_blank_ends(best_prop_names); - } else { - best_prop_names = " "; - } - } else if(nextbest_prop_names.empty() && strlen((char*) lang) >= 2 && fulfilled_translation == 0 && lang[0] == localebase[0] && lang[1] == localebase[1]) { - if(value2) { - nextbest_prop_names = (char*) value2; - remove_blank_ends(nextbest_prop_names); - } else { - nextbest_prop_names = " "; - } - } else if(nextbest_prop_names.empty() && default_prop_names.empty() && value2 && !require_translation) { - nextbest_prop_names = (char*) value2; - remove_blank_ends(nextbest_prop_names); - } - } - if(value2) xmlFree(value2); - if(lang) xmlFree(lang); - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "description")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child2, propdescr, best_propdescr, next_best_propdescr) - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "unit")) { - XML_DO_FROM_TEXT(child2, dp->setUnit) - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "key")) { - XML_GET_TRUE_FROM_TEXT(child2, b) - dp->setKey(b); - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "hidden")) { - XML_GET_TRUE_FROM_TEXT(child2, b) - dp->setHidden(b); - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "brackets")) { - XML_GET_TRUE_FROM_TEXT(child2, b) - dp->setUsesBrackets(b); - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "approximate")) { - XML_GET_TRUE_FROM_TEXT(child2, b) - dp->setApproximate(b); - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "case_sensitive")) { - XML_GET_TRUE_FROM_TEXT(child2, b) - dp->setCaseSensitive(b); - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "type")) { - XML_GET_STRING_FROM_TEXT(child2, stmp) - if(stmp == "text") { - dp->setPropertyType(PROPERTY_STRING); - } else if(stmp == "number") { - dp->setPropertyType(PROPERTY_NUMBER); - } else if(stmp == "expression") { - dp->setPropertyType(PROPERTY_EXPRESSION); - } - } - child2 = child2->next; - } - if(!proptitle.empty() && proptitle[0] == '!') {\ - size_t i = proptitle.find('!', 1); - if(i == string::npos) { - dp->setTitle(proptitle); - } else if(i + 1 < proptitle.length()) { - dp->setTitle(proptitle.substr(i + 1, proptitle.length() - (i + 1))); - } - } else { - dp->setTitle(proptitle); - } - dp->setDescription(propdescr); - if(new_names) { - size_t names_i = 0, i2 = 0; - string *str_names; - bool had_ref = false; - if(best_prop_names == "-") {best_prop_names = ""; nextbest_prop_names = "";} - if(!best_prop_names.empty()) {str_names = &best_prop_names;} - else if(!nextbest_prop_names.empty()) {str_names = &nextbest_prop_names;} - else {str_names = &default_prop_names;} - if(!str_names->empty() && (*str_names)[0] == '!') { - names_i = str_names->find('!', 1) + 1; - } - while(true) { - size_t i3 = names_i; - names_i = str_names->find(",", i3); - if(i2 == 0) { - i2 = str_names->find(":", i3); - } - bool b_prop_ref = false; - if(i2 < names_i) { - bool b = true; - for(; i3 < i2; i3++) { - switch((*str_names)[i3]) { - case '-': {b = false; break;} - case 'r': {b_prop_ref = b; b = true; break;} - } - } - i3++; - i2 = 0; - } - if(names_i == string::npos) {stmp = str_names->substr(i3, str_names->length() - i3);} - else {stmp = str_names->substr(i3, names_i - i3);} - remove_blank_ends(stmp); - if(!stmp.empty()) { - if(b_prop_ref) had_ref = true; - dp->addName(stmp, b_prop_ref); - } - if(names_i == string::npos) {break;} - names_i++; - } - if(str_names != &default_prop_names && !default_prop_names.empty()) { - if(default_prop_names[0] == '!') { - names_i = default_prop_names.find('!', 1) + 1; - } else { - names_i = 0; - } - i2 = 0; - while(true) { - size_t i3 = names_i; - names_i = default_prop_names.find(",", i3); - if(i2 == 0) { - i2 = default_prop_names.find(":", i3); - } - bool b_prop_ref = false; - if(i2 < names_i) { - bool b = true; - for(; i3 < i2; i3++) { - switch(default_prop_names[i3]) { - case '-': {b = false; break;} - case 'r': {b_prop_ref = b; b = true; break;} - } - } - i3++; - i2 = 0; - } - if(b_prop_ref || (!had_ref && names_i == string::npos)) { - had_ref = true; - if(names_i == string::npos) {stmp = default_prop_names.substr(i3, default_prop_names.length() - i3);} - else {stmp = default_prop_names.substr(i3, names_i - i3);} - remove_blank_ends(stmp); - size_t i4 = dp->hasName(stmp); - if(i4 > 0) { - dp->setNameIsReference(i4, true); - } else if(!stmp.empty()) { - dp->addName(stmp, true); - } - } - if(names_i == string::npos) {break;} - names_i++; - } - } - if(!had_ref && dp->countNames() > 0) dp->setNameIsReference(1, true); - } else { - bool b = false; - for(size_t i = 0; i < 10; i++) { - if(!prop_names[i].empty()) { - if(!b && ref_prop_names[i].empty()) { - dp->addName(prop_names[i], true, i + 1); - b = true; - } else { - dp->addName(prop_names[i], false, i + 1); - } - prop_names[i] = ""; - } - } - for(size_t i = 0; i < 10; i++) { - if(!ref_prop_names[i].empty()) { - if(!b) { - dp->addName(ref_prop_names[i], true); - b = true; - } else { - dp->addName(ref_prop_names[i], false); - } - ref_prop_names[i] = ""; - } - } - } - dp->setUserModified(is_user_defs); - dc->addProperty(dp); - } else if(!xmlStrcmp(child->name, (const xmlChar*) "argument")) { - child2 = child->xmlChildrenNode; - argname = ""; best_argname = false; next_best_argname = false; - while(child2 != NULL) { - if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname) - } - child2 = child2->next; - } - itmp = 1; - XML_GET_INT_FROM_PROP(child, "index", itmp); - if(dc->getArgumentDefinition(itmp)) { - dc->getArgumentDefinition(itmp)->setName(argname); - } - } else if(!xmlStrcmp(child->name, (const xmlChar*) "object_argument")) { - child2 = child->xmlChildrenNode; - argname = ""; best_argname = false; next_best_argname = false; - while(child2 != NULL) { - if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname) - } - child2 = child2->next; - } - itmp = 1; - if(dc->getArgumentDefinition(itmp)) { - if(!argname.empty() && argname[0] == '!') { - size_t i = argname.find('!', 1); - if(i == string::npos) { - dc->getArgumentDefinition(itmp)->setName(argname); - } else if(i + 1 < argname.length()) { - dc->getArgumentDefinition(itmp)->setName(argname.substr(i + 1, argname.length() - (i + 1))); - } - } else { - dc->getArgumentDefinition(itmp)->setName(argname); - } - } - } else if(!xmlStrcmp(child->name, (const xmlChar*) "property_argument")) { - child2 = child->xmlChildrenNode; - argname = ""; best_argname = false; next_best_argname = false; - while(child2 != NULL) { - if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname) - } - child2 = child2->next; - } - itmp = 2; - if(dc->getArgumentDefinition(itmp)) { - if(!argname.empty() && argname[0] == '!') { - size_t i = argname.find('!', 1); - if(i == string::npos) { - dc->getArgumentDefinition(itmp)->setName(argname); - } else if(i + 1 < argname.length()) { - dc->getArgumentDefinition(itmp)->setName(argname.substr(i + 1, argname.length() - (i + 1))); - } - } else { - dc->getArgumentDefinition(itmp)->setName(argname); - } - } - } else if(!xmlStrcmp(child->name, (const xmlChar*) "default_property")) { - XML_DO_FROM_TEXT(child, dc->setDefaultProperty) - } else if(!builtin && !xmlStrcmp(child->name, (const xmlChar*) "copyright")) { - XML_DO_FROM_TEXT(child, dc->setCopyright) - } else if(!builtin && !xmlStrcmp(child->name, (const xmlChar*) "datafile")) { - XML_DO_FROM_TEXT(child, dc->setDefaultDataFile) - } else if(!xmlStrcmp(child->name, (const xmlChar*) "example")) { - XML_DO_FROM_TEXT(child, dc->setExample); - } else ITEM_READ_NAME(functionNameIsValid) - else ITEM_READ_DTH - else { - ITEM_READ_NAMES - } - child = child->next; - } - if(new_names) { - if(builtin) { - ITEM_SAVE_BUILTIN_NAMES - } - ITEM_SET_BEST_NAMES(functionNameIsValid) - ITEM_SET_REFERENCE_NAMES(functionNameIsValid) - if(builtin) { - ITEM_SET_BUILTIN_NAMES - } - } else { - if(builtin) { - BUILTIN_NAMES_1 - } - ITEM_SET_NAME_2 - ITEM_SET_NAME_3 - if(builtin) { - BUILTIN_NAMES_2 - } - } - ITEM_SET_DTH - if(check_duplicates && !is_user_defs) { - for(size_t i = 1; i <= dc->countNames();) { - if(getActiveFunction(dc->getName(i).name)) dc->removeName(i); - else i++; - } - } - if(!builtin && dc->countNames() == 0) { - dc->destroy(); - dc = NULL; - } else { - dc->setChanged(builtin && is_user_defs); - if(!builtin) addDataSet(dc, true, is_user_defs); - } - done_something = true; - } else if(!xmlStrcmp(cur->name, (const xmlChar*) "builtin_function")) { - XML_GET_STRING_FROM_PROP(cur, "name", name) - f = getFunction(name); - if(f) { - XML_GET_FALSE_FROM_PROP(cur, "active", active) - f->setLocal(is_user_defs, active); - f->setCategory(category); - item = f; - child = cur->xmlChildrenNode; - ITEM_INIT_DTH - ITEM_INIT_NAME - while(child != NULL) { - if(!xmlStrcmp(child->name, (const xmlChar*) "argument")) { - child2 = child->xmlChildrenNode; - argname = ""; best_argname = false; next_best_argname = false; - while(child2 != NULL) { - if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname) - } - child2 = child2->next; - } - itmp = 1; - XML_GET_INT_FROM_PROP(child, "index", itmp); - if(f->getArgumentDefinition(itmp)) { - if(!argname.empty() && argname[0] == '!') { - size_t i = argname.find('!', 1); - if(i == string::npos) { - f->getArgumentDefinition(itmp)->setName(argname); - } else if(i + 1 < argname.length()) { - f->getArgumentDefinition(itmp)->setName(argname.substr(i + 1, argname.length() - (i + 1))); - } - } else { - f->getArgumentDefinition(itmp)->setName(argname); - } - } else if(itmp <= f->maxargs() || itmp <= f->minargs()) { - if(!argname.empty() && argname[0] == '!') { - size_t i = argname.find('!', 1); - if(i == string::npos) { - f->setArgumentDefinition(itmp, new Argument(argname, false)); - } else if(i + 1 < argname.length()) { - f->setArgumentDefinition(itmp, new Argument(argname.substr(i + 1, argname.length() - (i + 1)), false)); - } - } else { - f->setArgumentDefinition(itmp, new Argument(argname, false)); - } - } - } else if(!xmlStrcmp(child->name, (const xmlChar*) "example")) { - XML_DO_FROM_TEXT(child, f->setExample); - } else ITEM_READ_NAME(functionNameIsValid) - else ITEM_READ_DTH - else { - ITEM_READ_NAMES - } - child = child->next; - } - if(new_names) { - ITEM_SAVE_BUILTIN_NAMES - ITEM_SET_BEST_NAMES(functionNameIsValid) - ITEM_SET_REFERENCE_NAMES(functionNameIsValid) - ITEM_SET_BUILTIN_NAMES - } else { - BUILTIN_NAMES_1 - ITEM_SET_NAME_2 - ITEM_SET_NAME_3 - BUILTIN_NAMES_2 - } - ITEM_SET_DTH - f->setChanged(false); - done_something = true; - } - } else if(!xmlStrcmp(cur->name, (const xmlChar*) "unknown")) { - if(VERSION_BEFORE(0, 6, 3)) { - XML_GET_STRING_FROM_PROP(cur, "name", name) - } else { - name = ""; - } - XML_GET_FALSE_FROM_PROP(cur, "active", active) - svalue = ""; - v = new UnknownVariable(category, "", "", is_user_defs, false, active); - item = v; - done_something = true; - child = cur->xmlChildrenNode; - b = true; - ITEM_INIT_DTH - ITEM_INIT_NAME - while(child != NULL) { - if(!xmlStrcmp(child->name, (const xmlChar*) "type")) { - XML_GET_STRING_FROM_TEXT(child, stmp); - if(!((UnknownVariable*) v)->assumptions()) ((UnknownVariable*) v)->setAssumptions(new Assumptions()); - if(stmp == "integer") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_INTEGER); - else if(stmp == "rational") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_RATIONAL); - else if(stmp == "real") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_REAL); - else if(stmp == "complex") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_COMPLEX); - else if(stmp == "number") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_NUMBER); - else if(stmp == "non-matrix") { - if(VERSION_BEFORE(0, 9, 13)) { - ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_NUMBER); - } else { - ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_NONMATRIX); - } - } else if(stmp == "none") { - if(VERSION_BEFORE(0, 9, 13)) { - ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_NUMBER); - } else { - ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_NONE); - } - } - } else if(!xmlStrcmp(child->name, (const xmlChar*) "sign")) { - XML_GET_STRING_FROM_TEXT(child, stmp); - if(!((UnknownVariable*) v)->assumptions()) ((UnknownVariable*) v)->setAssumptions(new Assumptions()); - if(stmp == "non-zero") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_NONZERO); - else if(stmp == "non-positive") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_NONPOSITIVE); - else if(stmp == "negative") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_NEGATIVE); - else if(stmp == "non-negative") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_NONNEGATIVE); - else if(stmp == "positive") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_POSITIVE); - else if(stmp == "unknown") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_UNKNOWN); - } else ITEM_READ_NAME(variableNameIsValid) - else ITEM_READ_DTH - else { - ITEM_READ_NAMES - } - child = child->next; - } - if(new_names) { - ITEM_SET_BEST_NAMES(variableNameIsValid) - ITEM_SET_REFERENCE_NAMES(variableNameIsValid) - } else { - ITEM_SET_NAME_1(variableNameIsValid) - ITEM_SET_NAME_2 - ITEM_SET_NAME_3 - } - ITEM_SET_DTH - if(check_duplicates && !is_user_defs) { - for(size_t i = 1; i <= v->countNames();) { - if(getActiveVariable(v->getName(i).name) || getActiveUnit(v->getName(i).name) || getCompositeUnit(v->getName(i).name)) v->removeName(i); - else i++; - } - } - for(size_t i = 1; i <= v->countNames(); i++) { - if(v->getName(i).name == "x") {v_x->destroy(); v_x = (UnknownVariable*) v; break;} - if(v->getName(i).name == "y") {v_y->destroy(); v_y = (UnknownVariable*) v; break;} - if(v->getName(i).name == "z") {v_z->destroy(); v_z = (UnknownVariable*) v; break;} - } - if(v->countNames() == 0) { - v->destroy(); - v = NULL; - } else { - addVariable(v, true, is_user_defs); - v->setChanged(false); - } - } else if(!xmlStrcmp(cur->name, (const xmlChar*) "variable")) { - if(VERSION_BEFORE(0, 6, 3)) { - XML_GET_STRING_FROM_PROP(cur, "name", name) - } else { - name = ""; - } - XML_GET_FALSE_FROM_PROP(cur, "active", active) - svalue = ""; - v = new KnownVariable(category, "", "", "", is_user_defs, false, active); - item = v; - done_something = true; - child = cur->xmlChildrenNode; - b = true; - ITEM_INIT_DTH - ITEM_INIT_NAME - while(child != NULL) { - if(!xmlStrcmp(child->name, (const xmlChar*) "value")) { - XML_DO_FROM_TEXT(child, ((KnownVariable*) v)->set); - XML_GET_STRING_FROM_PROP(child, "relative_uncertainty", suncertainty) - unc_rel = false; - if(suncertainty.empty()) {XML_GET_STRING_FROM_PROP(child, "uncertainty", suncertainty)} - else unc_rel = true; - ((KnownVariable*) v)->setUncertainty(suncertainty, unc_rel); - XML_DO_FROM_PROP(child, "unit", ((KnownVariable*) v)->setUnit) - XML_GET_PREC_FROM_PROP(child, prec) - v->setPrecision(prec); - XML_GET_APPROX_FROM_PROP(child, b); - if(b) v->setApproximate(true); - } else ITEM_READ_NAME(variableNameIsValid) - else ITEM_READ_DTH - else { - ITEM_READ_NAMES - } - child = child->next; - } - if(new_names) { - ITEM_SET_BEST_NAMES(variableNameIsValid) - ITEM_SET_REFERENCE_NAMES(variableNameIsValid) - } else { - ITEM_SET_NAME_1(variableNameIsValid) - ITEM_SET_NAME_2 - ITEM_SET_NAME_3 - } - ITEM_SET_DTH - if(check_duplicates && !is_user_defs) { - for(size_t i = 1; i <= v->countNames();) { - if(getActiveVariable(v->getName(i).name) || getActiveUnit(v->getName(i).name) || getCompositeUnit(v->getName(i).name)) v->removeName(i); - else i++; - } - } - if(v->countNames() == 0) { - v->destroy(); - v = NULL; - } else { - addVariable(v, true, is_user_defs); - item->setChanged(false); - } - } else if(!xmlStrcmp(cur->name, (const xmlChar*) "builtin_variable")) { - XML_GET_STRING_FROM_PROP(cur, "name", name) - v = getVariable(name); - if(v) { - XML_GET_FALSE_FROM_PROP(cur, "active", active) - v->setLocal(is_user_defs, active); - v->setCategory(category); - item = v; - child = cur->xmlChildrenNode; - ITEM_INIT_DTH - ITEM_INIT_NAME - while(child != NULL) { - ITEM_READ_NAME(variableNameIsValid) - else ITEM_READ_DTH - else { - ITEM_READ_NAMES - } - child = child->next; - } - if(new_names) { - ITEM_SAVE_BUILTIN_NAMES - ITEM_SET_BEST_NAMES(variableNameIsValid) - ITEM_SET_REFERENCE_NAMES(variableNameIsValid) - ITEM_SET_BUILTIN_NAMES - } else { - BUILTIN_NAMES_1 - ITEM_SET_NAME_2 - ITEM_SET_NAME_3 - BUILTIN_NAMES_2 - } - ITEM_SET_DTH - v->setChanged(false); - done_something = true; - } - } else if(!xmlStrcmp(cur->name, (const xmlChar*) "unit")) { - XML_GET_STRING_FROM_PROP(cur, "type", type) - if(type == "base") { - if(VERSION_BEFORE(0, 6, 3)) { - XML_GET_STRING_FROM_PROP(cur, "name", name) - } else { - name = ""; - } - XML_GET_FALSE_FROM_PROP(cur, "active", active) - u = new Unit(category, "", "", "", "", is_user_defs, false, active); - item = u; - child = cur->xmlChildrenNode; - singular = ""; best_singular = false; next_best_singular = false; - plural = ""; best_plural = false; next_best_plural = false; - countries = "", best_countries = false, next_best_countries = false; - use_with_prefixes_set = false; - ITEM_INIT_DTH - ITEM_INIT_NAME - while(child != NULL) { - if(!xmlStrcmp(child->name, (const xmlChar*) "system")) { - XML_DO_FROM_TEXT(child, u->setSystem) - } else if(!xmlStrcmp(child->name, (const xmlChar*) "use_with_prefixes")) { - XML_GET_TRUE_FROM_TEXT(child, use_with_prefixes) - use_with_prefixes_set = true; - } else if((VERSION_BEFORE(0, 6, 3)) && !xmlStrcmp(child->name, (const xmlChar*) "singular")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child, singular, best_singular, next_best_singular) - if(!unitNameIsValid(singular, version_numbers, is_user_defs)) { - singular = ""; - } - } else if((VERSION_BEFORE(0, 6, 3)) && !xmlStrcmp(child->name, (const xmlChar*) "plural") && !xmlGetProp(child, (xmlChar*) "index")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child, plural, best_plural, next_best_plural) - if(!unitNameIsValid(plural, version_numbers, is_user_defs)) { - plural = ""; - } - } else if(!xmlStrcmp(child->name, (const xmlChar*) "countries")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child, countries, best_countries, next_best_countries) - } else ITEM_READ_NAME(unitNameIsValid) - else ITEM_READ_DTH - else { - ITEM_READ_NAMES - } - child = child->next; - } - u->setCountries(countries); - if(new_names) { - ITEM_SET_BEST_NAMES(unitNameIsValid) - ITEM_SET_REFERENCE_NAMES(unitNameIsValid) - } else { - ITEM_SET_SHORT_NAME - ITEM_SET_SINGULAR - ITEM_SET_PLURAL - ITEM_SET_NAME_2 - ITEM_SET_NAME_3 - } - ITEM_SET_DTH - if(use_with_prefixes_set) { - u->setUseWithPrefixesByDefault(use_with_prefixes); - } - if(check_duplicates && !is_user_defs) { - for(size_t i = 1; i <= u->countNames();) { - if(getActiveVariable(u->getName(i).name) || getActiveUnit(u->getName(i).name) || getCompositeUnit(u->getName(i).name)) u->removeName(i); - else i++; - } - } - if(u->countNames() == 0) { - u->destroy(); - u = NULL; - } else { - if(!is_user_defs && u->referenceName() == "s") u_second = u; - addUnit(u, true, is_user_defs); - u->setChanged(false); - } - done_something = true; - } else if(type == "alias") { - if(VERSION_BEFORE(0, 6, 3)) { - XML_GET_STRING_FROM_PROP(cur, "name", name) - } else { - name = ""; - } - XML_GET_FALSE_FROM_PROP(cur, "active", active) - u = NULL; - child = cur->xmlChildrenNode; - singular = ""; best_singular = false; next_best_singular = false; - plural = ""; best_plural = false; next_best_plural = false; - countries = "", best_countries = false, next_best_countries = false; - bool b_currency = false; - use_with_prefixes_set = false; - usystem = ""; - prec = -1; - ITEM_INIT_DTH - ITEM_INIT_NAME - unc_rel = false; - while(child != NULL) { - if(!xmlStrcmp(child->name, (const xmlChar*) "base")) { - child2 = child->xmlChildrenNode; - exponent = 1; - mix_priority = 0; - mix_min = 0; - svalue = ""; - inverse = ""; - suncertainty = ""; - b = true; - while(child2 != NULL) { - if(!xmlStrcmp(child2->name, (const xmlChar*) "unit")) { - XML_GET_STRING_FROM_TEXT(child2, base); - u = getUnit(base); - b_currency = (!is_user_defs && u && u == u_euro); - if(!u) { - u = getCompositeUnit(base); - } - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "relation")) { - XML_GET_STRING_FROM_TEXT(child2, svalue); - XML_GET_APPROX_FROM_PROP(child2, b) - XML_GET_PREC_FROM_PROP(child2, prec) - XML_GET_STRING_FROM_PROP(child2, "relative_uncertainty", suncertainty) - if(suncertainty.empty()) {XML_GET_STRING_FROM_PROP(child2, "uncertainty", suncertainty)} - else unc_rel = true; - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "reverse_relation")) { - XML_GET_STRING_FROM_TEXT(child2, inverse); - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "inverse_relation")) { - XML_GET_STRING_FROM_TEXT(child2, inverse); - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "exponent")) { - XML_GET_STRING_FROM_TEXT(child2, stmp); - if(stmp.empty()) { - exponent = 1; - } else { - exponent = s2i(stmp); - } - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "mix")) { - XML_GET_INT_FROM_PROP(child2, "min", mix_min); - XML_GET_STRING_FROM_TEXT(child2, stmp); - if(stmp.empty()) { - mix_priority = 0; - } else { - mix_priority = s2i(stmp); - } - } - child2 = child2->next; - } - } else if(!xmlStrcmp(child->name, (const xmlChar*) "system")) { - XML_GET_STRING_FROM_TEXT(child, usystem); - } else if(!xmlStrcmp(child->name, (const xmlChar*) "use_with_prefixes")) { - XML_GET_TRUE_FROM_TEXT(child, use_with_prefixes) - use_with_prefixes_set = true; - } else if((VERSION_BEFORE(0, 6, 3)) && !xmlStrcmp(child->name, (const xmlChar*) "singular")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child, singular, best_singular, next_best_singular) - if(!unitNameIsValid(singular, version_numbers, is_user_defs)) { - singular = ""; - } - } else if((VERSION_BEFORE(0, 6, 3)) && !xmlStrcmp(child->name, (const xmlChar*) "plural") && !xmlGetProp(child, (xmlChar*) "index")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child, plural, best_plural, next_best_plural) - if(!unitNameIsValid(plural, version_numbers, is_user_defs)) { - plural = ""; - } - } else if(!xmlStrcmp(child->name, (const xmlChar*) "countries")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child, countries, best_countries, next_best_countries) - } else ITEM_READ_NAME(unitNameIsValid) - else ITEM_READ_DTH - else { - ITEM_READ_NAMES - } - child = child->next; - } - if(!u) { - ITEM_CLEAR_NAMES - if(!in_unfinished) { - unfinished_nodes.push_back(cur); - unfinished_cats.push_back(category); - } - } else { - au = new AliasUnit(category, name, plural, singular, title, u, svalue, exponent, inverse, is_user_defs, false, active); - au->setCountries(countries); - if(mix_priority > 0) { - au->setMixWithBase(mix_priority); - au->setMixWithBaseMinimum(mix_min); - } - au->setDescription(description); - au->setPrecision(prec); - if(b) au->setApproximate(true); - au->setUncertainty(suncertainty, unc_rel); - au->setHidden(hidden); - au->setSystem(usystem); - if(use_with_prefixes_set) { - au->setUseWithPrefixesByDefault(use_with_prefixes); - } - item = au; - if(new_names) { - ITEM_SET_BEST_NAMES(unitNameIsValid) - ITEM_SET_REFERENCE_NAMES(unitNameIsValid) - } else { - ITEM_SET_NAME_2 - ITEM_SET_NAME_3 - } - if(b_currency && !au->referenceName().empty()) { - u = getUnit(au->referenceName()); - if(u && u->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) u)->baseUnit() == u_euro) u->destroy(); - } - if(check_duplicates && !is_user_defs) { - for(size_t i = 1; i <= au->countNames();) { - if(getActiveVariable(au->getName(i).name) || getActiveUnit(au->getName(i).name) || getCompositeUnit(au->getName(i).name)) au->removeName(i); - else i++; - } - } - if(au->countNames() == 0) { - au->destroy(); - au = NULL; - } else { - if(!is_user_defs && au->baseUnit() == u_second) { - if(au->referenceName() == "d" || au->referenceName() == "day") u_day = au; - else if(au->referenceName() == "year") u_year = au; - else if(au->referenceName() == "month") u_month = au; - else if(au->referenceName() == "min") u_minute = au; - else if(au->referenceName() == "h") u_hour = au; - } - addUnit(au, true, is_user_defs); - au->setChanged(false); - } - done_something = true; - } - } else if(type == "composite") { - if(VERSION_BEFORE(0, 6, 3)) { - XML_GET_STRING_FROM_PROP(cur, "name", name) - } else { - name = ""; - } - XML_GET_FALSE_FROM_PROP(cur, "active", active) - child = cur->xmlChildrenNode; - usystem = ""; - cu = NULL; - ITEM_INIT_DTH - ITEM_INIT_NAME - b = true; - while(child != NULL) { - u = NULL; - if(!xmlStrcmp(child->name, (const xmlChar*) "part")) { - child2 = child->xmlChildrenNode; - p = NULL; - exponent = 1; - while(child2 != NULL) { - if(!xmlStrcmp(child2->name, (const xmlChar*) "unit")) { - XML_GET_STRING_FROM_TEXT(child2, base); - u = getUnit(base); - if(!u) { - u = getCompositeUnit(base); - } - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "prefix")) { - XML_GET_STRING_FROM_PROP(child2, "type", stmp) - XML_GET_STRING_FROM_TEXT(child2, svalue); - p = NULL; - if(stmp == "binary") { - litmp = s2i(svalue); - if(litmp != 0) { - p = getExactBinaryPrefix(litmp); - if(!p) b = false; - } - } else if(stmp == "number") { - nr.set(stmp); - if(!nr.isZero()) { - p = getExactPrefix(stmp); - if(!p) b = false; - } - } else { - litmp = s2i(svalue); - if(litmp != 0) { - p = getExactDecimalPrefix(litmp); - if(!p) b = false; - } - } - if(!b) { - if(cu) { - delete cu; - } - cu = NULL; - break; - } - } else if(!xmlStrcmp(child2->name, (const xmlChar*) "exponent")) { - XML_GET_STRING_FROM_TEXT(child2, stmp); - if(stmp.empty()) { - exponent = 1; - } else { - exponent = s2i(stmp); - } - } - child2 = child2->next; - } - if(!b) break; - if(u) { - if(!cu) { - cu = new CompositeUnit("", "", "", "", is_user_defs, false, active); - } - cu->add(u, exponent, p); - } else { - if(cu) delete cu; - cu = NULL; - if(!in_unfinished) { - unfinished_nodes.push_back(cur); - unfinished_cats.push_back(category); - } - break; - } - } else if(!xmlStrcmp(child->name, (const xmlChar*) "system")) { - XML_GET_STRING_FROM_TEXT(child, usystem); - } else if(!xmlStrcmp(child->name, (const xmlChar*) "use_with_prefixes")) { - XML_GET_TRUE_FROM_TEXT(child, use_with_prefixes) - use_with_prefixes_set = true; - } else ITEM_READ_NAME(unitNameIsValid) - else ITEM_READ_DTH - else { - ITEM_READ_NAMES - } - child = child->next; - } - if(cu) { - item = cu; - cu->setCategory(category); - cu->setSystem(usystem); - /*if(use_with_prefixes_set) { - cu->setUseWithPrefixesByDefault(use_with_prefixes); - }*/ - if(new_names) { - ITEM_SET_BEST_NAMES(unitNameIsValid) - ITEM_SET_REFERENCE_NAMES(unitNameIsValid) - } else { - ITEM_SET_NAME_1(unitNameIsValid) - ITEM_SET_NAME_2 - ITEM_SET_NAME_3 - } - ITEM_SET_DTH - if(check_duplicates && !is_user_defs) { - for(size_t i = 1; i <= cu->countNames();) { - if(getActiveVariable(cu->getName(i).name) || getActiveUnit(cu->getName(i).name) || getCompositeUnit(cu->getName(i).name)) cu->removeName(i); - else i++; - } - } - if(cu->countNames() == 0) { - cu->destroy(); - cu = NULL; - } else { - addUnit(cu, true, is_user_defs); - cu->setChanged(false); - } - done_something = true; - } else { - ITEM_CLEAR_NAMES - } - } - } else if(!xmlStrcmp(cur->name, (const xmlChar*) "builtin_unit")) { - XML_GET_STRING_FROM_PROP(cur, "name", name) - u = getUnit(name); - if(!u) { - u = getCompositeUnit(name); - } - if(u) { - XML_GET_FALSE_FROM_PROP(cur, "active", active) - u->setLocal(is_user_defs, active); - u->setCategory(category); - item = u; - child = cur->xmlChildrenNode; - singular = ""; best_singular = false; next_best_singular = false; - plural = ""; best_plural = false; next_best_plural = false; - countries = "", best_countries = false, next_best_countries = false; - use_with_prefixes_set = false; - ITEM_INIT_DTH - ITEM_INIT_NAME - while(child != NULL) { - if(!xmlStrcmp(child->name, (const xmlChar*) "singular")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child, singular, best_singular, next_best_singular) - if(!unitNameIsValid(singular, version_numbers, is_user_defs)) { - singular = ""; - } - } else if(!xmlStrcmp(child->name, (const xmlChar*) "plural") && !xmlGetProp(child, (xmlChar*) "index")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child, plural, best_plural, next_best_plural) - if(!unitNameIsValid(plural, version_numbers, is_user_defs)) { - plural = ""; - } - } else if(!xmlStrcmp(child->name, (const xmlChar*) "use_with_prefixes")) { - XML_GET_TRUE_FROM_TEXT(child, use_with_prefixes) - use_with_prefixes_set = true; - } else if(!xmlStrcmp(child->name, (const xmlChar*) "countries")) { - XML_GET_LOCALE_STRING_FROM_TEXT(child, countries, best_countries, next_best_countries) - } else ITEM_READ_NAME(unitNameIsValid) - else ITEM_READ_DTH - else { - ITEM_READ_NAMES - } - child = child->next; - } - if(use_with_prefixes_set) { - u->setUseWithPrefixesByDefault(use_with_prefixes); - } - u->setCountries(countries); - if(new_names) { - ITEM_SAVE_BUILTIN_NAMES - ITEM_SET_BEST_NAMES(unitNameIsValid) - ITEM_SET_REFERENCE_NAMES(unitNameIsValid) - ITEM_SET_BUILTIN_NAMES - } else { - BUILTIN_UNIT_NAMES_1 - ITEM_SET_SINGULAR - ITEM_SET_PLURAL - ITEM_SET_NAME_2 - ITEM_SET_NAME_3 - BUILTIN_NAMES_2 - } - ITEM_SET_DTH - if(u_usd && u->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) u)->firstBaseUnit() == u_usd) u->setHidden(true); - u->setChanged(false); - done_something = true; - } - } else if(!xmlStrcmp(cur->name, (const xmlChar*) "prefix")) { - child = cur->xmlChildrenNode; - XML_GET_STRING_FROM_PROP(cur, "type", type) - uname = ""; sexp = ""; svalue = ""; name = ""; - bool b_best = false; - while(child != NULL) { - if(!xmlStrcmp(child->name, (const xmlChar*) "name")) { - lang = xmlNodeGetLang(child); - if(!lang) { - if(name.empty()) { - XML_GET_STRING_FROM_TEXT(child, name); - } - } else { - if(!b_best && !locale.empty()) { - if(locale == (char*) lang) { - XML_GET_STRING_FROM_TEXT(child, name); - b_best = true; - } else if(strlen((char*) lang) >= 2 && lang[0] == localebase[0] && lang[1] == localebase[1]) { - XML_GET_STRING_FROM_TEXT(child, name); - } - } - xmlFree(lang); - } - } else if(!xmlStrcmp(child->name, (const xmlChar*) "abbreviation")) { - XML_GET_STRING_FROM_TEXT(child, stmp); - } else if(!xmlStrcmp(child->name, (const xmlChar*) "unicode")) { - XML_GET_STRING_FROM_TEXT(child, uname); - } else if(!xmlStrcmp(child->name, (const xmlChar*) "exponent")) { - XML_GET_STRING_FROM_TEXT(child, sexp); - } else if(!xmlStrcmp(child->name, (const xmlChar*) "value")) { - XML_GET_STRING_FROM_TEXT(child, svalue); - } - child = child->next; - } - if(type == "decimal") { - addPrefix(new DecimalPrefix(s2i(sexp), name, stmp, uname)); - } else if(type == "number") { - addPrefix(new NumberPrefix(svalue, name, stmp, uname)); - } else if(type == "binary") { - addPrefix(new BinaryPrefix(s2i(sexp), name, stmp, uname)); - } else { - if(svalue.empty()) { - addPrefix(new DecimalPrefix(s2i(sexp), name, stmp, uname)); - } else { - addPrefix(new NumberPrefix(svalue, name, stmp, uname)); - } - } - done_something = true; - } - after_load_object: - cur = NULL; - if(in_unfinished) { - if(done_something) { - in_unfinished--; - unfinished_nodes.erase(unfinished_nodes.begin() + in_unfinished); - unfinished_cats.erase(unfinished_cats.begin() + in_unfinished); - } - if((int) unfinished_nodes.size() > in_unfinished) { - cur = unfinished_nodes[in_unfinished]; - category = unfinished_cats[in_unfinished]; - } else if(done_something && unfinished_nodes.size() > 0) { - cur = unfinished_nodes[0]; - category = unfinished_cats[0]; - in_unfinished = 0; - done_something = false; - } - in_unfinished++; - done_something = false; - } - } - if(in_unfinished) { - break; - } - while(!nodes.empty() && nodes.back().empty()) { - size_t cat_i = category.rfind("/"); - if(cat_i == string::npos) { - category = ""; - } else { - category = category.substr(0, cat_i); - } - nodes.pop_back(); - } - if(!nodes.empty()) { - cur = nodes.back().front(); - nodes.back().pop(); - nodes.resize(nodes.size() + 1); - } else { - if(unfinished_nodes.size() > 0) { - cur = unfinished_nodes[0]; - category = unfinished_cats[0]; - in_unfinished = 1; - done_something = false; - } else { - cur = NULL; - } - } - if(cur == NULL) { - break; - } - } - xmlFreeDoc(doc); - return true; -} -bool Calculator::saveDefinitions() { - - recursiveMakeDir(getLocalDataDir()); - string homedir = buildPath(getLocalDataDir(), "definitions"); - makeDir(homedir); - bool b = true; - if(!saveFunctions(buildPath(homedir, "functions.xml").c_str())) b = false; - if(!saveUnits(buildPath(homedir, "units.xml").c_str())) b = false; - if(!saveVariables(buildPath(homedir, "variables.xml").c_str())) b = false; - if(!saveDataSets(buildPath(homedir, "datasets.xml").c_str())) b = false; - if(!saveDataObjects()) b = false; - return b; -} - -struct node_tree_item { - xmlNodePtr node; - string category; - vector items; -}; - -int Calculator::saveDataObjects() { - int returnvalue = 1; - for(size_t i = 0; i < data_sets.size(); i++) { - int rv = data_sets[i]->saveObjects(NULL, false); - if(rv <= 0) returnvalue = rv; - } - return returnvalue; -} - -int Calculator::savePrefixes(const char* file_name, bool save_global) { - if(!save_global) { - return true; - } - xmlDocPtr doc = xmlNewDoc((xmlChar*) "1.0"); - xmlNodePtr cur, newnode; - doc->children = xmlNewDocNode(doc, NULL, (xmlChar*) "QALCULATE", NULL); - xmlNewProp(doc->children, (xmlChar*) "version", (xmlChar*) VERSION); - cur = doc->children; - for(size_t i = 0; i < prefixes.size(); i++) { - newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "prefix", NULL); - if(!prefixes[i]->longName(false).empty()) xmlNewTextChild(newnode, NULL, (xmlChar*) "name", (xmlChar*) prefixes[i]->longName(false).c_str()); - if(!prefixes[i]->shortName(false).empty()) xmlNewTextChild(newnode, NULL, (xmlChar*) "abbreviation", (xmlChar*) prefixes[i]->shortName(false).c_str()); - if(!prefixes[i]->unicodeName(false).empty()) xmlNewTextChild(newnode, NULL, (xmlChar*) "unicode", (xmlChar*) prefixes[i]->unicodeName(false).c_str()); - switch(prefixes[i]->type()) { - case PREFIX_DECIMAL: { - xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "decimal"); - xmlNewTextChild(newnode, NULL, (xmlChar*) "exponent", (xmlChar*) i2s(((DecimalPrefix*) prefixes[i])->exponent()).c_str()); - break; - } - case PREFIX_BINARY: { - xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "binary"); - xmlNewTextChild(newnode, NULL, (xmlChar*) "exponent", (xmlChar*) i2s(((BinaryPrefix*) prefixes[i])->exponent()).c_str()); - break; - } - case PREFIX_NUMBER: { - xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "number"); - xmlNewTextChild(newnode, NULL, (xmlChar*) "value", (xmlChar*) prefixes[i]->value().print(save_printoptions).c_str()); - break; - } - } - } - int returnvalue = xmlSaveFormatFile(file_name, doc, 1); - xmlFreeDoc(doc); - return returnvalue; -} - -#define SAVE_NAMES(o)\ - str = "";\ - for(size_t i2 = 1;;) {\ - ename = &o->getName(i2);\ - if(ename->abbreviation) {str += 'a';}\ - bool b_cs = (ename->abbreviation || text_length_is_one(ename->name));\ - if(ename->case_sensitive && !b_cs) {str += 'c';}\ - if(!ename->case_sensitive && b_cs) {str += "-c";}\ - if(ename->avoid_input) {str += 'i';}\ - if(ename->completion_only) {str += 'o';}\ - if(ename->plural) {str += 'p';}\ - if(ename->reference) {str += 'r';}\ - if(ename->suffix) {str += 's';}\ - if(ename->unicode) {str += 'u';}\ - if(str.empty() || str[str.length() - 1] == ',') {\ - if(i2 == 1 && o->countNames() == 1) {\ - if(save_global) {\ - xmlNewTextChild(newnode, NULL, (xmlChar*) "_names", (xmlChar*) ename->name.c_str());\ - } else {\ - xmlNewTextChild(newnode, NULL, (xmlChar*) "names", (xmlChar*) ename->name.c_str());\ - }\ - break;\ - }\ - } else {\ - str += ':';\ - }\ - str += ename->name;\ - i2++;\ - if(i2 > o->countNames()) {\ - if(save_global) {\ - xmlNewTextChild(newnode, NULL, (xmlChar*) "_names", (xmlChar*) str.c_str());\ - } else {\ - xmlNewTextChild(newnode, NULL, (xmlChar*) "names", (xmlChar*) str.c_str());\ - }\ - break;\ - }\ - str += ',';\ - } - -string Calculator::temporaryCategory() const { - return _("Temporary"); -} - -int Calculator::saveVariables(const char* file_name, bool save_global) { - string str; - const ExpressionName *ename; - xmlDocPtr doc = xmlNewDoc((xmlChar*) "1.0"); - xmlNodePtr cur, newnode, newnode2; - doc->children = xmlNewDocNode(doc, NULL, (xmlChar*) "QALCULATE", NULL); - xmlNewProp(doc->children, (xmlChar*) "version", (xmlChar*) VERSION); - node_tree_item top; - top.category = ""; - top.node = doc->children; - node_tree_item *item; - string cat, cat_sub; - for(size_t i = 0; i < variables.size(); i++) { - if((save_global || variables[i]->isLocal() || variables[i]->hasChanged()) && variables[i]->category() != _("Temporary") && variables[i]->category() != "Temporary") { - item = ⊤ - if(!variables[i]->category().empty()) { - cat = variables[i]->category(); - size_t cat_i = cat.find("/"); size_t cat_i_prev = 0; - bool b = false; - while(true) { - if(cat_i == string::npos) { - cat_sub = cat.substr(cat_i_prev, cat.length() - cat_i_prev); - } else { - cat_sub = cat.substr(cat_i_prev, cat_i - cat_i_prev); - } - b = false; - for(size_t i2 = 0; i2 < item->items.size(); i2++) { - if(cat_sub == item->items[i2].category) { - item = &item->items[i2]; - b = true; - break; - } - } - if(!b) { - item->items.resize(item->items.size() + 1); - item->items[item->items.size() - 1].node = xmlNewTextChild(item->node, NULL, (xmlChar*) "category", NULL); - item = &item->items[item->items.size() - 1]; - item->category = cat_sub; - if(save_global) { - xmlNewTextChild(item->node, NULL, (xmlChar*) "_title", (xmlChar*) item->category.c_str()); - } else { - xmlNewTextChild(item->node, NULL, (xmlChar*) "title", (xmlChar*) item->category.c_str()); - } - } - if(cat_i == string::npos) { - break; - } - cat_i_prev = cat_i + 1; - cat_i = cat.find("/", cat_i_prev); - } - } - cur = item->node; - if(!save_global && !variables[i]->isLocal() && variables[i]->hasChanged()) { - if(variables[i]->isActive()) { - xmlNewTextChild(cur, NULL, (xmlChar*) "activate", (xmlChar*) variables[i]->referenceName().c_str()); - } else { - xmlNewTextChild(cur, NULL, (xmlChar*) "deactivate", (xmlChar*) variables[i]->referenceName().c_str()); - } - } else if(save_global || variables[i]->isLocal()) { - if(variables[i]->isBuiltin()) { - if(variables[i]->isKnown()) { - newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "builtin_variable", NULL); - } else { - newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "builtin_unknown", NULL); - } - xmlNewProp(newnode, (xmlChar*) "name", (xmlChar*) variables[i]->referenceName().c_str()); - } else { - if(variables[i]->isKnown()) { - newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "variable", NULL); - } else { - newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "unknown", NULL); - } - } - if(!variables[i]->isActive()) xmlNewProp(newnode, (xmlChar*) "active", (xmlChar*) "false"); - if(variables[i]->isHidden()) xmlNewTextChild(newnode, NULL, (xmlChar*) "hidden", (xmlChar*) "true"); - if(!variables[i]->title(false).empty()) { - if(save_global) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "_title", (xmlChar*) variables[i]->title(false).c_str()); - } else { - xmlNewTextChild(newnode, NULL, (xmlChar*) "title", (xmlChar*) variables[i]->title(false).c_str()); - } - } - SAVE_NAMES(variables[i]) - if(!variables[i]->description().empty()) { - str = variables[i]->description(); - if(save_global) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "_description", (xmlChar*) str.c_str()); - } else { - xmlNewTextChild(newnode, NULL, (xmlChar*) "description", (xmlChar*) str.c_str()); - } - } - if(!variables[i]->isBuiltin()) { - if(variables[i]->isKnown()) { - bool is_approx = false; - save_printoptions.is_approximate = &is_approx; - if(((KnownVariable*) variables[i])->isExpression()) { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "value", (xmlChar*) ((KnownVariable*) variables[i])->expression().c_str()); - bool unc_rel = false; - if(!((KnownVariable*) variables[i])->uncertainty(&unc_rel).empty()) xmlNewProp(newnode2, (xmlChar*) (unc_rel ? "relative_uncertainty" : "uncertainty"), (xmlChar*) ((KnownVariable*) variables[i])->uncertainty().c_str()); - if(!((KnownVariable*) variables[i])->unit().empty()) xmlNewProp(newnode2, (xmlChar*) "unit", (xmlChar*) ((KnownVariable*) variables[i])->unit().c_str()); - } else { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "value", (xmlChar*) ((KnownVariable*) variables[i])->get().print(save_printoptions).c_str()); - } - save_printoptions.is_approximate = NULL; - if(variables[i]->isApproximate() || is_approx) xmlNewProp(newnode2, (xmlChar*) "approximate", (xmlChar*) "true"); - if(variables[i]->precision() >= 0) xmlNewProp(newnode2, (xmlChar*) "precision", (xmlChar*) i2s(variables[i]->precision()).c_str()); - } else { - if(((UnknownVariable*) variables[i])->assumptions()) { - switch(((UnknownVariable*) variables[i])->assumptions()->type()) { - case ASSUMPTION_TYPE_INTEGER: { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "type", (xmlChar*) "integer"); - break; - } - case ASSUMPTION_TYPE_RATIONAL: { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "type", (xmlChar*) "rational"); - break; - } - case ASSUMPTION_TYPE_REAL: { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "type", (xmlChar*) "real"); - break; - } - case ASSUMPTION_TYPE_COMPLEX: { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "type", (xmlChar*) "complex"); - break; - } - case ASSUMPTION_TYPE_NUMBER: { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "type", (xmlChar*) "number"); - break; - } - case ASSUMPTION_TYPE_NONMATRIX: { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "type", (xmlChar*) "non-matrix"); - break; - } - case ASSUMPTION_TYPE_NONE: { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "type", (xmlChar*) "none"); - break; - } - } - switch(((UnknownVariable*) variables[i])->assumptions()->sign()) { - case ASSUMPTION_SIGN_NONZERO: { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "sign", (xmlChar*) "non-zero"); - break; - } - case ASSUMPTION_SIGN_NONPOSITIVE: { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "sign", (xmlChar*) "non-positive"); - break; - } - case ASSUMPTION_SIGN_NEGATIVE: { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "sign", (xmlChar*) "negative"); - break; - } - case ASSUMPTION_SIGN_NONNEGATIVE: { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "sign", (xmlChar*) "non-negative"); - break; - } - case ASSUMPTION_SIGN_POSITIVE: { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "sign", (xmlChar*) "positive"); - break; - } - case ASSUMPTION_SIGN_UNKNOWN: { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "sign", (xmlChar*) "unknown"); - break; - } - } - } - } - } - } - } - } - int returnvalue = xmlSaveFormatFile(file_name, doc, 1); - xmlFreeDoc(doc); - return returnvalue; -} - -int Calculator::saveUnits(const char* file_name, bool save_global) { - string str; - xmlDocPtr doc = xmlNewDoc((xmlChar*) "1.0"); - xmlNodePtr cur, newnode, newnode2, newnode3; - doc->children = xmlNewDocNode(doc, NULL, (xmlChar*) "QALCULATE", NULL); - xmlNewProp(doc->children, (xmlChar*) "version", (xmlChar*) VERSION); - const ExpressionName *ename; - CompositeUnit *cu = NULL; - AliasUnit *au = NULL; - Unit *u; - node_tree_item top; - top.category = ""; - top.node = doc->children; - node_tree_item *item; - string cat, cat_sub; - for(size_t i = 0; i < units.size(); i++) { - u = units[i]; - if(save_global || u->isLocal() || u->hasChanged()) { - item = ⊤ - if(!u->category().empty()) { - cat = u->category(); - size_t cat_i = cat.find("/"); size_t cat_i_prev = 0; - bool b = false; - while(true) { - if(cat_i == string::npos) { - cat_sub = cat.substr(cat_i_prev, cat.length() - cat_i_prev); - } else { - cat_sub = cat.substr(cat_i_prev, cat_i - cat_i_prev); - } - b = false; - for(size_t i2 = 0; i2 < item->items.size(); i2++) { - if(cat_sub == item->items[i2].category) { - item = &item->items[i2]; - b = true; - break; - } - } - if(!b) { - item->items.resize(item->items.size() + 1); - item->items[item->items.size() - 1].node = xmlNewTextChild(item->node, NULL, (xmlChar*) "category", NULL); - item = &item->items[item->items.size() - 1]; - item->category = cat_sub; - if(save_global) { - xmlNewTextChild(item->node, NULL, (xmlChar*) "_title", (xmlChar*) item->category.c_str()); - } else { - xmlNewTextChild(item->node, NULL, (xmlChar*) "title", (xmlChar*) item->category.c_str()); - } - } - if(cat_i == string::npos) { - break; - } - cat_i_prev = cat_i + 1; - cat_i = cat.find("/", cat_i_prev); - } - } - cur = item->node; - if(!save_global && !u->isLocal() && u->hasChanged()) { - if(u->isActive()) { - xmlNewTextChild(cur, NULL, (xmlChar*) "activate", (xmlChar*) u->referenceName().c_str()); - } else { - xmlNewTextChild(cur, NULL, (xmlChar*) "deactivate", (xmlChar*) u->referenceName().c_str()); - } - } else if(save_global || u->isLocal()) { - if(u->isBuiltin()) { - newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "builtin_unit", NULL); - xmlNewProp(newnode, (xmlChar*) "name", (xmlChar*) u->referenceName().c_str()); - } else { - newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "unit", NULL); - switch(u->subtype()) { - case SUBTYPE_BASE_UNIT: { - xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "base"); - break; - } - case SUBTYPE_ALIAS_UNIT: { - au = (AliasUnit*) u; - xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "alias"); - break; - } - case SUBTYPE_COMPOSITE_UNIT: { - cu = (CompositeUnit*) u; - xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "composite"); - break; - } - } - } - if(!u->isActive()) xmlNewProp(newnode, (xmlChar*) "active", (xmlChar*) "false"); - if(u->isHidden()) xmlNewTextChild(newnode, NULL, (xmlChar*) "hidden", (xmlChar*) "true"); - if(!u->system().empty()) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "system", (xmlChar*) u->system().c_str()); - } - if(!u->isSIUnit() || !u->useWithPrefixesByDefault()) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "use_with_prefixes", u->useWithPrefixesByDefault() ? (xmlChar*) "true" : (xmlChar*) "false"); - } - if(!u->title(false).empty()) { - if(save_global) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "_title", (xmlChar*) u->title(false).c_str()); - } else { - xmlNewTextChild(newnode, NULL, (xmlChar*) "title", (xmlChar*) u->title(false).c_str()); - } - } - if(save_global && u->subtype() == SUBTYPE_COMPOSITE_UNIT) { - save_global = false; - SAVE_NAMES(u) - save_global = true; - } else { - SAVE_NAMES(u) - } - if(!u->description().empty()) { - str = u->description(); - if(save_global) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "_description", (xmlChar*) str.c_str()); - } else { - xmlNewTextChild(newnode, NULL, (xmlChar*) "description", (xmlChar*) str.c_str()); - } - } - if(!u->isBuiltin()) { - if(u->subtype() == SUBTYPE_COMPOSITE_UNIT) { - for(size_t i2 = 1; i2 <= cu->countUnits(); i2++) { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "part", NULL); - int exp = 1; - Prefix *p = NULL; - Unit *u = cu->get(i2, &exp, &p); - xmlNewTextChild(newnode2, NULL, (xmlChar*) "unit", (xmlChar*) u->referenceName().c_str()); - if(p) { - switch(p->type()) { - case PREFIX_DECIMAL: { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "prefix", (xmlChar*) i2s(((DecimalPrefix*) p)->exponent()).c_str()); - break; - } - case PREFIX_BINARY: { - newnode3 = xmlNewTextChild(newnode2, NULL, (xmlChar*) "prefix", (xmlChar*) i2s(((BinaryPrefix*) p)->exponent()).c_str()); - xmlNewProp(newnode3, (xmlChar*) "type", (xmlChar*) "binary"); - break; - } - case PREFIX_NUMBER: { - newnode3 = xmlNewTextChild(newnode2, NULL, (xmlChar*) "prefix", (xmlChar*) p->value().print(save_printoptions).c_str()); - xmlNewProp(newnode3, (xmlChar*) "type", (xmlChar*) "number"); - break; - } - } - } - xmlNewTextChild(newnode2, NULL, (xmlChar*) "exponent", (xmlChar*) i2s(exp).c_str()); - } - } - if(u->subtype() == SUBTYPE_ALIAS_UNIT) { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "base", NULL); - xmlNewTextChild(newnode2, NULL, (xmlChar*) "unit", (xmlChar*) au->firstBaseUnit()->referenceName().c_str()); - newnode3 = xmlNewTextChild(newnode2, NULL, (xmlChar*) "relation", (xmlChar*) au->expression().c_str()); - if(au->isApproximate()) xmlNewProp(newnode3, (xmlChar*) "approximate", (xmlChar*) "true"); - if(au->precision() >= 0) xmlNewProp(newnode3, (xmlChar*) "precision", (xmlChar*) i2s(u->precision()).c_str()); - bool unc_rel = false; - if(!au->uncertainty(&unc_rel).empty()) xmlNewProp(newnode3, (xmlChar*) (unc_rel ? "relative_uncertainty" : "uncertainty"), (xmlChar*) au->uncertainty().c_str()); - if(!au->inverseExpression().empty()) { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "inverse_relation", (xmlChar*) au->inverseExpression().c_str()); - } - xmlNewTextChild(newnode2, NULL, (xmlChar*) "exponent", (xmlChar*) i2s(au->firstBaseExponent()).c_str()); - if(au->mixWithBase() > 0) { - newnode3 = xmlNewTextChild(newnode2, NULL, (xmlChar*) "mix", (xmlChar*) i2s(au->mixWithBase()).c_str()); - if(au->mixWithBaseMinimum() > 1) xmlNewProp(newnode3, (xmlChar*) "min", (xmlChar*) i2s(au->mixWithBaseMinimum()).c_str()); - } - } - } - } - } - } - int returnvalue = xmlSaveFormatFile(file_name, doc, 1); - xmlFreeDoc(doc); - return returnvalue; -} - -int Calculator::saveFunctions(const char* file_name, bool save_global) { - xmlDocPtr doc = xmlNewDoc((xmlChar*) "1.0"); - xmlNodePtr cur, newnode, newnode2; - doc->children = xmlNewDocNode(doc, NULL, (xmlChar*) "QALCULATE", NULL); - xmlNewProp(doc->children, (xmlChar*) "version", (xmlChar*) VERSION); - const ExpressionName *ename; - node_tree_item top; - top.category = ""; - top.node = doc->children; - node_tree_item *item; - string cat, cat_sub; - Argument *arg; - IntegerArgument *iarg; - NumberArgument *farg; - string str; - for(size_t i = 0; i < functions.size(); i++) { - if(functions[i]->subtype() != SUBTYPE_DATA_SET && (save_global || functions[i]->isLocal() || functions[i]->hasChanged())) { - item = ⊤ - if(!functions[i]->category().empty()) { - cat = functions[i]->category(); - size_t cat_i = cat.find("/"); size_t cat_i_prev = 0; - bool b = false; - while(true) { - if(cat_i == string::npos) { - cat_sub = cat.substr(cat_i_prev, cat.length() - cat_i_prev); - } else { - cat_sub = cat.substr(cat_i_prev, cat_i - cat_i_prev); - } - b = false; - for(size_t i2 = 0; i2 < item->items.size(); i2++) { - if(cat_sub == item->items[i2].category) { - item = &item->items[i2]; - b = true; - break; - } - } - if(!b) { - item->items.resize(item->items.size() + 1); - item->items[item->items.size() - 1].node = xmlNewTextChild(item->node, NULL, (xmlChar*) "category", NULL); - item = &item->items[item->items.size() - 1]; - item->category = cat_sub; - if(save_global) { - xmlNewTextChild(item->node, NULL, (xmlChar*) "_title", (xmlChar*) item->category.c_str()); - } else { - xmlNewTextChild(item->node, NULL, (xmlChar*) "title", (xmlChar*) item->category.c_str()); - } - } - if(cat_i == string::npos) { - break; - } - cat_i_prev = cat_i + 1; - cat_i = cat.find("/", cat_i_prev); - } - } - cur = item->node; - if(!save_global && !functions[i]->isLocal() && functions[i]->hasChanged()) { - if(functions[i]->isActive()) { - xmlNewTextChild(cur, NULL, (xmlChar*) "activate", (xmlChar*) functions[i]->referenceName().c_str()); - } else { - xmlNewTextChild(cur, NULL, (xmlChar*) "deactivate", (xmlChar*) functions[i]->referenceName().c_str()); - } - } else if(save_global || functions[i]->isLocal()) { - if(functions[i]->isBuiltin()) { - newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "builtin_function", NULL); - xmlNewProp(newnode, (xmlChar*) "name", (xmlChar*) functions[i]->referenceName().c_str()); - } else { - newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "function", NULL); - } - if(!functions[i]->isActive()) xmlNewProp(newnode, (xmlChar*) "active", (xmlChar*) "false"); - if(functions[i]->isHidden()) xmlNewTextChild(newnode, NULL, (xmlChar*) "hidden", (xmlChar*) "true"); - if(!functions[i]->title(false).empty()) { - if(save_global) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "_title", (xmlChar*) functions[i]->title(false).c_str()); - } else { - xmlNewTextChild(newnode, NULL, (xmlChar*) "title", (xmlChar*) functions[i]->title(false).c_str()); - } - } - SAVE_NAMES(functions[i]) - if(!functions[i]->description().empty()) { - str = functions[i]->description(); - if(save_global) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "_description", (xmlChar*) str.c_str()); - } else { - xmlNewTextChild(newnode, NULL, (xmlChar*) "description", (xmlChar*) str.c_str()); - } - } - if(!functions[i]->example(true).empty()) newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "example", (xmlChar*) functions[i]->example(true).c_str()); - if(functions[i]->isBuiltin()) { - cur = newnode; - for(size_t i2 = 1; i2 <= functions[i]->lastArgumentDefinitionIndex(); i2++) { - arg = functions[i]->getArgumentDefinition(i2); - if(arg && !arg->name().empty()) { - newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "argument", NULL); - if(save_global) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "_title", (xmlChar*) arg->name().c_str()); - } else { - xmlNewTextChild(newnode, NULL, (xmlChar*) "title", (xmlChar*) arg->name().c_str()); - } - xmlNewProp(newnode, (xmlChar*) "index", (xmlChar*) i2s(i2).c_str()); - } - } - } else { - for(size_t i2 = 1; i2 <= ((UserFunction*) functions[i])->countSubfunctions(); i2++) { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "subfunction", (xmlChar*) ((UserFunction*) functions[i])->getSubfunction(i2).c_str()); - if(((UserFunction*) functions[i])->subfunctionPrecalculated(i2)) xmlNewProp(newnode2, (xmlChar*) "precalculate", (xmlChar*) "true"); - else xmlNewProp(newnode2, (xmlChar*) "precalculate", (xmlChar*) "false"); - - } - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "expression", (xmlChar*) ((UserFunction*) functions[i])->formula().c_str()); - if(functions[i]->isApproximate()) xmlNewProp(newnode2, (xmlChar*) "approximate", (xmlChar*) "true"); - if(functions[i]->precision() >= 0) xmlNewProp(newnode2, (xmlChar*) "precision", (xmlChar*) i2s(functions[i]->precision()).c_str()); - if(!functions[i]->condition().empty()) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "condition", (xmlChar*) functions[i]->condition().c_str()); - } - cur = newnode; - for(size_t i2 = 1; i2 <= functions[i]->lastArgumentDefinitionIndex(); i2++) { - arg = functions[i]->getArgumentDefinition(i2); - if(arg) { - newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "argument", NULL); - if(!arg->name().empty()) { - if(save_global) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "_title", (xmlChar*) arg->name().c_str()); - } else { - xmlNewTextChild(newnode, NULL, (xmlChar*) "title", (xmlChar*) arg->name().c_str()); - } - } - switch(arg->type()) { - case ARGUMENT_TYPE_TEXT: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "text"); break;} - case ARGUMENT_TYPE_SYMBOLIC: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "symbol"); break;} - case ARGUMENT_TYPE_DATE: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "date"); break;} - case ARGUMENT_TYPE_INTEGER: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "integer"); break;} - case ARGUMENT_TYPE_NUMBER: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "number"); break;} - case ARGUMENT_TYPE_VECTOR: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "vector"); break;} - case ARGUMENT_TYPE_MATRIX: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "matrix"); break;} - case ARGUMENT_TYPE_BOOLEAN: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "boolean"); break;} - case ARGUMENT_TYPE_FUNCTION: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "function"); break;} - case ARGUMENT_TYPE_UNIT: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "unit"); break;} - case ARGUMENT_TYPE_VARIABLE: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "variable"); break;} - case ARGUMENT_TYPE_EXPRESSION_ITEM: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "object"); break;} - case ARGUMENT_TYPE_ANGLE: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "angle"); break;} - case ARGUMENT_TYPE_DATA_OBJECT: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "data-object"); break;} - case ARGUMENT_TYPE_DATA_PROPERTY: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "data-property"); break;} - default: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "free");} - } - xmlNewProp(newnode, (xmlChar*) "index", (xmlChar*) i2s(i2).c_str()); - if(!arg->tests()) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "test", (xmlChar*) "false"); - } - if(!arg->alerts()) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "alert", (xmlChar*) "false"); - } - if(arg->zeroForbidden()) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "zero_forbidden", (xmlChar*) "true"); - } - if(arg->matrixAllowed()) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "matrix_allowed", (xmlChar*) "true"); - } - switch(arg->type()) { - case ARGUMENT_TYPE_INTEGER: { - iarg = (IntegerArgument*) arg; - if(iarg->min()) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "min", (xmlChar*) iarg->min()->print(save_printoptions).c_str()); - } - if(iarg->max()) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "max", (xmlChar*) iarg->max()->print(save_printoptions).c_str()); - } - break; - } - case ARGUMENT_TYPE_NUMBER: { - farg = (NumberArgument*) arg; - if(farg->min()) { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "min", (xmlChar*) farg->min()->print(save_printoptions).c_str()); - if(farg->includeEqualsMin()) { - xmlNewProp(newnode2, (xmlChar*) "include_equals", (xmlChar*) "true"); - } else { - xmlNewProp(newnode2, (xmlChar*) "include_equals", (xmlChar*) "false"); - } - } - if(farg->max()) { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "max", (xmlChar*) farg->max()->print(save_printoptions).c_str()); - if(farg->includeEqualsMax()) { - xmlNewProp(newnode2, (xmlChar*) "include_equals", (xmlChar*) "true"); - } else { - xmlNewProp(newnode2, (xmlChar*) "include_equals", (xmlChar*) "false"); - } - } - if(!farg->complexAllowed()) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "complex_allowed", (xmlChar*) "false"); - } - break; - } - } - if(!arg->getCustomCondition().empty()) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "condition", (xmlChar*) arg->getCustomCondition().c_str()); - } - } - } - } - } - } - } - int returnvalue = xmlSaveFormatFile(file_name, doc, 1); - xmlFreeDoc(doc); - return returnvalue; -} -int Calculator::saveDataSets(const char* file_name, bool save_global) { - xmlDocPtr doc = xmlNewDoc((xmlChar*) "1.0"); - xmlNodePtr cur, newnode, newnode2; - doc->children = xmlNewDocNode(doc, NULL, (xmlChar*) "QALCULATE", NULL); - xmlNewProp(doc->children, (xmlChar*) "version", (xmlChar*) VERSION); - const ExpressionName *ename; - node_tree_item top; - top.category = ""; - top.node = doc->children; - node_tree_item *item; - string cat, cat_sub; - Argument *arg; - DataSet *ds; - DataProperty *dp; - string str; - for(size_t i = 0; i < functions.size(); i++) { - if(functions[i]->subtype() == SUBTYPE_DATA_SET && (save_global || functions[i]->isLocal() || functions[i]->hasChanged())) { - item = ⊤ - ds = (DataSet*) functions[i]; - if(!ds->category().empty()) { - cat = ds->category(); - size_t cat_i = cat.find("/"); size_t cat_i_prev = 0; - bool b = false; - while(true) { - if(cat_i == string::npos) { - cat_sub = cat.substr(cat_i_prev, cat.length() - cat_i_prev); - } else { - cat_sub = cat.substr(cat_i_prev, cat_i - cat_i_prev); - } - b = false; - for(size_t i2 = 0; i2 < item->items.size(); i2++) { - if(cat_sub == item->items[i2].category) { - item = &item->items[i2]; - b = true; - break; - } - } - if(!b) { - item->items.resize(item->items.size() + 1); - item->items[item->items.size() - 1].node = xmlNewTextChild(item->node, NULL, (xmlChar*) "category", NULL); - item = &item->items[item->items.size() - 1]; - item->category = cat_sub; - if(save_global) { - xmlNewTextChild(item->node, NULL, (xmlChar*) "_title", (xmlChar*) item->category.c_str()); - } else { - xmlNewTextChild(item->node, NULL, (xmlChar*) "title", (xmlChar*) item->category.c_str()); - } - } - if(cat_i == string::npos) { - break; - } - cat_i_prev = cat_i + 1; - cat_i = cat.find("/", cat_i_prev); - } - } - cur = item->node; - if(save_global || ds->isLocal() || ds->hasChanged()) { - if(save_global || ds->isLocal()) { - newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "dataset", NULL); - } else { - newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "builtin_dataset", NULL); - xmlNewProp(newnode, (xmlChar*) "name", (xmlChar*) ds->referenceName().c_str()); - } - if(!ds->isActive()) xmlNewProp(newnode, (xmlChar*) "active", (xmlChar*) "false"); - if(ds->isHidden()) xmlNewTextChild(newnode, NULL, (xmlChar*) "hidden", (xmlChar*) "true"); - if(!ds->title(false).empty()) { - if(save_global) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "_title", (xmlChar*) ds->title(false).c_str()); - } else { - xmlNewTextChild(newnode, NULL, (xmlChar*) "title", (xmlChar*) ds->title(false).c_str()); - } - } - if((save_global || ds->isLocal()) && !ds->defaultDataFile().empty()) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "datafile", (xmlChar*) ds->defaultDataFile().c_str()); - } - SAVE_NAMES(ds) - if(!ds->description().empty()) { - str = ds->description(); - if(save_global) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "_description", (xmlChar*) str.c_str()); - } else { - xmlNewTextChild(newnode, NULL, (xmlChar*) "description", (xmlChar*) str.c_str()); - } - } - if((save_global || ds->isLocal()) && !ds->copyright().empty()) { - if(save_global) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "_copyright", (xmlChar*) ds->copyright().c_str()); - } else { - xmlNewTextChild(newnode, NULL, (xmlChar*) "copyright", (xmlChar*) ds->copyright().c_str()); - } - } - arg = ds->getArgumentDefinition(1); - if(arg && ((!save_global && !ds->isLocal()) || arg->name() != _("Object"))) { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "object_argument", NULL); - if(save_global) { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "_title", (xmlChar*) arg->name().c_str()); - } else { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "title", (xmlChar*) arg->name().c_str()); - } - } - arg = ds->getArgumentDefinition(2); - if(arg && ((!save_global && !ds->isLocal()) || arg->name() != _("Property"))) { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "property_argument", NULL); - if(save_global) { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "_title", (xmlChar*) arg->name().c_str()); - } else { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "title", (xmlChar*) arg->name().c_str()); - } - } - if((!save_global && !ds->isLocal()) || ds->getDefaultValue(2) != _("info")) { - xmlNewTextChild(newnode, NULL, (xmlChar*) "default_property", (xmlChar*) ds->getDefaultValue(2).c_str()); - } - DataPropertyIter it; - dp = ds->getFirstProperty(&it); - while(dp) { - if(save_global || ds->isLocal() || dp->isUserModified()) { - newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "property", NULL); - if(!dp->title(false).empty()) { - if(save_global) { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "_title", (xmlChar*) dp->title().c_str()); - } else { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "title", (xmlChar*) dp->title().c_str()); - } - } - switch(dp->propertyType()) { - case PROPERTY_STRING: { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "type", (xmlChar*) "text"); - break; - } - case PROPERTY_NUMBER: { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "type", (xmlChar*) "number"); - break; - } - case PROPERTY_EXPRESSION: { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "type", (xmlChar*) "expression"); - break; - } - } - if(dp->isHidden()) { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "hidden", (xmlChar*) "true"); - } - if(dp->isKey()) { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "key", (xmlChar*) "true"); - } - if(dp->isApproximate()) { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "approximate", (xmlChar*) "true"); - } - if(dp->usesBrackets()) { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "brackets", (xmlChar*) "true"); - } - if(dp->isCaseSensitive()) { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "case_sensitive", (xmlChar*) "true"); - } - if(!dp->getUnitString().empty()) { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "unit", (xmlChar*) dp->getUnitString().c_str()); - } - str = ""; - for(size_t i2 = 1;;) { - if(dp->nameIsReference(i2)) {str += 'r';} - if(str.empty() || str[str.length() - 1] == ',') { - if(i2 == 1 && dp->countNames() == 1) { - if(save_global) { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "_names", (xmlChar*) dp->getName(i2).c_str()); - } else { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "names", (xmlChar*) dp->getName(i2).c_str()); - } - break; - } - } else { - str += ':'; - } - str += dp->getName(i2); - i2++; - if(i2 > dp->countNames()) { - if(save_global) { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "_names", (xmlChar*) str.c_str()); - } else { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "names", (xmlChar*) str.c_str()); - } - break; - } - str += ','; - } - if(!dp->description().empty()) { - str = dp->description(); - if(save_global) { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "_description", (xmlChar*) str.c_str()); - } else { - xmlNewTextChild(newnode2, NULL, (xmlChar*) "description", (xmlChar*) str.c_str()); - } - } - } - dp = ds->getNextProperty(&it); - } - } - } - } - int returnvalue = xmlSaveFormatFile(file_name, doc, 1); - xmlFreeDoc(doc); - return returnvalue; -} - -bool Calculator::importCSV(MathStructure &mstruct, const char *file_name, int first_row, string delimiter, vector *headers) { - FILE *file = fopen(file_name, "r"); - if(file == NULL) { - return false; - } - if(first_row < 1) { - first_row = 1; - } - char line[10000]; - string stmp, str1, str2; - long int row = 0, rows = 1; - int columns = 1; - int column; - mstruct = m_empty_matrix; - size_t is, is_n; - bool v_added = false; - while(fgets(line, 10000, file)) { - row++; - if(row >= first_row) { - stmp = line; - remove_blank_ends(stmp); - if(row == first_row) { - if(stmp.empty()) { - row--; - } else { - is = 0; - while((is_n = stmp.find(delimiter, is)) != string::npos) { - columns++; - if(headers) { - str1 = stmp.substr(is, is_n - is); - remove_blank_ends(str1); - headers->push_back(str1); - } - is = is_n + delimiter.length(); - } - if(headers) { - str1 = stmp.substr(is, stmp.length() - is); - remove_blank_ends(str1); - headers->push_back(str1); - } - mstruct.resizeMatrix(1, columns, m_undefined); - } - } - if((!headers || row > first_row) && !stmp.empty()) { - is = 0; - column = 1; - if(v_added) { - mstruct.addRow(m_undefined); - rows++; - } - while(column <= columns) { - is_n = stmp.find(delimiter, is); - if(is_n == string::npos) { - str1 = stmp.substr(is, stmp.length() - is); - } else { - str1 = stmp.substr(is, is_n - is); - is = is_n + delimiter.length(); - } - parse(&mstruct[rows - 1][column - 1], str1); - column++; - if(is_n == string::npos) { - break; - } - } - v_added = true; - } +Variable* Calculator::getVariableById(int id) const { + switch(id) { + case VARIABLE_ID_E: {return v_e;} + case VARIABLE_ID_PI: {return v_pi;} + case VARIABLE_ID_EULER: {return v_euler;} + case VARIABLE_ID_CATALAN: {return v_catalan;} + case VARIABLE_ID_I: {return v_i;} + case VARIABLE_ID_PLUS_INFINITY: {return v_pinf;} + case VARIABLE_ID_MINUS_INFINITY: {return v_minf;} + case VARIABLE_ID_X: {return v_x;} + case VARIABLE_ID_Y: {return v_y;} + case VARIABLE_ID_Z: {return v_z;} + case VARIABLE_ID_N: {return v_n;} + case VARIABLE_ID_C: {return v_C;} + case VARIABLE_ID_UNDEFINED: {return v_undef;} + } + unordered_map::iterator it = priv->id_variables.find(id); + if(it == priv->id_variables.end()) return NULL; + return it->second; +} +Variable* Calculator::getActiveVariable(string name_) { + if(name_.empty()) return NULL; + for(size_t i = 0; i < variables.size(); i++) { + if(variables[i]->isActive() && variables[i]->hasName(name_)) { + return variables[i]; } } - return true; + return NULL; } - -bool Calculator::importCSV(const char *file_name, int first_row, bool headers, string delimiter, bool to_matrix, string name, string title, string category) { - FILE *file = fopen(file_name, "r"); - if(file == NULL) { - return false; - } - if(first_row < 1) { - first_row = 1; - } - string filestr = file_name; - remove_blank_ends(filestr); - size_t i = filestr.find_last_of("/"); - if(i != string::npos) { - filestr = filestr.substr(i + 1, filestr.length() - (i + 1)); +ExpressionItem* Calculator::addExpressionItem(ExpressionItem *item, bool force) { + switch(item->type()) { + case TYPE_VARIABLE: { + return addVariable((Variable*) item, force); + } + case TYPE_FUNCTION: { + if(item->subtype() == SUBTYPE_DATA_SET) return addDataSet((DataSet*) item, force); + else return addFunction((MathFunction*) item, force); + } + case TYPE_UNIT: { + return addUnit((Unit*) item, force); + } } - remove_blank_ends(name); - if(name.empty()) { - name = filestr; - i = name.find_last_of("/"); - if(i != string::npos) name = name.substr(i + 1, name.length() - i); - i = name.find_last_of("."); - if(i != string::npos) name = name.substr(0, i); - } - - char line[10000]; - string stmp, str1, str2; - int row = 0; - int columns = 1, rows = 1; - int column; - vector header; - vector vectors; - MathStructure mstruct = m_empty_matrix; - size_t is, is_n; - bool v_added = false; - while(fgets(line, 10000, file)) { - row++; - if(row >= first_row) { - stmp = line; - remove_blank_ends(stmp); - if(row == first_row) { - if(stmp.empty()) { - row--; - } else { - is = 0; - while((is_n = stmp.find(delimiter, is)) != string::npos) { - columns++; - if(headers) { - str1 = stmp.substr(is, is_n - is); - remove_blank_ends(str1); - header.push_back(str1); - } - if(!to_matrix) { - vectors.push_back(m_empty_vector); - } - is = is_n + delimiter.length(); - } - if(headers) { - str1 = stmp.substr(is, stmp.length() - is); - remove_blank_ends(str1); - header.push_back(str1); - } - if(to_matrix) { - mstruct.resizeMatrix(1, columns, m_undefined); - } else { - vectors.push_back(m_empty_vector); - } - } - } - if((!headers || row > first_row) && !stmp.empty()) { - if(to_matrix && v_added) { - mstruct.addRow(m_undefined); - rows++; - } - is = 0; - column = 1; - while(column <= columns) { - is_n = stmp.find(delimiter, is); - if(is_n == string::npos) { - str1 = stmp.substr(is, stmp.length() - is); - } else { - str1 = stmp.substr(is, is_n - is); - is = is_n + delimiter.length(); - } - if(to_matrix) { - parse(&mstruct[rows - 1][column - 1], str1); - } else { - vectors[column - 1].addChild(parse(str1)); - } - column++; - if(is_n == string::npos) { - break; - } - } - for(; column <= columns; column++) { - if(!to_matrix) { - vectors[column - 1].addChild(m_undefined); - } - } - v_added = true; - } + return NULL; +} +MathFunction* Calculator::addFunction(MathFunction *f, bool force, bool check_names) { + if(check_names) { + for(size_t i = 1; i <= f->countNames(); i++) { + f->setName(getName(f->getName(i).name, f, force), i); } } - if(to_matrix) { - addVariable(new KnownVariable(category, name, mstruct, title)); + if(!f->isLocal() && functions.size() > 0 && functions[functions.size() - 1]->isLocal()) { + functions.insert(functions.begin(), f); } else { - if(vectors.size() > 1) { - if(!category.empty()) { - category += "/"; - } - category += name; - } - for(size_t i = 0; i < vectors.size(); i++) { - str1 = ""; - str2 = ""; - if(vectors.size() > 1) { - str1 += name; - str1 += "_"; - if(title.empty()) { - str2 += name; - str2 += " "; - } else { - str2 += title; - str2 += " "; - } - if(i < header.size()) { - str1 += header[i]; - str2 += header[i]; - } else { - str1 += _("column"); - str1 += "_"; - str1 += i2s(i + 1); - str2 += _("Column "); - str2 += i2s(i + 1); - } - gsub(" ", "_", str1); - } else { - str1 = name; - str2 = title; - if(i < header.size()) { - str2 += " ("; - str2 += header[i]; - str2 += ")"; - } - } - addVariable(new KnownVariable(category, str1, vectors[i], str2)); + functions.push_back(f); + } + functionNameChanged(f, true); + for(vector::iterator it = deleted_functions.begin(); it != deleted_functions.end(); ++it) { + if(*it == f) { + deleted_functions.erase(it); + break; } } - return true; + f->setRegistered(true); + f->setChanged(false); + if(f->id() != 0) priv->id_functions[f->id()] = f; + return f; } -bool Calculator::exportCSV(const MathStructure &mstruct, const char *file_name, string delimiter) { - FILE *file = fopen(file_name, "w+"); - if(file == NULL) { - return false; +DataSet* Calculator::addDataSet(DataSet *dc, bool force, bool check_names) { + addFunction(dc, force, check_names); + data_sets.push_back(dc); + return dc; +} +DataSet* Calculator::getDataSet(size_t index) { + if(index > 0 && index <= data_sets.size()) { + return data_sets[index - 1]; } - MathStructure mcsv(mstruct); - PrintOptions po; - po.number_fraction_format = FRACTION_DECIMAL; - po.decimalpoint_sign = "."; - po.comma_sign = ","; - if(mcsv.isMatrix()) { - for(size_t i = 0; i < mcsv.size(); i++) { - for(size_t i2 = 0; i2 < mcsv[i].size(); i2++) { - if(i2 > 0) fputs(delimiter.c_str(), file); - mcsv[i][i2].format(po); - fputs(mcsv[i][i2].print(po).c_str(), file); - } - fputs("\n", file); - } - } else if(mcsv.isVector()) { - for(size_t i = 0; i < mcsv.size(); i++) { - mcsv[i].format(po); - fputs(mcsv[i].print(po).c_str(), file); - fputs("\n", file); + return 0; +} +DataSet* Calculator::getDataSet(string name) { + if(name.empty()) return NULL; + for(size_t i = 0; i < data_sets.size(); i++) { + if(data_sets[i]->hasName(name)) { + return data_sets[i]; } - } else { - mcsv.format(po); - fputs(mcsv.print(po).c_str(), file); - fputs("\n", file); } - fclose(file); - return true; + return NULL; } -int Calculator::testCondition(string expression) { - MathStructure mstruct = calculate(expression); - if(mstruct.isNumber()) { - if(mstruct.number().isPositive()) { - return 1; - } else { - return 0; +MathFunction* Calculator::getFunction(string name_) { + if(name_.empty()) return NULL; + for(size_t i = 0; i < functions.size(); i++) { + if(functions[i]->hasName(name_)) { + return functions[i]; } } - return -1; -} - -void Calculator::startPrintControl(int milli_timeout) { - startControl(milli_timeout); + return NULL; } -void Calculator::abortPrint() { - abort(); +MathFunction* Calculator::getFunctionById(int id) const { + switch(id) { + case FUNCTION_ID_SIN: {return f_sin;} + case FUNCTION_ID_COS: {return f_cos;} + case FUNCTION_ID_TAN: {return f_tan;} + case FUNCTION_ID_ASIN: {return f_asin;} + case FUNCTION_ID_ACOS: {return f_acos;} + case FUNCTION_ID_ATAN: {return f_atan;} + case FUNCTION_ID_SINH: {return f_sinh;} + case FUNCTION_ID_COSH: {return f_cosh;} + case FUNCTION_ID_TANH: {return f_tanh;} + case FUNCTION_ID_ASINH: {return f_asinh;} + case FUNCTION_ID_ACOSH: {return f_acosh;} + case FUNCTION_ID_ATANH: {return f_atanh;} + case FUNCTION_ID_SINC: {return f_sinc;} + case FUNCTION_ID_LOG: {return f_ln;} + case FUNCTION_ID_LOGN: {return f_logn;} + case FUNCTION_ID_SQRT: {return f_sqrt;} + case FUNCTION_ID_CBRT: {return f_cbrt;} + case FUNCTION_ID_ROOT: {return f_root;} + case FUNCTION_ID_CIS: {return priv->f_cis;} + case FUNCTION_ID_ABS: {return f_abs;} + case FUNCTION_ID_SIGNUM: {return f_signum;} + case FUNCTION_ID_POLYLOG: {return f_Li;} + case FUNCTION_ID_GAMMA: {return f_gamma;} + case FUNCTION_ID_ERF: {return f_erf;} + case FUNCTION_ID_ERFC: {return f_erfc;} + case FUNCTION_ID_ERFI: {return priv->f_erfi;} + case FUNCTION_ID_STRIP_UNITS: {return f_stripunits;} + case FUNCTION_ID_UNCERTAINTY: {return f_uncertainty;} + case FUNCTION_ID_INTERVAL: {return f_interval;} + case FUNCTION_ID_FACTORIAL: {return f_factorial;} + case FUNCTION_ID_DOUBLE_FACTORIAL: {return f_factorial2;} + case FUNCTION_ID_I_GAMMA: {return f_igamma;} + case FUNCTION_ID_SININT: {return f_Si;} + case FUNCTION_ID_COSINT: {return f_Ci;} + case FUNCTION_ID_SINHINT: {return f_Shi;} + case FUNCTION_ID_COSHINT: {return f_Chi;} + case FUNCTION_ID_LOGINT: {return f_li;} + case FUNCTION_ID_EXPINT: {return f_Ei;} + case FUNCTION_ID_FRESNEL_S: {return priv->f_fresnels;} + case FUNCTION_ID_FRESNEL_C: {return priv->f_fresnelc;} + case FUNCTION_ID_RE: {return f_re;} + case FUNCTION_ID_IM: {return f_im;} + case FUNCTION_ID_ARG: {return f_arg;} + case FUNCTION_ID_INTEGRATE: {return f_integrate;} + case FUNCTION_ID_DIFFERENTIATE: {return f_diff;} + case FUNCTION_ID_BETA: {return f_beta;} + case FUNCTION_ID_BESSELY: {return f_bessely;} + case FUNCTION_ID_BESSELJ: {return f_besselj;} + case FUNCTION_ID_HEAVISIDE: {return f_heaviside;} + case FUNCTION_ID_DIRAC: {return f_dirac;} + case FUNCTION_ID_DIGAMMA: {return f_digamma;} + case FUNCTION_ID_AIRY: {return f_airy;} + case FUNCTION_ID_ZETA: {return f_zeta;} + case FUNCTION_ID_LAMBERT_W: {return f_lambert_w;} + case FUNCTION_ID_IF: {return f_if;} + case FUNCTION_ID_SHIFT: {return f_shift;} + case FUNCTION_ID_XOR: {return f_xor;} + } + unordered_map::iterator it = priv->id_functions.find(id); + if(it == priv->id_functions.end()) return NULL; + return it->second; } -bool Calculator::printingAborted() { - return aborted(); +MathFunction* Calculator::getActiveFunction(string name_) { + if(name_.empty()) return NULL; + for(size_t i = 0; i < functions.size(); i++) { + if(functions[i]->isActive() && functions[i]->hasName(name_)) { + return functions[i]; + } + } + return NULL; } -string Calculator::printingAbortedMessage() const { - return abortedMessage(); +bool Calculator::variableNameIsValid(const string &name_) { + return !name_.empty() && name_.find_first_of(ILLEGAL_IN_NAMES) == string::npos && is_not_in(NUMBERS, name_[0]); } -string Calculator::timedOutString() const { - return _("timed out"); +bool Calculator::functionNameIsValid(const string &name_) { + return !name_.empty() && name_.find_first_of(ILLEGAL_IN_NAMES) == string::npos && is_not_in(NUMBERS, name_[0]); } -bool Calculator::printingControlled() const { - return isControlled(); +bool Calculator::unitNameIsValid(const string &name_) { + return !name_.empty() && name_.find_first_of(ILLEGAL_IN_UNITNAMES) == string::npos; } -void Calculator::stopPrintControl() { - stopControl(); +bool Calculator::variableNameIsValid(const char *name_) { + if(strlen(name_) == 0) return false; + if(is_in(NUMBERS, name_[0])) return false; + for(size_t i = 0; name_[i] != '\0'; i++) { + if(is_in(ILLEGAL_IN_NAMES, name_[i])) return false; + } + return true; } - -void Calculator::startControl(int milli_timeout) { - b_controlled = true; - i_aborted = 0; - i_timeout = milli_timeout; - if(i_timeout > 0) { -#ifndef CLOCK_MONOTONIC - gettimeofday(&t_end, NULL); -#else - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - t_end.tv_sec = ts.tv_sec; - t_end.tv_usec = ts.tv_nsec / 1000; -#endif - long int usecs = t_end.tv_usec + (long int) milli_timeout * 1000; - t_end.tv_usec = usecs % 1000000; - t_end.tv_sec += usecs / 1000000; +bool Calculator::functionNameIsValid(const char *name_) { + if(strlen(name_) == 0) return false; + if(is_in(NUMBERS, name_[0])) return false; + for(size_t i = 0; name_[i] != '\0'; i++) { + if(is_in(ILLEGAL_IN_NAMES, name_[i])) return false; } + return true; } -bool Calculator::aborted() { - if(!b_controlled) return false; - if(i_aborted > 0) return true; - if(i_timeout > 0) { -#ifndef CLOCK_MONOTONIC - struct timeval tv; - gettimeofday(&tv, NULL); - if(tv.tv_sec > t_end.tv_sec || (tv.tv_sec == t_end.tv_sec && tv.tv_usec > t_end.tv_usec)) { -#else - struct timespec tv; - clock_gettime(CLOCK_MONOTONIC, &tv); - if(tv.tv_sec > t_end.tv_sec || (tv.tv_sec == t_end.tv_sec && tv.tv_nsec / 1000 > t_end.tv_usec)) { -#endif - i_aborted = 2; - return true; - } +bool Calculator::unitNameIsValid(const char *name_) { + if(strlen(name_) == 0) return false; + for(size_t i = 0; name_[i] != '\0'; i++) { + if(is_in(ILLEGAL_IN_UNITNAMES, name_[i])) return false; } - return false; + return true; } -string Calculator::abortedMessage() const { - if(i_aborted == 2) return _("timed out"); - return _("aborted"); +#define VERSION_BEFORE(i1, i2, i3) (version_numbers[0] < i1 || (version_numbers[0] == i1 && (version_numbers[1] < i2 || (version_numbers[1] == i2 && version_numbers[2] < i3)))) +bool Calculator::variableNameIsValid(const string &name_, int version_numbers[3], bool is_user_defs) { + return variableNameIsValid(name_.c_str(), version_numbers, is_user_defs); } -bool Calculator::isControlled() const { - return b_controlled; +bool Calculator::functionNameIsValid(const string &name_, int version_numbers[3], bool is_user_defs) { + return functionNameIsValid(name_.c_str(), version_numbers, is_user_defs); } -void Calculator::stopControl() { - b_controlled = false; - i_aborted = 0; - i_timeout = 0; +bool Calculator::unitNameIsValid(const string &name_, int version_numbers[3], bool is_user_defs) { + return unitNameIsValid(name_.c_str(), version_numbers, is_user_defs); } - - -bool Calculator::loadExchangeRates() { - xmlDocPtr doc = NULL; - xmlNodePtr cur = NULL; - xmlChar *value; - bool global_file = false; - string currency, rate, sdate; - string filename = buildPath(getLocalDataDir(), "eurofxref-daily.xml"); - if(fileExists(filename)) { - doc = xmlParseFile(filename.c_str()); - } else { -#ifndef _WIN32 - string filename_old = buildPath(getOldLocalDir(), "eurofxref-daily.xml"); - if(fileExists(filename)) { - doc = xmlParseFile(filename_old.c_str()); - if(doc) { - recursiveMakeDir(getLocalDataDir()); - move_file(filename_old.c_str(), filename.c_str()); - removeDir(getOldLocalDir()); +bool Calculator::variableNameIsValid(const char *name_, int version_numbers[3], bool is_user_defs) { + if(strlen(name_) == 0) return false; + if(is_in(NUMBERS, name_[0])) return false; + bool b = false; + for(size_t i = 0; name_[i] != '\0'; i++) { + if(is_in(ILLEGAL_IN_NAMES, name_[i])) { + if(is_user_defs && VERSION_BEFORE(0, 8, 1) && name_[i] == BITWISE_NOT_CH) { + b = true; + } else { + return false; } } -#endif } - if(doc) cur = xmlDocGetRootElement(doc); - if(!cur) { - if(doc) xmlFreeDoc(doc); - filename = buildPath(getGlobalDefinitionsDir(), "eurofxref-daily.xml"); - doc = xmlParseFile(filename.c_str()); - if(!doc) return false; - cur = xmlDocGetRootElement(doc); - if(!cur) return false; - global_file = true; - } - Unit *u; - while(cur) { - if(!xmlStrcmp(cur->name, (const xmlChar*) "Cube")) { - if(global_file && sdate.empty()) { - XML_GET_STRING_FROM_PROP(cur, "time", sdate); - QalculateDateTime qdate; - if(qdate.set(sdate)) { - exchange_rates_time[0] = (time_t) qdate.timestamp().ulintValue(); - if(exchange_rates_time[0] > exchange_rates_check_time[0]) exchange_rates_check_time[0] = exchange_rates_time[0]; - } else { - sdate.clear(); - } - } - XML_GET_STRING_FROM_PROP(cur, "currency", currency); - if(!currency.empty()) { - XML_GET_STRING_FROM_PROP(cur, "rate", rate); - if(!rate.empty()) { - rate = "1/" + rate; - u = getUnit(currency); - if(!u) { - u = addUnit(new AliasUnit(_("Currency"), currency, "", "", "", u_euro, rate, 1, "", false, true)); - } else if(u->subtype() == SUBTYPE_ALIAS_UNIT) { - ((AliasUnit*) u)->setExpression(rate); - } - if(u) { - u->setApproximate(); - u->setPrecision(-2); - u->setChanged(false); - } - } + if(b) { + error(true, _("\"%s\" is not allowed in names anymore. Please change the name of \"%s\", or the variable will be lost."), BITWISE_NOT, name_, NULL); + } + return true; +} +bool Calculator::functionNameIsValid(const char *name_, int version_numbers[3], bool is_user_defs) { + if(strlen(name_) == 0) return false; + if(is_in(NUMBERS, name_[0])) return false; + bool b = false; + for(size_t i = 0; name_[i] != '\0'; i++) { + if(is_in(ILLEGAL_IN_NAMES, name_[i])) { + if(is_user_defs && VERSION_BEFORE(0, 8, 1) && name_[i] == BITWISE_NOT_CH) { + b = true; + } else { + return false; } } - if(cur->children) { - cur = cur->children; - } else if(cur->next) { - cur = cur->next; - } else { - cur = cur->parent; - if(cur) { - cur = cur->next; + } + if(b) { + error(true, _("\"%s\" is not allowed in names anymore. Please change the name \"%s\", or the function will be lost."), BITWISE_NOT, name_, NULL); + } + return true; +} +bool Calculator::unitNameIsValid(const char *name_, int version_numbers[3], bool is_user_defs) { + if(strlen(name_) == 0) return false; + bool b = false; + for(size_t i = 0; name_[i] != '\0'; i++) { + if(is_in(ILLEGAL_IN_UNITNAMES, name_[i])) { + if(is_user_defs && VERSION_BEFORE(0, 8, 1) && name_[i] == BITWISE_NOT_CH) { + b = true; + } else { + return false; } } } - xmlFreeDoc(doc); - if(sdate.empty()) { - struct stat stats; - if(stat(filename.c_str(), &stats) == 0) { - if(exchange_rates_time[0] >= stats.st_mtime) { -#ifdef _WIN32 - struct _utimbuf new_times; -#else - struct utimbuf new_times; -#endif - struct tm *temptm = localtime(&exchange_rates_time[0]); - if(temptm) { - struct tm extm = *temptm; - time_t time_now = time(NULL); - struct tm *newtm = localtime(&time_now); - if(newtm && newtm->tm_mday != extm.tm_mday) { - newtm->tm_hour = extm.tm_hour; - newtm->tm_min = extm.tm_min; - newtm->tm_sec = extm.tm_sec; - exchange_rates_time[0] = mktime(newtm); - } else { - time(&exchange_rates_time[0]); + if(b) { + error(true, _("\"%s\" is not allowed in names anymore. Please change the name \"%s\", or the unit will be lost."), BITWISE_NOT, name_, NULL); + } + return true; +} +string Calculator::convertToValidVariableName(string name_) { + if(name_.empty()) return "var_1"; + size_t i = 0; + while(true) { + i = name_.find_first_of(ILLEGAL_IN_NAMES_MINUS_SPACE_STR, i); + if(i == string::npos) + break; + name_.erase(name_.begin() + i); + } + gsub(SPACE, UNDERSCORE, name_); + while(is_in(NUMBERS, name_[0])) { + name_.erase(name_.begin()); + } + return name_; +} +string Calculator::convertToValidFunctionName(string name_) { + if(name_.empty()) return "func_1"; + return convertToValidVariableName(name_); +} +string Calculator::convertToValidUnitName(string name_) { + if(name_.empty()) return "new_unit"; + size_t i = 0; + string stmp = ILLEGAL_IN_NAMES_MINUS_SPACE_STR + NUMBERS; + while(true) { + i = name_.find_first_of(stmp, i); + if(i == string::npos) + break; + name_.erase(name_.begin() + i); + } + gsub(SPACE, UNDERSCORE, name_); + return name_; +} +bool Calculator::nameTaken(string name, ExpressionItem *object) { + if(name.empty()) return false; + if(object) { + switch(object->type()) { + case TYPE_VARIABLE: {} + case TYPE_UNIT: { + for(size_t index = 0; index < variables.size(); index++) { + if(variables[index]->isActive() && variables[index]->hasName(name)) { + return variables[index] != object; } - } else { - time(&exchange_rates_time[0]); } - new_times.modtime = exchange_rates_time[0]; - new_times.actime = exchange_rates_time[0]; -#ifdef _WIN32 - _utime(filename.c_str(), &new_times); -#else - utime(filename.c_str(), &new_times); -#endif - } else { - exchange_rates_time[0] = stats.st_mtime; - if(exchange_rates_time[0] > exchange_rates_check_time[0]) exchange_rates_check_time[0] = exchange_rates_time[0]; - } - } - } - - filename = buildPath(getLocalDataDir(), "btc.json"); - ifstream file2(filename.c_str()); - if(file2.is_open()) { - std::stringstream ssbuffer2; - ssbuffer2 << file2.rdbuf(); - string sbuffer = ssbuffer2.str(); - size_t i = sbuffer.find("\"amount\":"); - if(i != string::npos) { - i = sbuffer.find("\"", i + 9); - if(i != string::npos) { - size_t i2 = sbuffer.find("\"", i + 1); - ((AliasUnit*) u_btc)->setExpression(sbuffer.substr(i + 1, i2 - (i + 1))); - } - } - file2.close(); - struct stat stats; - if(stat(filename.c_str(), &stats) == 0) { - exchange_rates_time[1] = stats.st_mtime; - if(exchange_rates_time[1] > exchange_rates_check_time[1]) exchange_rates_check_time[1] = exchange_rates_time[1]; - } - } else { - exchange_rates_time[1] = ((time_t) 1531087L) * 1000; - if(exchange_rates_time[1] > exchange_rates_check_time[1]) exchange_rates_check_time[1] = exchange_rates_time[1]; - } - - Unit *u_usd = getUnit("USD"); - if(!u_usd) return true; - - string sbuffer; - filename = buildPath(getLocalDataDir(), "rates.html"); - ifstream file(filename.c_str()); - if(file.is_open()) { - std::stringstream ssbuffer; - ssbuffer << file.rdbuf(); - sbuffer = ssbuffer.str(); - } - if(sbuffer.empty()) { - if(file.is_open()) file.close(); - file.clear(); - filename = buildPath(getGlobalDefinitionsDir(), "rates.json"); - file.open(filename.c_str()); - if(!file.is_open()) return true; - std::stringstream ssbuffer; - ssbuffer << file.rdbuf(); - sbuffer = ssbuffer.str(); - string sname; - size_t i = sbuffer.find("\"currency_code\":"); - while(i != string::npos) { - i += 16; - size_t i2 = sbuffer.find("\"", i); - if(i2 == string::npos) break; - size_t i3 = sbuffer.find("\"", i2 + 1); - if(i3 != string::npos && i3 - (i2 + 1) == 3) { - currency = sbuffer.substr(i2 + 1, i3 - (i2 + 1)); - if(currency.length() == 3 && currency[0] >= 'A' && currency[0] <= 'Z') { - u = getUnit(currency); - if(!u || (u->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) u)->firstBaseUnit() == u_usd)) { - i2 = sbuffer.find("\"rate\":", i3 + 1); - size_t i4 = sbuffer.find("}", i3 + 1); - if(i2 != string::npos && i2 < i4) { - i3 = sbuffer.find(",", i2 + 7); - rate = sbuffer.substr(i2 + 7, i3 - (i2 + 7)); - rate = "1/" + rate; - if(!u) { - i2 = sbuffer.find("\"name\":\"", i3 + 1); - if(i2 != string::npos && i2 < i4) { - i3 = sbuffer.find("\"", i2 + 8); - if(i3 != string::npos) { - sname = sbuffer.substr(i2 + 8, i3 - (i2 + 8)); - remove_blank_ends(sname); - } - } else { - sname = ""; - } - u = addUnit(new AliasUnit(_("Currency"), currency, "", "", sname, u_usd, rate, 1, "", false, true), false, true); - if(u) u->setHidden(true); - } else { - ((AliasUnit*) u)->setBaseUnit(u_usd); - ((AliasUnit*) u)->setExpression(rate); - } - if(u) { - u->setApproximate(); - u->setPrecision(-2); - u->setChanged(false); - } - } + for(size_t i = 0; i < units.size(); i++) { + if(units[i]->isActive() && units[i]->hasName(name)) { + return units[i] != object; } } + break; } - i = sbuffer.find("\"currency_code\":", i); - } - file.close(); - exchange_rates_time[2] = ((time_t) 1527199L) * 1000; - if(exchange_rates_time[2] > exchange_rates_check_time[2]) exchange_rates_check_time[2] = exchange_rates_time[2]; - } else { - string sname; - size_t i = sbuffer.find("class=\'country\'"); - while(i != string::npos) { - currency = ""; sname = ""; rate = ""; - i += 15; - size_t i2 = sbuffer.find("data-currency-code=\"", i); - if(i2 != string::npos) { - i2 += 19; - size_t i3 = sbuffer.find("\"", i2 + 1); - if(i3 != string::npos) { - currency = sbuffer.substr(i2 + 1, i3 - (i2 + 1)); - remove_blank_ends(currency); - } - } - i2 = sbuffer.find("data-currency-name=\'", i); - if(i2 != string::npos) { - i2 += 19; - size_t i3 = sbuffer.find("|", i2 + 1); - if(i3 != string::npos) { - sname = sbuffer.substr(i2 + 1, i3 - (i2 + 1)); - remove_blank_ends(sname); - } - } - i2 = sbuffer.find("data-rate=\'", i); - if(i2 != string::npos) { - i2 += 10; - size_t i3 = sbuffer.find("'", i2 + 1); - if(i3 != string::npos) { - rate = sbuffer.substr(i2 + 1, i3 - (i2 + 1)); - remove_blank_ends(rate); - } - } - if(currency.length() == 3 && currency[0] >= 'A' && currency[0] <= 'Z' && !rate.empty()) { - u = getUnit(currency); - if(!u || (u->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) u)->firstBaseUnit() == u_usd)) { - rate = "1/" + rate; - if(!u) { - u = addUnit(new AliasUnit(_("Currency"), currency, "", "", sname, u_usd, rate, 1, "", false, true), false, true); - if(u) u->setHidden(true); - } else { - ((AliasUnit*) u)->setBaseUnit(u_usd); - ((AliasUnit*) u)->setExpression(rate); - } - if(u) { - u->setApproximate(); - u->setPrecision(-2); - u->setChanged(false); + case TYPE_FUNCTION: { + for(size_t index = 0; index < functions.size(); index++) { + if(functions[index]->isActive() && functions[index]->hasName(name)) { + return functions[index] != object; } } + break; } - i = sbuffer.find("class=\'country\'", i); - } - file.close(); - struct stat stats; - if(stat(filename.c_str(), &stats) == 0) { - exchange_rates_time[2] = stats.st_mtime; - if(exchange_rates_time[2] > exchange_rates_check_time[2]) exchange_rates_check_time[2] = exchange_rates_time[2]; } + } else { + return getActiveExpressionItem(name) != NULL; } - - return true; - -} -bool Calculator::hasGVFS() { - return false; -} -bool Calculator::hasGnomeVFS() { - return hasGVFS(); -} -bool Calculator::canFetch() { -#ifdef HAVE_LIBCURL - return true; -#else return false; -#endif } -string Calculator::getExchangeRatesFileName(int index) { - switch(index) { - case 1: {return buildPath(getLocalDataDir(), "eurofxref-daily.xml");} - case 2: {return buildPath(getLocalDataDir(), "btc.json");} - //case 3: {return buildPath(getLocalDataDir(), "rates.json");} - case 3: {return buildPath(getLocalDataDir(), "rates.html");} - default: {} - } - return ""; -} -time_t Calculator::getExchangeRatesTime(int index) { - if(index > 3) return 0; - if(index < 1) { - if(exchange_rates_time[1] < exchange_rates_time[0]) { - if(exchange_rates_time[2] < exchange_rates_time[1]) return exchange_rates_time[2]; - return exchange_rates_time[1]; - } - if(exchange_rates_time[2] < exchange_rates_time[0]) return exchange_rates_time[2]; - return exchange_rates_time[0]; - } - index--; - return exchange_rates_time[index]; -} -string Calculator::getExchangeRatesUrl(int index) { - switch(index) { - case 1: {return "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";} - case 2: {return "https://api.coinbase.com/v2/prices/spot?currency=EUR";} - //case 2: {return "http://www.mycurrency.net/service/rates";} - case 3: {return "https://www.mycurrency.net/=US";} - default: {} - } - return ""; -} -bool Calculator::fetchExchangeRates(int timeout, string) {return fetchExchangeRates(timeout);} -size_t write_data(void *ptr, size_t size, size_t nmemb, string *sbuffer) { - sbuffer->append((char*) ptr, size * nmemb); - return size * nmemb; -} -#define FETCH_FAIL_CLEANUP curl_easy_cleanup(curl); curl_global_cleanup(); time(&exchange_rates_check_time[0]); time(&exchange_rates_check_time[1]); time(&exchange_rates_check_time[2]); -bool Calculator::fetchExchangeRates(int timeout, int n) { -#ifdef HAVE_LIBCURL - if(n <= 0) n = 3; - - recursiveMakeDir(getLocalDataDir()); - string sbuffer; - char error_buffer[CURL_ERROR_SIZE]; - CURL *curl; - CURLcode res; - long int file_time = 0; - curl_global_init(CURL_GLOBAL_DEFAULT); - curl = curl_easy_init(); - if(!curl) {return false;} - curl_easy_setopt(curl, CURLOPT_URL, getExchangeRatesUrl(1).c_str()); - curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sbuffer); - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer); - error_buffer[0] = 0; - curl_easy_setopt(curl, CURLOPT_FILETIME, &file_time); -#ifdef _WIN32 - char exepath[MAX_PATH]; - GetModuleFileName(NULL, exepath, MAX_PATH); - string datadir(exepath); - datadir.resize(datadir.find_last_of('\\')); - if(datadir.substr(datadir.length() - 4) != "\\bin" && datadir.substr(datadir.length() - 6) != "\\.libs") { - string cainfo = buildPath(datadir, "ssl", "certs", "ca-bundle.crt"); - gsub("\\", "/", cainfo); - curl_easy_setopt(curl, CURLOPT_CAINFO, cainfo.c_str()); +bool Calculator::variableNameTaken(string name, Variable *object) { + if(name.empty()) return false; + for(size_t index = 0; index < variables.size(); index++) { + if(variables[index]->isActive() && variables[index]->hasName(name)) { + return variables[index] != object; + } } -#endif - res = curl_easy_perform(curl); - if(res != CURLE_OK) { - if(strlen(error_buffer)) error(true, _("Failed to download exchange rates from %s: %s."), "ECB", error_buffer, NULL); - else error(true, _("Failed to download exchange rates from %s: %s."), "ECB", curl_easy_strerror(res), NULL); - FETCH_FAIL_CLEANUP; - return false; - } - if(sbuffer.empty()) {error(true, _("Failed to download exchange rates from %s: %s."), "ECB", "Document empty", NULL); FETCH_FAIL_CLEANUP; return false;} - ofstream file(getExchangeRatesFileName(1).c_str(), ios::out | ios::trunc | ios::binary); - if(!file.is_open()) { - error(true, _("Failed to download exchange rates from %s: %s."), "ECB", strerror(errno), NULL); - FETCH_FAIL_CLEANUP - return false; - } - file << sbuffer; - file.close(); - if(file_time > 0) { -#ifdef _WIN32 - struct _utimbuf new_times; -#else - struct utimbuf new_times; -#endif - new_times.modtime = (time_t) file_time; - new_times.actime = (time_t) file_time; -#ifdef _WIN32 - _utime(getExchangeRatesFileName(1).c_str(), &new_times); -#else - utime(getExchangeRatesFileName(1).c_str(), &new_times); -#endif + for(size_t i = 0; i < units.size(); i++) { + if(units[i]->isActive() && units[i]->hasName(name)) { + return true; + } } - - if(n >= 2) { - - sbuffer = ""; - curl_easy_setopt(curl, CURLOPT_URL, getExchangeRatesUrl(2).c_str()); - curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sbuffer); - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer); - - res = curl_easy_perform(curl); - - if(res != CURLE_OK) {error(true, _("Failed to download exchange rates from %s: %s."), "coinbase.com", error_buffer, NULL); FETCH_FAIL_CLEANUP; return false;} - if(sbuffer.empty()) {error(true, _("Failed to download exchange rates from %s: %s."), "coinbase.com", "Document empty", NULL); FETCH_FAIL_CLEANUP; return false;} - ofstream file3(getExchangeRatesFileName(2).c_str(), ios::out | ios::trunc | ios::binary); - if(!file3.is_open()) { - error(true, _("Failed to download exchange rates from %s: %s."), "coinbase.com", strerror(errno), NULL); - FETCH_FAIL_CLEANUP - return false; + return false; +} +bool Calculator::unitNameTaken(string name, Unit *object) { + if(name.empty()) return false; + for(size_t index = 0; index < variables.size(); index++) { + if(variables[index]->isActive() && variables[index]->hasName(name)) { + return true; } - file3 << sbuffer; - file3.close(); - } - if(n >= 3) { - - sbuffer = ""; - curl_easy_setopt(curl, CURLOPT_URL, getExchangeRatesUrl(3).c_str()); - curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sbuffer); - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer); - res = curl_easy_perform(curl); - - if(res != CURLE_OK) {error(true, _("Failed to download exchange rates from %s: %s."), "mycurrency.net", error_buffer, NULL); FETCH_FAIL_CLEANUP; return false;} - if(sbuffer.empty() || sbuffer.find("Internal Server Error") != string::npos) {error(true, _("Failed to download exchange rates from %s: %s."), "mycurrency.net", "Document empty", NULL); FETCH_FAIL_CLEANUP; return false;} - ofstream file2(getExchangeRatesFileName(3).c_str(), ios::out | ios::trunc | ios::binary); - if(!file2.is_open()) { - error(true, _("Failed to download exchange rates from %s: %s."), "mycurrency.net", strerror(errno), NULL); - FETCH_FAIL_CLEANUP - return false; + for(size_t i = 0; i < units.size(); i++) { + if(units[i]->isActive() && units[i]->hasName(name)) { + return units[i] == object; } - file2 << sbuffer; - file2.close(); - } - - curl_easy_cleanup(curl); curl_global_cleanup(); - - return true; -#else return false; -#endif } -bool Calculator::checkExchangeRatesDate(unsigned int n_days, bool force_check, bool send_warning, int n) { - if(n <= 0) n = 3; - time_t extime = exchange_rates_time[0]; - if(n > 1 && exchange_rates_time[1] < extime) extime = exchange_rates_time[1]; - if(n > 2 && exchange_rates_time[2] < extime) extime = exchange_rates_time[2]; - time_t cextime = exchange_rates_check_time[0]; - if(n > 1 && exchange_rates_check_time[1] < cextime) cextime = exchange_rates_check_time[1]; - if(n > 2 && exchange_rates_check_time[2] < cextime) cextime = exchange_rates_check_time[2]; - if(extime > 0 && ((!force_check && cextime > 0 && difftime(time(NULL), cextime) < 86400 * n_days) || difftime(time(NULL), extime) < (86400 * n_days) + 3600)) return true; - time(&exchange_rates_check_time[0]); - if(n > 1) time(&exchange_rates_check_time[1]); - if(n > 2) time(&exchange_rates_check_time[2]); - if(send_warning) error(false, _("It has been %s day(s) since the exchange rates last were updated."), i2s((int) floor(difftime(time(NULL), extime) / 86400)).c_str(), NULL); +bool Calculator::functionNameTaken(string name, MathFunction *object) { + if(name.empty()) return false; + for(size_t index = 0; index < functions.size(); index++) { + if(functions[index]->isActive() && functions[index]->hasName(name)) { + return functions[index] != object; + } + } return false; } -void Calculator::setExchangeRatesWarningEnabled(bool enable) { - b_exchange_rates_warning_enabled = enable; -} -bool Calculator::exchangeRatesWarningEnabled() const { - return b_exchange_rates_warning_enabled; -} -int Calculator::exchangeRatesUsed() const { - return b_exchange_rates_used; -} -void Calculator::resetExchangeRatesUsed() { - b_exchange_rates_used = 0; -} -void Calculator::setExchangeRatesUsed(int index) { - if(index > b_exchange_rates_used) b_exchange_rates_used = index; - if(b_exchange_rates_warning_enabled) checkExchangeRatesDate(7, false, true); -} - -bool Calculator::canPlot() { -#ifdef _WIN32 - LPSTR lpFilePart; - char filename[MAX_PATH]; - return SearchPath(NULL, "gnuplot", ".exe", MAX_PATH, filename, &lpFilePart); -#else - FILE *pipe = popen("gnuplot - 2>/dev/null", "w"); - if(!pipe) return false; - return pclose(pipe) == 0; -#endif -} - -extern bool fix_intervals(MathStructure &mstruct, const EvaluationOptions &eo, bool *failed = NULL, long int min_precision = 2, bool function_middle = false); -void parse_and_precalculate_plot(string &expression, MathStructure &mstruct, const ParseOptions &po, EvaluationOptions &eo) { - eo.approximation = APPROXIMATION_APPROXIMATE; - ParseOptions po2 = po; - po2.read_precision = DONT_READ_PRECISION; - eo.parse_options = po2; - eo.interval_calculation = INTERVAL_CALCULATION_NONE; - mstruct = CALCULATOR->parse(expression, po2); - MathStructure mbak(mstruct); - eo.calculate_functions = false; - eo.expand = false; - CALCULATOR->beginTemporaryStopMessages(); - mstruct.eval(eo); - int im = 0; - if(CALCULATOR->endTemporaryStopMessages(NULL, &im) > 0 || im > 0) mstruct = mbak; - eo.calculate_functions = true; - eo.expand = true; -} - -MathStructure Calculator::expressionToPlotVector(string expression, const MathStructure &min, const MathStructure &max, int steps, MathStructure *x_vector, string x_var, const ParseOptions &po, int msecs) { - Variable *v = getActiveVariable(x_var); - MathStructure x_mstruct; - if(v) x_mstruct = v; - else x_mstruct = x_var; - EvaluationOptions eo; - MathStructure mparse; - if(msecs > 0) startControl(msecs); - beginTemporaryStopIntervalArithmetic(); - parse_and_precalculate_plot(expression, mparse, po, eo); - beginTemporaryStopMessages(); - MathStructure y_vector(mparse.generateVector(x_mstruct, min, max, steps, x_vector, eo)); - endTemporaryStopMessages(); - endTemporaryStopIntervalArithmetic(); - if(msecs > 0) { - if(aborted()) error(true, _("It took too long to generate the plot data."), NULL); - stopControl(); - } - if(y_vector.size() == 0) { - error(true, _("Unable to generate plot data with current min, max and sampling rate."), NULL); - } - return y_vector; -} -MathStructure Calculator::expressionToPlotVector(string expression, float min, float max, int steps, MathStructure *x_vector, string x_var, const ParseOptions &po, int msecs) { - MathStructure min_mstruct(min), max_mstruct(max); - ParseOptions po2 = po; - po2.read_precision = DONT_READ_PRECISION; - MathStructure y_vector(expressionToPlotVector(expression, min_mstruct, max_mstruct, steps, x_vector, x_var, po2, msecs)); - return y_vector; -} -MathStructure Calculator::expressionToPlotVector(string expression, const MathStructure &min, const MathStructure &max, const MathStructure &step, MathStructure *x_vector, string x_var, const ParseOptions &po, int msecs) { - Variable *v = getActiveVariable(x_var); - MathStructure x_mstruct; - if(v) x_mstruct = v; - else x_mstruct = x_var; - EvaluationOptions eo; - MathStructure mparse; - if(msecs > 0) startControl(msecs); - beginTemporaryStopIntervalArithmetic(); - parse_and_precalculate_plot(expression, mparse, po, eo); - beginTemporaryStopMessages(); - MathStructure y_vector(mparse.generateVector(x_mstruct, min, max, step, x_vector, eo)); - endTemporaryStopMessages(); - endTemporaryStopIntervalArithmetic(); - if(msecs > 0) { - if(aborted()) error(true, _("It took too long to generate the plot data."), NULL); - stopControl(); - } - if(y_vector.size() == 0) { - error(true, _("Unable to generate plot data with current min, max and step size."), NULL); - } - return y_vector; -} -MathStructure Calculator::expressionToPlotVector(string expression, float min, float max, float step, MathStructure *x_vector, string x_var, const ParseOptions &po, int msecs) { - MathStructure min_mstruct(min), max_mstruct(max), step_mstruct(step); - ParseOptions po2 = po; - po2.read_precision = DONT_READ_PRECISION; - MathStructure y_vector(expressionToPlotVector(expression, min_mstruct, max_mstruct, step_mstruct, x_vector, x_var, po2, msecs)); - return y_vector; -} -MathStructure Calculator::expressionToPlotVector(string expression, const MathStructure &x_vector, string x_var, const ParseOptions &po, int msecs) { - Variable *v = getActiveVariable(x_var); - MathStructure x_mstruct; - if(v) x_mstruct = v; - else x_mstruct = x_var; - EvaluationOptions eo; - MathStructure mparse; - if(msecs > 0) startControl(msecs); - beginTemporaryStopIntervalArithmetic(); - parse_and_precalculate_plot(expression, mparse, po, eo); - beginTemporaryStopMessages(); - MathStructure y_vector(mparse.generateVector(x_mstruct, x_vector, eo).eval(eo)); - endTemporaryStopMessages(); - endTemporaryStopIntervalArithmetic(); - if(msecs > 0) { - if(aborted()) error(true, _("It took too long to generate the plot data."), NULL); - stopControl(); - } - return y_vector; -} - -extern bool testComplexZero(const Number *this_nr, const Number *i_nr); - -bool Calculator::plotVectors(PlotParameters *param, const vector &y_vectors, const vector &x_vectors, vector &pdps, bool persistent, int msecs) { - - string homedir = getLocalTmpDir(); - recursiveMakeDir(homedir); - - string commandline_extra; - string title; - - if(!param) { - PlotParameters pp; - param = &pp; - } - - string plot; - - if(param->filename.empty()) { - if(!param->color) { - commandline_extra += " -mono"; - } - plot += "set terminal pop\n"; - } else { - persistent = true; - if(param->filetype == PLOT_FILETYPE_AUTO) { - size_t i = param->filename.rfind("."); - if(i == string::npos) { - param->filetype = PLOT_FILETYPE_PNG; - error(false, _("No extension in file name. Saving as PNG image."), NULL); - } else { - string ext = param->filename.substr(i + 1, param->filename.length() - (i + 1)); - if(ext == "png") { - param->filetype = PLOT_FILETYPE_PNG; - } else if(ext == "ps") { - param->filetype = PLOT_FILETYPE_PS; - } else if(ext == "pdf") { - param->filetype = PLOT_FILETYPE_PDF; - } else if(ext == "eps") { - param->filetype = PLOT_FILETYPE_EPS; - } else if(ext == "svg") { - param->filetype = PLOT_FILETYPE_SVG; - } else if(ext == "fig") { - param->filetype = PLOT_FILETYPE_FIG; - } else if(ext == "tex") { - param->filetype = PLOT_FILETYPE_LATEX; - } else { - param->filetype = PLOT_FILETYPE_PNG; - error(false, _("Unknown extension in file name. Saving as PNG image."), NULL); - } - } - } - plot += "set terminal "; - switch(param->filetype) { - case PLOT_FILETYPE_FIG: { - plot += "fig "; - if(param->color) { - plot += "color"; - } else { - plot += "monochrome"; - } - break; - } - case PLOT_FILETYPE_SVG: { - plot += "svg"; - break; - } - case PLOT_FILETYPE_LATEX: { - plot += "latex "; - break; - } - case PLOT_FILETYPE_PS: { - plot += "postscript "; - if(param->color) { - plot += "color"; - } else { - plot += "monochrome"; - } - plot += " \"Times\""; - break; - } - case PLOT_FILETYPE_PDF: { - plot += "pdf "; - if(param->color) { - plot += "color"; - } else { - plot += "monochrome"; - } - break; - } - case PLOT_FILETYPE_EPS: { - plot += "postscript eps "; - if(param->color) { - plot += "color"; - } else { - plot += "monochrome"; +bool Calculator::unitIsUsedByOtherUnits(const Unit *u) const { + const Unit *u2; + for(size_t i = 0; i < units.size(); i++) { + if(units[i] != u) { + u2 = units[i]; + while(u2->subtype() == SUBTYPE_ALIAS_UNIT) { + u2 = ((AliasUnit*) u2)->firstBaseUnit(); + if(u2 == u) { + return true; } - plot += " \"Times\""; - break; } - default: { - plot += "png "; - break; - } - } - plot += "\nset output \""; - plot += param->filename; - plot += "\"\n"; - } - - switch(param->legend_placement) { - case PLOT_LEGEND_NONE: {plot += "set nokey\n"; break;} - case PLOT_LEGEND_TOP_LEFT: {plot += "set key top left\n"; break;} - case PLOT_LEGEND_TOP_RIGHT: {plot += "set key top right\n"; break;} - case PLOT_LEGEND_BOTTOM_LEFT: {plot += "set key bottom left\n"; break;} - case PLOT_LEGEND_BOTTOM_RIGHT: {plot += "set key bottom right\n"; break;} - case PLOT_LEGEND_BELOW: {plot += "set key below\n"; break;} - case PLOT_LEGEND_OUTSIDE: {plot += "set key outside\n"; break;} - } - if(!param->x_label.empty()) { - title = param->x_label; - gsub("\"", "\\\"", title); - plot += "set xlabel \""; - plot += title; - plot += "\"\n"; - } - if(!param->y_label.empty()) { - string title = param->y_label; - gsub("\"", "\\\"", title); - plot += "set ylabel \""; - plot += title; - plot += "\"\n"; - } - if(!param->title.empty()) { - title = param->title; - gsub("\"", "\\\"", title); - plot += "set title \""; - plot += title; - plot += "\"\n"; - } - if(param->grid) { - plot += "set grid\n"; - - } - if(!param->auto_y_min || !param->auto_y_max) { - plot += "set yrange ["; - if(!param->auto_y_min) plot += d2s(param->y_min); - plot += ":"; - if(!param->auto_y_max) plot += d2s(param->y_max); - plot += "]"; - plot += "\n"; - } - if(param->x_log) { - plot += "set logscale x "; - plot += i2s(param->x_log_base); - plot += "\n"; } - if(param->show_all_borders) { - plot += "set border 15\n"; + return false; +} + +string Calculator::getName(string name, ExpressionItem *object, bool force, bool always_append) { + ExpressionItem *item = NULL; + if(!object) { + } else if(object->type() == TYPE_FUNCTION) { + item = getActiveFunction(name); } else { - bool xaxis2 = false, yaxis2 = false; - for(size_t i = 0; i < pdps.size(); i++) { - if(pdps[i] && pdps[i]->xaxis2) { - xaxis2 = true; - } - if(pdps[i] && pdps[i]->yaxis2) { - yaxis2 = true; - } + item = getActiveVariable(name); + if(!item) { + item = getActiveUnit(name); } - if(xaxis2 && yaxis2) { - plot += "set border 15\nset x2tics\nset y2tics\n"; - } else if(xaxis2) { - plot += "set border 7\nset x2tics\n"; - } else if(yaxis2) { - plot += "set border 11\nset y2tics\n"; - } else { - plot += "set border 3\n"; + if(!item) { + item = getCompositeUnit(name); } - plot += "set xtics nomirror\nset ytics nomirror\n"; } - size_t samples = 1000; - for(size_t i = 0; i < y_vectors.size(); i++) { - if(!y_vectors[i].isUndefined()) { - if(y_vectors[i].size() > 3000) { - samples = 6000; - break; + if(item && force && !name.empty() && item != object && object) { + if(!item->isLocal()) { + bool b = item->hasChanged(); + if(object->isActive()) { + item->setActive(false); } - if(y_vectors[i].size() * 2 > samples) samples = y_vectors[i].size() * 2; - } - } - plot += "set samples "; - plot += i2s(samples); - plot += "\n"; - plot += "plot "; - for(size_t i = 0; i < y_vectors.size(); i++) { - if(!y_vectors[i].isUndefined()) { - if(i != 0) { - plot += ","; - } - string filename = "gnuplot_data"; - filename += i2s(i + 1); - filename = buildPath(homedir, filename); -#ifdef _WIN32 - gsub("\\", "\\\\", filename); -#endif - plot += "\""; - plot += filename; - plot += "\""; - if(i < pdps.size()) { - switch(pdps[i]->smoothing) { - case PLOT_SMOOTHING_UNIQUE: {plot += " smooth unique"; break;} - case PLOT_SMOOTHING_CSPLINES: {plot += " smooth csplines"; break;} - case PLOT_SMOOTHING_BEZIER: {plot += " smooth bezier"; break;} - case PLOT_SMOOTHING_SBEZIER: {plot += " smooth sbezier"; break;} - default: {} - } - if(pdps[i]->xaxis2 && pdps[i]->yaxis2) { - plot += " axis x2y2"; - } else if(pdps[i]->xaxis2) { - plot += " axis x2y1"; - } else if(pdps[i]->yaxis2) { - plot += " axis x1y2"; - } - if(!pdps[i]->title.empty()) { - title = pdps[i]->title; - gsub("\"", "\\\"", title); - plot += " title \""; - plot += title; - plot += "\""; - } - switch(pdps[i]->style) { - case PLOT_STYLE_LINES: {plot += " with lines"; break;} - case PLOT_STYLE_POINTS: {plot += " with points"; break;} - case PLOT_STYLE_POINTS_LINES: {plot += " with linespoints"; break;} - case PLOT_STYLE_BOXES: {plot += " with boxes"; break;} - case PLOT_STYLE_HISTOGRAM: {plot += " with histeps"; break;} - case PLOT_STYLE_STEPS: {plot += " with steps"; break;} - case PLOT_STYLE_CANDLESTICKS: {plot += " with candlesticks"; break;} - case PLOT_STYLE_DOTS: {plot += " with dots"; break;} - } - if(param->linewidth < 1) { - plot += " lw 2"; - } else { - plot += " lw "; - plot += i2s(param->linewidth); - } + if(!object->isLocal()) { + item->setChanged(b); + } + } else { + if(object->isActive()) { + item->destroy(); } } + return name; } - plot += "\n"; - - string plot_data; - PrintOptions po; - po.number_fraction_format = FRACTION_DECIMAL; - po.interval_display = INTERVAL_DISPLAY_MIDPOINT; - po.decimalpoint_sign = "."; - po.comma_sign = ","; - for(size_t serie = 0; serie < y_vectors.size(); serie++) { - if(!y_vectors[serie].isUndefined()) { - string filename = "gnuplot_data"; - filename += i2s(serie + 1); - string filepath = buildPath(homedir, filename); - FILE *fdata = fopen(filepath.c_str(), "w+"); - if(!fdata) { - error(true, _("Could not create temporary file %s"), filepath.c_str(), NULL); - return false; - } - plot_data = ""; - int non_numerical = 0, non_real = 0; - //string str = ""; - if(msecs > 0) startControl(msecs); - ComparisonResult ct1 = COMPARISON_RESULT_EQUAL, ct2 = COMPARISON_RESULT_EQUAL; - size_t last_index = string::npos, last_index2 = string::npos; - bool check_continuous = pdps[serie]->test_continuous && (pdps[serie]->style == PLOT_STYLE_LINES || pdps[serie]->style == PLOT_STYLE_POINTS_LINES); - bool prev_failed = false; - for(size_t i = 1; i <= y_vectors[serie].countChildren(); i++) { - ComparisonResult ct = COMPARISON_RESULT_UNKNOWN; - bool invalid_nr = false, b_imagzero_x = false, b_imagzero_y = false; - if(!y_vectors[serie].getChild(i)->isNumber()) { - invalid_nr = true; - non_numerical++; - //if(non_numerical == 1) str = y_vectors[serie].getChild(i)->print(po); - } else if(!y_vectors[serie].getChild(i)->number().isReal()) { - b_imagzero_y = testComplexZero(&y_vectors[serie].getChild(i)->number(), y_vectors[serie].getChild(i)->number().internalImaginary()); - if(!b_imagzero_y) { - invalid_nr = true; - non_real++; - //if(non_numerical + non_real == 1) str = y_vectors[serie].getChild(i)->print(po); - } + int i2 = 1; + bool changed = false; + if(name.empty()) { + name = "var"; + always_append = true; + item = NULL; + changed = true; + } + string stmp = name; + if(always_append) { + stmp += NAME_NUMBER_PRE_STR; + stmp += "1"; + } + if(changed || (item && item != object)) { + if(item) { + i2++; + stmp = name; + stmp += NAME_NUMBER_PRE_STR; + stmp += i2s(i2); + } + while(true) { + if(!object) { + item = getActiveFunction(stmp); + if(!item) { + item = getActiveVariable(stmp); } - if(serie < x_vectors.size() && !x_vectors[serie].isUndefined() && x_vectors[serie].countChildren() == y_vectors[serie].countChildren()) { - if(!x_vectors[serie].getChild(i)->isNumber()) { - invalid_nr = true; - non_numerical++; - //if(non_numerical == 1) str = x_vectors[serie].getChild(i)->print(po); - } else if(!x_vectors[serie].getChild(i)->number().isReal()) { - b_imagzero_x = testComplexZero(&x_vectors[serie].getChild(i)->number(), x_vectors[serie].getChild(i)->number().internalImaginary()); - if(!b_imagzero_x) { - invalid_nr = true; - non_real++; - //if(non_numerical + non_real == 1) str = x_vectors[serie].getChild(i)->print(po); - } - } - if(!invalid_nr) { - if(b_imagzero_y) plot_data += x_vectors[serie].getChild(i)->number().realPart().print(po); - else plot_data += x_vectors[serie].getChild(i)->print(po); - plot_data += " "; - } + if(!item) { + item = getActiveUnit(stmp); } - if(!invalid_nr) { - if(check_continuous && !prev_failed) { - if(i == 1 || ct2 == COMPARISON_RESULT_UNKNOWN) ct = COMPARISON_RESULT_EQUAL; - else ct = y_vectors[serie].getChild(i - 1)->number().compare(y_vectors[serie].getChild(i)->number()); - if((ct == COMPARISON_RESULT_GREATER || ct == COMPARISON_RESULT_LESS) && (ct1 == COMPARISON_RESULT_GREATER || ct1 == COMPARISON_RESULT_LESS) && (ct2 == COMPARISON_RESULT_GREATER || ct2 == COMPARISON_RESULT_LESS) && ct1 != ct2 && ct != ct2) { - if(last_index2 != string::npos) plot_data.insert(last_index2 + 1, " \n"); - } - } - if(b_imagzero_x) plot_data += y_vectors[serie].getChild(i)->number().realPart().print(po); - else plot_data += y_vectors[serie].getChild(i)->print(po); - plot_data += "\n"; - prev_failed = false; - } else if(!prev_failed) { - ct = COMPARISON_RESULT_UNKNOWN; - plot_data += " \n"; - prev_failed = true; - } - last_index2 = last_index; - last_index = plot_data.length() - 1; - ct1 = ct2; - ct2 = ct; - if(aborted()) { - fclose(fdata); - if(msecs > 0) { - error(true, _("It took too long to generate the plot data."), NULL); - stopControl(); - } - return false; + if(!item) { + item = getCompositeUnit(stmp); } - } - if(msecs > 0) stopControl(); - /*if(non_numerical > 0 || non_real > 0) { - string stitle; - if(serie < pdps.size() && !pdps[serie]->title.empty()) { - stitle = pdps[serie]->title.c_str(); - } else { - stitle = i2s(serie).c_str(); + } else if(object->type() == TYPE_FUNCTION) { + item = getActiveFunction(stmp); + } else { + item = getActiveVariable(stmp); + if(!item) { + item = getActiveUnit(stmp); } - if(non_numerical > 0) { - error(true, _("Series %s contains non-numerical data (\"%s\" first of %s) which can not be properly plotted."), stitle.c_str(), str.c_str(), i2s(non_numerical).c_str(), NULL); - } else { - error(true, _("Series %s contains non-real data (\"%s\" first of %s) which can not be properly plotted."), stitle.c_str(), str.c_str(), i2s(non_real).c_str(), NULL); + if(!item) { + item = getCompositeUnit(stmp); } - }*/ - fputs(plot_data.c_str(), fdata); - fflush(fdata); - fclose(fdata); - } - } - - return invokeGnuplot(plot, commandline_extra, persistent); -} -bool Calculator::invokeGnuplot(string commands, string commandline_extra, bool persistent) { - FILE *pipe = NULL; - if(!b_gnuplot_open || !gnuplot_pipe || persistent || commandline_extra != gnuplot_cmdline) { - if(!persistent) { - closeGnuplot(); - } - string commandline = "gnuplot"; - if(persistent) { - commandline += " -persist"; - } - commandline += commandline_extra; -#ifdef _WIN32 - commandline += " - 2>nul"; - pipe = _popen(commandline.c_str(), "w"); -#else - commandline += " - 2>/dev/null"; - pipe = popen(commandline.c_str(), "w"); -#endif - if(!pipe) { - error(true, _("Failed to invoke gnuplot. Make sure that you have gnuplot installed in your path."), NULL); - return false; - } - if(!persistent && pipe) { - gnuplot_pipe = pipe; - b_gnuplot_open = true; - gnuplot_cmdline = commandline_extra; + } + if(item && item != object) { + i2++; + stmp = name; + stmp += NAME_NUMBER_PRE_STR; + stmp += i2s(i2); + } else { + break; + } } - } else { - pipe = gnuplot_pipe; - } - if(!pipe) { - return false; } - if(!persistent) { - fputs("clear\n", pipe); - fputs("reset\n", pipe); - } - fputs(commands.c_str(), pipe); - fflush(pipe); - if(persistent) { - return pclose(pipe) == 0; - } - return true; -} -bool Calculator::closeGnuplot() { - if(gnuplot_pipe) { -#ifdef _WIN32 - int rv = _pclose(gnuplot_pipe); -#else - int rv = pclose(gnuplot_pipe); -#endif - gnuplot_pipe = NULL; - b_gnuplot_open = false; - return rv == 0; + if(i2 > 1 && !always_append) { + error(false, _("Name \"%s\" is in use. Replacing with \"%s\"."), name.c_str(), stmp.c_str(), NULL); } - gnuplot_pipe = NULL; - b_gnuplot_open = false; - return true; -} -bool Calculator::gnuplotOpen() { - return b_gnuplot_open && gnuplot_pipe; + return stmp; } diff -Nru libqalculate-3.6.0/libqalculate/Calculator-convert.cc libqalculate-3.7.0/libqalculate/Calculator-convert.cc --- libqalculate-3.6.0/libqalculate/Calculator-convert.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Calculator-convert.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,1172 @@ +/* + Qalculate + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Unit.h" +#include "Variable.h" +#include "Function.h" +#include "DataSet.h" +#include "ExpressionItem.h" +#include "Prefix.h" +#include "Number.h" + +#include +#include +#include +#include +#include + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +#include "Calculator_p.h" + +MathStructure Calculator::convertToMixedUnits(const MathStructure &mstruct, const EvaluationOptions &eo) { + if(eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_NONE) return mstruct; + if(!mstruct.isMultiplication()) return mstruct; + if(mstruct.size() != 2) return mstruct; + size_t n_messages = messages.size(); + if(mstruct[1].isUnit() && (!mstruct[1].prefix() || mstruct[1].prefix() == decimal_null_prefix) && mstruct[0].isNumber()) { + Prefix *p = mstruct[1].prefix(); + MathStructure mstruct_new(mstruct); + Unit *u = mstruct[1].unit(); + Number nr = mstruct[0].number(); + if(!nr.isReal()) return mstruct; + if(nr.isOne()) return mstruct; + if(u->subtype() == SUBTYPE_COMPOSITE_UNIT) return mstruct; + bool negated = false; + if(nr.isNegative()) { + nr.negate(); + negated = true; + } + bool accept_obsolete = (u->subtype() == SUBTYPE_ALIAS_UNIT && abs(((AliasUnit*) u)->mixWithBase()) > 1); + Unit *original_u = u; + Unit *last_nonobsolete_u = u; + Number last_nonobsolete_nr = nr; + Number nr_one(1, 1); + Number nr_ten(10, 1); + while(eo.mixed_units_conversion > MIXED_UNITS_CONVERSION_DOWNWARDS && nr.isGreaterThan(nr_one)) { + Unit *best_u = NULL; + Number best_nr; + int best_priority = 0; + for(size_t i = 0; i < units.size(); i++) { + Unit *ui = units[i]; + if(ui->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) ui)->firstBaseUnit() == u && ((AliasUnit*) ui)->firstBaseExponent() == 1) { + AliasUnit *aui = (AliasUnit*) ui; + int priority_i = aui->mixWithBase(); + if(((priority_i > 0 && (!best_u || priority_i <= best_priority)) || (best_priority == 0 && priority_i == 0 && ((eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_FORCE_INTEGER && aui->expression().find_first_not_of(NUMBERS) == string::npos) || eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_FORCE_ALL))) && (aui->mixWithBaseMinimum() <= 1 || nr.isGreaterThanOrEqualTo(aui->mixWithBaseMinimum()))) { + MathStructure mstruct_nr(nr); + MathStructure m_exp(m_one); + aui->convertFromFirstBaseUnit(mstruct_nr, m_exp); + mstruct_nr.eval(eo); + if(mstruct_nr.isNumber() && m_exp.isOne() && mstruct_nr.number().isLessThan(nr) && mstruct_nr.number().isGreaterThanOrEqualTo(nr_one) && (!best_u || mstruct_nr.number().isLessThan(best_nr))) { + best_u = ui; + best_nr = mstruct_nr.number(); + best_priority = priority_i; + } + } + } + } + if(!best_u) break; + u = best_u; + nr = best_nr; + if(accept_obsolete || best_priority <= 1) { + last_nonobsolete_u = u; + last_nonobsolete_nr = nr; + } + } + u = last_nonobsolete_u; + nr = last_nonobsolete_nr; + if(u != original_u) { + if(negated) last_nonobsolete_nr.negate(); + mstruct_new[0].set(last_nonobsolete_nr); + mstruct_new[1].set(u, p); + } + while(u->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) u)->firstBaseUnit()->subtype() != SUBTYPE_COMPOSITE_UNIT && ((AliasUnit*) u)->firstBaseExponent() == 1 && (((AliasUnit*) u)->mixWithBase() != 0 || eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_FORCE_ALL || (eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_FORCE_INTEGER && ((AliasUnit*) u)->expression().find_first_not_of(NUMBERS) == string::npos)) && !nr.isInteger() && !nr.isZero()) { + Number int_nr(nr); + int_nr.trunc(); + if(eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_DOWNWARDS_KEEP && int_nr.isZero()) break; + nr -= int_nr; + MathStructure mstruct_nr(nr); + MathStructure m_exp(m_one); + ((AliasUnit*) u)->convertToFirstBaseUnit(mstruct_nr, m_exp); + mstruct_nr.eval(eo); + while(!accept_obsolete && ((AliasUnit*) u)->firstBaseUnit()->subtype() == SUBTYPE_ALIAS_UNIT && abs(((AliasUnit*) ((AliasUnit*) u)->firstBaseUnit())->mixWithBase()) > 1) { + u = ((AliasUnit*) u)->firstBaseUnit(); + if(((AliasUnit*) u)->firstBaseExponent() == 1 && (((AliasUnit*) u)->mixWithBase() != 0 || eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_FORCE_ALL || (eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_FORCE_INTEGER && ((AliasUnit*) u)->expression().find_first_not_of(NUMBERS) == string::npos))) { + ((AliasUnit*) u)->convertToFirstBaseUnit(mstruct_nr, m_exp); + mstruct_nr.eval(eo); + if(!mstruct_nr.isNumber() || !m_exp.isOne()) break; + } else { + mstruct_nr.setUndefined(); + break; + } + } + if(!mstruct_nr.isNumber() || !m_exp.isOne()) break; + if(eo.mixed_units_conversion == MIXED_UNITS_CONVERSION_FORCE_ALL && mstruct_nr.number().isLessThanOrEqualTo(nr)) break; + u = ((AliasUnit*) u)->firstBaseUnit(); + nr = mstruct_nr.number(); + MathStructure mstruct_term; + if(negated) { + Number pos_nr(nr); + pos_nr.negate(); + mstruct_term.set(pos_nr); + } else { + mstruct_term.set(nr); + } + mstruct_term *= MathStructure(u, p); + if(int_nr.isZero()) { + if(mstruct_new.isAddition()) mstruct_new[mstruct_new.size() - 1].set(mstruct_term); + else mstruct_new.set(mstruct_term); + } else { + if(negated) int_nr.negate(); + if(mstruct_new.isAddition()) mstruct_new[mstruct_new.size() - 1][0].set(int_nr); + else mstruct_new[0].set(int_nr); + mstruct_new.add(mstruct_term, true); + } + } + cleanMessages(mstruct_new, n_messages + 1); + return mstruct_new; + } + return mstruct; +} + +MathStructure Calculator::convert(double value, Unit *from_unit, Unit *to_unit, const EvaluationOptions &eo) { + size_t n_messages = messages.size(); + MathStructure mstruct(value); + mstruct *= from_unit; + mstruct.eval(eo); + if(eo.approximation == APPROXIMATION_EXACT) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_TRY_EXACT; + mstruct.convert(to_unit, true, NULL, false, eo2); + } else { + mstruct.convert(to_unit, true, NULL, false, eo); + } + mstruct.divide(to_unit, true); + mstruct.eval(eo); + cleanMessages(mstruct, n_messages + 1); + return mstruct; + +} +MathStructure Calculator::convert(string str, Unit *from_unit, Unit *to_unit, int msecs, const EvaluationOptions &eo) { + return convertTimeOut(str, from_unit, to_unit, msecs, eo); +} +MathStructure Calculator::convertTimeOut(string str, Unit *from_unit, Unit *to_unit, int msecs, const EvaluationOptions &eo) { + MathStructure mstruct; + parse(&mstruct, str, eo.parse_options); + mstruct *= from_unit; + b_busy = true; + if(!calculate_thread->running && !calculate_thread->start()) return mstruct; + bool had_msecs = msecs > 0; + tmp_evaluationoptions = eo; + tmp_proc_command = PROC_NO_COMMAND; + bool b_parse = false; + if(!calculate_thread->write(b_parse)) {calculate_thread->cancel(); return mstruct;} + void *x = (void*) &mstruct; + if(!calculate_thread->write(x)) {calculate_thread->cancel(); return mstruct;} + while(msecs > 0 && b_busy) { + sleep_ms(10); + msecs -= 10; + } + if(had_msecs && b_busy) { + abort(); + mstruct.setAborted(); + return mstruct; + } + if(eo.approximation == APPROXIMATION_EXACT) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_TRY_EXACT; + mstruct.convert(to_unit, true, NULL, false, eo2); + } else { + mstruct.convert(to_unit, true, NULL, false, eo); + } + mstruct.divide(to_unit, true); + b_busy = true; + if(!calculate_thread->write(b_parse)) {calculate_thread->cancel(); return mstruct;} + x = (void*) &mstruct; + if(!calculate_thread->write(x)) {calculate_thread->cancel(); return mstruct;} + while(msecs > 0 && b_busy) { + sleep_ms(10); + msecs -= 10; + } + if(had_msecs && b_busy) { + abort(); + mstruct.setAborted(); + } + return mstruct; +} +MathStructure Calculator::convert(string str, Unit *from_unit, Unit *to_unit, const EvaluationOptions &eo) { + size_t n_messages = messages.size(); + MathStructure mstruct; + parse(&mstruct, str, eo.parse_options); + mstruct *= from_unit; + mstruct.eval(eo); + if(eo.approximation == APPROXIMATION_EXACT) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_TRY_EXACT; + mstruct.convert(to_unit, true, NULL, false, eo2); + } else { + mstruct.convert(to_unit, true, NULL, false, eo); + } + mstruct.divide(to_unit, true); + mstruct.eval(eo); + cleanMessages(mstruct, n_messages + 1); + return mstruct; +} +MathStructure Calculator::convert(const MathStructure &mstruct, KnownVariable *to_var, const EvaluationOptions &eo) { + if(mstruct.contains(to_var, true) > 0) return mstruct; + size_t n_messages = messages.size(); + if(b_var_units && !to_var->unit().empty() && to_var->isExpression()) { + CompositeUnit cu("", "temporary_composite_convert", "", to_var->unit()); + if(cu.countUnits() > 0) { + AliasUnit au("", "temporary_alias_convert", "", "", "", &cu, to_var->expression()); + bool unc_rel = false; + if(!to_var->uncertainty(&unc_rel).empty()) au.setUncertainty(to_var->uncertainty(), unc_rel); + au.setApproximate(to_var->isApproximate()); + au.setPrecision(to_var->precision()); + MathStructure mstruct_new(convert(mstruct, &au, eo, false, false)); + if(mstruct_new.contains(&au)) { + mstruct_new.replace(&au, to_var); + return mstruct_new; + } + } + } + MathStructure mstruct_new(mstruct); + mstruct_new /= to_var->get(); + mstruct_new.eval(eo); + mstruct_new *= to_var; + cleanMessages(mstruct, n_messages + 1); + return mstruct_new; +} +MathStructure Calculator::convert(const MathStructure &mstruct, Unit *to_unit, const EvaluationOptions &eo, bool always_convert, bool convert_to_mixed_units) { + if(!mstruct.containsType(STRUCT_UNIT, true)) return mstruct; + CompositeUnit *cu = NULL; + if(to_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) cu = (CompositeUnit*) to_unit; + if(cu && cu->countUnits() == 0) return mstruct; + MathStructure mstruct_new(mstruct); + size_t n_messages = messages.size(); + if(to_unit->hasNonlinearRelationTo(to_unit->baseUnit()) && to_unit->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { + mstruct_new = convert(mstruct, to_unit->baseUnit(), eo, always_convert, convert_to_mixed_units); + mstruct_new.calculateDivide(((CompositeUnit*) to_unit->baseUnit())->generateMathStructure(false, eo.keep_prefixes), eo); + to_unit->convertFromBaseUnit(mstruct_new); + mstruct_new.eval(eo); + mstruct_new.multiply(MathStructure(to_unit, eo.keep_prefixes ? decimal_null_prefix : NULL)); + EvaluationOptions eo2 = eo; + eo2.sync_units = false; + eo2.keep_prefixes = true; + mstruct_new.eval(eo2); + cleanMessages(mstruct, n_messages + 1); + return mstruct_new; + } + //bool b_simple = !cu && (to_unit->subtype() != SUBTYPE_ALIAS_UNIT || (((AliasUnit*) to_unit)->baseUnit()->subtype() != SUBTYPE_COMPOSITE_UNIT && ((AliasUnit*) to_unit)->baseExponent() == 1)); + + bool b_changed = false; + if(mstruct_new.isAddition()) { + if(aborted()) return mstruct; + mstruct_new.factorizeUnits(); + if(!b_changed && !mstruct_new.equals(mstruct, true, true)) b_changed = true; + } + + if(!mstruct_new.isPower() && !mstruct_new.isUnit() && !mstruct_new.isMultiplication()) { + if(mstruct_new.size() > 0) { + for(size_t i = 0; i < mstruct_new.size(); i++) { + if(aborted()) return mstruct; + if(!mstruct_new.isFunction() || !mstruct_new.function()->getArgumentDefinition(i + 1) || mstruct_new.function()->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) { + mstruct_new[i] = convert(mstruct_new[i], to_unit, eo, false, convert_to_mixed_units); + if(!b_changed && !mstruct_new.equals(mstruct[i], true, true)) b_changed = true; + } + } + if(b_changed) { + mstruct_new.childrenUpdated(); + EvaluationOptions eo2 = eo; + //eo2.calculate_functions = false; + eo2.sync_units = false; + eo2.keep_prefixes = true; + mstruct_new.eval(eo2); + cleanMessages(mstruct, n_messages + 1); + } + return mstruct_new; + } + } else { + EvaluationOptions eo2 = eo; + eo2.keep_prefixes = true; + bool b = false; + if(eo.approximation == APPROXIMATION_EXACT) eo2.approximation = APPROXIMATION_TRY_EXACT; + if(mstruct_new.convert(to_unit, true, NULL, false, eo2, eo.keep_prefixes ? decimal_null_prefix : NULL) || always_convert) { + b = true; + } else { + CompositeUnit *cu2 = cu; + if(to_unit->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) to_unit)->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { + cu2 = (CompositeUnit*) ((AliasUnit*) to_unit)->baseUnit(); + } + if(cu2) { + switch(mstruct_new.type()) { + case STRUCT_UNIT: { + if(cu2->containsRelativeTo(mstruct_new.unit())) { + b = true; + } + break; + } + case STRUCT_MULTIPLICATION: { + for(size_t i = 1; i <= mstruct_new.countChildren(); i++) { + if(aborted()) return mstruct; + if(mstruct_new.getChild(i)->isUnit() && cu2->containsRelativeTo(mstruct_new.getChild(i)->unit())) { + b = true; + } + if(mstruct_new.getChild(i)->isPower() && mstruct_new.getChild(i)->base()->isUnit() && cu2->containsRelativeTo(mstruct_new.getChild(i)->base()->unit())) { + b = true; + } + } + break; + } + case STRUCT_POWER: { + if(mstruct_new.base()->isUnit() && cu2->containsRelativeTo(mstruct_new.base()->unit())) { + b = true; + } + break; + } + default: {} + } + } + } + if(b) { + eo2.approximation = eo.approximation; + eo2.sync_units = true; + eo2.keep_prefixes = false; + MathStructure mbak(mstruct_new); + mstruct_new.divide(MathStructure(to_unit, NULL)); + mstruct_new.eval(eo2); + if(mstruct_new.containsType(STRUCT_UNIT)) { + mbak.inverse(); + mbak.divide(MathStructure(to_unit, NULL)); + mbak.eval(eo2); + if(!mbak.containsType(STRUCT_UNIT)) mstruct_new = mbak; + } + + if(cu) { + MathStructure mstruct_cu(cu->generateMathStructure(false, eo.keep_prefixes)); + Prefix *p = NULL; + size_t i = 1; + Unit *u = cu->get(i, NULL, &p); + while(u) { + mstruct_new.setPrefixForUnit(u, p); + i++; + u = cu->get(i, NULL, &p); + } + mstruct_new.multiply(mstruct_cu); + } else { + mstruct_new.multiply(MathStructure(to_unit, eo.keep_prefixes ? decimal_null_prefix : NULL)); + } + + eo2.sync_units = false; + eo2.keep_prefixes = true; + mstruct_new.eval(eo2); + + cleanMessages(mstruct, n_messages + 1); + + if(convert_to_mixed_units && eo2.mixed_units_conversion != MIXED_UNITS_CONVERSION_NONE) { + eo2.mixed_units_conversion = MIXED_UNITS_CONVERSION_DOWNWARDS_KEEP; + return convertToMixedUnits(mstruct_new, eo2); + } else { + return mstruct_new; + } + } + } + + return mstruct; + +} +MathStructure Calculator::convertToBaseUnits(const MathStructure &mstruct, const EvaluationOptions &eo) { + if(!mstruct.containsType(STRUCT_UNIT, true)) return mstruct; + size_t n_messages = messages.size(); + MathStructure mstruct_new(mstruct); + mstruct_new.convertToBaseUnits(true, NULL, true, eo); + if(!mstruct_new.equals(mstruct, true, true)) { + EvaluationOptions eo2 = eo; + eo2.approximation = eo.approximation; + eo2.keep_prefixes = false; + eo2.isolate_x = false; + eo2.test_comparisons = false; + //eo2.calculate_functions = false; + mstruct_new.eval(eo2); + cleanMessages(mstruct, n_messages + 1); + } + return mstruct_new; +} +Unit *Calculator::findMatchingUnit(const MathStructure &mstruct) { + switch(mstruct.type()) { + case STRUCT_POWER: { + if(mstruct.base()->isUnit() && mstruct.exponent()->isNumber() && mstruct.exponent()->number().isInteger() && mstruct.exponent()->number() < 10 && mstruct.exponent()->number() > -10) { + Unit *u_base = mstruct.base()->unit(); + int exp = mstruct.exponent()->number().intValue(); + if(u_base->subtype() == SUBTYPE_ALIAS_UNIT) { + u_base = u_base->baseUnit(); + exp *= ((AliasUnit*) u_base)->baseExponent(); + } + for(size_t i = 0; i < units.size(); i++) { + Unit *u = units[i]; + if(u->subtype() == SUBTYPE_ALIAS_UNIT && u->baseUnit() == u_base && ((AliasUnit*) u)->baseExponent() == exp) { + return u; + } + } + CompositeUnit *cu = new CompositeUnit("", "temporary_find_matching_unit"); + cu->add(u_base, exp); + Unit *u = getOptimalUnit(cu); + if(u != cu && !u->isRegistered()) { + delete u; + } else if(u != cu) { + MathStructure mtest(mstruct); + mtest.divide(u); + mtest.eval(); + if(mtest.isNumber()) { + delete cu; + return u; + } + } + delete cu; + } + return findMatchingUnit(mstruct[0]); + } + case STRUCT_UNIT: { + return mstruct.unit(); + } + case STRUCT_MULTIPLICATION: { + if(mstruct.size() == 2 && !mstruct[0].isUnit_exp()) { + return findMatchingUnit(mstruct[1]); + } + CompositeUnit *cu = new CompositeUnit("", "temporary_find_matching_unit"); + for(size_t i = 1; i <= mstruct.countChildren(); i++) { + if(mstruct.getChild(i)->isUnit()) { + cu->add(mstruct.getChild(i)->unit()->baseUnit()); + } else if(mstruct.getChild(i)->isPower() && mstruct.getChild(i)->base()->isUnit() && mstruct.getChild(i)->exponent()->isNumber() && mstruct.getChild(i)->exponent()->number().isInteger()) { + cu->add(mstruct.getChild(i)->base()->unit()->baseUnit(), mstruct.getChild(i)->exponent()->number().intValue()); + } + } + if(cu->countUnits() == 1) { + int exp = 1; + Unit *u_base = cu->get(1, &exp); + if(exp == 1) return u_base; + for(size_t i = 0; i < units.size(); i++) { + Unit *u = units[i]; + if(u->subtype() == SUBTYPE_ALIAS_UNIT && u->baseUnit() == u_base && ((AliasUnit*) u)->baseExponent() == exp) { + return u; + } + } + } + if(cu->countUnits() > 1) { + for(size_t i = 0; i < units.size(); i++) { + Unit *u = units[i]; + if(u->subtype() == SUBTYPE_COMPOSITE_UNIT) { + if(((CompositeUnit*) u)->countUnits() == cu->countUnits()) { + bool b = true; + for(size_t i2 = 1; i2 <= cu->countUnits(); i2++) { + int exp1 = 1, exp2 = 1; + Unit *ui1 = cu->get(i2, &exp1); + b = false; + for(size_t i3 = 1; i3 <= cu->countUnits(); i3++) { + Unit *ui2 = ((CompositeUnit*) u)->get(i3, &exp2); + if(ui1 == ui2->baseUnit()) { + b = (exp1 == exp2); + break; + } + } + if(!b) break; + } + if(b) { + delete cu; + return u; + } + } + } + } + } + Unit *u = getOptimalUnit(cu); + if(u != cu && !u->isRegistered()) { + if(cu->countUnits() > 1 && u->subtype() == SUBTYPE_COMPOSITE_UNIT) { + MathStructure m_u = ((CompositeUnit*) u)->generateMathStructure(); + if(m_u != cu->generateMathStructure()) { + Unit *u2 = findMatchingUnit(m_u); + if(u2) { + MathStructure mtest(mstruct); + mtest.divide(u2); + mtest.eval(); + if(mtest.isNumber()) { + delete cu; + delete u; + return u2; + } + } + } + } + delete u; + } else if(u != cu) { + MathStructure mtest(mstruct); + mtest.divide(u); + mtest.eval(); + if(mtest.isNumber()) { + delete cu; + return u; + } + } + delete cu; + break; + } + default: { + for(size_t i = 0; i < mstruct.size(); i++) { + if(aborted()) return NULL; + if(!mstruct.isFunction() || !mstruct.function()->getArgumentDefinition(i + 1) || mstruct.function()->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) { + Unit *u = findMatchingUnit(mstruct[i]); + if(u) return u; + } + } + break; + } + } + return NULL; +} +Unit *Calculator::getBestUnit(Unit *u, bool allow_only_div, bool convert_to_local_currency) {return getOptimalUnit(u, allow_only_div, convert_to_local_currency);} +Unit *Calculator::getOptimalUnit(Unit *u, bool allow_only_div, bool convert_to_local_currency) { + switch(u->subtype()) { + case SUBTYPE_BASE_UNIT: { + if(convert_to_local_currency && u->isCurrency()) { + Unit *u_local_currency = getLocalCurrency(); + if(u_local_currency) return u_local_currency; + } + return u; + } + case SUBTYPE_ALIAS_UNIT: { + AliasUnit *au = (AliasUnit*) u; + if(au->baseExponent() == 1 && au->baseUnit()->subtype() == SUBTYPE_BASE_UNIT) { + if(au->isCurrency()) { + if(!convert_to_local_currency) return u; + Unit *u_local_currency = getLocalCurrency(); + if(u_local_currency) return u_local_currency; + } + return (Unit*) au->baseUnit(); + } else if(au->isSIUnit() && (au->firstBaseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT || au->firstBaseExponent() != 1)) { + return u; + } else { + return getOptimalUnit((Unit*) au->firstBaseUnit()); + } + } + case SUBTYPE_COMPOSITE_UNIT: { + CompositeUnit *cu = (CompositeUnit*) u; + int exp, b_exp; + int points = 0; + bool minus = false; + bool has_positive = false; + int new_points; + int new_points_m; + int max_points = 0; + for(size_t i = 1; i <= cu->countUnits(); i++) { + cu->get(i, &exp); + if(exp < 0) { + max_points -= exp; + } else { + max_points += exp; + has_positive = true; + } + } + for(size_t i = 0; i < units.size(); i++) { + if(units[i]->subtype() == SUBTYPE_COMPOSITE_UNIT) { + CompositeUnit *cu2 = (CompositeUnit*) units[i]; + if(cu == cu2 && !cu2->isHidden()) { + points = max_points - 1; + } else if(!cu2->isHidden() && cu2->isSIUnit() && cu2->countUnits() == cu->countUnits()) { + bool b_match = true; + for(size_t i2 = 1; i2 <= cu->countUnits(); i2++) { + int exp2; + if(cu->get(i2, &exp) != cu2->get(i2, &exp2) || exp != exp2) { + b_match = false; + break; + } + } + if(b_match) { + points = max_points - 1; + break; + } + } + } + } + Unit *best_u = NULL; + Unit *bu, *u2; + AliasUnit *au; + for(size_t i = 0; i < units.size(); i++) { + u2 = units[i]; + if(u2->subtype() == SUBTYPE_BASE_UNIT && (points == 0 || (points == 1 && minus))) { + for(size_t i2 = 1; i2 <= cu->countUnits(); i2++) { + if(cu->get(i2, &exp)->baseUnit() == u2 && !cu->get(i2)->hasNonlinearRelationTo(u2)) { + points = 1; + best_u = u2; + minus = !has_positive && (exp < 0); + break; + } + } + } else if(!u2->isSIUnit()) { + } else if(u2->subtype() == SUBTYPE_ALIAS_UNIT) { + au = (AliasUnit*) u2; + bu = (Unit*) au->baseUnit(); + b_exp = au->baseExponent(); + new_points = 0; + new_points_m = 0; + if((b_exp != 1 || bu->subtype() == SUBTYPE_COMPOSITE_UNIT) && !au->hasNonlinearRelationTo(bu)) { + if(bu->subtype() == SUBTYPE_BASE_UNIT) { + for(size_t i2 = 1; i2 <= cu->countUnits(); i2++) { + if(cu->get(i2, &exp) == bu) { + bool m = false; + if(b_exp < 0 && exp < 0) { + b_exp = -b_exp; + exp = -exp; + } else if(b_exp < 0) { + b_exp = -b_exp; + m = true; + } else if(exp < 0) { + exp = -exp; + m = true; + } + new_points = exp - b_exp; + if(new_points < 0) { + new_points = -new_points; + } + new_points = exp - new_points; + if(!allow_only_div && m && new_points >= max_points) { + new_points = -1; + } + if(new_points > points || (!m && minus && new_points == points)) { + points = new_points; + minus = m; + best_u = au; + } + break; + } + } + } else if(au->firstBaseExponent() != 1 || au->firstBaseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { + MathStructure cu_mstruct = ((CompositeUnit*) bu)->generateMathStructure(); + if(b_exp != 1) { + if(cu_mstruct.isMultiplication()) { + for(size_t i2 = 0; i2 < cu_mstruct.size(); i2++) { + if(cu_mstruct[i2].isPower()) cu_mstruct[i2][1].number() *= b_exp; + else cu_mstruct[i2].raise(b_exp); + } + } else if(cu_mstruct.isPower()) { + cu_mstruct[1].number() *= b_exp; + } else { + cu_mstruct.raise(b_exp); + } + } + cu_mstruct = convertToBaseUnits(cu_mstruct); + if(cu_mstruct.isMultiplication()) { + for(size_t i2 = 1; i2 <= cu_mstruct.countChildren(); i2++) { + bu = NULL; + if(cu_mstruct.getChild(i2)->isUnit()) { + bu = cu_mstruct.getChild(i2)->unit(); + b_exp = 1; + } else if(cu_mstruct.getChild(i2)->isPower() && cu_mstruct.getChild(i2)->base()->isUnit() && cu_mstruct.getChild(i2)->exponent()->isNumber() && cu_mstruct.getChild(i2)->exponent()->number().isInteger()) { + bu = cu_mstruct.getChild(i2)->base()->unit(); + b_exp = cu_mstruct.getChild(i2)->exponent()->number().intValue(); + } + if(bu) { + bool b = false; + for(size_t i3 = 1; i3 <= cu->countUnits(); i3++) { + if(cu->get(i3, &exp) == bu) { + b = true; + bool m = false; + if(exp < 0 && b_exp > 0) { + new_points -= b_exp; + exp = -exp; + m = true; + } else if(exp > 0 && b_exp < 0) { + new_points += b_exp; + b_exp = -b_exp; + m = true; + } else { + if(b_exp < 0) new_points_m += b_exp; + else new_points_m -= b_exp; + } + if(exp < 0) { + exp = -exp; + b_exp = -b_exp; + } + if(exp >= b_exp) { + if(m) new_points_m += exp - (exp - b_exp); + else new_points += exp - (exp - b_exp); + } else { + if(m) new_points_m += exp - (b_exp - exp); + else new_points += exp - (b_exp - exp); + } + break; + } + } + if(!b) { + if(b_exp < 0) b_exp = -b_exp; + new_points -= b_exp; + new_points_m -= b_exp; + } + } + } + if(!allow_only_div && new_points_m >= max_points) { + new_points_m = -1; + } + if(new_points > points && new_points >= new_points_m) { + minus = false; + points = new_points; + best_u = au; + } else if(new_points_m > points || (new_points_m == points && minus)) { + minus = true; + points = new_points_m; + best_u = au; + } + } + } + } + } + if(points >= max_points && !minus) break; + } + if(!best_u) return u; + best_u = getOptimalUnit(best_u, false, convert_to_local_currency); + if(points > 1 && points < max_points - 1) { + CompositeUnit *cu_new = new CompositeUnit("", "temporary_composite_convert"); + bool return_cu = minus; + if(minus) { + cu_new->add(best_u, -1); + } else { + cu_new->add(best_u); + } + MathStructure cu_mstruct = ((CompositeUnit*) u)->generateMathStructure(); + if(minus) cu_mstruct *= best_u; + else cu_mstruct /= best_u; + cu_mstruct = convertToBaseUnits(cu_mstruct); + CompositeUnit *cu2 = new CompositeUnit("", "temporary_composite_convert_to_optimal_unit"); + bool b = false; + for(size_t i = 1; i <= cu_mstruct.countChildren(); i++) { + if(cu_mstruct.getChild(i)->isUnit()) { + b = true; + cu2->add(cu_mstruct.getChild(i)->unit()); + } else if(cu_mstruct.getChild(i)->isPower() && cu_mstruct.getChild(i)->base()->isUnit() && cu_mstruct.getChild(i)->exponent()->isNumber() && cu_mstruct.getChild(i)->exponent()->number().isInteger()) { + if(cu_mstruct.getChild(i)->exponent()->number().isGreaterThan(10) || cu_mstruct.getChild(i)->exponent()->number().isLessThan(-10)) { + if(aborted() || cu_mstruct.getChild(i)->exponent()->number().isGreaterThan(1000) || cu_mstruct.getChild(i)->exponent()->number().isLessThan(-1000)) { + b = false; + break; + } + } + b = true; + cu2->add(cu_mstruct.getChild(i)->base()->unit(), cu_mstruct.getChild(i)->exponent()->number().intValue()); + } + } + if(b) { + Unit *u2 = getOptimalUnit(cu2, true, convert_to_local_currency); + b = false; + if(u2->subtype() == SUBTYPE_COMPOSITE_UNIT) { + for(size_t i3 = 1; i3 <= ((CompositeUnit*) u2)->countUnits(); i3++) { + Unit *cu_unit = ((CompositeUnit*) u2)->get(i3, &exp); + for(size_t i4 = 1; i4 <= cu_new->countUnits(); i4++) { + if(cu_new->get(i4, &b_exp) == cu_unit) { + b = true; + cu_new->setExponent(i4, b_exp + exp); + break; + } + } + if(!b) cu_new->add(cu_unit, exp); + } + return_cu = true; + } else if(u2->subtype() == SUBTYPE_ALIAS_UNIT) { + return_cu = true; + for(size_t i3 = 1; i3 <= cu_new->countUnits(); i3++) { + if(cu_new->get(i3, &exp) == u2) { + b = true; + cu_new->setExponent(i3, exp + 1); + break; + } + } + if(!b) cu_new->add(u2); + } + if(!u2->isRegistered() && u2 != cu2) delete u2; + } + delete cu2; + if(return_cu) { + return cu_new; + } else { + delete cu_new; + return best_u; + } + } + if(minus) { + CompositeUnit *cu_new = new CompositeUnit("", "temporary_composite_convert"); + cu_new->add(best_u, -1); + return cu_new; + } else { + return best_u; + } + } + } + return u; +} +MathStructure Calculator::convertToBestUnit(const MathStructure &mstruct, const EvaluationOptions &eo, bool convert_to_si_units) {return convertToOptimalUnit(mstruct, eo, convert_to_si_units);} +MathStructure Calculator::convertToOptimalUnit(const MathStructure &mstruct, const EvaluationOptions &eo, bool convert_to_si_units) { + EvaluationOptions eo2 = eo; + //eo2.calculate_functions = false; + eo2.sync_units = false; + eo2.isolate_x = false; + eo2.test_comparisons = false; + switch(mstruct.type()) { + case STRUCT_POWER: { + if(mstruct.base()->isUnit() && mstruct.exponent()->isNumber() && mstruct.exponent()->number().isRational() && !mstruct.exponent()->number().isZero()) { + MathStructure mstruct_new(mstruct); + int old_points = 0; + bool overflow = false; + if(mstruct_new.exponent()->isInteger()) old_points = mstruct_new.exponent()->number().intValue(&overflow); + else old_points = mstruct_new.exponent()->number().numerator().intValue(&overflow) + mstruct_new.exponent()->number().denominator().intValue() * (mstruct_new.exponent()->number().isNegative() ? -1 : 1); + if(overflow) return mstruct_new; + bool old_minus = false; + if(old_points < 0) { + old_points = -old_points; + old_minus = true; + } + bool is_si_units = mstruct_new.base()->unit()->isSIUnit(); + if(mstruct_new.base()->unit()->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { + mstruct_new.convertToBaseUnits(true, NULL, true, eo2, true); + if(mstruct_new.equals(mstruct, true, true)) { + return mstruct_new; + } else { + mstruct_new.eval(eo2); + } + mstruct_new = convertToOptimalUnit(mstruct_new, eo, convert_to_si_units); + if(mstruct_new.equals(mstruct, true, true)) return mstruct_new; + } else { + CompositeUnit *cu = new CompositeUnit("", "temporary_composite_convert_to_optimal_unit"); + cu->add(mstruct_new.base()->unit(), mstruct_new.exponent()->number().numerator().intValue()); + Unit *u = getOptimalUnit(cu, false, eo.local_currency_conversion); + if(u == cu) { + delete cu; + return mstruct_new; + } + if(eo.approximation == APPROXIMATION_EXACT && cu->hasApproximateRelationTo(u, true)) { + if(!u->isRegistered()) delete u; + delete cu; + return mstruct_new; + } + delete cu; + mstruct_new = convert(mstruct_new, u, eo, true); + if(!u->isRegistered()) delete u; + } + int new_points = 0; + bool new_is_si_units = true; + bool new_minus = true; + bool is_currency = false; + if(mstruct_new.isMultiplication()) { + for(size_t i = 1; i <= mstruct_new.countChildren(); i++) { + if(mstruct_new.getChild(i)->isUnit()) { + if(new_is_si_units && !mstruct_new.getChild(i)->unit()->isSIUnit()) new_is_si_units = false; + is_currency = mstruct_new.getChild(i)->unit()->isCurrency(); + new_points++; + new_minus = false; + } else if(mstruct_new.getChild(i)->isPower() && mstruct_new.getChild(i)->base()->isUnit() && mstruct_new.getChild(i)->exponent()->isNumber() && mstruct_new.getChild(i)->exponent()->number().isRational()) { + int points = 0; + if(mstruct_new.getChild(i)->exponent()->isInteger()) points = mstruct_new.getChild(i)->exponent()->number().intValue(); + else points = mstruct_new.getChild(i)->exponent()->number().numerator().intValue() + mstruct_new.getChild(i)->exponent()->number().denominator().intValue() * (mstruct_new.getChild(i)->exponent()->number().isNegative() ? -1 : 1); + if(new_is_si_units && !mstruct_new.getChild(i)->base()->unit()->isSIUnit()) new_is_si_units = false; + is_currency = mstruct_new.getChild(i)->base()->unit()->isCurrency(); + if(points < 0) { + new_points -= points; + } else { + new_points += points; + new_minus = false; + } + + } + } + } else if(mstruct_new.isPower() && mstruct_new.base()->isUnit() && mstruct_new.exponent()->isNumber() && mstruct_new.exponent()->number().isRational()) { + int points = 0; + if(mstruct_new.exponent()->isInteger()) points = mstruct_new.exponent()->number().intValue(); + else points = mstruct_new.exponent()->number().numerator().intValue() + mstruct_new.exponent()->number().denominator().intValue() * (mstruct_new.exponent()->number().isNegative() ? -1 : 1); + if(new_is_si_units && !mstruct_new.base()->unit()->isSIUnit()) new_is_si_units = false; + is_currency = mstruct_new.base()->unit()->isCurrency(); + if(points < 0) { + new_points = -points; + } else { + new_points = points; + new_minus = false; + } + } else if(mstruct_new.isUnit()) { + if(!mstruct_new.unit()->isSIUnit()) new_is_si_units = false; + is_currency = mstruct_new.unit()->isCurrency(); + new_points = 1; + new_minus = false; + } + if(new_points == 0) return mstruct; + if((new_points > old_points && (!convert_to_si_units || is_si_units || !new_is_si_units)) || (new_points == old_points && (new_minus || !old_minus) && (!is_currency || !eo.local_currency_conversion) && (!convert_to_si_units || !new_is_si_units))) return mstruct; + return mstruct_new; + } + } + case STRUCT_BITWISE_XOR: {} + case STRUCT_BITWISE_OR: {} + case STRUCT_BITWISE_AND: {} + case STRUCT_BITWISE_NOT: {} + case STRUCT_LOGICAL_XOR: {} + case STRUCT_LOGICAL_OR: {} + case STRUCT_LOGICAL_AND: {} + case STRUCT_LOGICAL_NOT: {} + case STRUCT_COMPARISON: {} + case STRUCT_FUNCTION: {} + case STRUCT_VECTOR: {} + case STRUCT_ADDITION: { + if(!mstruct.containsType(STRUCT_UNIT, true)) return mstruct; + MathStructure mstruct_new(mstruct); + bool b = false; + for(size_t i = 0; i < mstruct_new.size(); i++) { + if(aborted()) return mstruct; + if(!mstruct_new.isFunction() || !mstruct_new.function()->getArgumentDefinition(i + 1) || mstruct_new.function()->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) { + mstruct_new[i] = convertToOptimalUnit(mstruct_new[i], eo, convert_to_si_units); + if(!b && !mstruct_new[i].equals(mstruct[i], true, true)) b = true; + } + } + if(b) { + mstruct_new.childrenUpdated(); + if(mstruct.isAddition()) mstruct_new.eval(eo2); + } + return mstruct_new; + } + case STRUCT_UNIT: { + if((!mstruct.unit()->isCurrency() || !eo.local_currency_conversion) && (!convert_to_si_units || mstruct.unit()->isSIUnit())) return mstruct; + Unit *u = getOptimalUnit(mstruct.unit(), false, eo.local_currency_conversion); + if(u != mstruct.unit()) { + if((u->isSIUnit() || (u->isCurrency() && eo.local_currency_conversion)) && (eo.approximation != APPROXIMATION_EXACT || !mstruct.unit()->hasApproximateRelationTo(u, true))) { + MathStructure mstruct_new = convert(mstruct, u, eo, true); + if(!u->isRegistered()) delete u; + return mstruct_new; + } + if(!u->isRegistered()) delete u; + } + break; + } + case STRUCT_MULTIPLICATION: { + if(!mstruct.containsType(STRUCT_UNIT, true)) return mstruct; + int old_points = 0; + bool old_minus = true; + bool is_si_units = true; + bool is_currency = false; + bool child_updated = false; + MathStructure mstruct_old(mstruct); + for(size_t i = 1; i <= mstruct_old.countChildren(); i++) { + if(aborted()) return mstruct_old; + if(mstruct_old.getChild(i)->isUnit()) { + if(is_si_units && !mstruct_old.getChild(i)->unit()->isSIUnit()) is_si_units = false; + is_currency = mstruct_old.getChild(i)->unit()->isCurrency(); + old_points++; + old_minus = false; + } else if(mstruct_old.getChild(i)->isPower() && mstruct_old.getChild(i)->base()->isUnit() && mstruct_old.getChild(i)->exponent()->isNumber() && mstruct_old.getChild(i)->exponent()->number().isRational()) { + int points = 0; + if(mstruct_old.getChild(i)->exponent()->number().isInteger()) points = mstruct_old.getChild(i)->exponent()->number().intValue(); + else points = mstruct_old.getChild(i)->exponent()->number().numerator().intValue() + mstruct_old.getChild(i)->exponent()->number().denominator().intValue() * (mstruct_old.getChild(i)->exponent()->number().isNegative() ? -1 : 1);; + if(is_si_units && !mstruct_old.getChild(i)->base()->unit()->isSIUnit()) is_si_units = false; + is_currency = mstruct_old.getChild(i)->base()->unit()->isCurrency(); + if(points < 0) { + old_points -= points; + } else { + old_points += points; + old_minus = false; + } + } else if(mstruct_old.getChild(i)->size() > 0 && !aborted()) { + mstruct_old[i - 1] = convertToOptimalUnit(mstruct_old[i - 1], eo, convert_to_si_units); + mstruct_old.childUpdated(i); + if(!mstruct_old[i - 1].equals(mstruct[i - 1], true, true)) child_updated = true; + } + } + if(child_updated) mstruct_old.eval(eo2); + if((!is_currency || !eo.local_currency_conversion) && (!convert_to_si_units || is_si_units) && old_points <= 1 && !old_minus) { + return mstruct_old; + } + MathStructure mstruct_new(mstruct_old); + mstruct_new.convertToBaseUnits(true, NULL, true, eo2, true); + if(!mstruct_new.equals(mstruct, true, true)) { + mstruct_new.eval(eo2); + } + if(mstruct_new.type() != STRUCT_MULTIPLICATION) { + if(!mstruct_new.containsInterval(true, true, false, 1, true) && !aborted()) mstruct_new = convertToOptimalUnit(mstruct_new, eo, convert_to_si_units); + } else { + CompositeUnit *cu = new CompositeUnit("", "temporary_composite_convert_to_optimal_unit"); + bool b = false; + child_updated = false; + for(size_t i = 1; i <= mstruct_new.countChildren(); i++) { + if(aborted()) return mstruct_old; + if(mstruct_new.getChild(i)->isUnit()) { + b = true; + cu->add(mstruct_new.getChild(i)->unit()); + } else if(mstruct_new.getChild(i)->isPower() && mstruct_new.getChild(i)->base()->isUnit() && mstruct_new.getChild(i)->exponent()->isNumber() && mstruct_new.getChild(i)->exponent()->number().isInteger()) { + b = true; + cu->add(mstruct_new.getChild(i)->base()->unit(), mstruct_new.getChild(i)->exponent()->number().intValue()); + } else if(mstruct_new.getChild(i)->size() > 0 && !mstruct_new.getChild(i)->containsInterval(true, true, false, 1, true) && !aborted()) { + MathStructure m_i_old(mstruct_new[i - 1]); + mstruct_new[i - 1] = convertToOptimalUnit(mstruct_new[i - 1], eo, convert_to_si_units); + mstruct_new.childUpdated(i); + if(!mstruct_new[i - 1].equals(m_i_old, true, true)) child_updated = true; + } + } + bool is_converted = false; + if(b) { + Unit *u = getOptimalUnit(cu, false, eo.local_currency_conversion); + if(u != cu) { + if(eo.approximation != APPROXIMATION_EXACT || !cu->hasApproximateRelationTo(u, true)) { + mstruct_new = convert(mstruct_new, u, eo, true); + is_converted = true; + } + if(!u->isRegistered()) delete u; + } + } + delete cu; + if((!b || !is_converted) && (!convert_to_si_units || is_si_units)) { + return mstruct_old; + } + if(child_updated) mstruct_new.eval(eo2); + } + if((eo.approximation == APPROXIMATION_EXACT && !mstruct_old.isApproximate()) && (mstruct_new.isApproximate() || (mstruct_old.containsInterval(true, true, false, 0, true) <= 0 && mstruct_new.containsInterval(true, true, false, 0, true) > 0))) return mstruct_old; + if(mstruct_new.equals(mstruct_old, true, true)) return mstruct_old; + int new_points = 0; + bool new_minus = true; + bool new_is_si_units = true; + bool new_is_currency = false; + if(mstruct_new.isMultiplication()) { + for(size_t i = 1; i <= mstruct_new.countChildren(); i++) { + if(aborted()) return mstruct_old; + if(mstruct_new.getChild(i)->isUnit()) { + if(new_is_si_units && !mstruct_new.getChild(i)->unit()->isSIUnit()) new_is_si_units = false; + new_is_currency = mstruct_new.getChild(i)->unit()->isCurrency(); + new_points++; + new_minus = false; + } else if(mstruct_new.getChild(i)->isPower() && mstruct_new.getChild(i)->base()->isUnit() && mstruct_new.getChild(i)->exponent()->isNumber() && mstruct_new.getChild(i)->exponent()->number().isRational()) { + int points = 0; + if(mstruct_new.getChild(i)->exponent()->number().isInteger()) points = mstruct_new.getChild(i)->exponent()->number().intValue(); + else points = mstruct_new.getChild(i)->exponent()->number().numerator().intValue() + mstruct_new.getChild(i)->exponent()->number().denominator().intValue() * (mstruct_new.getChild(i)->exponent()->number().isNegative() ? -1 : 1); + if(new_is_si_units && !mstruct_new.getChild(i)->base()->unit()->isSIUnit()) new_is_si_units = false; + new_is_currency = mstruct_new.getChild(i)->base()->unit()->isCurrency(); + if(points < 0) { + new_points -= points; + } else { + new_points += points; + new_minus = false; + } + } + } + } else if(mstruct_new.isPower() && mstruct_new.base()->isUnit() && mstruct_new.exponent()->isNumber() && mstruct_new.exponent()->number().isRational()) { + int points = 0; + if(mstruct_new.exponent()->number().isInteger()) points = mstruct_new.exponent()->number().intValue(); + else points = mstruct_new.exponent()->number().numerator().intValue() + mstruct_new.exponent()->number().denominator().intValue() * (mstruct_new.exponent()->number().isNegative() ? -1 : 1); + if(new_is_si_units && !mstruct_new.base()->unit()->isSIUnit()) new_is_si_units = false; + new_is_currency = mstruct_new.base()->unit()->isCurrency(); + if(points < 0) { + new_points = -points; + } else { + new_points = points; + new_minus = false; + } + } else if(mstruct_new.isUnit()) { + if(!mstruct_new.unit()->isSIUnit()) new_is_si_units = false; + new_is_currency = mstruct_new.unit()->isCurrency(); + new_points = 1; + new_minus = false; + } + if(new_points == 0) return mstruct_old; + if((new_points > old_points && (!convert_to_si_units || is_si_units || !new_is_si_units)) || (new_points == old_points && (new_minus || !old_minus) && (!new_is_currency || !eo.local_currency_conversion) && (!convert_to_si_units || !new_is_si_units))) return mstruct_old; + return mstruct_new; + } + default: {} + } + return mstruct; +} +MathStructure Calculator::convertToCompositeUnit(const MathStructure &mstruct, CompositeUnit *cu, const EvaluationOptions &eo, bool always_convert) { + return convert(mstruct, cu, eo, always_convert); +} +MathStructure Calculator::convert(const MathStructure &mstruct_to_convert, string str2, const EvaluationOptions &eo, MathStructure *to_struct) { + if(to_struct) to_struct->setUndefined(); + remove_blank_ends(str2); + if(str2.empty()) return mstruct_to_convert; + current_stage = MESSAGE_STAGE_CONVERSION; + int do_prefix = 0; + if(str2.length() > 1 && str2[1] == '?' && (str2[0] == 'b' || str2[0] == 'a' || str2[0] == 'd')) { + do_prefix = 2; + } else if(str2[0] == '?') { + do_prefix = 1; + } + EvaluationOptions eo2 = eo; + eo2.keep_prefixes = !do_prefix; + if(str2[0] == '-') eo2.mixed_units_conversion = MIXED_UNITS_CONVERSION_NONE; + else if(str2[0] == '+') eo2.mixed_units_conversion = MIXED_UNITS_CONVERSION_FORCE_INTEGER; + else if(eo2.mixed_units_conversion != MIXED_UNITS_CONVERSION_NONE) eo2.mixed_units_conversion = MIXED_UNITS_CONVERSION_DOWNWARDS_KEEP; + if(do_prefix || str2[0] == '0' || str2[0] == '+' || str2[0] == '-') { + str2 = str2.substr(do_prefix > 1 ? 2 : 1, str2.length() - (do_prefix > 1 ? 2 : 1)); + remove_blank_ends(str2); + if(str2.empty()) { + current_stage = MESSAGE_STAGE_UNSET; + return convertToMixedUnits(mstruct_to_convert, eo2); + } + } + MathStructure mstruct; + bool b = false; + Unit *u = getUnit(str2); + if(!u) u = getCompositeUnit(str2); + Variable *v = NULL; + if(!u) v = getVariable(str2); + if(!u && !v) { + for(size_t i = 0; i < signs.size(); i++) { + if(str2 == signs[i]) { + u = getUnit(real_signs[i]); + if(!u) v = getVariable(real_signs[i]); + break; + } + } + } + if(v && !v->isKnown()) v = NULL; + if(u) { + if(to_struct) to_struct->set(u); + mstruct.set(convert(mstruct_to_convert, u, eo2, false, false)); + b = true; + } else if(v) { + if(to_struct) to_struct->set(v); + mstruct.set(convert(mstruct_to_convert, (KnownVariable*) v, eo2)); + b = true; + } else { + current_stage = MESSAGE_STAGE_CONVERSION_PARSING; + CompositeUnit cu("", "temporary_composite_convert", "", str2); + if(cu.countUnits() == 2 && cu.get(1)->referenceName() == "g" && cu.get(2)->referenceName() == "m" && str2.substr(0, 2) == "kg") { + int exp; Prefix *p; + if(cu.get(1, &exp, &p) && exp == 1 && p && p->value() == 1000 && cu.get(2, &exp, &p) && exp == -2) { + Unit *u = getUnit("pond"); + if(u) { + MathStructure mtest(convertToBaseUnits(mstruct_to_convert, eo)); + mtest.sort(); + if(mtest.isMultiplication() && mtest.size() >= 3 && mtest[mtest.size() - 3].isUnit() && mtest[mtest.size() - 3].unit()->referenceName() == "g" && mtest[mtest.size() - 2].isPower() && mtest[mtest.size() - 2][1].isMinusOne() && mtest[mtest.size() - 2][0].isUnit() && mtest[mtest.size() - 2][0].unit()->referenceName() == "m" && mtest[mtest.size() - 1].isPower() && mtest[mtest.size() - 1][1] == Number(-2, 1) && mtest[mtest.size() - 1][0].isUnit() && mtest[mtest.size() - 1][0].unit()->referenceName() == "s") { + str2.replace(1, 2, "pond"); + cu.setBaseExpression(str2); + } + } + } + } + current_stage = MESSAGE_STAGE_CONVERSION; + if(to_struct) to_struct->set(cu.generateMathStructure()); + if(cu.countUnits() > 0) { + mstruct.set(convert(mstruct_to_convert, &cu, eo2, false, false)); + b = true; + } + } + if(!b) return mstruct_to_convert; + if(!v && eo2.mixed_units_conversion != MIXED_UNITS_CONVERSION_NONE) mstruct.set(convertToMixedUnits(mstruct, eo2)); + current_stage = MESSAGE_STAGE_UNSET; + return mstruct; +} + diff -Nru libqalculate-3.6.0/libqalculate/Calculator-definitions.cc libqalculate-3.7.0/libqalculate/Calculator-definitions.cc --- libqalculate-3.6.0/libqalculate/Calculator-definitions.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Calculator-definitions.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,3775 @@ +/* + Qalculate + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Unit.h" +#include "Variable.h" +#include "Function.h" +#include "DataSet.h" +#include "ExpressionItem.h" +#include "Prefix.h" +#include "Number.h" +#include "QalculateDateTime.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "MathStructure-support.h" + +#ifdef HAVE_LIBCURL +# include +#endif + +using std::string; +using std::cout; +using std::vector; +using std::ostream; +using std::ofstream; +using std::endl; +using std::ios; +using std::ifstream; +using std::iterator; +using std::list; +using std::queue; + +#include "Calculator_p.h" + +#define XML_GET_PREC_FROM_PROP(node, i) value = xmlGetProp(node, (xmlChar*) "precision"); if(value) {i = s2i((char*) value); xmlFree(value);} else {i = -1;} +#define XML_GET_APPROX_FROM_PROP(node, b) value = xmlGetProp(node, (xmlChar*) "approximate"); if(value) {b = !xmlStrcmp(value, (const xmlChar*) "true");} else {value = xmlGetProp(node, (xmlChar*) "precise"); if(value) {b = xmlStrcmp(value, (const xmlChar*) "true");} else {b = false;}} if(value) xmlFree(value); +#define XML_GET_FALSE_FROM_PROP(node, name, b) value = xmlGetProp(node, (xmlChar*) name); if(value && !xmlStrcmp(value, (const xmlChar*) "false")) {b = false;} else {b = true;} if(value) xmlFree(value); +#define XML_GET_TRUE_FROM_PROP(node, name, b) value = xmlGetProp(node, (xmlChar*) name); if(value && !xmlStrcmp(value, (const xmlChar*) "true")) {b = true;} else {b = false;} if(value) xmlFree(value); +#define XML_GET_BOOL_FROM_PROP(node, name, b) value = xmlGetProp(node, (xmlChar*) name); if(value && !xmlStrcmp(value, (const xmlChar*) "false")) {b = false;} else if(value && !xmlStrcmp(value, (const xmlChar*) "true")) {b = true;} if(value) xmlFree(value); +#define XML_GET_FALSE_FROM_TEXT(node, b) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if(value && !xmlStrcmp(value, (const xmlChar*) "false")) {b = false;} else {b = true;} if(value) xmlFree(value); +#define XML_GET_TRUE_FROM_TEXT(node, b) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if(value && !xmlStrcmp(value, (const xmlChar*) "true")) {b = true;} else {b = false;} if(value) xmlFree(value); +#define XML_GET_BOOL_FROM_TEXT(node, b) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if(value && !xmlStrcmp(value, (const xmlChar*) "false")) {b = false;} else if(value && !xmlStrcmp(value, (const xmlChar*) "true")) {b = true;} if(value) xmlFree(value); +#define XML_GET_STRING_FROM_PROP(node, name, str) value = xmlGetProp(node, (xmlChar*) name); if(value) {str = (char*) value; remove_blank_ends(str); xmlFree(value);} else str = ""; +#define XML_GET_STRING_FROM_TEXT(node, str) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if(value) {str = (char*) value; remove_blank_ends(str); xmlFree(value);} else str = ""; +#define XML_DO_FROM_PROP(node, name, action) value = xmlGetProp(node, (xmlChar*) name); if(value) action((char*) value); else action(""); if(value) xmlFree(value); +#define XML_DO_FROM_TEXT(node, action) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if(value) {action((char*) value); xmlFree(value);} else action(""); +#define XML_GET_INT_FROM_PROP(node, name, i) value = xmlGetProp(node, (xmlChar*) name); if(value) {i = s2i((char*) value); xmlFree(value);} +#define XML_GET_INT_FROM_TEXT(node, i) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if(value) {i = s2i((char*) value); xmlFree(value);} +#define XML_GET_LOCALE_STRING_FROM_TEXT(node, str, best, next_best) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); lang = xmlNodeGetLang(node); if(!best) {if(!lang) {if(!next_best) {if(value) {str = (char*) value; remove_blank_ends(str);} else str = ""; if(locale.empty()) {best = true;}}} else {if(locale == (char*) lang) {best = true; if(value) {str = (char*) value; remove_blank_ends(str);} else str = "";} else if(!next_best && strlen((char*) lang) >= 2 && fulfilled_translation == 0 && lang[0] == localebase[0] && lang[1] == localebase[1]) {next_best = true; if(value) {str = (char*) value; remove_blank_ends(str);} else str = "";} else if(!next_best && str.empty() && value) {str = (char*) value; remove_blank_ends(str);}}} if(value) xmlFree(value); if(lang) xmlFree(lang); +#define XML_GET_LOCALE_STRING_FROM_TEXT_REQ(node, str, best, next_best) value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); lang = xmlNodeGetLang(node); if(!best) {if(!lang) {if(!next_best) {if(value) {str = (char*) value; remove_blank_ends(str);} else str = ""; if(locale.empty()) {best = true;}}} else {if(locale == (char*) lang) {best = true; if(value) {str = (char*) value; remove_blank_ends(str);} else str = "";} else if(!next_best && strlen((char*) lang) >= 2 && fulfilled_translation == 0 && lang[0] == localebase[0] && lang[1] == localebase[1]) {next_best = true; if(value) {str = (char*) value; remove_blank_ends(str);} else str = "";} else if(!next_best && str.empty() && value && !require_translation) {str = (char*) value; remove_blank_ends(str);}}} if(value) xmlFree(value); if(lang) xmlFree(lang); + +#define VERSION_BEFORE(i1, i2, i3) (version_numbers[0] < i1 || (version_numbers[0] == i1 && (version_numbers[1] < i2 || (version_numbers[1] == i2 && version_numbers[2] < i3)))) + +bool Calculator::loadGlobalDefinitions() { + bool b = true; + if(!loadDefinitions(buildPath(getGlobalDefinitionsDir(), "prefixes.xml").c_str(), false)) b = false; + if(!loadDefinitions(buildPath(getGlobalDefinitionsDir(), "currencies.xml").c_str(), false)) b = false; + if(!loadDefinitions(buildPath(getGlobalDefinitionsDir(), "units.xml").c_str(), false)) b = false; + if(!loadDefinitions(buildPath(getGlobalDefinitionsDir(), "functions.xml").c_str(), false)) b = false; + if(!loadDefinitions(buildPath(getGlobalDefinitionsDir(), "datasets.xml").c_str(), false)) b = false; + if(!loadDefinitions(buildPath(getGlobalDefinitionsDir(), "variables.xml").c_str(), false)) b = false; + return b; +} +bool Calculator::loadGlobalDefinitions(string filename) { + return loadDefinitions(buildPath(getGlobalDefinitionsDir(), filename).c_str(), false); +} +bool Calculator::loadGlobalPrefixes() { + return loadGlobalDefinitions("prefixes.xml"); +} +bool Calculator::loadGlobalCurrencies() { + return loadGlobalDefinitions("currencies.xml"); +} +bool Calculator::loadGlobalUnits() { + bool b = loadGlobalDefinitions("currencies.xml"); + return loadGlobalDefinitions("units.xml") && b; +} +bool Calculator::loadGlobalVariables() { + return loadGlobalDefinitions("variables.xml"); +} +bool Calculator::loadGlobalFunctions() { + return loadGlobalDefinitions("functions.xml"); +} +bool Calculator::loadGlobalDataSets() { + return loadGlobalDefinitions("datasets.xml"); +} +bool Calculator::loadLocalDefinitions() { + string homedir = buildPath(getLocalDataDir(), "definitions"); + if(!dirExists(homedir)) { + string homedir_old = buildPath(getOldLocalDir(), "definitions"); + if(dirExists(homedir)) { + if(!dirExists(getLocalDataDir())) { + recursiveMakeDir(getLocalDataDir()); + } + if(makeDir(homedir)) { + list eps_old; + struct dirent *ep_old; + DIR *dp_old = opendir(homedir_old.c_str()); + if(dp_old) { + while((ep_old = readdir(dp_old))) { +#ifdef _DIRENT_HAVE_D_TYPE + if(ep_old->d_type != DT_DIR) { +#endif + if(strcmp(ep_old->d_name, "..") != 0 && strcmp(ep_old->d_name, ".") != 0 && strcmp(ep_old->d_name, "datasets") != 0) { + eps_old.push_back(ep_old->d_name); + } +#ifdef _DIRENT_HAVE_D_TYPE + } +#endif + } + closedir(dp_old); + } + for(list::iterator it = eps_old.begin(); it != eps_old.end(); ++it) { + move_file(buildPath(homedir_old, *it).c_str(), buildPath(homedir, *it).c_str()); + } + if(removeDir(homedir_old)) { + removeDir(getOldLocalDir()); + } + } + } + } + list eps; + struct dirent *ep; + DIR *dp = opendir(homedir.c_str()); + if(dp) { + while((ep = readdir(dp))) { +#ifdef _DIRENT_HAVE_D_TYPE + if(ep->d_type != DT_DIR) { +#endif + if(strcmp(ep->d_name, "..") != 0 && strcmp(ep->d_name, ".") != 0 && strcmp(ep->d_name, "datasets") != 0) { + eps.push_back(ep->d_name); + } +#ifdef _DIRENT_HAVE_D_TYPE + } +#endif + } + closedir(dp); + } + eps.sort(); + for(list::iterator it = eps.begin(); it != eps.end(); ++it) { + loadDefinitions(buildPath(homedir, *it).c_str(), (*it) == "functions.xml" || (*it) == "variables.xml" || (*it) == "units.xml" || (*it) == "datasets.xml", true); + } + for(size_t i = 0; i < variables.size(); i++) { + if(!variables[i]->isLocal() && !variables[i]->isActive() && !getActiveExpressionItem(variables[i])) variables[i]->setActive(true); + } + for(size_t i = 0; i < units.size(); i++) { + if(!units[i]->isLocal() && !units[i]->isActive() && !getActiveExpressionItem(units[i])) units[i]->setActive(true); + } + for(size_t i = 0; i < functions.size(); i++) { + if(!functions[i]->isLocal() && !functions[i]->isActive() && !getActiveExpressionItem(functions[i])) functions[i]->setActive(true); + } + return true; +} + +#define ITEM_SAVE_BUILTIN_NAMES\ + if(!is_user_defs) {item->setRegistered(false);} \ + for(size_t i = 1; i <= item->countNames(); i++) { \ + if(item->getName(i).reference) { \ + for(size_t i2 = 0; i2 < 10; i2++) { \ + if(ref_names[i2].name.empty()) { \ + ref_names[i2] = item->getName(i); \ + break; \ + } \ + } \ + } \ + } \ + item->clearNames(); + +#define ITEM_SET_BEST_NAMES(validation) \ + size_t names_i = 0, i2 = 0; \ + string *str_names; \ + if(best_names == "-") {best_names = ""; nextbest_names = "";} \ + if(!best_names.empty()) {str_names = &best_names;} \ + else if(!nextbest_names.empty()) {str_names = &nextbest_names;} \ + else {str_names = &default_names;} \ + if(!str_names->empty() && (*str_names)[0] == '!') { \ + names_i = str_names->find('!', 1) + 1; \ + } \ + while(true) { \ + size_t i3 = names_i; \ + names_i = str_names->find(",", i3); \ + if(i2 == 0) { \ + i2 = str_names->find(":", i3); \ + } \ + bool case_set = false; \ + ename.unicode = false; \ + ename.abbreviation = false; \ + ename.case_sensitive = false; \ + ename.suffix = false; \ + ename.avoid_input = false; \ + ename.completion_only = false; \ + ename.reference = false; \ + ename.plural = false; \ + if(i2 < names_i) { \ + bool b = true; \ + for(; i3 < i2; i3++) { \ + switch((*str_names)[i3]) { \ + case '-': {b = false; break;} \ + case 'a': {ename.abbreviation = b; b = true; break;} \ + case 'c': {ename.case_sensitive = b; b = true; case_set = true; break;} \ + case 'i': {ename.avoid_input = b; b = true; break;} \ + case 'p': {ename.plural = b; b = true; break;} \ + case 'r': {ename.reference = b; b = true; break;} \ + case 's': {ename.suffix = b; b = true; break;} \ + case 'u': {ename.unicode = b; b = true; break;} \ + case 'o': {ename.completion_only = b; b = true; break;} \ + } \ + } \ + i3++; \ + i2 = 0; \ + } \ + if(names_i == string::npos) {ename.name = str_names->substr(i3, str_names->length() - i3);} \ + else {ename.name = str_names->substr(i3, names_i - i3);} \ + remove_blank_ends(ename.name); \ + if(!ename.name.empty() && validation(ename.name, version_numbers, is_user_defs)) { \ + if(!case_set) { \ + ename.case_sensitive = ename.abbreviation || text_length_is_one(ename.name); \ + } \ + item->addName(ename); \ + } \ + if(names_i == string::npos) {break;} \ + names_i++; \ + } + +#define ITEM_SET_BUILTIN_NAMES \ + for(size_t i = 0; i < 10; i++) { \ + if(ref_names[i].name.empty()) { \ + break; \ + } else { \ + size_t i4 = item->hasName(ref_names[i].name, ref_names[i].case_sensitive); \ + if(i4 > 0) { \ + const ExpressionName *enameptr = &item->getName(i4); \ + ref_names[i].case_sensitive = enameptr->case_sensitive; \ + ref_names[i].abbreviation = enameptr->abbreviation; \ + ref_names[i].avoid_input = enameptr->avoid_input; \ + ref_names[i].completion_only = enameptr->completion_only; \ + ref_names[i].plural = enameptr->plural; \ + ref_names[i].suffix = enameptr->suffix; \ + item->setName(ref_names[i], i4); \ + } else { \ + item->addName(ref_names[i]); \ + } \ + ref_names[i].name = ""; \ + } \ + } \ + if(!is_user_defs) { \ + item->setRegistered(true); \ + nameChanged(item); \ + } + +#define ITEM_SET_REFERENCE_NAMES(validation) \ + if(str_names != &default_names && !default_names.empty()) { \ + if(default_names[0] == '!') { \ + names_i = default_names.find('!', 1) + 1; \ + } else { \ + names_i = 0; \ + } \ + i2 = 0; \ + while(true) { \ + size_t i3 = names_i; \ + names_i = default_names.find(",", i3); \ + if(i2 == 0) { \ + i2 = default_names.find(":", i3); \ + } \ + bool case_set = false; \ + ename.unicode = false; \ + ename.abbreviation = false; \ + ename.case_sensitive = false; \ + ename.suffix = false; \ + ename.avoid_input = false; \ + ename.completion_only = false; \ + ename.reference = false; \ + ename.plural = false; \ + if(i2 < names_i) { \ + bool b = true; \ + for(; i3 < i2; i3++) { \ + switch(default_names[i3]) { \ + case '-': {b = false; break;} \ + case 'a': {ename.abbreviation = b; b = true; break;} \ + case 'c': {ename.case_sensitive = b; b = true; case_set = true; break;} \ + case 'i': {ename.avoid_input = b; b = true; break;} \ + case 'p': {ename.plural = b; b = true; break;} \ + case 'r': {ename.reference = b; b = true; break;} \ + case 's': {ename.suffix = b; b = true; break;} \ + case 'u': {ename.unicode = b; b = true; break;} \ + case 'o': {ename.completion_only = b; b = true; break;} \ + } \ + } \ + i3++; \ + i2 = 0; \ + } \ + if(ename.reference) { \ + if(names_i == string::npos) {ename.name = default_names.substr(i3, default_names.length() - i3);} \ + else {ename.name = default_names.substr(i3, names_i - i3);} \ + remove_blank_ends(ename.name); \ + size_t i4 = item->hasName(ename.name, ename.case_sensitive); \ + if(i4 > 0) { \ + const ExpressionName *enameptr = &item->getName(i4); \ + ename.suffix = enameptr->suffix; \ + ename.abbreviation = enameptr->abbreviation; \ + ename.avoid_input = enameptr->avoid_input; \ + ename.completion_only = enameptr->completion_only; \ + ename.plural = enameptr->plural; \ + ename.case_sensitive = enameptr->case_sensitive; \ + item->setName(ename, i4); \ + } else if(!ename.name.empty() && validation(ename.name, version_numbers, is_user_defs)) { \ + if(!case_set) { \ + ename.case_sensitive = ename.abbreviation || text_length_is_one(ename.name); \ + } \ + item->addName(ename); \ + } \ + } \ + if(names_i == string::npos) {break;} \ + names_i++; \ + } \ + } + + +#define ITEM_READ_NAME(validation)\ + if(!new_names && (!xmlStrcmp(child->name, (const xmlChar*) "name") || !xmlStrcmp(child->name, (const xmlChar*) "abbreviation") || !xmlStrcmp(child->name, (const xmlChar*) "plural"))) {\ + name_index = 1;\ + XML_GET_INT_FROM_PROP(child, "index", name_index)\ + if(name_index > 0 && name_index <= 10) {\ + name_index--;\ + names[name_index] = empty_expression_name;\ + ref_names[name_index] = empty_expression_name;\ + value2 = NULL;\ + bool case_set = false;\ + if(child->name[0] == 'a') {\ + names[name_index].abbreviation = true;\ + ref_names[name_index].abbreviation = true;\ + } else if(child->name[0] == 'p') {\ + names[name_index].plural = true;\ + ref_names[name_index].plural = true;\ + }\ + child2 = child->xmlChildrenNode;\ + while(child2 != NULL) {\ + if((!best_name[name_index] || (ref_names[name_index].name.empty() && !locale.empty())) && !xmlStrcmp(child2->name, (const xmlChar*) "name")) {\ + lang = xmlNodeGetLang(child2);\ + if(!lang) {\ + value2 = xmlNodeListGetString(doc, child2->xmlChildrenNode, 1);\ + if(!value2 || validation((char*) value2, version_numbers, is_user_defs)) {\ + if(locale.empty()) {\ + best_name[name_index] = true;\ + if(value2) names[name_index].name = (char*) value2;\ + else names[name_index].name = "";\ + } else if(!require_translation) {\ + if(!best_name[name_index] && !nextbest_name[name_index]) {\ + if(value2) names[name_index].name = (char*) value2;\ + else names[name_index].name = "";\ + }\ + if(value2) ref_names[name_index].name = (char*) value2;\ + else ref_names[name_index].name = "";\ + }\ + }\ + } else if(!best_name[name_index] && !locale.empty()) {\ + if(locale == (char*) lang) {\ + value2 = xmlNodeListGetString(doc, child2->xmlChildrenNode, 1);\ + if(!value2 || validation((char*) value2, version_numbers, is_user_defs)) {\ + best_name[name_index] = true;\ + if(value2) names[name_index].name = (char*) value2;\ + else names[name_index].name = "";\ + }\ + } else if(!nextbest_name[name_index] && strlen((char*) lang) >= 2 && fulfilled_translation == 0 && lang[0] == localebase[0] && lang[1] == localebase[1]) {\ + value2 = xmlNodeListGetString(doc, child2->xmlChildrenNode, 1);\ + if(!value2 || validation((char*) value2, version_numbers, is_user_defs)) {\ + nextbest_name[name_index] = true; \ + if(value2) names[name_index].name = (char*) value2;\ + else names[name_index].name = "";\ + }\ + }\ + }\ + if(value2) xmlFree(value2);\ + if(lang) xmlFree(lang);\ + value2 = NULL; lang = NULL;\ + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "unicode")) {\ + XML_GET_BOOL_FROM_TEXT(child2, names[name_index].unicode)\ + ref_names[name_index].unicode = names[name_index].unicode;\ + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "reference")) {\ + XML_GET_BOOL_FROM_TEXT(child2, names[name_index].reference)\ + ref_names[name_index].reference = names[name_index].reference;\ + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "suffix")) {\ + XML_GET_BOOL_FROM_TEXT(child2, names[name_index].suffix)\ + ref_names[name_index].suffix = names[name_index].suffix;\ + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "avoid_input")) {\ + XML_GET_BOOL_FROM_TEXT(child2, names[name_index].avoid_input)\ + ref_names[name_index].avoid_input = names[name_index].avoid_input;\ + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "completion_only")) {\ + XML_GET_BOOL_FROM_TEXT(child2, names[name_index].completion_only)\ + ref_names[name_index].completion_only = names[name_index].completion_only;\ + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "plural")) {\ + XML_GET_BOOL_FROM_TEXT(child2, names[name_index].plural)\ + ref_names[name_index].plural = names[name_index].plural;\ + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "abbreviation")) {\ + XML_GET_BOOL_FROM_TEXT(child2, names[name_index].abbreviation)\ + ref_names[name_index].abbreviation = names[name_index].abbreviation;\ + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "case_sensitive")) {\ + XML_GET_BOOL_FROM_TEXT(child2, names[name_index].case_sensitive)\ + ref_names[name_index].case_sensitive = names[name_index].case_sensitive;\ + case_set = true;\ + }\ + child2 = child2->next;\ + }\ + if(!case_set) {\ + ref_names[name_index].case_sensitive = ref_names[name_index].abbreviation || text_length_is_one(ref_names[name_index].name);\ + names[name_index].case_sensitive = names[name_index].abbreviation || text_length_is_one(names[name_index].name);\ + }\ + if(names[name_index].reference) {\ + if(!ref_names[name_index].name.empty()) {\ + if(ref_names[name_index].name == names[name_index].name) {\ + ref_names[name_index].name = "";\ + } else {\ + names[name_index].reference = false;\ + }\ + }\ + } else if(!ref_names[name_index].name.empty()) {\ + ref_names[name_index].name = "";\ + }\ + }\ + } + +#define ITEM_READ_DTH \ + if(!xmlStrcmp(child->name, (const xmlChar*) "description")) {\ + XML_GET_LOCALE_STRING_FROM_TEXT(child, description, best_description, next_best_description)\ + } else if(!xmlStrcmp(child->name, (const xmlChar*) "title")) {\ + XML_GET_LOCALE_STRING_FROM_TEXT_REQ(child, title, best_title, next_best_title)\ + } else if(!xmlStrcmp(child->name, (const xmlChar*) "hidden")) {\ + XML_GET_TRUE_FROM_TEXT(child, hidden);\ + } + +#define ITEM_READ_NAMES \ + if(new_names && ((best_names.empty() && fulfilled_translation != 2) || default_names.empty()) && !xmlStrcmp(child->name, (const xmlChar*) "names")) {\ + value = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);\ + lang = xmlNodeGetLang(child);\ + if(!lang) {\ + if(default_names.empty()) {\ + if(value) {\ + default_names = (char*) value;\ + remove_blank_ends(default_names);\ + } else {\ + default_names = "";\ + }\ + }\ + } else if(best_names.empty()) {\ + if(locale == (char*) lang) {\ + if(value) {\ + best_names = (char*) value;\ + remove_blank_ends(best_names);\ + } else {\ + best_names = " ";\ + }\ + } else if(nextbest_names.empty() && strlen((char*) lang) >= 2 && fulfilled_translation == 0 && lang[0] == localebase[0] && lang[1] == localebase[1]) {\ + if(value) {\ + nextbest_names = (char*) value;\ + remove_blank_ends(nextbest_names);\ + } else {\ + nextbest_names = " ";\ + }\ + } else if(nextbest_names.empty() && default_names.empty() && value && !require_translation) {\ + nextbest_names = (char*) value;\ + remove_blank_ends(nextbest_names);\ + }\ + }\ + if(value) xmlFree(value);\ + if(lang) xmlFree(lang);\ + } + +#define ITEM_INIT_DTH \ + hidden = false;\ + title = ""; best_title = false; next_best_title = false;\ + description = ""; best_description = false; next_best_description = false;\ + if(fulfilled_translation > 0) require_translation = false; \ + else {XML_GET_TRUE_FROM_PROP(cur, "require_translation", require_translation)} + +#define ITEM_INIT_NAME \ + if(new_names) {\ + best_names = "";\ + nextbest_names = "";\ + default_names = "";\ + } else {\ + for(size_t i = 0; i < 10; i++) {\ + best_name[i] = false;\ + nextbest_name[i] = false;\ + }\ + } + + +#define ITEM_SET_NAME_1(validation)\ + if(!name.empty() && validation(name, version_numbers, is_user_defs)) {\ + ename.name = name;\ + ename.unicode = false;\ + ename.abbreviation = false;\ + ename.case_sensitive = text_length_is_one(ename.name);\ + ename.suffix = false;\ + ename.avoid_input = false;\ + ename.completion_only = false;\ + ename.reference = true;\ + ename.plural = false;\ + item->addName(ename);\ + } + +#define ITEM_SET_NAME_2\ + for(size_t i = 0; i < 10; i++) {\ + if(!names[i].name.empty()) {\ + item->addName(names[i], i + 1);\ + names[i].name = "";\ + } else if(!ref_names[i].name.empty()) {\ + item->addName(ref_names[i], i + 1);\ + ref_names[i].name = "";\ + }\ + } + +#define ITEM_SET_NAME_3\ + for(size_t i = 0; i < 10; i++) {\ + if(!ref_names[i].name.empty()) {\ + item->addName(ref_names[i]);\ + ref_names[i].name = "";\ + }\ + } + +#define ITEM_SET_DTH\ + item->setDescription(description);\ + if(!title.empty() && title[0] == '!') {\ + size_t i = title.find('!', 1);\ + if(i == string::npos) {\ + item->setTitle(title);\ + } else if(i + 1 == title.length()) {\ + item->setTitle("");\ + } else {\ + item->setTitle(title.substr(i + 1, title.length() - (i + 1)));\ + }\ + } else {\ + item->setTitle(title);\ + }\ + item->setHidden(hidden); + +#define ITEM_SET_SHORT_NAME\ + if(!name.empty() && unitNameIsValid(name, version_numbers, is_user_defs)) {\ + ename.name = name;\ + ename.unicode = false;\ + ename.abbreviation = true;\ + ename.case_sensitive = true;\ + ename.suffix = false;\ + ename.avoid_input = false;\ + ename.completion_only = false;\ + ename.reference = true;\ + ename.plural = false;\ + item->addName(ename);\ + } + +#define ITEM_SET_SINGULAR\ + if(!singular.empty()) {\ + ename.name = singular;\ + ename.unicode = false;\ + ename.abbreviation = false;\ + ename.case_sensitive = text_length_is_one(ename.name);\ + ename.suffix = false;\ + ename.avoid_input = false;\ + ename.completion_only = false;\ + ename.reference = false;\ + ename.plural = false;\ + item->addName(ename);\ + } + +#define ITEM_SET_PLURAL\ + if(!plural.empty()) {\ + ename.name = plural;\ + ename.unicode = false;\ + ename.abbreviation = false;\ + ename.case_sensitive = text_length_is_one(ename.name);\ + ename.suffix = false;\ + ename.avoid_input = false;\ + ename.completion_only = false;\ + ename.reference = false;\ + ename.plural = true;\ + item->addName(ename);\ + } + +#define BUILTIN_NAMES_1\ + if(!is_user_defs) item->setRegistered(false);\ + bool has_ref_name;\ + for(size_t i = 1; i <= item->countNames(); i++) {\ + if(item->getName(i).reference) {\ + has_ref_name = false;\ + for(size_t i2 = 0; i2 < 10; i2++) {\ + if(names[i2].name == item->getName(i).name || ref_names[i2].name == item->getName(i).name) {\ + has_ref_name = true;\ + break;\ + }\ + }\ + if(!has_ref_name) {\ + for(int i2 = 9; i2 >= 0; i2--) {\ + if(ref_names[i2].name.empty()) {\ + ref_names[i2] = item->getName(i);\ + break;\ + }\ + }\ + }\ + }\ + }\ + item->clearNames(); + +#define BUILTIN_UNIT_NAMES_1\ + if(!is_user_defs) item->setRegistered(false);\ + bool has_ref_name;\ + for(size_t i = 1; i <= item->countNames(); i++) {\ + if(item->getName(i).reference) {\ + has_ref_name = item->getName(i).name == singular || item->getName(i).name == plural;\ + for(size_t i2 = 0; !has_ref_name && i2 < 10; i2++) {\ + if(names[i2].name == item->getName(i).name || ref_names[i2].name == item->getName(i).name) {\ + has_ref_name = true;\ + break;\ + }\ + }\ + if(!has_ref_name) {\ + for(int i2 = 9; i2 >= 0; i2--) {\ + if(ref_names[i2].name.empty()) {\ + ref_names[i2] = item->getName(i);\ + break;\ + }\ + }\ + }\ + }\ + }\ + item->clearNames(); + +#define BUILTIN_NAMES_2\ + if(!is_user_defs) {\ + item->setRegistered(true);\ + nameChanged(item);\ + } + +#define ITEM_CLEAR_NAMES\ + for(size_t i = 0; i < 10; i++) {\ + if(!names[i].name.empty()) {\ + names[i].name = "";\ + }\ + if(!ref_names[i].name.empty()) {\ + ref_names[i].name = "";\ + }\ + } + +int Calculator::loadDefinitions(const char* file_name, bool is_user_defs, bool check_duplicates) { + + xmlDocPtr doc; + xmlNodePtr cur, child, child2, child3; + string version, stmp, name, uname, type, svalue, sexp, plural, countries, singular, category_title, category, description, title, inverse, suncertainty, base, argname, usystem; + bool unc_rel; + bool best_title, next_best_title, best_category_title, next_best_category_title, best_description, next_best_description; + bool best_plural, next_best_plural, best_singular, next_best_singular, best_argname, next_best_argname, best_countries, next_best_countries; + bool best_proptitle, next_best_proptitle, best_propdescr, next_best_propdescr; + string proptitle, propdescr; + ExpressionName names[10]; + ExpressionName ref_names[10]; + string prop_names[10]; + string ref_prop_names[10]; + bool best_name[10]; + bool nextbest_name[10]; + string best_names, nextbest_names, default_names; + string best_prop_names, nextbest_prop_names, default_prop_names; + int name_index, prec; + ExpressionName ename; + + string locale; +#ifdef _WIN32 + WCHAR wlocale[LOCALE_NAME_MAX_LENGTH]; + if(LCIDToLocaleName(LOCALE_USER_DEFAULT, wlocale, LOCALE_NAME_MAX_LENGTH, 0) != 0) locale = utf8_encode(wlocale); + gsub("-", "_", locale); +#else + char *clocale = setlocale(LC_MESSAGES, NULL); + if(clocale) locale = clocale; +#endif + + if(b_ignore_locale || locale == "POSIX" || locale == "C") { + locale = ""; + } else { + size_t i = locale.find('.'); + if(i != string::npos) locale = locale.substr(0, i); + } + + int fulfilled_translation = 0; + string localebase; + if(locale.length() > 2) { + localebase = locale.substr(0, 2); + if(locale == "en_US") { + fulfilled_translation = 2; + } else if(localebase == "en") { + fulfilled_translation = 1; + } + } else { + localebase = locale; + if(locale == "en") { + fulfilled_translation = 2; + } + } + while(localebase.length() < 2) { + localebase += " "; + fulfilled_translation = 2; + } + + int exponent = 1, litmp = 0, mix_priority = 0, mix_min = 0; + bool active = false, hidden = false, b = false, require_translation = false, use_with_prefixes = false, use_with_prefixes_set = false; + Number nr; + ExpressionItem *item; + MathFunction *f; + Variable *v; + Unit *u; + AliasUnit *au; + CompositeUnit *cu; + Prefix *p; + Argument *arg; + DataSet *dc; + DataProperty *dp; + int itmp; + IntegerArgument *iarg; + NumberArgument *farg; + xmlChar *value, *lang, *value2; + int in_unfinished = 0; + bool done_something = false; + doc = xmlParseFile(file_name); + if(doc == NULL) { + return false; + } + cur = xmlDocGetRootElement(doc); + if(cur == NULL) { + xmlFreeDoc(doc); + return false; + } + while(cur != NULL) { + if(!xmlStrcmp(cur->name, (const xmlChar*) "QALCULATE")) { + XML_GET_STRING_FROM_PROP(cur, "version", version) + break; + } + cur = cur->next; + } + if(cur == NULL) { + error(true, _("File not identified as Qalculate! definitions file: %s."), file_name, NULL); + xmlFreeDoc(doc); + return false; + } + int version_numbers[] = {3, 7, 0}; + parse_qalculate_version(version, version_numbers); + + bool new_names = version_numbers[0] > 0 || version_numbers[1] > 9 || (version_numbers[1] == 9 && version_numbers[2] >= 4); + + ParseOptions po; + + vector unfinished_nodes; + vector unfinished_cats; + queue sub_items; + vector > nodes; + + category = ""; + nodes.resize(1); + + Unit *u_usd = getUnit("USD"); + + while(true) { + if(!in_unfinished) { + category_title = ""; best_category_title = false; next_best_category_title = false; + child = cur->xmlChildrenNode; + while(child != NULL) { + if(!xmlStrcmp(child->name, (const xmlChar*) "title")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child, category_title, best_category_title, next_best_category_title) + } else if(!xmlStrcmp(child->name, (const xmlChar*) "category")) { + nodes.back().push(child); + } else { + sub_items.push(child); + } + child = child->next; + } + if(!category.empty()) { + category += "/"; + } + if(!category_title.empty() && category_title[0] == '!') {\ + size_t i = category_title.find('!', 1); + if(i == string::npos) { + category += category_title; + } else if(i + 1 < category_title.length()) { + category += category_title.substr(i + 1, category_title.length() - (i + 1)); + } + } else { + category += category_title; + } + } + while(!sub_items.empty() || (in_unfinished && cur)) { + if(!in_unfinished) { + cur = sub_items.front(); + sub_items.pop(); + } + if(!xmlStrcmp(cur->name, (const xmlChar*) "activate")) { + XML_GET_STRING_FROM_TEXT(cur, name) + ExpressionItem *item = getInactiveExpressionItem(name); + if(item && !item->isLocal()) { + item->setActive(true); + done_something = true; + } + } else if(!xmlStrcmp(cur->name, (const xmlChar*) "deactivate")) { + XML_GET_STRING_FROM_TEXT(cur, name) + ExpressionItem *item = getActiveExpressionItem(name); + if(item && !item->isLocal()) { + item->setActive(false); + done_something = true; + } + } else if(!xmlStrcmp(cur->name, (const xmlChar*) "function")) { + if(VERSION_BEFORE(0, 6, 3)) { + XML_GET_STRING_FROM_PROP(cur, "name", name) + } else { + name = ""; + } + XML_GET_FALSE_FROM_PROP(cur, "active", active) + f = new UserFunction(category, "", "", is_user_defs, 0, "", "", 0, active); + item = f; + done_something = true; + child = cur->xmlChildrenNode; + ITEM_INIT_DTH + ITEM_INIT_NAME + while(child != NULL) { + if(!xmlStrcmp(child->name, (const xmlChar*) "expression")) { + XML_DO_FROM_TEXT(child, ((UserFunction*) f)->setFormula); + XML_GET_PREC_FROM_PROP(child, prec) + f->setPrecision(prec); + XML_GET_APPROX_FROM_PROP(child, b) + f->setApproximate(b); + } else if(!xmlStrcmp(child->name, (const xmlChar*) "condition")) { + XML_DO_FROM_TEXT(child, f->setCondition); + } else if(!xmlStrcmp(child->name, (const xmlChar*) "subfunction")) { + XML_GET_FALSE_FROM_PROP(child, "precalculate", b); + value = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); + if(value) ((UserFunction*) f)->addSubfunction((char*) value, b); + else ((UserFunction*) f)->addSubfunction("", true); + if(value) xmlFree(value); + } else if(!xmlStrcmp(child->name, (const xmlChar*) "argument")) { + farg = NULL; iarg = NULL; + XML_GET_STRING_FROM_PROP(child, "type", type); + if(type == "text") { + arg = new TextArgument(); + } else if(type == "symbol") { + arg = new SymbolicArgument(); + } else if(type == "date") { + arg = new DateArgument(); + } else if(type == "integer") { + iarg = new IntegerArgument(); + arg = iarg; + } else if(type == "number") { + farg = new NumberArgument(); + arg = farg; + } else if(type == "vector") { + arg = new VectorArgument(); + } else if(type == "matrix") { + arg = new MatrixArgument(); + } else if(type == "boolean") { + arg = new BooleanArgument(); + } else if(type == "function") { + arg = new FunctionArgument(); + } else if(type == "unit") { + arg = new UnitArgument(); + } else if(type == "variable") { + arg = new VariableArgument(); + } else if(type == "object") { + arg = new ExpressionItemArgument(); + } else if(type == "angle") { + arg = new AngleArgument(); + } else if(type == "data-object") { + arg = new DataObjectArgument(NULL, ""); + } else if(type == "data-property") { + arg = new DataPropertyArgument(NULL, ""); + } else { + arg = new Argument(); + } + child2 = child->xmlChildrenNode; + argname = ""; best_argname = false; next_best_argname = false; + while(child2 != NULL) { + if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname) + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "min")) { + if(farg) { + XML_DO_FROM_TEXT(child2, nr.set); + farg->setMin(&nr); + XML_GET_FALSE_FROM_PROP(child, "include_equals", b) + farg->setIncludeEqualsMin(b); + } else if(iarg) { + XML_GET_STRING_FROM_TEXT(child2, stmp); + Number integ(stmp); + iarg->setMin(&integ); + } + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "max")) { + if(farg) { + XML_DO_FROM_TEXT(child2, nr.set); + farg->setMax(&nr); + XML_GET_FALSE_FROM_PROP(child, "include_equals", b) + farg->setIncludeEqualsMax(b); + } else if(iarg) { + XML_GET_STRING_FROM_TEXT(child2, stmp); + Number integ(stmp); + iarg->setMax(&integ); + } + } else if(farg && !xmlStrcmp(child2->name, (const xmlChar*) "complex_allowed")) { + XML_GET_FALSE_FROM_TEXT(child2, b); + farg->setComplexAllowed(b); + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "condition")) { + XML_DO_FROM_TEXT(child2, arg->setCustomCondition); + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "matrix_allowed")) { + XML_GET_TRUE_FROM_TEXT(child2, b); + arg->setMatrixAllowed(b); + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "zero_forbidden")) { + XML_GET_TRUE_FROM_TEXT(child2, b); + arg->setZeroForbidden(b); + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "test")) { + XML_GET_FALSE_FROM_TEXT(child2, b); + arg->setTests(b); + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "handle_vector")) { + XML_GET_FALSE_FROM_TEXT(child2, b); + arg->setHandleVector(b); + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "alert")) { + XML_GET_FALSE_FROM_TEXT(child2, b); + arg->setAlerts(b); + } + child2 = child2->next; + } + if(!argname.empty() && argname[0] == '!') { + size_t i = argname.find('!', 1); + if(i == string::npos) { + arg->setName(argname); + } else if(i + 1 < argname.length()) { + arg->setName(argname.substr(i + 1, argname.length() - (i + 1))); + } + } else { + arg->setName(argname); + } + itmp = 1; + XML_GET_INT_FROM_PROP(child, "index", itmp); + f->setArgumentDefinition(itmp, arg); + } else if(!xmlStrcmp(child->name, (const xmlChar*) "example")) { + XML_DO_FROM_TEXT(child, f->setExample); + } else ITEM_READ_NAME(functionNameIsValid) + else ITEM_READ_DTH + else { + ITEM_READ_NAMES + } + child = child->next; + } + if(new_names) { + ITEM_SET_BEST_NAMES(functionNameIsValid) + ITEM_SET_REFERENCE_NAMES(functionNameIsValid) + } else { + ITEM_SET_NAME_1(functionNameIsValid) + ITEM_SET_NAME_2 + ITEM_SET_NAME_3 + } + ITEM_SET_DTH + if(check_duplicates && !is_user_defs) { + for(size_t i = 1; i <= f->countNames();) { + if(getActiveFunction(f->getName(i).name)) f->removeName(i); + else i++; + } + } + if(f->countNames() == 0) { + f->destroy(); + f = NULL; + } else { + f->setChanged(false); + addFunction(f, true, is_user_defs); + } + } else if(!xmlStrcmp(cur->name, (const xmlChar*) "dataset") || !xmlStrcmp(cur->name, (const xmlChar*) "builtin_dataset")) { + bool builtin = !xmlStrcmp(cur->name, (const xmlChar*) "builtin_dataset"); + XML_GET_FALSE_FROM_PROP(cur, "active", active) + if(builtin) { + XML_GET_STRING_FROM_PROP(cur, "name", name) + dc = getDataSet(name); + if(!dc) { + goto after_load_object; + } + dc->setCategory(category); + } else { + dc = new DataSet(category, "", "", "", "", is_user_defs); + } + item = dc; + done_something = true; + child = cur->xmlChildrenNode; + ITEM_INIT_DTH + ITEM_INIT_NAME + while(child != NULL) { + if(!xmlStrcmp(child->name, (const xmlChar*) "property")) { + dp = new DataProperty(dc); + child2 = child->xmlChildrenNode; + if(new_names) { + default_prop_names = ""; best_prop_names = ""; nextbest_prop_names = ""; + } else { + for(size_t i = 0; i < 10; i++) { + best_name[i] = false; + nextbest_name[i] = false; + } + } + proptitle = ""; best_proptitle = false; next_best_proptitle = false; + propdescr = ""; best_propdescr = false; next_best_propdescr = false; + while(child2 != NULL) { + if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child2, proptitle, best_proptitle, next_best_proptitle) + } else if(!new_names && !xmlStrcmp(child2->name, (const xmlChar*) "name")) { + name_index = 1; + XML_GET_INT_FROM_PROP(child2, "index", name_index) + if(name_index > 0 && name_index <= 10) { + name_index--; + prop_names[name_index] = ""; + ref_prop_names[name_index] = ""; + value2 = NULL; + child3 = child2->xmlChildrenNode; + while(child3 != NULL) { + if((!best_name[name_index] || (ref_prop_names[name_index].empty() && !locale.empty())) && !xmlStrcmp(child3->name, (const xmlChar*) "name")) { + lang = xmlNodeGetLang(child3); + if(!lang) { + value2 = xmlNodeListGetString(doc, child3->xmlChildrenNode, 1); + if(locale.empty()) { + best_name[name_index] = true; + if(value2) prop_names[name_index] = (char*) value2; + else prop_names[name_index] = ""; + } else { + if(!best_name[name_index] && !nextbest_name[name_index]) { + if(value2) prop_names[name_index] = (char*) value2; + else prop_names[name_index] = ""; + } + if(value2) ref_prop_names[name_index] = (char*) value2; + else ref_prop_names[name_index] = ""; + } + } else if(!best_name[name_index] && !locale.empty()) { + if(locale == (char*) lang) { + value2 = xmlNodeListGetString(doc, child3->xmlChildrenNode, 1); + best_name[name_index] = true; + if(value2) prop_names[name_index] = (char*) value2; + else prop_names[name_index] = ""; + } else if(!nextbest_name[name_index] && strlen((char*) lang) >= 2 && fulfilled_translation == 0 && lang[0] == localebase[0] && lang[1] == localebase[1]) { + value2 = xmlNodeListGetString(doc, child3->xmlChildrenNode, 1); + nextbest_name[name_index] = true; + if(value2) prop_names[name_index] = (char*) value2; + else prop_names[name_index] = ""; + } + } + if(value2) xmlFree(value2); + if(lang) xmlFree(lang); + value2 = NULL; lang = NULL; + } + child3 = child3->next; + } + if(!ref_prop_names[name_index].empty() && ref_prop_names[name_index] == prop_names[name_index]) { + ref_prop_names[name_index] = ""; + } + } + } else if(new_names && !xmlStrcmp(child2->name, (const xmlChar*) "names") && ((best_prop_names.empty() && fulfilled_translation != 2) || default_prop_names.empty())) { + value2 = xmlNodeListGetString(doc, child2->xmlChildrenNode, 1); + lang = xmlNodeGetLang(child2); + if(!lang) { + if(default_prop_names.empty()) { + if(value2) { + default_prop_names = (char*) value2; + remove_blank_ends(default_prop_names); + } else { + default_prop_names = ""; + } + } + } else { + if(locale == (char*) lang) { + if(value2) { + best_prop_names = (char*) value2; + remove_blank_ends(best_prop_names); + } else { + best_prop_names = " "; + } + } else if(nextbest_prop_names.empty() && strlen((char*) lang) >= 2 && fulfilled_translation == 0 && lang[0] == localebase[0] && lang[1] == localebase[1]) { + if(value2) { + nextbest_prop_names = (char*) value2; + remove_blank_ends(nextbest_prop_names); + } else { + nextbest_prop_names = " "; + } + } else if(nextbest_prop_names.empty() && default_prop_names.empty() && value2 && !require_translation) { + nextbest_prop_names = (char*) value2; + remove_blank_ends(nextbest_prop_names); + } + } + if(value2) xmlFree(value2); + if(lang) xmlFree(lang); + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "description")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child2, propdescr, best_propdescr, next_best_propdescr) + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "unit")) { + XML_DO_FROM_TEXT(child2, dp->setUnit) + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "key")) { + XML_GET_TRUE_FROM_TEXT(child2, b) + dp->setKey(b); + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "hidden")) { + XML_GET_TRUE_FROM_TEXT(child2, b) + dp->setHidden(b); + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "brackets")) { + XML_GET_TRUE_FROM_TEXT(child2, b) + dp->setUsesBrackets(b); + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "approximate")) { + XML_GET_TRUE_FROM_TEXT(child2, b) + dp->setApproximate(b); + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "case_sensitive")) { + XML_GET_TRUE_FROM_TEXT(child2, b) + dp->setCaseSensitive(b); + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "type")) { + XML_GET_STRING_FROM_TEXT(child2, stmp) + if(stmp == "text") { + dp->setPropertyType(PROPERTY_STRING); + } else if(stmp == "number") { + dp->setPropertyType(PROPERTY_NUMBER); + } else if(stmp == "expression") { + dp->setPropertyType(PROPERTY_EXPRESSION); + } + } + child2 = child2->next; + } + if(!proptitle.empty() && proptitle[0] == '!') {\ + size_t i = proptitle.find('!', 1); + if(i == string::npos) { + dp->setTitle(proptitle); + } else if(i + 1 < proptitle.length()) { + dp->setTitle(proptitle.substr(i + 1, proptitle.length() - (i + 1))); + } + } else { + dp->setTitle(proptitle); + } + dp->setDescription(propdescr); + if(new_names) { + size_t names_i = 0, i2 = 0; + string *str_names; + bool had_ref = false; + if(best_prop_names == "-") {best_prop_names = ""; nextbest_prop_names = "";} + if(!best_prop_names.empty()) {str_names = &best_prop_names;} + else if(!nextbest_prop_names.empty()) {str_names = &nextbest_prop_names;} + else {str_names = &default_prop_names;} + if(!str_names->empty() && (*str_names)[0] == '!') { + names_i = str_names->find('!', 1) + 1; + } + while(true) { + size_t i3 = names_i; + names_i = str_names->find(",", i3); + if(i2 == 0) { + i2 = str_names->find(":", i3); + } + bool b_prop_ref = false; + if(i2 < names_i) { + bool b = true; + for(; i3 < i2; i3++) { + switch((*str_names)[i3]) { + case '-': {b = false; break;} + case 'r': {b_prop_ref = b; b = true; break;} + } + } + i3++; + i2 = 0; + } + if(names_i == string::npos) {stmp = str_names->substr(i3, str_names->length() - i3);} + else {stmp = str_names->substr(i3, names_i - i3);} + remove_blank_ends(stmp); + if(!stmp.empty()) { + if(b_prop_ref) had_ref = true; + dp->addName(stmp, b_prop_ref); + } + if(names_i == string::npos) {break;} + names_i++; + } + if(str_names != &default_prop_names && !default_prop_names.empty()) { + if(default_prop_names[0] == '!') { + names_i = default_prop_names.find('!', 1) + 1; + } else { + names_i = 0; + } + i2 = 0; + while(true) { + size_t i3 = names_i; + names_i = default_prop_names.find(",", i3); + if(i2 == 0) { + i2 = default_prop_names.find(":", i3); + } + bool b_prop_ref = false; + if(i2 < names_i) { + bool b = true; + for(; i3 < i2; i3++) { + switch(default_prop_names[i3]) { + case '-': {b = false; break;} + case 'r': {b_prop_ref = b; b = true; break;} + } + } + i3++; + i2 = 0; + } + if(b_prop_ref || (!had_ref && names_i == string::npos)) { + had_ref = true; + if(names_i == string::npos) {stmp = default_prop_names.substr(i3, default_prop_names.length() - i3);} + else {stmp = default_prop_names.substr(i3, names_i - i3);} + remove_blank_ends(stmp); + size_t i4 = dp->hasName(stmp); + if(i4 > 0) { + dp->setNameIsReference(i4, true); + } else if(!stmp.empty()) { + dp->addName(stmp, true); + } + } + if(names_i == string::npos) {break;} + names_i++; + } + } + if(!had_ref && dp->countNames() > 0) dp->setNameIsReference(1, true); + } else { + bool b = false; + for(size_t i = 0; i < 10; i++) { + if(!prop_names[i].empty()) { + if(!b && ref_prop_names[i].empty()) { + dp->addName(prop_names[i], true, i + 1); + b = true; + } else { + dp->addName(prop_names[i], false, i + 1); + } + prop_names[i] = ""; + } + } + for(size_t i = 0; i < 10; i++) { + if(!ref_prop_names[i].empty()) { + if(!b) { + dp->addName(ref_prop_names[i], true); + b = true; + } else { + dp->addName(ref_prop_names[i], false); + } + ref_prop_names[i] = ""; + } + } + } + dp->setUserModified(is_user_defs); + dc->addProperty(dp); + } else if(!xmlStrcmp(child->name, (const xmlChar*) "argument")) { + child2 = child->xmlChildrenNode; + argname = ""; best_argname = false; next_best_argname = false; + while(child2 != NULL) { + if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname) + } + child2 = child2->next; + } + itmp = 1; + XML_GET_INT_FROM_PROP(child, "index", itmp); + if(dc->getArgumentDefinition(itmp)) { + dc->getArgumentDefinition(itmp)->setName(argname); + } + } else if(!xmlStrcmp(child->name, (const xmlChar*) "object_argument")) { + child2 = child->xmlChildrenNode; + argname = ""; best_argname = false; next_best_argname = false; + while(child2 != NULL) { + if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname) + } + child2 = child2->next; + } + itmp = 1; + if(dc->getArgumentDefinition(itmp)) { + if(!argname.empty() && argname[0] == '!') { + size_t i = argname.find('!', 1); + if(i == string::npos) { + dc->getArgumentDefinition(itmp)->setName(argname); + } else if(i + 1 < argname.length()) { + dc->getArgumentDefinition(itmp)->setName(argname.substr(i + 1, argname.length() - (i + 1))); + } + } else { + dc->getArgumentDefinition(itmp)->setName(argname); + } + } + } else if(!xmlStrcmp(child->name, (const xmlChar*) "property_argument")) { + child2 = child->xmlChildrenNode; + argname = ""; best_argname = false; next_best_argname = false; + while(child2 != NULL) { + if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname) + } + child2 = child2->next; + } + itmp = 2; + if(dc->getArgumentDefinition(itmp)) { + if(!argname.empty() && argname[0] == '!') { + size_t i = argname.find('!', 1); + if(i == string::npos) { + dc->getArgumentDefinition(itmp)->setName(argname); + } else if(i + 1 < argname.length()) { + dc->getArgumentDefinition(itmp)->setName(argname.substr(i + 1, argname.length() - (i + 1))); + } + } else { + dc->getArgumentDefinition(itmp)->setName(argname); + } + } + } else if(!xmlStrcmp(child->name, (const xmlChar*) "default_property")) { + XML_DO_FROM_TEXT(child, dc->setDefaultProperty) + } else if(!builtin && !xmlStrcmp(child->name, (const xmlChar*) "copyright")) { + XML_DO_FROM_TEXT(child, dc->setCopyright) + } else if(!builtin && !xmlStrcmp(child->name, (const xmlChar*) "datafile")) { + XML_DO_FROM_TEXT(child, dc->setDefaultDataFile) + } else if(!xmlStrcmp(child->name, (const xmlChar*) "example")) { + XML_DO_FROM_TEXT(child, dc->setExample); + } else ITEM_READ_NAME(functionNameIsValid) + else ITEM_READ_DTH + else { + ITEM_READ_NAMES + } + child = child->next; + } + if(new_names) { + if(builtin) { + ITEM_SAVE_BUILTIN_NAMES + } + ITEM_SET_BEST_NAMES(functionNameIsValid) + ITEM_SET_REFERENCE_NAMES(functionNameIsValid) + if(builtin) { + ITEM_SET_BUILTIN_NAMES + } + } else { + if(builtin) { + BUILTIN_NAMES_1 + } + ITEM_SET_NAME_2 + ITEM_SET_NAME_3 + if(builtin) { + BUILTIN_NAMES_2 + } + } + ITEM_SET_DTH + if(check_duplicates && !is_user_defs) { + for(size_t i = 1; i <= dc->countNames();) { + if(getActiveFunction(dc->getName(i).name)) dc->removeName(i); + else i++; + } + } + if(!builtin && dc->countNames() == 0) { + dc->destroy(); + dc = NULL; + } else { + dc->setChanged(builtin && is_user_defs); + if(!builtin) addDataSet(dc, true, is_user_defs); + } + done_something = true; + } else if(!xmlStrcmp(cur->name, (const xmlChar*) "builtin_function")) { + XML_GET_STRING_FROM_PROP(cur, "name", name) + f = getFunction(name); + if(f) { + XML_GET_FALSE_FROM_PROP(cur, "active", active) + f->setLocal(is_user_defs, active); + f->setCategory(category); + item = f; + child = cur->xmlChildrenNode; + ITEM_INIT_DTH + ITEM_INIT_NAME + while(child != NULL) { + if(!xmlStrcmp(child->name, (const xmlChar*) "argument")) { + child2 = child->xmlChildrenNode; + argname = ""; best_argname = false; next_best_argname = false; + while(child2 != NULL) { + if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname) + } + child2 = child2->next; + } + itmp = 1; + XML_GET_INT_FROM_PROP(child, "index", itmp); + if(f->getArgumentDefinition(itmp)) { + if(!argname.empty() && argname[0] == '!') { + size_t i = argname.find('!', 1); + if(i == string::npos) { + f->getArgumentDefinition(itmp)->setName(argname); + } else if(i + 1 < argname.length()) { + f->getArgumentDefinition(itmp)->setName(argname.substr(i + 1, argname.length() - (i + 1))); + } + } else { + f->getArgumentDefinition(itmp)->setName(argname); + } + } else if(itmp <= f->maxargs() || itmp <= f->minargs()) { + if(!argname.empty() && argname[0] == '!') { + size_t i = argname.find('!', 1); + if(i == string::npos) { + f->setArgumentDefinition(itmp, new Argument(argname, false)); + } else if(i + 1 < argname.length()) { + f->setArgumentDefinition(itmp, new Argument(argname.substr(i + 1, argname.length() - (i + 1)), false)); + } + } else { + f->setArgumentDefinition(itmp, new Argument(argname, false)); + } + } + } else if(!xmlStrcmp(child->name, (const xmlChar*) "example")) { + XML_DO_FROM_TEXT(child, f->setExample); + } else ITEM_READ_NAME(functionNameIsValid) + else ITEM_READ_DTH + else { + ITEM_READ_NAMES + } + child = child->next; + } + if(new_names) { + ITEM_SAVE_BUILTIN_NAMES + ITEM_SET_BEST_NAMES(functionNameIsValid) + ITEM_SET_REFERENCE_NAMES(functionNameIsValid) + ITEM_SET_BUILTIN_NAMES + } else { + BUILTIN_NAMES_1 + ITEM_SET_NAME_2 + ITEM_SET_NAME_3 + BUILTIN_NAMES_2 + } + ITEM_SET_DTH + f->setChanged(false); + done_something = true; + } + } else if(!xmlStrcmp(cur->name, (const xmlChar*) "unknown")) { + if(VERSION_BEFORE(0, 6, 3)) { + XML_GET_STRING_FROM_PROP(cur, "name", name) + } else { + name = ""; + } + XML_GET_FALSE_FROM_PROP(cur, "active", active) + svalue = ""; + v = new UnknownVariable(category, "", "", is_user_defs, false, active); + item = v; + done_something = true; + child = cur->xmlChildrenNode; + b = true; + ITEM_INIT_DTH + ITEM_INIT_NAME + while(child != NULL) { + if(!xmlStrcmp(child->name, (const xmlChar*) "type")) { + XML_GET_STRING_FROM_TEXT(child, stmp); + if(!((UnknownVariable*) v)->assumptions()) ((UnknownVariable*) v)->setAssumptions(new Assumptions()); + if(stmp == "integer") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_INTEGER); + else if(stmp == "rational") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_RATIONAL); + else if(stmp == "real") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_REAL); + else if(stmp == "complex") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_COMPLEX); + else if(stmp == "number") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_NUMBER); + else if(stmp == "non-matrix") { + if(VERSION_BEFORE(0, 9, 13)) { + ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_NUMBER); + } else { + ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_NONMATRIX); + } + } else if(stmp == "none") { + if(VERSION_BEFORE(0, 9, 13)) { + ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_NUMBER); + } else { + ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_NONE); + } + } + } else if(!xmlStrcmp(child->name, (const xmlChar*) "sign")) { + XML_GET_STRING_FROM_TEXT(child, stmp); + if(!((UnknownVariable*) v)->assumptions()) ((UnknownVariable*) v)->setAssumptions(new Assumptions()); + if(stmp == "non-zero") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_NONZERO); + else if(stmp == "non-positive") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_NONPOSITIVE); + else if(stmp == "negative") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_NEGATIVE); + else if(stmp == "non-negative") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_NONNEGATIVE); + else if(stmp == "positive") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_POSITIVE); + else if(stmp == "unknown") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_UNKNOWN); + } else ITEM_READ_NAME(variableNameIsValid) + else ITEM_READ_DTH + else { + ITEM_READ_NAMES + } + child = child->next; + } + if(new_names) { + ITEM_SET_BEST_NAMES(variableNameIsValid) + ITEM_SET_REFERENCE_NAMES(variableNameIsValid) + } else { + ITEM_SET_NAME_1(variableNameIsValid) + ITEM_SET_NAME_2 + ITEM_SET_NAME_3 + } + ITEM_SET_DTH + if(check_duplicates && !is_user_defs) { + for(size_t i = 1; i <= v->countNames();) { + if(getActiveVariable(v->getName(i).name) || getActiveUnit(v->getName(i).name) || getCompositeUnit(v->getName(i).name)) v->removeName(i); + else i++; + } + } + for(size_t i = 1; i <= v->countNames(); i++) { + if(v->getName(i).name == "x") {v_x->destroy(); v_x = (UnknownVariable*) v; break;} + if(v->getName(i).name == "y") {v_y->destroy(); v_y = (UnknownVariable*) v; break;} + if(v->getName(i).name == "z") {v_z->destroy(); v_z = (UnknownVariable*) v; break;} + } + if(v->countNames() == 0) { + v->destroy(); + v = NULL; + } else { + addVariable(v, true, is_user_defs); + v->setChanged(false); + } + } else if(!xmlStrcmp(cur->name, (const xmlChar*) "variable")) { + if(VERSION_BEFORE(0, 6, 3)) { + XML_GET_STRING_FROM_PROP(cur, "name", name) + } else { + name = ""; + } + XML_GET_FALSE_FROM_PROP(cur, "active", active) + svalue = ""; + v = new KnownVariable(category, "", "", "", is_user_defs, false, active); + item = v; + done_something = true; + child = cur->xmlChildrenNode; + b = true; + ITEM_INIT_DTH + ITEM_INIT_NAME + while(child != NULL) { + if(!xmlStrcmp(child->name, (const xmlChar*) "value")) { + XML_DO_FROM_TEXT(child, ((KnownVariable*) v)->set); + XML_GET_STRING_FROM_PROP(child, "relative_uncertainty", suncertainty) + unc_rel = false; + if(suncertainty.empty()) {XML_GET_STRING_FROM_PROP(child, "uncertainty", suncertainty)} + else unc_rel = true; + ((KnownVariable*) v)->setUncertainty(suncertainty, unc_rel); + XML_DO_FROM_PROP(child, "unit", ((KnownVariable*) v)->setUnit) + XML_GET_PREC_FROM_PROP(child, prec) + v->setPrecision(prec); + XML_GET_APPROX_FROM_PROP(child, b); + if(b) v->setApproximate(true); + } else ITEM_READ_NAME(variableNameIsValid) + else ITEM_READ_DTH + else { + ITEM_READ_NAMES + } + child = child->next; + } + if(new_names) { + ITEM_SET_BEST_NAMES(variableNameIsValid) + ITEM_SET_REFERENCE_NAMES(variableNameIsValid) + } else { + ITEM_SET_NAME_1(variableNameIsValid) + ITEM_SET_NAME_2 + ITEM_SET_NAME_3 + } + ITEM_SET_DTH + if(check_duplicates && !is_user_defs) { + for(size_t i = 1; i <= v->countNames();) { + if(getActiveVariable(v->getName(i).name) || getActiveUnit(v->getName(i).name) || getCompositeUnit(v->getName(i).name)) v->removeName(i); + else i++; + } + } + if(v->countNames() == 0) { + v->destroy(); + v = NULL; + } else { + addVariable(v, true, is_user_defs); + item->setChanged(false); + } + } else if(!xmlStrcmp(cur->name, (const xmlChar*) "builtin_variable")) { + XML_GET_STRING_FROM_PROP(cur, "name", name) + v = getVariable(name); + if(v) { + XML_GET_FALSE_FROM_PROP(cur, "active", active) + v->setLocal(is_user_defs, active); + v->setCategory(category); + item = v; + child = cur->xmlChildrenNode; + ITEM_INIT_DTH + ITEM_INIT_NAME + while(child != NULL) { + ITEM_READ_NAME(variableNameIsValid) + else ITEM_READ_DTH + else { + ITEM_READ_NAMES + } + child = child->next; + } + if(new_names) { + ITEM_SAVE_BUILTIN_NAMES + ITEM_SET_BEST_NAMES(variableNameIsValid) + ITEM_SET_REFERENCE_NAMES(variableNameIsValid) + ITEM_SET_BUILTIN_NAMES + } else { + BUILTIN_NAMES_1 + ITEM_SET_NAME_2 + ITEM_SET_NAME_3 + BUILTIN_NAMES_2 + } + ITEM_SET_DTH + v->setChanged(false); + done_something = true; + } + } else if(!xmlStrcmp(cur->name, (const xmlChar*) "unit")) { + XML_GET_STRING_FROM_PROP(cur, "type", type) + if(type == "base") { + if(VERSION_BEFORE(0, 6, 3)) { + XML_GET_STRING_FROM_PROP(cur, "name", name) + } else { + name = ""; + } + XML_GET_FALSE_FROM_PROP(cur, "active", active) + u = new Unit(category, "", "", "", "", is_user_defs, false, active); + item = u; + child = cur->xmlChildrenNode; + singular = ""; best_singular = false; next_best_singular = false; + plural = ""; best_plural = false; next_best_plural = false; + countries = "", best_countries = false, next_best_countries = false; + use_with_prefixes_set = false; + ITEM_INIT_DTH + ITEM_INIT_NAME + while(child != NULL) { + if(!xmlStrcmp(child->name, (const xmlChar*) "system")) { + XML_DO_FROM_TEXT(child, u->setSystem) + } else if(!xmlStrcmp(child->name, (const xmlChar*) "use_with_prefixes")) { + XML_GET_TRUE_FROM_TEXT(child, use_with_prefixes) + use_with_prefixes_set = true; + } else if((VERSION_BEFORE(0, 6, 3)) && !xmlStrcmp(child->name, (const xmlChar*) "singular")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child, singular, best_singular, next_best_singular) + if(!unitNameIsValid(singular, version_numbers, is_user_defs)) { + singular = ""; + } + } else if((VERSION_BEFORE(0, 6, 3)) && !xmlStrcmp(child->name, (const xmlChar*) "plural") && !xmlGetProp(child, (xmlChar*) "index")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child, plural, best_plural, next_best_plural) + if(!unitNameIsValid(plural, version_numbers, is_user_defs)) { + plural = ""; + } + } else if(!xmlStrcmp(child->name, (const xmlChar*) "countries")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child, countries, best_countries, next_best_countries) + } else ITEM_READ_NAME(unitNameIsValid) + else ITEM_READ_DTH + else { + ITEM_READ_NAMES + } + child = child->next; + } + u->setCountries(countries); + if(new_names) { + ITEM_SET_BEST_NAMES(unitNameIsValid) + ITEM_SET_REFERENCE_NAMES(unitNameIsValid) + } else { + ITEM_SET_SHORT_NAME + ITEM_SET_SINGULAR + ITEM_SET_PLURAL + ITEM_SET_NAME_2 + ITEM_SET_NAME_3 + } + ITEM_SET_DTH + if(use_with_prefixes_set) { + u->setUseWithPrefixesByDefault(use_with_prefixes); + } + if(check_duplicates && !is_user_defs) { + for(size_t i = 1; i <= u->countNames();) { + if(getActiveVariable(u->getName(i).name) || getActiveUnit(u->getName(i).name) || getCompositeUnit(u->getName(i).name)) u->removeName(i); + else i++; + } + } + if(u->countNames() == 0) { + u->destroy(); + u = NULL; + } else { + if(!is_user_defs && u->referenceName() == "s") u_second = u; + addUnit(u, true, is_user_defs); + u->setChanged(false); + } + done_something = true; + } else if(type == "alias") { + if(VERSION_BEFORE(0, 6, 3)) { + XML_GET_STRING_FROM_PROP(cur, "name", name) + } else { + name = ""; + } + XML_GET_FALSE_FROM_PROP(cur, "active", active) + u = NULL; + child = cur->xmlChildrenNode; + singular = ""; best_singular = false; next_best_singular = false; + plural = ""; best_plural = false; next_best_plural = false; + countries = "", best_countries = false, next_best_countries = false; + bool b_currency = false; + use_with_prefixes_set = false; + usystem = ""; + prec = -1; + ITEM_INIT_DTH + ITEM_INIT_NAME + unc_rel = false; + while(child != NULL) { + if(!xmlStrcmp(child->name, (const xmlChar*) "base")) { + child2 = child->xmlChildrenNode; + exponent = 1; + mix_priority = 0; + mix_min = 0; + svalue = ""; + inverse = ""; + suncertainty = ""; + b = true; + while(child2 != NULL) { + if(!xmlStrcmp(child2->name, (const xmlChar*) "unit")) { + XML_GET_STRING_FROM_TEXT(child2, base); + u = getUnit(base); + b_currency = (!is_user_defs && u && u == u_euro); + if(!u) { + u = getCompositeUnit(base); + } + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "relation")) { + XML_GET_STRING_FROM_TEXT(child2, svalue); + XML_GET_APPROX_FROM_PROP(child2, b) + XML_GET_PREC_FROM_PROP(child2, prec) + XML_GET_STRING_FROM_PROP(child2, "relative_uncertainty", suncertainty) + if(suncertainty.empty()) {XML_GET_STRING_FROM_PROP(child2, "uncertainty", suncertainty)} + else unc_rel = true; + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "reverse_relation")) { + XML_GET_STRING_FROM_TEXT(child2, inverse); + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "inverse_relation")) { + XML_GET_STRING_FROM_TEXT(child2, inverse); + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "exponent")) { + XML_GET_STRING_FROM_TEXT(child2, stmp); + if(stmp.empty()) { + exponent = 1; + } else { + exponent = s2i(stmp); + } + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "mix")) { + XML_GET_INT_FROM_PROP(child2, "min", mix_min); + XML_GET_STRING_FROM_TEXT(child2, stmp); + if(stmp.empty()) { + mix_priority = 0; + } else { + mix_priority = s2i(stmp); + } + } + child2 = child2->next; + } + } else if(!xmlStrcmp(child->name, (const xmlChar*) "system")) { + XML_GET_STRING_FROM_TEXT(child, usystem); + } else if(!xmlStrcmp(child->name, (const xmlChar*) "use_with_prefixes")) { + XML_GET_TRUE_FROM_TEXT(child, use_with_prefixes) + use_with_prefixes_set = true; + } else if((VERSION_BEFORE(0, 6, 3)) && !xmlStrcmp(child->name, (const xmlChar*) "singular")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child, singular, best_singular, next_best_singular) + if(!unitNameIsValid(singular, version_numbers, is_user_defs)) { + singular = ""; + } + } else if((VERSION_BEFORE(0, 6, 3)) && !xmlStrcmp(child->name, (const xmlChar*) "plural") && !xmlGetProp(child, (xmlChar*) "index")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child, plural, best_plural, next_best_plural) + if(!unitNameIsValid(plural, version_numbers, is_user_defs)) { + plural = ""; + } + } else if(!xmlStrcmp(child->name, (const xmlChar*) "countries")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child, countries, best_countries, next_best_countries) + } else ITEM_READ_NAME(unitNameIsValid) + else ITEM_READ_DTH + else { + ITEM_READ_NAMES + } + child = child->next; + } + if(!u) { + ITEM_CLEAR_NAMES + if(!in_unfinished) { + unfinished_nodes.push_back(cur); + unfinished_cats.push_back(category); + } + } else { + au = new AliasUnit(category, name, plural, singular, title, u, svalue, exponent, inverse, is_user_defs, false, active); + au->setCountries(countries); + if(mix_priority > 0) { + au->setMixWithBase(mix_priority); + au->setMixWithBaseMinimum(mix_min); + } + au->setDescription(description); + au->setPrecision(prec); + if(b) au->setApproximate(true); + au->setUncertainty(suncertainty, unc_rel); + au->setHidden(hidden); + au->setSystem(usystem); + if(use_with_prefixes_set) { + au->setUseWithPrefixesByDefault(use_with_prefixes); + } + item = au; + if(new_names) { + ITEM_SET_BEST_NAMES(unitNameIsValid) + ITEM_SET_REFERENCE_NAMES(unitNameIsValid) + } else { + ITEM_SET_NAME_2 + ITEM_SET_NAME_3 + } + if(b_currency && !au->referenceName().empty()) { + u = getUnit(au->referenceName()); + if(u && u->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) u)->baseUnit() == u_euro) u->destroy(); + } + if(check_duplicates && !is_user_defs) { + for(size_t i = 1; i <= au->countNames();) { + if(getActiveVariable(au->getName(i).name) || getActiveUnit(au->getName(i).name) || getCompositeUnit(au->getName(i).name)) au->removeName(i); + else i++; + } + } + if(au->countNames() == 0) { + au->destroy(); + au = NULL; + } else { + if(!is_user_defs && au->baseUnit() == u_second) { + if(au->referenceName() == "d" || au->referenceName() == "day") u_day = au; + else if(au->referenceName() == "year") u_year = au; + else if(au->referenceName() == "month") u_month = au; + else if(au->referenceName() == "min") u_minute = au; + else if(au->referenceName() == "h") u_hour = au; + } + addUnit(au, true, is_user_defs); + au->setChanged(false); + } + done_something = true; + } + } else if(type == "composite") { + if(VERSION_BEFORE(0, 6, 3)) { + XML_GET_STRING_FROM_PROP(cur, "name", name) + } else { + name = ""; + } + XML_GET_FALSE_FROM_PROP(cur, "active", active) + child = cur->xmlChildrenNode; + usystem = ""; + cu = NULL; + ITEM_INIT_DTH + ITEM_INIT_NAME + b = true; + while(child != NULL) { + u = NULL; + if(!xmlStrcmp(child->name, (const xmlChar*) "part")) { + child2 = child->xmlChildrenNode; + p = NULL; + exponent = 1; + while(child2 != NULL) { + if(!xmlStrcmp(child2->name, (const xmlChar*) "unit")) { + XML_GET_STRING_FROM_TEXT(child2, base); + u = getUnit(base); + if(!u) { + u = getCompositeUnit(base); + } + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "prefix")) { + XML_GET_STRING_FROM_PROP(child2, "type", stmp) + XML_GET_STRING_FROM_TEXT(child2, svalue); + p = NULL; + if(stmp == "binary") { + litmp = s2i(svalue); + if(litmp != 0) { + p = getExactBinaryPrefix(litmp); + if(!p) b = false; + } + } else if(stmp == "number") { + nr.set(stmp); + if(!nr.isZero()) { + p = getExactPrefix(stmp); + if(!p) b = false; + } + } else { + litmp = s2i(svalue); + if(litmp != 0) { + p = getExactDecimalPrefix(litmp); + if(!p) b = false; + } + } + if(!b) { + if(cu) { + delete cu; + } + cu = NULL; + break; + } + } else if(!xmlStrcmp(child2->name, (const xmlChar*) "exponent")) { + XML_GET_STRING_FROM_TEXT(child2, stmp); + if(stmp.empty()) { + exponent = 1; + } else { + exponent = s2i(stmp); + } + } + child2 = child2->next; + } + if(!b) break; + if(u) { + if(!cu) { + cu = new CompositeUnit("", "", "", "", is_user_defs, false, active); + } + cu->add(u, exponent, p); + } else { + if(cu) delete cu; + cu = NULL; + if(!in_unfinished) { + unfinished_nodes.push_back(cur); + unfinished_cats.push_back(category); + } + break; + } + } else if(!xmlStrcmp(child->name, (const xmlChar*) "system")) { + XML_GET_STRING_FROM_TEXT(child, usystem); + } else if(!xmlStrcmp(child->name, (const xmlChar*) "use_with_prefixes")) { + XML_GET_TRUE_FROM_TEXT(child, use_with_prefixes) + use_with_prefixes_set = true; + } else ITEM_READ_NAME(unitNameIsValid) + else ITEM_READ_DTH + else { + ITEM_READ_NAMES + } + child = child->next; + } + if(cu) { + item = cu; + cu->setCategory(category); + cu->setSystem(usystem); + /*if(use_with_prefixes_set) { + cu->setUseWithPrefixesByDefault(use_with_prefixes); + }*/ + if(new_names) { + ITEM_SET_BEST_NAMES(unitNameIsValid) + ITEM_SET_REFERENCE_NAMES(unitNameIsValid) + } else { + ITEM_SET_NAME_1(unitNameIsValid) + ITEM_SET_NAME_2 + ITEM_SET_NAME_3 + } + ITEM_SET_DTH + if(check_duplicates && !is_user_defs) { + for(size_t i = 1; i <= cu->countNames();) { + if(getActiveVariable(cu->getName(i).name) || getActiveUnit(cu->getName(i).name) || getCompositeUnit(cu->getName(i).name)) cu->removeName(i); + else i++; + } + } + if(cu->countNames() == 0) { + cu->destroy(); + cu = NULL; + } else { + addUnit(cu, true, is_user_defs); + cu->setChanged(false); + } + done_something = true; + } else { + ITEM_CLEAR_NAMES + } + } + } else if(!xmlStrcmp(cur->name, (const xmlChar*) "builtin_unit")) { + XML_GET_STRING_FROM_PROP(cur, "name", name) + u = getUnit(name); + if(!u) { + u = getCompositeUnit(name); + } + if(u) { + XML_GET_FALSE_FROM_PROP(cur, "active", active) + u->setLocal(is_user_defs, active); + u->setCategory(category); + item = u; + child = cur->xmlChildrenNode; + singular = ""; best_singular = false; next_best_singular = false; + plural = ""; best_plural = false; next_best_plural = false; + countries = "", best_countries = false, next_best_countries = false; + use_with_prefixes_set = false; + ITEM_INIT_DTH + ITEM_INIT_NAME + while(child != NULL) { + if(!xmlStrcmp(child->name, (const xmlChar*) "singular")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child, singular, best_singular, next_best_singular) + if(!unitNameIsValid(singular, version_numbers, is_user_defs)) { + singular = ""; + } + } else if(!xmlStrcmp(child->name, (const xmlChar*) "plural") && !xmlGetProp(child, (xmlChar*) "index")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child, plural, best_plural, next_best_plural) + if(!unitNameIsValid(plural, version_numbers, is_user_defs)) { + plural = ""; + } + } else if(!xmlStrcmp(child->name, (const xmlChar*) "use_with_prefixes")) { + XML_GET_TRUE_FROM_TEXT(child, use_with_prefixes) + use_with_prefixes_set = true; + } else if(!xmlStrcmp(child->name, (const xmlChar*) "countries")) { + XML_GET_LOCALE_STRING_FROM_TEXT(child, countries, best_countries, next_best_countries) + } else ITEM_READ_NAME(unitNameIsValid) + else ITEM_READ_DTH + else { + ITEM_READ_NAMES + } + child = child->next; + } + if(use_with_prefixes_set) { + u->setUseWithPrefixesByDefault(use_with_prefixes); + } + u->setCountries(countries); + if(new_names) { + ITEM_SAVE_BUILTIN_NAMES + ITEM_SET_BEST_NAMES(unitNameIsValid) + ITEM_SET_REFERENCE_NAMES(unitNameIsValid) + ITEM_SET_BUILTIN_NAMES + } else { + BUILTIN_UNIT_NAMES_1 + ITEM_SET_SINGULAR + ITEM_SET_PLURAL + ITEM_SET_NAME_2 + ITEM_SET_NAME_3 + BUILTIN_NAMES_2 + } + ITEM_SET_DTH + if(u_usd && u->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) u)->firstBaseUnit() == u_usd) u->setHidden(true); + u->setChanged(false); + done_something = true; + } + } else if(!xmlStrcmp(cur->name, (const xmlChar*) "prefix")) { + child = cur->xmlChildrenNode; + XML_GET_STRING_FROM_PROP(cur, "type", type) + uname = ""; sexp = ""; svalue = ""; name = ""; + bool b_best = false; + while(child != NULL) { + if(!xmlStrcmp(child->name, (const xmlChar*) "name")) { + lang = xmlNodeGetLang(child); + if(!lang) { + if(name.empty()) { + XML_GET_STRING_FROM_TEXT(child, name); + } + } else { + if(!b_best && !locale.empty()) { + if(locale == (char*) lang) { + XML_GET_STRING_FROM_TEXT(child, name); + b_best = true; + } else if(strlen((char*) lang) >= 2 && lang[0] == localebase[0] && lang[1] == localebase[1]) { + XML_GET_STRING_FROM_TEXT(child, name); + } + } + xmlFree(lang); + } + } else if(!xmlStrcmp(child->name, (const xmlChar*) "abbreviation")) { + XML_GET_STRING_FROM_TEXT(child, stmp); + } else if(!xmlStrcmp(child->name, (const xmlChar*) "unicode")) { + XML_GET_STRING_FROM_TEXT(child, uname); + } else if(!xmlStrcmp(child->name, (const xmlChar*) "exponent")) { + XML_GET_STRING_FROM_TEXT(child, sexp); + } else if(!xmlStrcmp(child->name, (const xmlChar*) "value")) { + XML_GET_STRING_FROM_TEXT(child, svalue); + } + child = child->next; + } + if(type == "decimal") { + addPrefix(new DecimalPrefix(s2i(sexp), name, stmp, uname)); + } else if(type == "number") { + addPrefix(new NumberPrefix(svalue, name, stmp, uname)); + } else if(type == "binary") { + addPrefix(new BinaryPrefix(s2i(sexp), name, stmp, uname)); + } else { + if(svalue.empty()) { + addPrefix(new DecimalPrefix(s2i(sexp), name, stmp, uname)); + } else { + addPrefix(new NumberPrefix(svalue, name, stmp, uname)); + } + } + done_something = true; + } + after_load_object: + cur = NULL; + if(in_unfinished) { + if(done_something) { + in_unfinished--; + unfinished_nodes.erase(unfinished_nodes.begin() + in_unfinished); + unfinished_cats.erase(unfinished_cats.begin() + in_unfinished); + } + if((int) unfinished_nodes.size() > in_unfinished) { + cur = unfinished_nodes[in_unfinished]; + category = unfinished_cats[in_unfinished]; + } else if(done_something && unfinished_nodes.size() > 0) { + cur = unfinished_nodes[0]; + category = unfinished_cats[0]; + in_unfinished = 0; + done_something = false; + } + in_unfinished++; + done_something = false; + } + } + if(in_unfinished) { + break; + } + while(!nodes.empty() && nodes.back().empty()) { + size_t cat_i = category.rfind("/"); + if(cat_i == string::npos) { + category = ""; + } else { + category = category.substr(0, cat_i); + } + nodes.pop_back(); + } + if(!nodes.empty()) { + cur = nodes.back().front(); + nodes.back().pop(); + nodes.resize(nodes.size() + 1); + } else { + if(unfinished_nodes.size() > 0) { + cur = unfinished_nodes[0]; + category = unfinished_cats[0]; + in_unfinished = 1; + done_something = false; + } else { + cur = NULL; + } + } + if(cur == NULL) { + break; + } + } + xmlFreeDoc(doc); + return true; +} +bool Calculator::saveDefinitions() { + + recursiveMakeDir(getLocalDataDir()); + string homedir = buildPath(getLocalDataDir(), "definitions"); + makeDir(homedir); + bool b = true; + if(!saveFunctions(buildPath(homedir, "functions.xml").c_str())) b = false; + if(!saveUnits(buildPath(homedir, "units.xml").c_str())) b = false; + if(!saveVariables(buildPath(homedir, "variables.xml").c_str())) b = false; + if(!saveDataSets(buildPath(homedir, "datasets.xml").c_str())) b = false; + if(!saveDataObjects()) b = false; + return b; +} + +struct node_tree_item { + xmlNodePtr node; + string category; + vector items; +}; + +int Calculator::saveDataObjects() { + int returnvalue = 1; + for(size_t i = 0; i < data_sets.size(); i++) { + int rv = data_sets[i]->saveObjects(NULL, false); + if(rv <= 0) returnvalue = rv; + } + return returnvalue; +} + +int Calculator::savePrefixes(const char* file_name, bool save_global) { + if(!save_global) { + return true; + } + xmlDocPtr doc = xmlNewDoc((xmlChar*) "1.0"); + xmlNodePtr cur, newnode; + doc->children = xmlNewDocNode(doc, NULL, (xmlChar*) "QALCULATE", NULL); + xmlNewProp(doc->children, (xmlChar*) "version", (xmlChar*) VERSION); + cur = doc->children; + for(size_t i = 0; i < prefixes.size(); i++) { + newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "prefix", NULL); + if(!prefixes[i]->longName(false).empty()) xmlNewTextChild(newnode, NULL, (xmlChar*) "name", (xmlChar*) prefixes[i]->longName(false).c_str()); + if(!prefixes[i]->shortName(false).empty()) xmlNewTextChild(newnode, NULL, (xmlChar*) "abbreviation", (xmlChar*) prefixes[i]->shortName(false).c_str()); + if(!prefixes[i]->unicodeName(false).empty()) xmlNewTextChild(newnode, NULL, (xmlChar*) "unicode", (xmlChar*) prefixes[i]->unicodeName(false).c_str()); + switch(prefixes[i]->type()) { + case PREFIX_DECIMAL: { + xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "decimal"); + xmlNewTextChild(newnode, NULL, (xmlChar*) "exponent", (xmlChar*) i2s(((DecimalPrefix*) prefixes[i])->exponent()).c_str()); + break; + } + case PREFIX_BINARY: { + xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "binary"); + xmlNewTextChild(newnode, NULL, (xmlChar*) "exponent", (xmlChar*) i2s(((BinaryPrefix*) prefixes[i])->exponent()).c_str()); + break; + } + case PREFIX_NUMBER: { + xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "number"); + xmlNewTextChild(newnode, NULL, (xmlChar*) "value", (xmlChar*) prefixes[i]->value().print(save_printoptions).c_str()); + break; + } + } + } + int returnvalue = xmlSaveFormatFile(file_name, doc, 1); + xmlFreeDoc(doc); + return returnvalue; +} + +#define SAVE_NAMES(o)\ + str = "";\ + for(size_t i2 = 1;;) {\ + ename = &o->getName(i2);\ + if(ename->abbreviation) {str += 'a';}\ + bool b_cs = (ename->abbreviation || text_length_is_one(ename->name));\ + if(ename->case_sensitive && !b_cs) {str += 'c';}\ + if(!ename->case_sensitive && b_cs) {str += "-c";}\ + if(ename->avoid_input) {str += 'i';}\ + if(ename->completion_only) {str += 'o';}\ + if(ename->plural) {str += 'p';}\ + if(ename->reference) {str += 'r';}\ + if(ename->suffix) {str += 's';}\ + if(ename->unicode) {str += 'u';}\ + if(str.empty() || str[str.length() - 1] == ',') {\ + if(i2 == 1 && o->countNames() == 1) {\ + if(save_global) {\ + xmlNewTextChild(newnode, NULL, (xmlChar*) "_names", (xmlChar*) ename->name.c_str());\ + } else {\ + xmlNewTextChild(newnode, NULL, (xmlChar*) "names", (xmlChar*) ename->name.c_str());\ + }\ + break;\ + }\ + } else {\ + str += ':';\ + }\ + str += ename->name;\ + i2++;\ + if(i2 > o->countNames()) {\ + if(save_global) {\ + xmlNewTextChild(newnode, NULL, (xmlChar*) "_names", (xmlChar*) str.c_str());\ + } else {\ + xmlNewTextChild(newnode, NULL, (xmlChar*) "names", (xmlChar*) str.c_str());\ + }\ + break;\ + }\ + str += ',';\ + } + +string Calculator::temporaryCategory() const { + return _("Temporary"); +} + +int Calculator::saveVariables(const char* file_name, bool save_global) { + string str; + const ExpressionName *ename; + xmlDocPtr doc = xmlNewDoc((xmlChar*) "1.0"); + xmlNodePtr cur, newnode, newnode2; + doc->children = xmlNewDocNode(doc, NULL, (xmlChar*) "QALCULATE", NULL); + xmlNewProp(doc->children, (xmlChar*) "version", (xmlChar*) VERSION); + node_tree_item top; + top.category = ""; + top.node = doc->children; + node_tree_item *item; + string cat, cat_sub; + for(size_t i = 0; i < variables.size(); i++) { + if((save_global || variables[i]->isLocal() || variables[i]->hasChanged()) && variables[i]->category() != _("Temporary") && variables[i]->category() != "Temporary") { + item = ⊤ + if(!variables[i]->category().empty()) { + cat = variables[i]->category(); + size_t cat_i = cat.find("/"); size_t cat_i_prev = 0; + bool b = false; + while(true) { + if(cat_i == string::npos) { + cat_sub = cat.substr(cat_i_prev, cat.length() - cat_i_prev); + } else { + cat_sub = cat.substr(cat_i_prev, cat_i - cat_i_prev); + } + b = false; + for(size_t i2 = 0; i2 < item->items.size(); i2++) { + if(cat_sub == item->items[i2].category) { + item = &item->items[i2]; + b = true; + break; + } + } + if(!b) { + item->items.resize(item->items.size() + 1); + item->items[item->items.size() - 1].node = xmlNewTextChild(item->node, NULL, (xmlChar*) "category", NULL); + item = &item->items[item->items.size() - 1]; + item->category = cat_sub; + if(save_global) { + xmlNewTextChild(item->node, NULL, (xmlChar*) "_title", (xmlChar*) item->category.c_str()); + } else { + xmlNewTextChild(item->node, NULL, (xmlChar*) "title", (xmlChar*) item->category.c_str()); + } + } + if(cat_i == string::npos) { + break; + } + cat_i_prev = cat_i + 1; + cat_i = cat.find("/", cat_i_prev); + } + } + cur = item->node; + if(!save_global && !variables[i]->isLocal() && variables[i]->hasChanged()) { + if(variables[i]->isActive()) { + xmlNewTextChild(cur, NULL, (xmlChar*) "activate", (xmlChar*) variables[i]->referenceName().c_str()); + } else { + xmlNewTextChild(cur, NULL, (xmlChar*) "deactivate", (xmlChar*) variables[i]->referenceName().c_str()); + } + } else if(save_global || variables[i]->isLocal()) { + if(variables[i]->isBuiltin()) { + if(variables[i]->isKnown()) { + newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "builtin_variable", NULL); + } else { + newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "builtin_unknown", NULL); + } + xmlNewProp(newnode, (xmlChar*) "name", (xmlChar*) variables[i]->referenceName().c_str()); + } else { + if(variables[i]->isKnown()) { + newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "variable", NULL); + } else { + newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "unknown", NULL); + } + } + if(!variables[i]->isActive()) xmlNewProp(newnode, (xmlChar*) "active", (xmlChar*) "false"); + if(variables[i]->isHidden()) xmlNewTextChild(newnode, NULL, (xmlChar*) "hidden", (xmlChar*) "true"); + if(!variables[i]->title(false).empty()) { + if(save_global) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "_title", (xmlChar*) variables[i]->title(false).c_str()); + } else { + xmlNewTextChild(newnode, NULL, (xmlChar*) "title", (xmlChar*) variables[i]->title(false).c_str()); + } + } + SAVE_NAMES(variables[i]) + if(!variables[i]->description().empty()) { + str = variables[i]->description(); + if(save_global) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "_description", (xmlChar*) str.c_str()); + } else { + xmlNewTextChild(newnode, NULL, (xmlChar*) "description", (xmlChar*) str.c_str()); + } + } + if(!variables[i]->isBuiltin()) { + if(variables[i]->isKnown()) { + bool is_approx = false; + save_printoptions.is_approximate = &is_approx; + if(((KnownVariable*) variables[i])->isExpression()) { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "value", (xmlChar*) ((KnownVariable*) variables[i])->expression().c_str()); + bool unc_rel = false; + if(!((KnownVariable*) variables[i])->uncertainty(&unc_rel).empty()) xmlNewProp(newnode2, (xmlChar*) (unc_rel ? "relative_uncertainty" : "uncertainty"), (xmlChar*) ((KnownVariable*) variables[i])->uncertainty().c_str()); + if(!((KnownVariable*) variables[i])->unit().empty()) xmlNewProp(newnode2, (xmlChar*) "unit", (xmlChar*) ((KnownVariable*) variables[i])->unit().c_str()); + } else { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "value", (xmlChar*) ((KnownVariable*) variables[i])->get().print(save_printoptions).c_str()); + } + save_printoptions.is_approximate = NULL; + if(variables[i]->isApproximate() || is_approx) xmlNewProp(newnode2, (xmlChar*) "approximate", (xmlChar*) "true"); + if(variables[i]->precision() >= 0) xmlNewProp(newnode2, (xmlChar*) "precision", (xmlChar*) i2s(variables[i]->precision()).c_str()); + } else { + if(((UnknownVariable*) variables[i])->assumptions()) { + switch(((UnknownVariable*) variables[i])->assumptions()->type()) { + case ASSUMPTION_TYPE_INTEGER: { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "type", (xmlChar*) "integer"); + break; + } + case ASSUMPTION_TYPE_RATIONAL: { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "type", (xmlChar*) "rational"); + break; + } + case ASSUMPTION_TYPE_REAL: { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "type", (xmlChar*) "real"); + break; + } + case ASSUMPTION_TYPE_COMPLEX: { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "type", (xmlChar*) "complex"); + break; + } + case ASSUMPTION_TYPE_NUMBER: { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "type", (xmlChar*) "number"); + break; + } + case ASSUMPTION_TYPE_NONMATRIX: { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "type", (xmlChar*) "non-matrix"); + break; + } + case ASSUMPTION_TYPE_NONE: { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "type", (xmlChar*) "none"); + break; + } + } + switch(((UnknownVariable*) variables[i])->assumptions()->sign()) { + case ASSUMPTION_SIGN_NONZERO: { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "sign", (xmlChar*) "non-zero"); + break; + } + case ASSUMPTION_SIGN_NONPOSITIVE: { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "sign", (xmlChar*) "non-positive"); + break; + } + case ASSUMPTION_SIGN_NEGATIVE: { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "sign", (xmlChar*) "negative"); + break; + } + case ASSUMPTION_SIGN_NONNEGATIVE: { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "sign", (xmlChar*) "non-negative"); + break; + } + case ASSUMPTION_SIGN_POSITIVE: { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "sign", (xmlChar*) "positive"); + break; + } + case ASSUMPTION_SIGN_UNKNOWN: { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "sign", (xmlChar*) "unknown"); + break; + } + } + } + } + } + } + } + } + int returnvalue = xmlSaveFormatFile(file_name, doc, 1); + xmlFreeDoc(doc); + return returnvalue; +} + +int Calculator::saveUnits(const char* file_name, bool save_global) { + string str; + xmlDocPtr doc = xmlNewDoc((xmlChar*) "1.0"); + xmlNodePtr cur, newnode, newnode2, newnode3; + doc->children = xmlNewDocNode(doc, NULL, (xmlChar*) "QALCULATE", NULL); + xmlNewProp(doc->children, (xmlChar*) "version", (xmlChar*) VERSION); + const ExpressionName *ename; + CompositeUnit *cu = NULL; + AliasUnit *au = NULL; + Unit *u; + node_tree_item top; + top.category = ""; + top.node = doc->children; + node_tree_item *item; + string cat, cat_sub; + for(size_t i = 0; i < units.size(); i++) { + u = units[i]; + if(save_global || u->isLocal() || u->hasChanged()) { + item = ⊤ + if(!u->category().empty()) { + cat = u->category(); + size_t cat_i = cat.find("/"); size_t cat_i_prev = 0; + bool b = false; + while(true) { + if(cat_i == string::npos) { + cat_sub = cat.substr(cat_i_prev, cat.length() - cat_i_prev); + } else { + cat_sub = cat.substr(cat_i_prev, cat_i - cat_i_prev); + } + b = false; + for(size_t i2 = 0; i2 < item->items.size(); i2++) { + if(cat_sub == item->items[i2].category) { + item = &item->items[i2]; + b = true; + break; + } + } + if(!b) { + item->items.resize(item->items.size() + 1); + item->items[item->items.size() - 1].node = xmlNewTextChild(item->node, NULL, (xmlChar*) "category", NULL); + item = &item->items[item->items.size() - 1]; + item->category = cat_sub; + if(save_global) { + xmlNewTextChild(item->node, NULL, (xmlChar*) "_title", (xmlChar*) item->category.c_str()); + } else { + xmlNewTextChild(item->node, NULL, (xmlChar*) "title", (xmlChar*) item->category.c_str()); + } + } + if(cat_i == string::npos) { + break; + } + cat_i_prev = cat_i + 1; + cat_i = cat.find("/", cat_i_prev); + } + } + cur = item->node; + if(!save_global && !u->isLocal() && u->hasChanged()) { + if(u->isActive()) { + xmlNewTextChild(cur, NULL, (xmlChar*) "activate", (xmlChar*) u->referenceName().c_str()); + } else { + xmlNewTextChild(cur, NULL, (xmlChar*) "deactivate", (xmlChar*) u->referenceName().c_str()); + } + } else if(save_global || u->isLocal()) { + if(u->isBuiltin()) { + newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "builtin_unit", NULL); + xmlNewProp(newnode, (xmlChar*) "name", (xmlChar*) u->referenceName().c_str()); + } else { + newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "unit", NULL); + switch(u->subtype()) { + case SUBTYPE_BASE_UNIT: { + xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "base"); + break; + } + case SUBTYPE_ALIAS_UNIT: { + au = (AliasUnit*) u; + xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "alias"); + break; + } + case SUBTYPE_COMPOSITE_UNIT: { + cu = (CompositeUnit*) u; + xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "composite"); + break; + } + } + } + if(!u->isActive()) xmlNewProp(newnode, (xmlChar*) "active", (xmlChar*) "false"); + if(u->isHidden()) xmlNewTextChild(newnode, NULL, (xmlChar*) "hidden", (xmlChar*) "true"); + if(!u->system().empty()) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "system", (xmlChar*) u->system().c_str()); + } + if(!u->isSIUnit() || !u->useWithPrefixesByDefault()) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "use_with_prefixes", u->useWithPrefixesByDefault() ? (xmlChar*) "true" : (xmlChar*) "false"); + } + if(!u->title(false).empty()) { + if(save_global) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "_title", (xmlChar*) u->title(false).c_str()); + } else { + xmlNewTextChild(newnode, NULL, (xmlChar*) "title", (xmlChar*) u->title(false).c_str()); + } + } + if(save_global && u->subtype() == SUBTYPE_COMPOSITE_UNIT) { + save_global = false; + SAVE_NAMES(u) + save_global = true; + } else { + SAVE_NAMES(u) + } + if(!u->description().empty()) { + str = u->description(); + if(save_global) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "_description", (xmlChar*) str.c_str()); + } else { + xmlNewTextChild(newnode, NULL, (xmlChar*) "description", (xmlChar*) str.c_str()); + } + } + if(!u->isBuiltin()) { + if(u->subtype() == SUBTYPE_COMPOSITE_UNIT) { + for(size_t i2 = 1; i2 <= cu->countUnits(); i2++) { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "part", NULL); + int exp = 1; + Prefix *p = NULL; + Unit *u = cu->get(i2, &exp, &p); + xmlNewTextChild(newnode2, NULL, (xmlChar*) "unit", (xmlChar*) u->referenceName().c_str()); + if(p) { + switch(p->type()) { + case PREFIX_DECIMAL: { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "prefix", (xmlChar*) i2s(((DecimalPrefix*) p)->exponent()).c_str()); + break; + } + case PREFIX_BINARY: { + newnode3 = xmlNewTextChild(newnode2, NULL, (xmlChar*) "prefix", (xmlChar*) i2s(((BinaryPrefix*) p)->exponent()).c_str()); + xmlNewProp(newnode3, (xmlChar*) "type", (xmlChar*) "binary"); + break; + } + case PREFIX_NUMBER: { + newnode3 = xmlNewTextChild(newnode2, NULL, (xmlChar*) "prefix", (xmlChar*) p->value().print(save_printoptions).c_str()); + xmlNewProp(newnode3, (xmlChar*) "type", (xmlChar*) "number"); + break; + } + } + } + xmlNewTextChild(newnode2, NULL, (xmlChar*) "exponent", (xmlChar*) i2s(exp).c_str()); + } + } + if(u->subtype() == SUBTYPE_ALIAS_UNIT) { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "base", NULL); + xmlNewTextChild(newnode2, NULL, (xmlChar*) "unit", (xmlChar*) au->firstBaseUnit()->referenceName().c_str()); + newnode3 = xmlNewTextChild(newnode2, NULL, (xmlChar*) "relation", (xmlChar*) au->expression().c_str()); + if(au->isApproximate()) xmlNewProp(newnode3, (xmlChar*) "approximate", (xmlChar*) "true"); + if(au->precision() >= 0) xmlNewProp(newnode3, (xmlChar*) "precision", (xmlChar*) i2s(u->precision()).c_str()); + bool unc_rel = false; + if(!au->uncertainty(&unc_rel).empty()) xmlNewProp(newnode3, (xmlChar*) (unc_rel ? "relative_uncertainty" : "uncertainty"), (xmlChar*) au->uncertainty().c_str()); + if(!au->inverseExpression().empty()) { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "inverse_relation", (xmlChar*) au->inverseExpression().c_str()); + } + xmlNewTextChild(newnode2, NULL, (xmlChar*) "exponent", (xmlChar*) i2s(au->firstBaseExponent()).c_str()); + if(au->mixWithBase() > 0) { + newnode3 = xmlNewTextChild(newnode2, NULL, (xmlChar*) "mix", (xmlChar*) i2s(au->mixWithBase()).c_str()); + if(au->mixWithBaseMinimum() > 1) xmlNewProp(newnode3, (xmlChar*) "min", (xmlChar*) i2s(au->mixWithBaseMinimum()).c_str()); + } + } + } + } + } + } + int returnvalue = xmlSaveFormatFile(file_name, doc, 1); + xmlFreeDoc(doc); + return returnvalue; +} + +int Calculator::saveFunctions(const char* file_name, bool save_global) { + xmlDocPtr doc = xmlNewDoc((xmlChar*) "1.0"); + xmlNodePtr cur, newnode, newnode2; + doc->children = xmlNewDocNode(doc, NULL, (xmlChar*) "QALCULATE", NULL); + xmlNewProp(doc->children, (xmlChar*) "version", (xmlChar*) VERSION); + const ExpressionName *ename; + node_tree_item top; + top.category = ""; + top.node = doc->children; + node_tree_item *item; + string cat, cat_sub; + Argument *arg; + IntegerArgument *iarg; + NumberArgument *farg; + string str; + for(size_t i = 0; i < functions.size(); i++) { + if(functions[i]->subtype() != SUBTYPE_DATA_SET && (save_global || functions[i]->isLocal() || functions[i]->hasChanged())) { + item = ⊤ + if(!functions[i]->category().empty()) { + cat = functions[i]->category(); + size_t cat_i = cat.find("/"); size_t cat_i_prev = 0; + bool b = false; + while(true) { + if(cat_i == string::npos) { + cat_sub = cat.substr(cat_i_prev, cat.length() - cat_i_prev); + } else { + cat_sub = cat.substr(cat_i_prev, cat_i - cat_i_prev); + } + b = false; + for(size_t i2 = 0; i2 < item->items.size(); i2++) { + if(cat_sub == item->items[i2].category) { + item = &item->items[i2]; + b = true; + break; + } + } + if(!b) { + item->items.resize(item->items.size() + 1); + item->items[item->items.size() - 1].node = xmlNewTextChild(item->node, NULL, (xmlChar*) "category", NULL); + item = &item->items[item->items.size() - 1]; + item->category = cat_sub; + if(save_global) { + xmlNewTextChild(item->node, NULL, (xmlChar*) "_title", (xmlChar*) item->category.c_str()); + } else { + xmlNewTextChild(item->node, NULL, (xmlChar*) "title", (xmlChar*) item->category.c_str()); + } + } + if(cat_i == string::npos) { + break; + } + cat_i_prev = cat_i + 1; + cat_i = cat.find("/", cat_i_prev); + } + } + cur = item->node; + if(!save_global && !functions[i]->isLocal() && functions[i]->hasChanged()) { + if(functions[i]->isActive()) { + xmlNewTextChild(cur, NULL, (xmlChar*) "activate", (xmlChar*) functions[i]->referenceName().c_str()); + } else { + xmlNewTextChild(cur, NULL, (xmlChar*) "deactivate", (xmlChar*) functions[i]->referenceName().c_str()); + } + } else if(save_global || functions[i]->isLocal()) { + if(functions[i]->isBuiltin()) { + newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "builtin_function", NULL); + xmlNewProp(newnode, (xmlChar*) "name", (xmlChar*) functions[i]->referenceName().c_str()); + } else { + newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "function", NULL); + } + if(!functions[i]->isActive()) xmlNewProp(newnode, (xmlChar*) "active", (xmlChar*) "false"); + if(functions[i]->isHidden()) xmlNewTextChild(newnode, NULL, (xmlChar*) "hidden", (xmlChar*) "true"); + if(!functions[i]->title(false).empty()) { + if(save_global) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "_title", (xmlChar*) functions[i]->title(false).c_str()); + } else { + xmlNewTextChild(newnode, NULL, (xmlChar*) "title", (xmlChar*) functions[i]->title(false).c_str()); + } + } + SAVE_NAMES(functions[i]) + if(!functions[i]->description().empty()) { + str = functions[i]->description(); + if(save_global) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "_description", (xmlChar*) str.c_str()); + } else { + xmlNewTextChild(newnode, NULL, (xmlChar*) "description", (xmlChar*) str.c_str()); + } + } + if(!functions[i]->example(true).empty()) newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "example", (xmlChar*) functions[i]->example(true).c_str()); + if(functions[i]->isBuiltin()) { + cur = newnode; + for(size_t i2 = 1; i2 <= functions[i]->lastArgumentDefinitionIndex(); i2++) { + arg = functions[i]->getArgumentDefinition(i2); + if(arg && !arg->name().empty()) { + newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "argument", NULL); + if(save_global) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "_title", (xmlChar*) arg->name().c_str()); + } else { + xmlNewTextChild(newnode, NULL, (xmlChar*) "title", (xmlChar*) arg->name().c_str()); + } + xmlNewProp(newnode, (xmlChar*) "index", (xmlChar*) i2s(i2).c_str()); + } + } + } else { + for(size_t i2 = 1; i2 <= ((UserFunction*) functions[i])->countSubfunctions(); i2++) { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "subfunction", (xmlChar*) ((UserFunction*) functions[i])->getSubfunction(i2).c_str()); + if(((UserFunction*) functions[i])->subfunctionPrecalculated(i2)) xmlNewProp(newnode2, (xmlChar*) "precalculate", (xmlChar*) "true"); + else xmlNewProp(newnode2, (xmlChar*) "precalculate", (xmlChar*) "false"); + + } + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "expression", (xmlChar*) ((UserFunction*) functions[i])->formula().c_str()); + if(functions[i]->isApproximate()) xmlNewProp(newnode2, (xmlChar*) "approximate", (xmlChar*) "true"); + if(functions[i]->precision() >= 0) xmlNewProp(newnode2, (xmlChar*) "precision", (xmlChar*) i2s(functions[i]->precision()).c_str()); + if(!functions[i]->condition().empty()) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "condition", (xmlChar*) functions[i]->condition().c_str()); + } + cur = newnode; + for(size_t i2 = 1; i2 <= functions[i]->lastArgumentDefinitionIndex(); i2++) { + arg = functions[i]->getArgumentDefinition(i2); + if(arg) { + newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "argument", NULL); + if(!arg->name().empty()) { + if(save_global) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "_title", (xmlChar*) arg->name().c_str()); + } else { + xmlNewTextChild(newnode, NULL, (xmlChar*) "title", (xmlChar*) arg->name().c_str()); + } + } + switch(arg->type()) { + case ARGUMENT_TYPE_TEXT: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "text"); break;} + case ARGUMENT_TYPE_SYMBOLIC: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "symbol"); break;} + case ARGUMENT_TYPE_DATE: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "date"); break;} + case ARGUMENT_TYPE_INTEGER: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "integer"); break;} + case ARGUMENT_TYPE_NUMBER: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "number"); break;} + case ARGUMENT_TYPE_VECTOR: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "vector"); break;} + case ARGUMENT_TYPE_MATRIX: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "matrix"); break;} + case ARGUMENT_TYPE_BOOLEAN: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "boolean"); break;} + case ARGUMENT_TYPE_FUNCTION: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "function"); break;} + case ARGUMENT_TYPE_UNIT: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "unit"); break;} + case ARGUMENT_TYPE_VARIABLE: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "variable"); break;} + case ARGUMENT_TYPE_EXPRESSION_ITEM: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "object"); break;} + case ARGUMENT_TYPE_ANGLE: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "angle"); break;} + case ARGUMENT_TYPE_DATA_OBJECT: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "data-object"); break;} + case ARGUMENT_TYPE_DATA_PROPERTY: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "data-property"); break;} + default: {xmlNewProp(newnode, (xmlChar*) "type", (xmlChar*) "free");} + } + xmlNewProp(newnode, (xmlChar*) "index", (xmlChar*) i2s(i2).c_str()); + if(!arg->tests()) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "test", (xmlChar*) "false"); + } + if(!arg->alerts()) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "alert", (xmlChar*) "false"); + } + if(arg->zeroForbidden()) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "zero_forbidden", (xmlChar*) "true"); + } + if(arg->matrixAllowed()) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "matrix_allowed", (xmlChar*) "true"); + } + switch(arg->type()) { + case ARGUMENT_TYPE_INTEGER: { + iarg = (IntegerArgument*) arg; + if(iarg->min()) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "min", (xmlChar*) iarg->min()->print(save_printoptions).c_str()); + } + if(iarg->max()) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "max", (xmlChar*) iarg->max()->print(save_printoptions).c_str()); + } + break; + } + case ARGUMENT_TYPE_NUMBER: { + farg = (NumberArgument*) arg; + if(farg->min()) { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "min", (xmlChar*) farg->min()->print(save_printoptions).c_str()); + if(farg->includeEqualsMin()) { + xmlNewProp(newnode2, (xmlChar*) "include_equals", (xmlChar*) "true"); + } else { + xmlNewProp(newnode2, (xmlChar*) "include_equals", (xmlChar*) "false"); + } + } + if(farg->max()) { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "max", (xmlChar*) farg->max()->print(save_printoptions).c_str()); + if(farg->includeEqualsMax()) { + xmlNewProp(newnode2, (xmlChar*) "include_equals", (xmlChar*) "true"); + } else { + xmlNewProp(newnode2, (xmlChar*) "include_equals", (xmlChar*) "false"); + } + } + if(!farg->complexAllowed()) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "complex_allowed", (xmlChar*) "false"); + } + break; + } + } + if(!arg->getCustomCondition().empty()) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "condition", (xmlChar*) arg->getCustomCondition().c_str()); + } + } + } + } + } + } + } + int returnvalue = xmlSaveFormatFile(file_name, doc, 1); + xmlFreeDoc(doc); + return returnvalue; +} +int Calculator::saveDataSets(const char* file_name, bool save_global) { + xmlDocPtr doc = xmlNewDoc((xmlChar*) "1.0"); + xmlNodePtr cur, newnode, newnode2; + doc->children = xmlNewDocNode(doc, NULL, (xmlChar*) "QALCULATE", NULL); + xmlNewProp(doc->children, (xmlChar*) "version", (xmlChar*) VERSION); + const ExpressionName *ename; + node_tree_item top; + top.category = ""; + top.node = doc->children; + node_tree_item *item; + string cat, cat_sub; + Argument *arg; + DataSet *ds; + DataProperty *dp; + string str; + for(size_t i = 0; i < functions.size(); i++) { + if(functions[i]->subtype() == SUBTYPE_DATA_SET && (save_global || functions[i]->isLocal() || functions[i]->hasChanged())) { + item = ⊤ + ds = (DataSet*) functions[i]; + if(!ds->category().empty()) { + cat = ds->category(); + size_t cat_i = cat.find("/"); size_t cat_i_prev = 0; + bool b = false; + while(true) { + if(cat_i == string::npos) { + cat_sub = cat.substr(cat_i_prev, cat.length() - cat_i_prev); + } else { + cat_sub = cat.substr(cat_i_prev, cat_i - cat_i_prev); + } + b = false; + for(size_t i2 = 0; i2 < item->items.size(); i2++) { + if(cat_sub == item->items[i2].category) { + item = &item->items[i2]; + b = true; + break; + } + } + if(!b) { + item->items.resize(item->items.size() + 1); + item->items[item->items.size() - 1].node = xmlNewTextChild(item->node, NULL, (xmlChar*) "category", NULL); + item = &item->items[item->items.size() - 1]; + item->category = cat_sub; + if(save_global) { + xmlNewTextChild(item->node, NULL, (xmlChar*) "_title", (xmlChar*) item->category.c_str()); + } else { + xmlNewTextChild(item->node, NULL, (xmlChar*) "title", (xmlChar*) item->category.c_str()); + } + } + if(cat_i == string::npos) { + break; + } + cat_i_prev = cat_i + 1; + cat_i = cat.find("/", cat_i_prev); + } + } + cur = item->node; + if(save_global || ds->isLocal() || ds->hasChanged()) { + if(save_global || ds->isLocal()) { + newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "dataset", NULL); + } else { + newnode = xmlNewTextChild(cur, NULL, (xmlChar*) "builtin_dataset", NULL); + xmlNewProp(newnode, (xmlChar*) "name", (xmlChar*) ds->referenceName().c_str()); + } + if(!ds->isActive()) xmlNewProp(newnode, (xmlChar*) "active", (xmlChar*) "false"); + if(ds->isHidden()) xmlNewTextChild(newnode, NULL, (xmlChar*) "hidden", (xmlChar*) "true"); + if(!ds->title(false).empty()) { + if(save_global) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "_title", (xmlChar*) ds->title(false).c_str()); + } else { + xmlNewTextChild(newnode, NULL, (xmlChar*) "title", (xmlChar*) ds->title(false).c_str()); + } + } + if((save_global || ds->isLocal()) && !ds->defaultDataFile().empty()) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "datafile", (xmlChar*) ds->defaultDataFile().c_str()); + } + SAVE_NAMES(ds) + if(!ds->description().empty()) { + str = ds->description(); + if(save_global) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "_description", (xmlChar*) str.c_str()); + } else { + xmlNewTextChild(newnode, NULL, (xmlChar*) "description", (xmlChar*) str.c_str()); + } + } + if((save_global || ds->isLocal()) && !ds->copyright().empty()) { + if(save_global) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "_copyright", (xmlChar*) ds->copyright().c_str()); + } else { + xmlNewTextChild(newnode, NULL, (xmlChar*) "copyright", (xmlChar*) ds->copyright().c_str()); + } + } + arg = ds->getArgumentDefinition(1); + if(arg && ((!save_global && !ds->isLocal()) || arg->name() != _("Object"))) { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "object_argument", NULL); + if(save_global) { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "_title", (xmlChar*) arg->name().c_str()); + } else { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "title", (xmlChar*) arg->name().c_str()); + } + } + arg = ds->getArgumentDefinition(2); + if(arg && ((!save_global && !ds->isLocal()) || arg->name() != _("Property"))) { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "property_argument", NULL); + if(save_global) { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "_title", (xmlChar*) arg->name().c_str()); + } else { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "title", (xmlChar*) arg->name().c_str()); + } + } + if((!save_global && !ds->isLocal()) || ds->getDefaultValue(2) != _("info")) { + xmlNewTextChild(newnode, NULL, (xmlChar*) "default_property", (xmlChar*) ds->getDefaultValue(2).c_str()); + } + DataPropertyIter it; + dp = ds->getFirstProperty(&it); + while(dp) { + if(save_global || ds->isLocal() || dp->isUserModified()) { + newnode2 = xmlNewTextChild(newnode, NULL, (xmlChar*) "property", NULL); + if(!dp->title(false).empty()) { + if(save_global) { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "_title", (xmlChar*) dp->title().c_str()); + } else { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "title", (xmlChar*) dp->title().c_str()); + } + } + switch(dp->propertyType()) { + case PROPERTY_STRING: { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "type", (xmlChar*) "text"); + break; + } + case PROPERTY_NUMBER: { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "type", (xmlChar*) "number"); + break; + } + case PROPERTY_EXPRESSION: { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "type", (xmlChar*) "expression"); + break; + } + } + if(dp->isHidden()) { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "hidden", (xmlChar*) "true"); + } + if(dp->isKey()) { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "key", (xmlChar*) "true"); + } + if(dp->isApproximate()) { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "approximate", (xmlChar*) "true"); + } + if(dp->usesBrackets()) { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "brackets", (xmlChar*) "true"); + } + if(dp->isCaseSensitive()) { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "case_sensitive", (xmlChar*) "true"); + } + if(!dp->getUnitString().empty()) { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "unit", (xmlChar*) dp->getUnitString().c_str()); + } + str = ""; + for(size_t i2 = 1;;) { + if(dp->nameIsReference(i2)) {str += 'r';} + if(str.empty() || str[str.length() - 1] == ',') { + if(i2 == 1 && dp->countNames() == 1) { + if(save_global) { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "_names", (xmlChar*) dp->getName(i2).c_str()); + } else { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "names", (xmlChar*) dp->getName(i2).c_str()); + } + break; + } + } else { + str += ':'; + } + str += dp->getName(i2); + i2++; + if(i2 > dp->countNames()) { + if(save_global) { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "_names", (xmlChar*) str.c_str()); + } else { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "names", (xmlChar*) str.c_str()); + } + break; + } + str += ','; + } + if(!dp->description().empty()) { + str = dp->description(); + if(save_global) { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "_description", (xmlChar*) str.c_str()); + } else { + xmlNewTextChild(newnode2, NULL, (xmlChar*) "description", (xmlChar*) str.c_str()); + } + } + } + dp = ds->getNextProperty(&it); + } + } + } + } + int returnvalue = xmlSaveFormatFile(file_name, doc, 1); + xmlFreeDoc(doc); + return returnvalue; +} + +bool Calculator::importCSV(MathStructure &mstruct, const char *file_name, int first_row, string delimiter, vector *headers) { + FILE *file = fopen(file_name, "r"); + if(file == NULL) { + return false; + } + if(first_row < 1) { + first_row = 1; + } + char line[10000]; + string stmp, str1, str2; + long int row = 0, rows = 1; + int columns = 1; + int column; + mstruct = m_empty_matrix; + size_t is, is_n; + bool v_added = false; + while(fgets(line, 10000, file)) { + row++; + if(row >= first_row) { + stmp = line; + remove_blank_ends(stmp); + if(row == first_row) { + if(stmp.empty()) { + row--; + } else { + is = 0; + while((is_n = stmp.find(delimiter, is)) != string::npos) { + columns++; + if(headers) { + str1 = stmp.substr(is, is_n - is); + remove_blank_ends(str1); + headers->push_back(str1); + } + is = is_n + delimiter.length(); + } + if(headers) { + str1 = stmp.substr(is, stmp.length() - is); + remove_blank_ends(str1); + headers->push_back(str1); + } + mstruct.resizeMatrix(1, columns, m_undefined); + } + } + if((!headers || row > first_row) && !stmp.empty()) { + is = 0; + column = 1; + if(v_added) { + mstruct.addRow(m_undefined); + rows++; + } + while(column <= columns) { + is_n = stmp.find(delimiter, is); + if(is_n == string::npos) { + str1 = stmp.substr(is, stmp.length() - is); + } else { + str1 = stmp.substr(is, is_n - is); + is = is_n + delimiter.length(); + } + parse(&mstruct[rows - 1][column - 1], str1); + column++; + if(is_n == string::npos) { + break; + } + } + v_added = true; + } + } + } + return true; +} + +bool Calculator::importCSV(const char *file_name, int first_row, bool headers, string delimiter, bool to_matrix, string name, string title, string category) { + FILE *file = fopen(file_name, "r"); + if(file == NULL) { + return false; + } + if(first_row < 1) { + first_row = 1; + } + string filestr = file_name; + remove_blank_ends(filestr); + size_t i = filestr.find_last_of("/"); + if(i != string::npos) { + filestr = filestr.substr(i + 1, filestr.length() - (i + 1)); + } + remove_blank_ends(name); + if(name.empty()) { + name = filestr; + i = name.find_last_of("/"); + if(i != string::npos) name = name.substr(i + 1, name.length() - i); + i = name.find_last_of("."); + if(i != string::npos) name = name.substr(0, i); + } + + char line[10000]; + string stmp, str1, str2; + int row = 0; + int columns = 1, rows = 1; + int column; + vector header; + vector vectors; + MathStructure mstruct = m_empty_matrix; + size_t is, is_n; + bool v_added = false; + while(fgets(line, 10000, file)) { + row++; + if(row >= first_row) { + stmp = line; + remove_blank_ends(stmp); + if(row == first_row) { + if(stmp.empty()) { + row--; + } else { + is = 0; + while((is_n = stmp.find(delimiter, is)) != string::npos) { + columns++; + if(headers) { + str1 = stmp.substr(is, is_n - is); + remove_blank_ends(str1); + header.push_back(str1); + } + if(!to_matrix) { + vectors.push_back(m_empty_vector); + } + is = is_n + delimiter.length(); + } + if(headers) { + str1 = stmp.substr(is, stmp.length() - is); + remove_blank_ends(str1); + header.push_back(str1); + } + if(to_matrix) { + mstruct.resizeMatrix(1, columns, m_undefined); + } else { + vectors.push_back(m_empty_vector); + } + } + } + if((!headers || row > first_row) && !stmp.empty()) { + if(to_matrix && v_added) { + mstruct.addRow(m_undefined); + rows++; + } + is = 0; + column = 1; + while(column <= columns) { + is_n = stmp.find(delimiter, is); + if(is_n == string::npos) { + str1 = stmp.substr(is, stmp.length() - is); + } else { + str1 = stmp.substr(is, is_n - is); + is = is_n + delimiter.length(); + } + if(to_matrix) { + parse(&mstruct[rows - 1][column - 1], str1); + } else { + vectors[column - 1].addChild(parse(str1)); + } + column++; + if(is_n == string::npos) { + break; + } + } + for(; column <= columns; column++) { + if(!to_matrix) { + vectors[column - 1].addChild(m_undefined); + } + } + v_added = true; + } + } + } + if(to_matrix) { + addVariable(new KnownVariable(category, name, mstruct, title)); + } else { + if(vectors.size() > 1) { + if(!category.empty()) { + category += "/"; + } + category += name; + } + for(size_t i = 0; i < vectors.size(); i++) { + str1 = ""; + str2 = ""; + if(vectors.size() > 1) { + str1 += name; + str1 += "_"; + if(title.empty()) { + str2 += name; + str2 += " "; + } else { + str2 += title; + str2 += " "; + } + if(i < header.size()) { + str1 += header[i]; + str2 += header[i]; + } else { + str1 += _("column"); + str1 += "_"; + str1 += i2s(i + 1); + str2 += _("Column "); + str2 += i2s(i + 1); + } + gsub(" ", "_", str1); + } else { + str1 = name; + str2 = title; + if(i < header.size()) { + str2 += " ("; + str2 += header[i]; + str2 += ")"; + } + } + addVariable(new KnownVariable(category, str1, vectors[i], str2)); + } + } + return true; +} +bool Calculator::exportCSV(const MathStructure &mstruct, const char *file_name, string delimiter) { + FILE *file = fopen(file_name, "w+"); + if(file == NULL) { + return false; + } + MathStructure mcsv(mstruct); + PrintOptions po; + po.number_fraction_format = FRACTION_DECIMAL; + po.decimalpoint_sign = "."; + po.comma_sign = ","; + if(mcsv.isMatrix()) { + for(size_t i = 0; i < mcsv.size(); i++) { + for(size_t i2 = 0; i2 < mcsv[i].size(); i2++) { + if(i2 > 0) fputs(delimiter.c_str(), file); + mcsv[i][i2].format(po); + fputs(mcsv[i][i2].print(po).c_str(), file); + } + fputs("\n", file); + } + } else if(mcsv.isVector()) { + for(size_t i = 0; i < mcsv.size(); i++) { + mcsv[i].format(po); + fputs(mcsv[i].print(po).c_str(), file); + fputs("\n", file); + } + } else { + mcsv.format(po); + fputs(mcsv.print(po).c_str(), file); + fputs("\n", file); + } + fclose(file); + return true; +} + +bool Calculator::loadExchangeRates() { + xmlDocPtr doc = NULL; + xmlNodePtr cur = NULL; + xmlChar *value; + bool global_file = false; + string currency, rate, sdate; + string filename = buildPath(getLocalDataDir(), "eurofxref-daily.xml"); + if(fileExists(filename)) { + doc = xmlParseFile(filename.c_str()); + } else { +#ifndef _WIN32 + string filename_old = buildPath(getOldLocalDir(), "eurofxref-daily.xml"); + if(fileExists(filename)) { + doc = xmlParseFile(filename_old.c_str()); + if(doc) { + recursiveMakeDir(getLocalDataDir()); + move_file(filename_old.c_str(), filename.c_str()); + removeDir(getOldLocalDir()); + } + } +#endif + } + if(doc) cur = xmlDocGetRootElement(doc); + if(!cur) { + if(doc) xmlFreeDoc(doc); + filename = buildPath(getGlobalDefinitionsDir(), "eurofxref-daily.xml"); + doc = xmlParseFile(filename.c_str()); + if(!doc) return false; + cur = xmlDocGetRootElement(doc); + if(!cur) return false; + global_file = true; + } + Unit *u; + while(cur) { + if(!xmlStrcmp(cur->name, (const xmlChar*) "Cube")) { + if(global_file && sdate.empty()) { + XML_GET_STRING_FROM_PROP(cur, "time", sdate); + QalculateDateTime qdate; + if(qdate.set(sdate)) { + exchange_rates_time[0] = (time_t) qdate.timestamp().ulintValue(); + if(exchange_rates_time[0] > exchange_rates_check_time[0]) exchange_rates_check_time[0] = exchange_rates_time[0]; + } else { + sdate.clear(); + } + } + XML_GET_STRING_FROM_PROP(cur, "currency", currency); + if(!currency.empty()) { + XML_GET_STRING_FROM_PROP(cur, "rate", rate); + if(!rate.empty()) { + rate = "1/" + rate; + u = getUnit(currency); + if(!u) { + u = addUnit(new AliasUnit(_("Currency"), currency, "", "", "", u_euro, rate, 1, "", false, true)); + } else if(u->subtype() == SUBTYPE_ALIAS_UNIT) { + ((AliasUnit*) u)->setExpression(rate); + } + if(u) { + u->setApproximate(); + u->setPrecision(-2); + u->setChanged(false); + } + } + } + } + if(cur->children) { + cur = cur->children; + } else if(cur->next) { + cur = cur->next; + } else { + cur = cur->parent; + if(cur) { + cur = cur->next; + } + } + } + xmlFreeDoc(doc); + if(sdate.empty()) { + struct stat stats; + if(stat(filename.c_str(), &stats) == 0) { + if(exchange_rates_time[0] >= stats.st_mtime) { +#ifdef _WIN32 + struct _utimbuf new_times; +#else + struct utimbuf new_times; +#endif + struct tm *temptm = localtime(&exchange_rates_time[0]); + if(temptm) { + struct tm extm = *temptm; + time_t time_now = time(NULL); + struct tm *newtm = localtime(&time_now); + if(newtm && newtm->tm_mday != extm.tm_mday) { + newtm->tm_hour = extm.tm_hour; + newtm->tm_min = extm.tm_min; + newtm->tm_sec = extm.tm_sec; + exchange_rates_time[0] = mktime(newtm); + } else { + time(&exchange_rates_time[0]); + } + } else { + time(&exchange_rates_time[0]); + } + new_times.modtime = exchange_rates_time[0]; + new_times.actime = exchange_rates_time[0]; +#ifdef _WIN32 + _utime(filename.c_str(), &new_times); +#else + utime(filename.c_str(), &new_times); +#endif + } else { + exchange_rates_time[0] = stats.st_mtime; + if(exchange_rates_time[0] > exchange_rates_check_time[0]) exchange_rates_check_time[0] = exchange_rates_time[0]; + } + } + } + + filename = getExchangeRatesFileName(2); + ifstream file2(filename.c_str()); + if(file2.is_open()) { + std::stringstream ssbuffer2; + ssbuffer2 << file2.rdbuf(); + string sbuffer = ssbuffer2.str(); + size_t i = sbuffer.find("\"amount\":"); + if(i != string::npos) { + i = sbuffer.find("\"", i + 9); + if(i != string::npos) { + size_t i2 = sbuffer.find("\"", i + 1); + ((AliasUnit*) u_btc)->setExpression(sbuffer.substr(i + 1, i2 - (i + 1))); + } + } + file2.close(); + struct stat stats; + if(stat(filename.c_str(), &stats) == 0) { + exchange_rates_time[1] = stats.st_mtime; + if(exchange_rates_time[1] > exchange_rates_check_time[1]) exchange_rates_check_time[1] = exchange_rates_time[1]; + } + } else { + exchange_rates_time[1] = ((time_t) 1531087L) * 1000; + if(exchange_rates_time[1] > exchange_rates_check_time[1]) exchange_rates_check_time[1] = exchange_rates_time[1]; + } + + filename = getExchangeRatesFileName(4); + ifstream file3(filename.c_str()); + if(file3.is_open()) { + std::stringstream ssbuffer3; + ssbuffer3 << file3.rdbuf(); + string sbuffer = ssbuffer3.str(); + size_t i = sbuffer.find("\"Cur_OfficialRate\":"); + if(i != string::npos) { + i = sbuffer.find_first_of(NUMBER_ELEMENTS, i + 19); + if(i != string::npos) { + size_t i2 = sbuffer.find_first_not_of(NUMBER_ELEMENTS, i); + if(i2 == string::npos) i2 = sbuffer.length(); + ((AliasUnit*) priv->u_byn)->setExpression(sbuffer.substr(i, i2 - i)); + } + } + i = sbuffer.find("\"Date\":"); + if(i != string::npos) { + i = sbuffer.find("\"", i + 7); + if(i != string::npos) { + size_t i2 = sbuffer.find("\"", i + 1); + QalculateDateTime qdate; + if(qdate.set(sbuffer.substr(i + 1, i2 - (i + 1)))) { + priv->exchange_rates_time2[0] = (time_t) qdate.timestamp().ulintValue(); + if(priv->exchange_rates_time2[0] > priv->exchange_rates_check_time2[0]) priv->exchange_rates_check_time2[0] = priv->exchange_rates_time2[0]; + } + } + } + file3.close(); + } else { + priv->exchange_rates_time2[0] = ((time_t) 1531087L) * 1000; + if(priv->exchange_rates_time2[0] > priv->exchange_rates_check_time2[0]) priv->exchange_rates_check_time2[0] = priv->exchange_rates_time2[0]; + } + + Unit *u_usd = getUnit("USD"); + if(!u_usd) return true; + + string sbuffer; + filename = getExchangeRatesFileName(3); + ifstream file(filename.c_str()); + if(file.is_open()) { + std::stringstream ssbuffer; + ssbuffer << file.rdbuf(); + sbuffer = ssbuffer.str(); + } + if(sbuffer.empty()) { + if(file.is_open()) file.close(); + file.clear(); + filename = buildPath(getGlobalDefinitionsDir(), "rates.json"); + file.open(filename.c_str()); + if(!file.is_open()) return true; + std::stringstream ssbuffer; + ssbuffer << file.rdbuf(); + sbuffer = ssbuffer.str(); + string sname; + size_t i = sbuffer.find("\"currency_code\":"); + while(i != string::npos) { + i += 16; + size_t i2 = sbuffer.find("\"", i); + if(i2 == string::npos) break; + size_t i3 = sbuffer.find("\"", i2 + 1); + if(i3 != string::npos && i3 - (i2 + 1) == 3) { + currency = sbuffer.substr(i2 + 1, i3 - (i2 + 1)); + if(currency.length() == 3 && currency[0] >= 'A' && currency[0] <= 'Z') { + u = getUnit(currency); + if(!u || (u->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) u)->firstBaseUnit() == u_usd)) { + i2 = sbuffer.find("\"rate\":", i3 + 1); + size_t i4 = sbuffer.find("}", i3 + 1); + if(i2 != string::npos && i2 < i4) { + i3 = sbuffer.find(",", i2 + 7); + rate = sbuffer.substr(i2 + 7, i3 - (i2 + 7)); + rate = "1/" + rate; + if(!u) { + i2 = sbuffer.find("\"name\":\"", i3 + 1); + if(i2 != string::npos && i2 < i4) { + i3 = sbuffer.find("\"", i2 + 8); + if(i3 != string::npos) { + sname = sbuffer.substr(i2 + 8, i3 - (i2 + 8)); + remove_blank_ends(sname); + } + } else { + sname = ""; + } + u = addUnit(new AliasUnit(_("Currency"), currency, "", "", sname, u_usd, rate, 1, "", false, true), false, true); + if(u) u->setHidden(true); + } else { + ((AliasUnit*) u)->setBaseUnit(u_usd); + ((AliasUnit*) u)->setExpression(rate); + } + if(u) { + u->setApproximate(); + u->setPrecision(-2); + u->setChanged(false); + } + } + } + } + } + i = sbuffer.find("\"currency_code\":", i); + } + file.close(); + exchange_rates_time[2] = ((time_t) 1527199L) * 1000; + if(exchange_rates_time[2] > exchange_rates_check_time[2]) exchange_rates_check_time[2] = exchange_rates_time[2]; + } else { + string sname; + size_t i = sbuffer.find("class=\'country\'"); + while(i != string::npos) { + currency = ""; sname = ""; rate = ""; + i += 15; + size_t i2 = sbuffer.find("data-currency-code=\"", i); + if(i2 != string::npos) { + i2 += 19; + size_t i3 = sbuffer.find("\"", i2 + 1); + if(i3 != string::npos) { + currency = sbuffer.substr(i2 + 1, i3 - (i2 + 1)); + remove_blank_ends(currency); + } + } + i2 = sbuffer.find("data-currency-name=\'", i); + if(i2 != string::npos) { + i2 += 19; + size_t i3 = sbuffer.find("|", i2 + 1); + if(i3 != string::npos) { + sname = sbuffer.substr(i2 + 1, i3 - (i2 + 1)); + remove_blank_ends(sname); + } + } + i2 = sbuffer.find("data-rate=\'", i); + if(i2 != string::npos) { + i2 += 10; + size_t i3 = sbuffer.find("'", i2 + 1); + if(i3 != string::npos) { + rate = sbuffer.substr(i2 + 1, i3 - (i2 + 1)); + remove_blank_ends(rate); + } + } + if(currency.length() == 3 && currency[0] >= 'A' && currency[0] <= 'Z' && !rate.empty()) { + u = getUnit(currency); + if(!u || (u->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) u)->firstBaseUnit() == u_usd)) { + rate = "1/" + rate; + if(!u) { + u = addUnit(new AliasUnit(_("Currency"), currency, "", "", sname, u_usd, rate, 1, "", false, true), false, true); + if(u) u->setHidden(true); + } else { + ((AliasUnit*) u)->setBaseUnit(u_usd); + ((AliasUnit*) u)->setExpression(rate); + } + if(u) { + u->setApproximate(); + u->setPrecision(-2); + u->setChanged(false); + } + } + } + i = sbuffer.find("class=\'country\'", i); + } + file.close(); + struct stat stats; + if(stat(filename.c_str(), &stats) == 0) { + exchange_rates_time[2] = stats.st_mtime; + if(exchange_rates_time[2] > exchange_rates_check_time[2]) exchange_rates_check_time[2] = exchange_rates_time[2]; + } + } + + return true; + +} +bool Calculator::hasGVFS() { + return false; +} +bool Calculator::hasGnomeVFS() { + return hasGVFS(); +} +bool Calculator::canFetch() { +#ifdef HAVE_LIBCURL + return true; +#else + return false; +#endif +} +string Calculator::getExchangeRatesFileName(int index) { + switch(index) { + case 1: {return buildPath(getLocalDataDir(), "eurofxref-daily.xml");} + case 2: {return buildPath(getLocalDataDir(), "btc.json");} + //case 3: {return buildPath(getLocalDataDir(), "rates.json");} + case 3: {return buildPath(getLocalDataDir(), "rates.html");} + case 4: {return buildPath(getLocalDataDir(), "nrby.json");} + default: {} + } + return ""; +} +time_t Calculator::getExchangeRatesTime(int index) { + if(index > 5) index = 5; + if(index < 1) { + time_t extime = exchange_rates_time[0]; + for(int i = 1; i < 4; i++) { + if(i > 2 && priv->exchange_rates_time2[i - 3] < extime) extime = priv->exchange_rates_time2[i - 3]; + else if(i <= 2 && exchange_rates_time[i] < extime) extime = exchange_rates_time[i]; + } + return extime; + } + index--; + if(index == 5) { + if(exchange_rates_time[2] < priv->exchange_rates_time2[0]) return exchange_rates_time[2]; + return priv->exchange_rates_time2[0]; + } + if(index > 2) return priv->exchange_rates_time2[index - 3]; + return exchange_rates_time[index]; +} + +string Calculator::getExchangeRatesUrl(int index) { + switch(index) { + case 1: {return "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";} + case 2: {return "https://api.coinbase.com/v2/prices/spot?currency=EUR";} + //case 2: {return "http://www.mycurrency.net/US.json";} + case 3: {return "https://www.mycurrency.net/=US";} + case 4: {return "http://www.nbrb.by/api/exrates/rates/eur?parammode=2";} + default: {} + } + return ""; +} +bool Calculator::fetchExchangeRates(int timeout, string) {return fetchExchangeRates(timeout);} +size_t write_data(void *ptr, size_t size, size_t nmemb, string *sbuffer) { + sbuffer->append((char*) ptr, size * nmemb); + return size * nmemb; +} +#define FETCH_FAIL_CLEANUP curl_easy_cleanup(curl); curl_global_cleanup(); time(&exchange_rates_check_time[0]); time(&exchange_rates_check_time[1]); time(&exchange_rates_check_time[2]); time(&priv->exchange_rates_check_time2[0]); +bool Calculator::fetchExchangeRates(int timeout, int n) { +#ifdef HAVE_LIBCURL + + recursiveMakeDir(getLocalDataDir()); + string sbuffer; + char error_buffer[CURL_ERROR_SIZE]; + CURL *curl; + CURLcode res; + long int file_time = 0; + curl_global_init(CURL_GLOBAL_DEFAULT); + curl = curl_easy_init(); + if(!curl) {return false;} + curl_easy_setopt(curl, CURLOPT_URL, getExchangeRatesUrl(1).c_str()); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sbuffer); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer); + error_buffer[0] = 0; + curl_easy_setopt(curl, CURLOPT_FILETIME, &file_time); +#ifdef _WIN32 + char exepath[MAX_PATH]; + GetModuleFileName(NULL, exepath, MAX_PATH); + string datadir(exepath); + datadir.resize(datadir.find_last_of('\\')); + if(datadir.substr(datadir.length() - 4) != "\\bin" && datadir.substr(datadir.length() - 6) != "\\.libs") { + string cainfo = buildPath(datadir, "ssl", "certs", "ca-bundle.crt"); + gsub("\\", "/", cainfo); + curl_easy_setopt(curl, CURLOPT_CAINFO, cainfo.c_str()); + } +#endif + res = curl_easy_perform(curl); + + if(res != CURLE_OK) { + if(strlen(error_buffer)) error(true, _("Failed to download exchange rates from %s: %s."), "ECB", error_buffer, NULL); + else error(true, _("Failed to download exchange rates from %s: %s."), "ECB", curl_easy_strerror(res), NULL); + FETCH_FAIL_CLEANUP; + return false; + } + if(sbuffer.empty()) {error(true, _("Failed to download exchange rates from %s: %s."), "ECB", "Document empty", NULL); FETCH_FAIL_CLEANUP; return false;} + ofstream file(getExchangeRatesFileName(1).c_str(), ios::out | ios::trunc | ios::binary); + if(!file.is_open()) { + error(true, _("Failed to download exchange rates from %s: %s."), "ECB", strerror(errno), NULL); + FETCH_FAIL_CLEANUP + return false; + } + file << sbuffer; + file.close(); + if(file_time > 0) { +#ifdef _WIN32 + struct _utimbuf new_times; +#else + struct utimbuf new_times; +#endif + new_times.modtime = (time_t) file_time; + new_times.actime = (time_t) file_time; +#ifdef _WIN32 + _utime(getExchangeRatesFileName(1).c_str(), &new_times); +#else + utime(getExchangeRatesFileName(1).c_str(), &new_times); +#endif + } + + if(n <= 0 || n >= 2) { + + sbuffer = ""; + curl_easy_setopt(curl, CURLOPT_URL, getExchangeRatesUrl(2).c_str()); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sbuffer); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer); + + res = curl_easy_perform(curl); + + if(res != CURLE_OK) {error(true, _("Failed to download exchange rates from %s: %s."), "coinbase.com", error_buffer, NULL); FETCH_FAIL_CLEANUP; return false;} + if(sbuffer.empty()) {error(true, _("Failed to download exchange rates from %s: %s."), "coinbase.com", "Document empty", NULL); FETCH_FAIL_CLEANUP; return false;} + ofstream file3(getExchangeRatesFileName(2).c_str(), ios::out | ios::trunc | ios::binary); + if(!file3.is_open()) { + error(true, _("Failed to download exchange rates from %s: %s."), "coinbase.com", strerror(errno), NULL); + FETCH_FAIL_CLEANUP + return false; + } + file3 << sbuffer; + file3.close(); + + } + + if(n <= 0 || (n >= 3 && n != 4)) { + + sbuffer = ""; + curl_easy_setopt(curl, CURLOPT_URL, getExchangeRatesUrl(3).c_str()); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sbuffer); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer); + res = curl_easy_perform(curl); + + if(res != CURLE_OK) {error(true, _("Failed to download exchange rates from %s: %s."), "mycurrency.net", error_buffer, NULL); FETCH_FAIL_CLEANUP; return false;} + if(sbuffer.empty() || sbuffer.find("Internal Server Error") != string::npos) {error(true, _("Failed to download exchange rates from %s: %s."), "mycurrency.net", "Document empty", NULL); FETCH_FAIL_CLEANUP; return false;} + ofstream file2(getExchangeRatesFileName(3).c_str(), ios::out | ios::trunc | ios::binary); + if(!file2.is_open()) { + error(true, _("Failed to download exchange rates from %s: %s."), "mycurrency.net", strerror(errno), NULL); + FETCH_FAIL_CLEANUP + return false; + } + file2 << sbuffer; + file2.close(); + + } + + if(n <= 0 || n >= 4) { + + sbuffer = ""; + curl_easy_setopt(curl, CURLOPT_URL, getExchangeRatesUrl(4).c_str()); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, (timeout > 4 && n <= 0) ? 4 : timeout); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sbuffer); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer); + + res = curl_easy_perform(curl); + + if(res != CURLE_OK) {error(true, _("Failed to download exchange rates from %s: %s."), "nbrb.by", error_buffer, NULL); FETCH_FAIL_CLEANUP; return false;} + if(sbuffer.empty()) {error(true, _("Failed to download exchange rates from %s: %s."), "nbrb.by", "Document empty", NULL); FETCH_FAIL_CLEANUP; return false;} + ofstream file4(getExchangeRatesFileName(4).c_str(), ios::out | ios::trunc | ios::binary); + if(!file4.is_open()) { + error(true, _("Failed to download exchange rates from %s: %s."), "nbrb.by", strerror(errno), NULL); + FETCH_FAIL_CLEANUP + return false; + } + file4 << sbuffer; + file4.close(); + + } + + curl_easy_cleanup(curl); curl_global_cleanup(); + + return true; +#else + return false; +#endif +} +bool Calculator::checkExchangeRatesDate(unsigned int n_days, bool force_check, bool send_warning, int n) { + if(n <= 0) n = 5; + time_t extime = exchange_rates_time[0]; + for(int i = 1; i < (n > 5 ? 4 : n); i++) { + if(i > 2 && priv->exchange_rates_time2[i - 3] < extime) extime = priv->exchange_rates_time2[i - 3]; + else if(i <= 2 && (i != 2 || n != 4) && exchange_rates_time[i] < extime) extime = exchange_rates_time[i]; + } + time_t cextime = exchange_rates_check_time[0]; + for(int i = 1; i < (n > 5 ? 4 : n); i++) { + if(i > 2 && priv->exchange_rates_check_time2[i - 3] < cextime) cextime = priv->exchange_rates_check_time2[i - 3]; + else if(i <= 2 && (i != 2 || n != 4) && exchange_rates_check_time[i] < cextime) cextime = exchange_rates_check_time[i]; + } + if(extime > 0 && ((!force_check && cextime > 0 && difftime(time(NULL), cextime) < 86400 * n_days) || difftime(time(NULL), extime) < (86400 * n_days) + 3600)) return true; + for(int i = 0; i < (n > 5 ? 4 : n); i++) { + if(i <= 2 && (i != 2 || n != 4)) time(&exchange_rates_check_time[i]); + else if(i > 2) time(&priv->exchange_rates_check_time2[i - 3]); + } + if(send_warning) error(false, _("It has been %s day(s) since the exchange rates last were updated."), i2s((int) floor(difftime(time(NULL), extime) / 86400)).c_str(), NULL); + return false; +} +void Calculator::setExchangeRatesWarningEnabled(bool enable) { + b_exchange_rates_warning_enabled = enable; +} +bool Calculator::exchangeRatesWarningEnabled() const { + return b_exchange_rates_warning_enabled; +} +int Calculator::exchangeRatesUsed() const { + return b_exchange_rates_used; +} +void Calculator::resetExchangeRatesUsed() { + b_exchange_rates_used = 0; +} +void Calculator::setExchangeRatesUsed(int index) { + if(index > b_exchange_rates_used) b_exchange_rates_used = index; + if(b_exchange_rates_warning_enabled) checkExchangeRatesDate(7, false, true); +} + diff -Nru libqalculate-3.6.0/libqalculate/Calculator.h libqalculate-3.7.0/libqalculate/Calculator.h --- libqalculate-3.6.0/libqalculate/Calculator.h 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Calculator.h 2020-01-21 22:54:40.000000000 +0000 @@ -177,6 +177,30 @@ #include enum { + VARIABLE_ID_I = 200, + VARIABLE_ID_PLUS_INFINITY = 201, + VARIABLE_ID_MINUS_INFINITY = 202, + VARIABLE_ID_UNDEFINED = 203, + VARIABLE_ID_X = 300, + VARIABLE_ID_Y = 301, + VARIABLE_ID_Z = 302, + VARIABLE_ID_N = 303, + VARIABLE_ID_C = 304 +}; + +enum { + UNIT_ID_EURO = 510, + UNIT_ID_BYN = 515, + UNIT_ID_BTC = 520, + UNIT_ID_SECOND = 550, + UNIT_ID_MINUTE = 551, + UNIT_ID_HOUR = 552, + UNIT_ID_DAY = 553, + UNIT_ID_MONTH = 554, + UNIT_ID_YEAR = 555 +}; + +enum { ELEMENT_CLASS_NOT_DEFINED, ALKALI_METALS, ALKALI_EARTH_METALS, @@ -840,6 +864,7 @@ ExpressionItem *getActiveExpressionItem(ExpressionItem *item); ExpressionItem *getExpressionItem(std::string name, ExpressionItem *item = NULL); Unit* getUnit(std::string name_); + Unit* getUnitById(int id) const; Unit* getActiveUnit(std::string name_); Unit* getCompositeUnit(std::string internal_name_); Unit* getLocalCurrency(); @@ -856,11 +881,14 @@ * @returns Prefix with provided name or NULL if not found. */ Prefix *getPrefix(std::string name_) const; + Prefix *getDecimalNullPrefix() const; + Prefix *getBinaryNullPrefix() const; Variable* addVariable(Variable *v, bool force = true, bool check_names = true); void variableNameChanged(Variable *v, bool new_item = false); void functionNameChanged(MathFunction *f, bool new_item = false); void unitNameChanged(Unit *u, bool new_item = false); Variable* getVariable(std::string name_); + Variable* getVariableById(int id) const; Variable* getActiveVariable(std::string name_); ExpressionItem *addExpressionItem(ExpressionItem *item, bool force = true); MathFunction* addFunction(MathFunction *f, bool force = true, bool check_names = true); @@ -868,6 +896,7 @@ DataSet* getDataSet(size_t index); DataSet* getDataSet(std::string name); MathFunction* getFunction(std::string name_); + MathFunction* getFunctionById(int id) const; MathFunction* getActiveFunction(std::string name_); /** Returns variable for an index (starting at zero). All variables can be traversed by starting at index zero and increasing the index until NULL is returned. * diff -Nru libqalculate-3.6.0/libqalculate/Calculator-parse.cc libqalculate-3.7.0/libqalculate/Calculator-parse.cc --- libqalculate-3.6.0/libqalculate/Calculator-parse.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Calculator-parse.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,3280 @@ +/* + Qalculate + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "util.h" +#include "MathStructure.h" +#include "Unit.h" +#include "Variable.h" +#include "Function.h" +#include "DataSet.h" +#include "ExpressionItem.h" +#include "Prefix.h" +#include "Number.h" + +#include +#include + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +#include "Calculator_p.h" + +// determine if character is not a numerical digit in a specific number base (-1=base using digits other than 0-9, a-z, A-Z; -12=duodecimal) +bool is_not_number(char c, int base) { + // 0-9 is always treated as a digit + if(c >= '0' && c <= '9') return false; + // in non standard bases every character might be a digit + if(base == -1) return false; + // duodecimal bases uses 0-9, E, X + if(base == -12) return c != 'E' && c != 'X'; + if(base <= 10) return true; + // bases 11-36 is case insensitive + if(base <= 36) { + if(c >= 'a' && c < 'a' + (base - 10)) return false; + if(c >= 'A' && c < 'A' + (base - 10)) return false; + return true; + } + // bases 37-62 is case sensitive + if(base <= 62) { + if(c >= 'a' && c < 'a' + (base - 36)) return false; + if(c >= 'A' && c < 'Z') return false; + return true; + } + return false; +} + +size_t Calculator::addId(MathStructure *mstruct, bool persistent) { + size_t id = 0; + if(priv->freed_ids.size() > 0) { + id = priv->freed_ids.back(); + priv->freed_ids.pop_back(); + } else { + priv->ids_i++; + id = priv->ids_i; + } + priv->ids_p[id] = persistent; + priv->id_structs[id] = mstruct; + return id; +} +size_t Calculator::parseAddId(MathFunction *f, const string &str, const ParseOptions &po, bool persistent) { + size_t id = 0; + if(priv->freed_ids.size() > 0) { + id = priv->freed_ids.back(); + priv->freed_ids.pop_back(); + } else { + priv->ids_i++; + id = priv->ids_i; + } + priv->ids_p[id] = persistent; + priv->id_structs[id] = new MathStructure(); + f->parse(*priv->id_structs[id], str, po); + return id; +} +size_t Calculator::parseAddIdAppend(MathFunction *f, const MathStructure &append_mstruct, const string &str, const ParseOptions &po, bool persistent) { + size_t id = 0; + if(priv->freed_ids.size() > 0) { + id = priv->freed_ids.back(); + priv->freed_ids.pop_back(); + } else { + priv->ids_i++; + id = priv->ids_i; + } + priv->ids_p[id] = persistent; + priv->id_structs[id] = new MathStructure(); + f->parse(*priv->id_structs[id], str, po); + priv->id_structs[id]->addChild(append_mstruct); + return id; +} +size_t Calculator::parseAddVectorId(const string &str, const ParseOptions &po, bool persistent) { + size_t id = 0; + if(priv->freed_ids.size() > 0) { + id = priv->freed_ids.back(); + priv->freed_ids.pop_back(); + } else { + priv->ids_i++; + id = priv->ids_i; + } + priv->ids_p[id] = persistent; + priv->id_structs[id] = new MathStructure(); + f_vector->args(str, *priv->id_structs[id], po); + return id; +} +MathStructure *Calculator::getId(size_t id) { + if(priv->id_structs.find(id) != priv->id_structs.end()) { + if(priv->ids_p[id]) { + return new MathStructure(*priv->id_structs[id]); + } else { + MathStructure *mstruct = priv->id_structs[id]; + priv->freed_ids.push_back(id); + priv->id_structs.erase(id); + priv->ids_p.erase(id); + return mstruct; + } + } + return NULL; +} + +void Calculator::delId(size_t id) { + if(priv->ids_p.find(id) != priv->ids_p.end()) { + priv->freed_ids.push_back(id); + priv->id_structs[id]->unref(); + priv->id_structs.erase(id); + priv->ids_p.erase(id); + } +} + +// case sensitive string comparison; compares whole name with str from str_index to str_index + name_length +bool compare_name(const string &name, const string &str, const size_t &name_length, const size_t &str_index, int base) { + if(name_length == 0) return false; + if(name[0] != str[str_index]) return false; + if(name_length == 1) { + if(base < 2 || base > 10) return is_not_number(str[str_index], base); + return true; + } + for(size_t i = 1; i < name_length; i++) { + if(name[i] != str[str_index + i]) return false; + } + // number base uses digits other than 0-9, check that at least one non-digit is used + if(base < 2 || base > 10) { + for(size_t i = 0; i < name_length; i++) { + if(is_not_number(str[str_index + i], base)) return true; + } + return false; + } + return true; +} + +// case insensitive string comparison; compares whole name with str from str_index to str_index + name_length +size_t compare_name_no_case(const string &name, const string &str, const size_t &name_length, const size_t &str_index, int base) { + if(name_length == 0) return 0; + size_t is = str_index; + for(size_t i = 0; i < name_length; i++, is++) { + if(is >= str.length()) return 0; + if((name[i] < 0 && i + 1 < name_length) || (str[is] < 0 && is + 1 < str.length())) { + // assumed Unicode character found + size_t i2 = 1, is2 = 1; + // determine length of Unicode character(s) + if(name[i] < 0) { + while(i2 + i < name_length && name[i2 + i] < 0) { + i2++; + } + } + if(str[is] < 0) { + while(is2 + is < str.length() && str[is2 + is] < 0) { + is2++; + } + } + // compare characters + bool isequal = (i2 == is2); + if(isequal) { + for(size_t i3 = 0; i3 < i2; i3++) { + if(str[is + i3] != name[i + i3]) { + isequal = false; + break; + } + } + } + // get lower case character and compare again + if(!isequal) { + char *gstr1 = utf8_strdown(name.c_str() + (sizeof(char) * i), i2); + char *gstr2 = utf8_strdown(str.c_str() + (sizeof(char) * (is)), is2); + if(!gstr1 || !gstr2) return 0; + if(strcmp(gstr1, gstr2) != 0) {free(gstr1); free(gstr2); return 0;} + free(gstr1); free(gstr2); + } + i += i2 - 1; + is += is2 - 1; + } else if(name[i] != str[is] && !((name[i] >= 'a' && name[i] <= 'z') && name[i] - 32 == str[is]) && !((name[i] <= 'Z' && name[i] >= 'A') && name[i] + 32 == str[is])) { + return 0; + } + } + // number base uses digits other than 0-9, check that at least one non-digit is used + if(base < 2 || base > 10) { + for(size_t i = str_index; i < is; i++) { + if(is_not_number(str[i], base)) return is - str_index; + } + return 0; + } + return is - str_index; +} + +const char *internal_signs[] = {SIGN_PLUSMINUS, "\b", "+/-", "\b", "⊻", "\a", "∠", "\x1c"}; +#define INTERNAL_SIGNS_COUNT 8 +#define INTERNAL_NUMBER_CHARS "\b" +#define INTERNAL_OPERATORS "\a\b%\x1c" +#define DUODECIMAL_CHARS "EX" + +void Calculator::parseSigns(string &str, bool convert_to_internal_representation) const { + vector q_begin; + vector q_end; + // collect quoted ranges + size_t quote_index = 0; + while(true) { + quote_index = str.find_first_of("\"\'", quote_index); + if(quote_index == string::npos) { + break; + } + q_begin.push_back(quote_index); + quote_index = str.find(str[quote_index], quote_index + 1); + if(quote_index == string::npos) { + q_end.push_back(str.length() - 1); + break; + } + q_end.push_back(quote_index); + quote_index++; + } + + // search and replace string alternatives + for(size_t i = 0; i < signs.size(); i++) { + size_t ui = str.find(signs[i]); + size_t ui2 = 0; + while(ui != string::npos) { + // check that found index is outside quotes + for(; ui2 < q_end.size(); ui2++) { + if(ui >= q_begin[ui2]) { + if(ui <= q_end[ui2]) { + ui = str.find(signs[i], q_end[ui2] + 1); + if(ui == string::npos) break; + } + } else { + break; + } + } + if(ui == string::npos) break; + // adjust quotion mark indeces + int index_shift = real_signs[i].length() - signs[i].length(); + for(size_t ui3 = ui2; ui3 < q_begin.size(); ui3++) { + q_begin[ui3] += index_shift; + q_end[ui3] += index_shift; + } + str.replace(ui, signs[i].length(), real_signs[i]); + ui = str.find(signs[i], ui + real_signs[i].length()); + } + } + + // replace Unicode exponents + size_t prev_ui = string::npos, space_n = 0; + while(true) { + // Unicode powers 0 and 4-9 use three chars and begin with \xe2\x81 + size_t ui = str.find("\xe2\x81", prev_ui == string::npos ? 0 : prev_ui); + if(ui != string::npos && (ui == str.length() - 2 || (str[ui + 2] != -80 && (str[ui + 2] < -76 || str[ui + 2] > -71)))) ui = string::npos; + // Unicode powers 1-3 use two chars and begin with \xc2 + size_t ui2 = str.find('\xc2', prev_ui == string::npos ? 0 : prev_ui); + if(ui2 != string::npos && (ui2 == str.length() - 1 || (str[ui2 + 1] != -71 && str[ui2 + 1] != -77 && str[ui2 + 1] != -78))) ui2 = string::npos; + if(ui2 != string::npos && (ui == string::npos || ui2 < ui)) ui = ui2; + if(ui != string::npos) { + // check that found index is outside quotes + for(size_t ui3 = 0; ui3 < q_end.size(); ui3++) { + if(ui <= q_end[ui3] && ui >= q_begin[ui3]) { + ui = str.find("\xe2\x81", q_end[ui3] + 1); + if(ui != string::npos && (ui == str.length() - 2 || (str[ui + 2] != -80 && (str[ui + 2] < -76 || str[ui + 2] > -71)))) ui = string::npos; + ui2 = str.find('\xc2', q_end[ui3] + 1); + if(ui2 != string::npos && (ui2 == str.length() - 1 || (str[ui2 + 1] != -71 && str[ui2 + 1] != -77 && str[ui2 + 1] != -78))) ui2 = string::npos; + if(ui2 != string::npos && (ui == string::npos || ui2 < ui)) ui = ui2; + if(ui == string::npos) break; + } + } + } + if(ui == string::npos) break; + int index_shift = (str[ui] == '\xc2' ? -2 : -3); + if(ui == prev_ui) index_shift += 1; + else index_shift += 4; + // adjust quotion mark indeces + for(size_t ui3 = 0; ui3 < q_begin.size(); ui3++) { + if(q_begin[ui3] >= ui) { + q_begin[ui3] += index_shift; + q_end[ui3] += index_shift; + } + } + // perform replacement; if next to previous Unicode power combine the powers + if(str[ui] == '\xc2') { + if(str[ui + 1] == -71) str.replace(ui, 2, ui == prev_ui ? "1)" : "^(1)"); + else if(str[ui + 1] == -78) str.replace(ui, 2, ui == prev_ui ? "2)" : "^(2)"); + else if(str[ui + 1] == -77) str.replace(ui, 2, ui == prev_ui ? "3)" : "^(3)"); + } else { + if(str[ui + 2] == -80) str.replace(ui, 3, ui == prev_ui ? "0)" : "^(0)"); + else if(str[ui + 2] == -76) str.replace(ui, 3, ui == prev_ui ? "4)" : "^(4)"); + else if(str[ui + 2] == -75) str.replace(ui, 3, ui == prev_ui ? "5)" : "^(5)"); + else if(str[ui + 2] == -74) str.replace(ui, 3, ui == prev_ui ? "6)" : "^(6)"); + else if(str[ui + 2] == -73) str.replace(ui, 3, ui == prev_ui ? "7)" : "^(7)"); + else if(str[ui + 2] == -72) str.replace(ui, 3, ui == prev_ui ? "8)" : "^(8)"); + else if(str[ui + 2] == -71) str.replace(ui, 3, ui == prev_ui ? "9)" : "^(9)"); + } + if(ui == prev_ui) { + str.erase(prev_ui - space_n - 1, 1); + prev_ui = ui + 1; + } else { + prev_ui = ui + 4; + } + space_n = 0; + while(prev_ui + 1 < str.length() && str[prev_ui] == SPACE_CH) { + space_n++; + prev_ui++; + } + } + + // replace Unicode fractions with three chars + prev_ui = string::npos; + while(true) { + // three char Unicode fractions begin with \xe2\x85 + size_t ui = str.find("\xe2\x85", prev_ui == string::npos ? 0 : prev_ui); + if(ui != string::npos && (ui == str.length() - 2 || str[ui + 2] < -112 || str[ui + 2] > -98)) ui = string::npos; + if(ui != string::npos) { + // check that found index is outside quotes + for(size_t ui3 = 0; ui3 < q_end.size(); ui3++) { + if(ui <= q_end[ui3] && ui >= q_begin[ui3]) { + ui = str.find("\xe2\x85", q_end[ui3] + 1); + if(ui != string::npos && (ui == str.length() - 2 || str[ui + 2] < -112 || str[ui + 2] > -98)) ui = string::npos; + if(ui == string::npos) break; + } + } + } + if(ui == string::npos) break; + // check if previous non-whitespace character is a numeral digit + space_n = 0; + while(ui > 0 && ui - 1 - space_n != 0 && str[ui - 1 - space_n] == SPACE_CH) space_n++; + bool b_add = (ui > 0 && is_in(NUMBER_ELEMENTS, str[ui - 1 - space_n])); + int index_shift = (b_add ? 6 : 5) - 3; + if(str[ui + 2] == -110) index_shift++; + // adjust quotion mark indeces + for(size_t ui2 = 0; ui2 < q_begin.size(); ui2++) { + if(q_begin[ui2] >= ui) { + q_begin[ui2] += index_shift; + q_end[ui2] += index_shift; + } + } + // perform replacement; interpret as addition if previous character is a numeral digit + if(str[ui + 2] == -98) str.replace(ui, 3, b_add ? "+(7/8)" : "(7/8)"); + else if(str[ui + 2] == -99) str.replace(ui, 3, b_add ? "+(5/8)" : "(5/8)"); + else if(str[ui + 2] == -100) str.replace(ui, 3, b_add ? "+(3/8)" : "(3/8)"); + else if(str[ui + 2] == -101) str.replace(ui, 3, b_add ? "+(1/8)" : "(1/8)"); + else if(str[ui + 2] == -102) str.replace(ui, 3, b_add ? "+(5/6)" : "(5/6)"); + else if(str[ui + 2] == -103) str.replace(ui, 3, b_add ? "+(1/6)" : "(1/6)"); + else if(str[ui + 2] == -104) str.replace(ui, 3, b_add ? "+(4/5)" : "(4/5)"); + else if(str[ui + 2] == -105) str.replace(ui, 3, b_add ? "+(3/5)" : "(3/5)"); + else if(str[ui + 2] == -106) str.replace(ui, 3, b_add ? "+(2/5)" : "(2/5)"); + else if(str[ui + 2] == -107) str.replace(ui, 3, b_add ? "+(1/5)" : "(1/5)"); + else if(str[ui + 2] == -108) str.replace(ui, 3, b_add ? "+(2/3)" : "(2/3)"); + else if(str[ui + 2] == -109) str.replace(ui, 3, b_add ? "+(1/3)" : "(1/3)"); + else if(str[ui + 2] == -110) {str.replace(ui, 3, b_add ? "+(1/10)" : "(1/10)"); ui++;} + else if(str[ui + 2] == -111) str.replace(ui, 3, b_add ? "+(1/9)" : "(1/9)"); + else if(str[ui + 2] == -112) str.replace(ui, 3, b_add ? "+(1/7)" : "(1/7)"); + if(b_add) prev_ui = ui + 6; + else prev_ui = ui + 5; + } + + // replace Unicode fractions with two chars + prev_ui = string::npos; + while(true) { + // two char Unicode fractions begin with \xc2 + size_t ui = str.find('\xc2', prev_ui == string::npos ? 0 : prev_ui); + if(ui != string::npos && (ui == str.length() - 1 || (str[ui + 1] != -66 && str[ui + 1] != -67 && str[ui + 1] != -68))) ui = string::npos; + if(ui != string::npos) { + // check that found index is outside quotes + for(size_t ui3 = 0; ui3 < q_end.size(); ui3++) { + if(ui <= q_end[ui3] && ui >= q_begin[ui3]) { + ui = str.find('\xc2', q_end[ui3] + 1); + if(ui != string::npos && (ui == str.length() - 1 || (str[ui + 1] != -66 && str[ui + 1] != -67 && str[ui + 1] != -68))) ui = string::npos; + if(ui == string::npos) break; + } + } + } + if(ui == string::npos) break; + // check if previous non-whitespace character is a numeral digit + space_n = 0; + while(ui > 0 && ui - 1 - space_n != 0 && str[ui - 1 - space_n] == SPACE_CH) space_n++; + bool b_add = (ui > 0 && is_in(NUMBER_ELEMENTS, str[ui - 1 - space_n])); + int index_shift = (b_add ? 6 : 5) - 2; + // adjust quotion mark indeces + for(size_t ui2 = 0; ui2 < q_begin.size(); ui2++) { + if(q_begin[ui2] >= ui) { + q_begin[ui2] += index_shift; + q_end[ui2] += index_shift; + } + } + // perform replacement; interpret as addition if previous character is a numeral digit + if(str[ui + 1] == -66) str.replace(ui, 2, b_add ? "+(3/4)" : "(3/4)"); + else if(str[ui + 1] == -67) str.replace(ui, 2, b_add ? "+(1/2)" : "(1/2)"); + else if(str[ui + 1] == -68) str.replace(ui, 2, b_add ? "+(1/4)" : "(1/4)"); + if(b_add) prev_ui = ui + 6; + else prev_ui = ui + 5; + } + + if(convert_to_internal_representation) { + // remove superfluous whitespace + remove_blank_ends(str); + remove_duplicate_blanks(str); + // replace operators with multiple chars with internal single character version + for(size_t i = 0; i < INTERNAL_SIGNS_COUNT; i += 2) { + size_t ui = str.find(internal_signs[i]); + size_t ui2 = 0; + while(ui != string::npos) { + // check that found index is outside quotes + for(; ui2 < q_end.size(); ui2++) { + if(ui >= q_begin[ui2]) { + if(ui <= q_end[ui2]) { + ui = str.find(internal_signs[i], q_end[ui2] + 1); + if(ui == string::npos) break; + } + } else { + break; + } + } + if(ui == string::npos) break; + // adjust quotion mark indeces + int index_shift = strlen(internal_signs[i + 1]) - strlen(internal_signs[i]); + for(size_t ui3 = ui2; ui3 < q_begin.size(); ui3++) { + q_begin[ui3] += index_shift; + q_end[ui3] += index_shift; + } + // perform replacement and search for next occurrence + str.replace(ui, strlen(internal_signs[i]), internal_signs[i + 1]); + ui = str.find(internal_signs[i], ui + strlen(internal_signs[i + 1])); + } + } + } +} + + +MathStructure Calculator::parse(string str, const ParseOptions &po) { + + MathStructure mstruct; + parse(&mstruct, str, po); + return mstruct; + +} + +void Calculator::parse(MathStructure *mstruct, string str, const ParseOptions &parseoptions) { + + ParseOptions po = parseoptions; + MathStructure *unended_function = po.unended_function; + po.unended_function = NULL; + + if(po.base == BASE_UNICODE || (po.base == BASE_CUSTOM && priv->custom_input_base_i > 62)) { + // Read whole expression as a number if the number base digits other than alphanumerical characters + mstruct->set(Number(str, po)); + return; + } + + // use parse option number base to determine which characters are used as numerical digits and set base accordingly. + // (-1=base using digits other than 0-9, a-z, A-Z; -12=duodecimal) + int base = po.base; + if(base == BASE_CUSTOM) { + base = (int) priv->custom_input_base_i; + } else if(base == BASE_GOLDEN_RATIO || base == BASE_SUPER_GOLDEN_RATIO || base == BASE_SQRT2) { + base = 2; + } else if(base == BASE_PI) { + base = 4; + } else if(base == BASE_E) { + base = 3; + } else if(base == BASE_DUODECIMAL) { + base = -12; + } else if(base < 2 || base > 36) { + base = -1; + } + + mstruct->clear(); + + const string *name = NULL; + string stmp, stmp2; + + bool b_prime_quote = true; + + // search for degree sign in epxressions (affects interpretation of ' and ") + size_t i_degree = str.find(SIGN_DEGREE); + if(i_degree != string::npos && i_degree < str.length() - strlen(SIGN_DEGREE) && is_not_in(NOT_IN_NAMES INTERNAL_OPERATORS NUMBER_ELEMENTS, str[i_degree + strlen(SIGN_DEGREE)])) i_degree = string::npos; + + if(base != -1 && base <= BASE_HEXADECIMAL) { + // replace single ' and " with prime and double prime (for ft/in or minutes/seconds of arc) + if(i_degree == string::npos) { + size_t i_quote = str.find('\'', 0); + size_t i_dquote = str.find('\"', 0); + if(i_quote == 0 || i_dquote == 0) { + b_prime_quote = false; + } else if((i_quote != string::npos && i_quote < str.length() - 1 && str.find('\'', i_quote + 1) != string::npos) || (i_quote != string::npos && i_dquote == i_quote + 1) || (i_dquote != string::npos && i_dquote < str.length() - 1 && str.find('\"', i_dquote + 1) != string::npos)) { + b_prime_quote = false; + while(i_dquote != string::npos) { + i_quote = str.rfind('\'', i_dquote - 1); + if(i_quote != string::npos) { + size_t i_prev = str.find_last_not_of(SPACES, i_quote - 1); + if(i_prev != string::npos && is_in(NUMBER_ELEMENTS, str[i_prev])) { + if(is_in(NUMBER_ELEMENTS, str[str.find_first_not_of(SPACES, i_quote + 1)]) && str.find_first_not_of(SPACES NUMBER_ELEMENTS, i_quote + 1) == i_dquote) { + if(i_prev == 0) { + b_prime_quote = true; + break; + } else { + i_prev = str.find_last_not_of(NUMBER_ELEMENTS, i_prev - 1); + if(i_prev == string::npos || (str[i_prev] != '\"' && str[i_prev] != '\'')) { + b_prime_quote = true; + break; + } + } + } + } + } + i_dquote = str.find('\"', i_dquote + 2); + } + } + } + if(b_prime_quote) { + gsub("\'", "′", str); + gsub("\"", "″", str); + } + } + + // replace alternative strings (primarily operators) with default ascii versions + parseSigns(str, true); + + // parse quoted string as symbolic MathStructure + for(size_t str_index = 0; str_index < str.length(); str_index++) { + if(str[str_index] == '\"' || str[str_index] == '\'') { + if(str_index == str.length() - 1) { + str.erase(str_index, 1); + } else { + size_t i = str.find(str[str_index], str_index + 1); + size_t name_length; + if(i == string::npos) { + i = str.length(); + name_length = i - str_index; + } else { + name_length = i - str_index + 1; + } + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + MathStructure *mstruct = new MathStructure(str.substr(str_index + 1, i - str_index - 1)); + stmp += i2s(addId(mstruct)); + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + str.replace(str_index, name_length, stmp); + str_index += stmp.length() - 1; + } + } + } + + + if(po.brackets_as_parentheses) { + // replace [ and ] with ( and ) + gsub(LEFT_VECTOR_WRAP, LEFT_PARENTHESIS, str); + gsub(RIGHT_VECTOR_WRAP, RIGHT_PARENTHESIS, str); + } + + // Transform var:=a to save(save, a) + size_t isave = 0; + if((isave = str.find(":=", 1)) != string::npos) { + string name = str.substr(0, isave); + string value = str.substr(isave + 2, str.length() - (isave + 2)); + str = value; + str += COMMA; + str += name; + f_save->parse(*mstruct, str, po); + return; + } + + if(po.default_dataset != NULL && str.length() > 1) { + size_t str_index = str.find(DOT_CH, 1); + while(str_index != string::npos) { + if(str_index + 1 < str.length() && ((is_not_number(str[str_index + 1], base) && is_not_in(INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index + 1]) && is_not_in(INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index - 1])) || (is_not_in(INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index + 1]) && is_not_number(str[str_index - 1], base) && is_not_in(INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index - 1])))) { + size_t dot_index = str.find_first_of(NOT_IN_NAMES INTERNAL_OPERATORS DOT, str_index + 1); + if(dot_index != string::npos && str[dot_index] == DOT_CH) { + str_index = dot_index; + } else { + size_t property_index = str.find_last_of(NOT_IN_NAMES INTERNAL_OPERATORS, str_index - 1); + if(property_index == string::npos) { + str.insert(0, 1, '.'); + str.insert(0, po.default_dataset->referenceName()); + str_index += po.default_dataset->referenceName().length() + 1; + } else { + str.insert(property_index + 1, 1, '.'); + str.insert(property_index + 1, po.default_dataset->referenceName()); + str_index += po.default_dataset->referenceName().length() + 1; + } + } + } + str_index = str.find(DOT_CH, str_index + 1); + } + } + + //remove spaces in numbers + size_t space_i = 0; + if(!po.rpn) { + space_i = str.find(SPACE_CH, 0); + while(space_i != string::npos) { + if(is_in(NUMBERS INTERNAL_NUMBER_CHARS DOT, str[space_i + 1]) && is_in(NUMBERS INTERNAL_NUMBER_CHARS DOT, str[space_i - 1])) { + str.erase(space_i, 1); + space_i--; + } + space_i = str.find(SPACE_CH, space_i + 1); + } + } + + if(base != -1 && base <= BASE_HEXADECIMAL) { + // replace prime and double prime with feet and inches, or arcminues and arcseconds (if degree sign was previously found) + bool b_degree = (i_degree != string::npos); + size_t i_quote = str.find("′"); + size_t i_dquote = str.find("″"); + while(i_quote != string::npos || i_dquote != string::npos) { + size_t i_op = 0; + if(i_quote == string::npos || i_dquote < i_quote) { + bool b = false; + if(b_degree) { + i_degree = str.rfind(SIGN_DEGREE, i_dquote - 1); + if(i_degree != string::npos && i_degree > 0 && i_degree < i_dquote) { + size_t i_op = str.find_first_not_of(SPACE, i_degree + strlen(SIGN_DEGREE)); + if(i_op != string::npos) { + i_op = str.find_first_not_of(SPACE, i_degree + strlen(SIGN_DEGREE)); + if(is_in(NUMBER_ELEMENTS, str[i_op])) i_op = str.find_first_not_of(NUMBER_ELEMENTS SPACE, i_op); + else i_op = 0; + } + size_t i_prev = string::npos; + if(i_op == i_dquote) { + i_prev = str.find_last_not_of(SPACE, i_degree - 1); + if(i_prev != string::npos) { + if(is_in(NUMBER_ELEMENTS, str[i_prev])) { + i_prev = str.find_last_not_of(NUMBER_ELEMENTS SPACE, i_prev); + if(i_prev == string::npos) i_prev = 0; + else i_prev++; + } else { + i_prev = string::npos; + } + } + } + if(i_prev != string::npos) { + str.insert(i_prev, LEFT_PARENTHESIS); + i_degree++; + i_op++; + str.replace(i_op, strlen("″"), "arcsec" RIGHT_PARENTHESIS); + str.replace(i_degree, strlen(SIGN_DEGREE), "deg" PLUS); + b = true; + } + } + } + if(!b) { + if(str.length() >= i_dquote + strlen("″") && is_in(NUMBERS, str[i_dquote + strlen("″")])) str.insert(i_dquote + strlen("″"), " "); + str.replace(i_dquote, strlen("″"), b_degree ? "arcsec" : "in"); + i_op = i_dquote; + } + } else { + bool b = false; + if(b_degree) { + i_degree = str.rfind(SIGN_DEGREE, i_quote - 1); + if(i_degree != string::npos && i_degree > 0 && i_degree < i_quote) { + size_t i_op = str.find_first_not_of(SPACE, i_degree + strlen(SIGN_DEGREE)); + if(i_op != string::npos) { + i_op = str.find_first_not_of(SPACE, i_degree + strlen(SIGN_DEGREE)); + if(is_in(NUMBER_ELEMENTS, str[i_op])) i_op = str.find_first_not_of(NUMBER_ELEMENTS SPACE, i_op); + else i_op = 0; + } + size_t i_prev = string::npos; + if(i_op == i_quote) { + i_prev = str.find_last_not_of(SPACE, i_degree - 1); + if(i_prev != string::npos) { + if(is_in(NUMBER_ELEMENTS, str[i_prev])) { + i_prev = str.find_last_not_of(NUMBER_ELEMENTS SPACE, i_prev); + if(i_prev == string::npos) i_prev = 0; + else i_prev++; + } else { + i_prev = string::npos; + } + } + } + if(i_prev != string::npos) { + str.insert(i_prev, LEFT_PARENTHESIS); + i_degree++; + i_quote++; + i_op++; + if(i_dquote != string::npos) { + i_dquote++; + size_t i_op2 = str.find_first_not_of(SPACE, i_quote + strlen("′")); + if(i_op2 != string::npos && is_in(NUMBER_ELEMENTS, str[i_op2])) i_op2 = str.find_first_not_of(NUMBER_ELEMENTS SPACE, i_op2); + else i_op2 = 0; + if(i_op2 == i_dquote) { + str.replace(i_dquote, strlen("″"), "arcsec" RIGHT_PARENTHESIS); + i_op = i_op2; + } + } + str.replace(i_quote, strlen("′"), i_op == i_quote ? "arcmin" RIGHT_PARENTHESIS : "arcmin" PLUS); + str.replace(i_degree, strlen(SIGN_DEGREE), "deg" PLUS); + b = true; + } + } + } + if(!b) { + i_op = str.find_first_not_of(SPACE, i_quote + strlen("′")); + if(i_op != string::npos && is_in(NUMBER_ELEMENTS, str[i_op])) i_op = str.find_first_not_of(NUMBER_ELEMENTS SPACE, i_op); + else i_op = 0; + size_t i_prev = string::npos; + if(((!b_degree && i_op == string::npos) || i_op == i_dquote) && i_quote != 0) { + i_prev = str.find_last_not_of(SPACE, i_quote - 1); + if(i_prev != string::npos) { + if(is_in(NUMBER_ELEMENTS, str[i_prev])) { + i_prev = str.find_last_not_of(NUMBER_ELEMENTS SPACE, i_prev); + if(i_prev == string::npos) i_prev = 0; + else i_prev++; + } else { + i_prev = string::npos; + } + } + } + if(i_prev != string::npos) { + str.insert(i_prev, LEFT_PARENTHESIS); + i_quote++; + if(i_op == string::npos) str += b_degree ? "arcsec" RIGHT_PARENTHESIS : "in" RIGHT_PARENTHESIS; + else str.replace(i_op + 1, strlen("″"), b_degree ? "arcsec" RIGHT_PARENTHESIS : "in" RIGHT_PARENTHESIS); + str.replace(i_quote, strlen("′"), b_degree ? "arcmin" PLUS : "ft" PLUS); + if(i_op == string::npos) break; + i_op++; + } else { + if(str.length() >= i_quote + strlen("′") && is_in(NUMBERS, str[i_quote + strlen("′")])) str.insert(i_quote + strlen("′"), " "); + str.replace(i_quote, strlen("′"), b_degree ? "arcmin" : "ft"); + i_op = i_quote; + } + } + } + if(i_dquote != string::npos) i_dquote = str.find("″", i_op); + if(i_quote != string::npos) i_quote = str.find("′", i_op); + } + } + + // Replace % with percent in case when it should not be interpreted as mod/rem + size_t i_mod = str.find("%"); + if(i_mod != string::npos && !v_percent->hasName("%")) i_mod = string::npos; + while(i_mod != string::npos) { + if(po.rpn) { + if(i_mod == 0 || is_not_in(OPERATORS "\\" INTERNAL_OPERATORS SPACE, str[i_mod - 1])) { + str.replace(i_mod, 1, v_percent->referenceName()); + i_mod += v_percent->referenceName().length() - 1; + } + } else if(i_mod == 0 || i_mod == str.length() - 1 || (is_in(RIGHT_PARENTHESIS RIGHT_VECTOR_WRAP COMMA OPERATORS "%\a\b", str[i_mod + 1]) && str[i_mod + 1] != BITWISE_NOT_CH && str[i_mod + 1] != NOT_CH) || is_in(LEFT_PARENTHESIS LEFT_VECTOR_WRAP COMMA OPERATORS "\a\b", str[i_mod - 1])) { + str.replace(i_mod, 1, v_percent->referenceName()); + i_mod += v_percent->referenceName().length() - 1; + } + i_mod = str.find("%", i_mod + 1); + } + + if(po.rpn) { + // add space between double operators in rpn mode in order to ensure that they are interpreted as two single operators + gsub("&&", "& &", str); + gsub("||", "| |", str); + gsub("\%\%", "\% \%", str); + } + + for(size_t str_index = 0; str_index < str.length(); str_index++) { + if(str[str_index] == LEFT_VECTOR_WRAP_CH) { + // vector + int i4 = 1; + size_t i3 = str_index; + while(true) { + i3 = str.find_first_of(LEFT_VECTOR_WRAP RIGHT_VECTOR_WRAP, i3 + 1); + if(i3 == string::npos) { + for(; i4 > 0; i4--) { + str += RIGHT_VECTOR_WRAP; + } + i3 = str.length() - 1; + } else if(str[i3] == LEFT_VECTOR_WRAP_CH) { + i4++; + } else if(str[i3] == RIGHT_VECTOR_WRAP_CH) { + i4--; + if(i4 > 0) { + size_t i5 = str.find_first_not_of(SPACE, i3 + 1); + if(i5 != string::npos && str[i5] == LEFT_VECTOR_WRAP_CH) { + str.insert(i5, COMMA); + } + } + } + if(i4 == 0) { + stmp2 = str.substr(str_index + 1, i3 - str_index - 1); + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + stmp += i2s(parseAddVectorId(stmp2, po)); + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + str.replace(str_index, i3 + 1 - str_index, stmp); + str_index += stmp.length() - 1; + break; + } + } + } else if(str[str_index] == '\\' && str_index + 1 < str.length() && (is_not_in(NOT_IN_NAMES INTERNAL_OPERATORS NUMBERS, str[str_index + 1]) || (!po.rpn && str_index > 0 && is_in(NUMBERS SPACE PLUS MINUS BITWISE_NOT NOT LEFT_PARENTHESIS, str[str_index + 1])))) { + if(is_in(NUMBERS SPACE PLUS MINUS BITWISE_NOT NOT LEFT_PARENTHESIS, str[str_index + 1])) { + // replace \ followed by number with // for integer division + str.replace(str_index, 1, "//"); + str_index++; + } else { + // replaced \ followed by a character with symbolic MathStructure + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + size_t l = 1; + if(str[str_index + l] < 0) { + do { + l++; + } while(str_index + l < str.length() && str[str_index + l] < 0 && (unsigned char) str[str_index + l] < 0xC0); + l--; + } + MathStructure *mstruct = new MathStructure(str.substr(str_index + 1, l)); + stmp += i2s(addId(mstruct)); + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + str.replace(str_index, l + 1, stmp); + str_index += stmp.length() - l; + } + } else if(str[str_index] == '!' && po.functions_enabled) { + // replace ! with factorial function when appropriate + if(str_index > 0 && (str.length() - str_index == 1 || str[str_index + 1] != EQUALS_CH)) { + stmp2 = ""; + size_t i5 = str.find_last_not_of(SPACE, str_index - 1); + size_t i3; + if(i5 == string::npos) { + } else if(str[i5] == RIGHT_PARENTHESIS_CH) { + if(i5 == 0) { + stmp2 = str.substr(0, i5 + 1); + } else { + i3 = i5 - 1; + size_t i4 = 1; + while(true) { + i3 = str.find_last_of(LEFT_PARENTHESIS RIGHT_PARENTHESIS, i3); + if(i3 == string::npos) { + stmp2 = str.substr(0, i5 + 1); + break; + } + if(str[i3] == RIGHT_PARENTHESIS_CH) { + i4++; + } else { + i4--; + if(i4 == 0) { + stmp2 = str.substr(i3, i5 + 1 - i3); + break; + } + } + if(i3 == 0) { + stmp2 = str.substr(0, i5 + 1); + break; + } + i3--; + } + } + } else if(str[i5] == ID_WRAP_RIGHT_CH && (i3 = str.find_last_of(ID_WRAP_LEFT, i5 - 1)) != string::npos) { + stmp2 = str.substr(i3, i5 + 1 - i3); + } else if(is_not_in(RESERVED OPERATORS INTERNAL_OPERATORS SPACES VECTOR_WRAPS PARENTHESISS COMMAS, str[i5])) { + i3 = str.find_last_of(RESERVED OPERATORS INTERNAL_OPERATORS SPACES VECTOR_WRAPS PARENTHESISS COMMAS, i5); + if(i3 == string::npos) { + stmp2 = str.substr(0, i5 + 1); + } else { + stmp2 = str.substr(i3 + 1, i5 - i3); + } + } + if(!stmp2.empty()) { + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + int ifac = 1; + i3 = str_index + 1; + size_t i4 = i3; + while((i3 = str.find_first_not_of(SPACE, i3)) != string::npos && str[i3] == '!') { + ifac++; + i3++; + i4 = i3; + } + if(ifac == 2) stmp += i2s(parseAddId(f_factorial2, stmp2, po)); + else if(ifac == 1) stmp += i2s(parseAddId(f_factorial, stmp2, po)); + else stmp += i2s(parseAddIdAppend(f_multifactorial, MathStructure(ifac, 1, 0), stmp2, po)); + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + str.replace(i5 - stmp2.length() + 1, stmp2.length() + i4 - i5 - 1, stmp); + str_index = stmp.length() + i5 - stmp2.length(); + } + } + } else if(!po.rpn && (str[str_index] == 'c' || str[str_index] == 'C') && str.length() > str_index + 6 && str[str_index + 5] == SPACE_CH && (str_index == 0 || is_in(OPERATORS INTERNAL_OPERATORS PARENTHESISS, str[str_index - 1])) && compare_name_no_case("compl", str, 5, str_index, base)) { + // interprate "compl" followed by space as bitwise not + str.replace(str_index, 6, BITWISE_NOT); + } else if(str[str_index] == SPACE_CH) { + size_t i = str.find(SPACE, str_index + 1); + if(po.rpn && i == string::npos) i = str.length(); + if(i != string::npos) { + // replace text operators, surrounded by space, with default operator characters + i -= str_index + 1; + size_t il = 0; + if(i == per_str_len && (il = compare_name_no_case(per_str, str, per_str_len, str_index + 1, base))) { + str.replace(str_index + 1, il, DIVISION); + str_index++; + } else if(i == times_str_len && (il = compare_name_no_case(times_str, str, times_str_len, str_index + 1, base))) { + str.replace(str_index + 1, il, MULTIPLICATION); + str_index++; + } else if(i == plus_str_len && (il = compare_name_no_case(plus_str, str, plus_str_len, str_index + 1, base))) { + str.replace(str_index + 1, il, PLUS); + str_index++; + } else if(i == minus_str_len && (il = compare_name_no_case(minus_str, str, minus_str_len, str_index + 1, base))) { + str.replace(str_index + 1, il, MINUS); + str_index++; + } else if(and_str_len > 0 && i == and_str_len && (il = compare_name_no_case(and_str, str, and_str_len, str_index + 1, base))) { + str.replace(str_index + 1, il, LOGICAL_AND); + str_index += 2; + } else if(i == AND_str_len && (il = compare_name_no_case(AND_str, str, AND_str_len, str_index + 1, base))) { + str.replace(str_index + 1, il, LOGICAL_AND); + str_index += 2; + } else if(or_str_len > 0 && i == or_str_len && (il = compare_name_no_case(or_str, str, or_str_len, str_index + 1, base))) { + str.replace(str_index + 1, il, LOGICAL_OR); + str_index += 2; + } else if(i == OR_str_len && (il = compare_name_no_case(OR_str, str, OR_str_len, str_index + 1, base))) { + str.replace(str_index + 1, il, LOGICAL_OR); + str_index += 2; + } else if(i == XOR_str_len && (il = compare_name_no_case(XOR_str, str, XOR_str_len, str_index + 1, base))) { + str.replace(str_index + 1, il, "\a"); + str_index++; + } else if(i == 5 && (il = compare_name_no_case("bitor", str, 5, str_index + 1, base))) { + str.replace(str_index + 1, il, BITWISE_OR); + str_index++; + } else if(i == 6 && (il = compare_name_no_case("bitand", str, 6, str_index + 1, base))) { + str.replace(str_index + 1, il, BITWISE_AND); + str_index++; + } else if(i == 3 && (il = compare_name_no_case("mod", str, 3, str_index + 1, base))) { + str.replace(str_index + 1, il, "\%\%"); + str_index += 2; + } else if(i == 3 && (il = compare_name_no_case("rem", str, 3, str_index + 1, base))) { + str.replace(str_index + 1, il, "%"); + str_index++; + } else if(i == 3 && (il = compare_name_no_case("div", str, 3, str_index + 1, base))) { + if(po.rpn) { + str.replace(str_index + 1, il, "\\"); + str_index++; + } else { + str.replace(str_index + 1, il, "//"); + str_index += 2; + } + } + } + } else if(str_index > 0 && base >= 2 && base <= 10 && is_in(EXPS, str[str_index]) && str_index + 1 < str.length() && (is_in(NUMBER_ELEMENTS, str[str_index + 1]) || (is_in(PLUS MINUS, str[str_index + 1]) && str_index + 2 < str.length() && is_in(NUMBER_ELEMENTS, str[str_index + 2]))) && is_in(NUMBER_ELEMENTS, str[str_index - 1])) { + //don't do anything when e is used instead of E for EXP + } else if(base <= 33 && str[str_index] == '0' && (str_index == 0 || is_in(NOT_IN_NAMES INTERNAL_OPERATORS, str[str_index - 1]))) { + if(str_index + 2 < str.length() && (str[str_index + 1] == 'x' || str[str_index + 1] == 'X') && is_in(NUMBER_ELEMENTS "abcdefABCDEF", str[str_index + 2])) { + //hexadecimal number 0x... + if(po.base == BASE_HEXADECIMAL) { + str.erase(str_index, 2); + } else { + size_t i; + if(po.rpn) i = str.find_first_not_of(NUMBER_ELEMENTS "abcdefABCDEF", str_index + 2); + else i = str.find_first_not_of(SPACE NUMBER_ELEMENTS "abcdefABCDEF", str_index + 2); + size_t name_length; + if(i == string::npos) i = str.length(); + while(str[i - 1] == SPACE_CH) i--; + name_length = i - str_index; + ParseOptions po_hex = po; + po_hex.base = BASE_HEXADECIMAL; + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + MathStructure *mstruct = new MathStructure(Number(str.substr(str_index, i - str_index), po_hex)); + stmp += i2s(addId(mstruct)); + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + str.replace(str_index, name_length, stmp); + str_index += stmp.length() - 1; + } + + } else if(base <= 12 && str_index + 2 < str.length() && (str[str_index + 1] == 'b' || str[str_index + 1] == 'B') && is_in("01", str[str_index + 2])) { + //binary number 0b... + if(po.base == BASE_BINARY) { + str.erase(str_index, 2); + } else { + size_t i; + if(po.rpn) i = str.find_first_not_of(NUMBER_ELEMENTS, str_index + 2); + else i = str.find_first_not_of(SPACE NUMBER_ELEMENTS, str_index + 2); + size_t name_length; + if(i == string::npos) i = str.length(); + while(str[i - 1] == SPACE_CH) i--; + name_length = i - str_index; + ParseOptions po_bin = po; + po_bin.base = BASE_BINARY; + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + MathStructure *mstruct = new MathStructure(Number(str.substr(str_index, i - str_index), po_bin)); + stmp += i2s(addId(mstruct)); + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + str.replace(str_index, name_length, stmp); + str_index += stmp.length() - 1; + } + } else if(base <= 24 && str_index + 2 < str.length() && (str[str_index + 1] == 'o' || str[str_index + 1] == 'O') && is_in(NUMBERS, str[str_index + 2])) { + //octal number 0o... + if(po.base == BASE_OCTAL) { + str.erase(str_index, 2); + } else { + size_t i; + if(po.rpn) i = str.find_first_not_of(NUMBER_ELEMENTS, str_index + 2); + else i = str.find_first_not_of(SPACE NUMBER_ELEMENTS, str_index + 2); + size_t name_length; + if(i == string::npos) i = str.length(); + while(str[i - 1] == SPACE_CH) i--; + name_length = i - str_index; + ParseOptions po_oct = po; + po_oct.base = BASE_OCTAL; + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + MathStructure *mstruct = new MathStructure(Number(str.substr(str_index, i - str_index), po_oct)); + stmp += i2s(addId(mstruct)); + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + str.replace(str_index, name_length, stmp); + str_index += stmp.length() - 1; + } + } + } else if(is_not_in(NUMBERS INTERNAL_OPERATORS NOT_IN_NAMES, str[str_index])) { + // search for variable, function, unit, prefix names + bool p_mode = false; + void *best_p_object = NULL; + Prefix *best_p = NULL; + size_t best_pl = 0; + size_t best_pnl = 0; + bool moved_forward = false; + const string *found_function_name = NULL; + bool case_sensitive = false; + size_t found_function_name_length = 0; + void *found_function = NULL, *object = NULL; + int vt2 = -1; + size_t ufv_index; + size_t name_length; + size_t vt3 = 0; + char ufvt = 0; + size_t last_name_char = str.find_first_of(NOT_IN_NAMES INTERNAL_OPERATORS, str_index + 1); + if(last_name_char == string::npos) { + last_name_char = str.length() - 1; + } else { + last_name_char--; + } + size_t last_unit_char = str.find_last_not_of(NUMBERS, last_name_char); + size_t name_chars_left = last_name_char - str_index + 1; + size_t unit_chars_left = last_unit_char - str_index + 1; + if(name_chars_left <= UFV_LENGTHS) { + ufv_index = name_chars_left - 1; + vt2 = 0; + } else { + ufv_index = 0; + } + Prefix *p = NULL; + while(vt2 < 4) { + name = NULL; + p = NULL; + switch(vt2) { + case -1: { + if(ufv_index < ufvl.size()) { + switch(ufvl_t[ufv_index]) { + case 'v': { + if(po.variables_enabled && !p_mode) { + name = &((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).name; + case_sensitive = ((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).case_sensitive; + name_length = name->length(); + if(name_length < found_function_name_length) { + name = NULL; + } else if(po.limit_implicit_multiplication) { + if(name_length != name_chars_left && name_length != unit_chars_left) name = NULL; + } else if(name_length > name_chars_left) { + name = NULL; + } + } + break; + } + case 'f': { + if(po.functions_enabled && !found_function_name && !p_mode) { + name = &((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).name; + case_sensitive = ((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).case_sensitive; + name_length = name->length(); + if(po.limit_implicit_multiplication) { + if(name_length != name_chars_left && name_length != unit_chars_left) name = NULL; + } else if(name_length > name_chars_left || name_length < found_function_name_length) { + name = NULL; + } + } + break; + } + case 'u': { + if(po.units_enabled && !p_mode) { + name = &((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).name; + case_sensitive = ((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).case_sensitive; + name_length = name->length(); + if(name_length < found_function_name_length) { + name = NULL; + } else if(po.limit_implicit_multiplication || ((ExpressionItem*) ufvl[ufv_index])->getName(ufvl_i[ufv_index]).plural) { + if(name_length != unit_chars_left) name = NULL; + } else if(name_length > unit_chars_left) { + name = NULL; + } + } + break; + } + case 'p': { + if(!p && po.units_enabled) { + name = &((Prefix*) ufvl[ufv_index])->shortName(); + name_length = name->length(); + if(name_length >= unit_chars_left || name_length < found_function_name_length) { + name = NULL; + } + } + case_sensitive = true; + break; + } + case 'P': { + if(!p && po.units_enabled) { + name = &((Prefix*) ufvl[ufv_index])->longName(); + name_length = name->length(); + if(name_length >= unit_chars_left || name_length < found_function_name_length) { + name = NULL; + } + } + case_sensitive = false; + break; + } + case 'q': { + if(!p && po.units_enabled) { + name = &((Prefix*) ufvl[ufv_index])->unicodeName(); + name_length = name->length(); + if(name_length >= unit_chars_left || name_length < found_function_name_length) { + name = NULL; + } + } + case_sensitive = true; + break; + } + } + ufvt = ufvl_t[ufv_index]; + object = ufvl[ufv_index]; + ufv_index++; + break; + } else { + if(found_function_name) { + vt2 = 4; + break; + } + vt2 = 0; + vt3 = 0; + if(po.limit_implicit_multiplication && unit_chars_left <= UFV_LENGTHS) { + ufv_index = unit_chars_left - 1; + } else { + ufv_index = UFV_LENGTHS - 1; + } + } + } + case 0: { + if(po.units_enabled && ufv_index < unit_chars_left - 1 && vt3 < ufv[vt2][ufv_index].size()) { + object = ufv[vt2][ufv_index][vt3]; + switch(ufv_i[vt2][ufv_index][vt3]) { + case 1: { + ufvt = 'P'; + name = &((Prefix*) object)->longName(); + name_length = name->length(); + case_sensitive = false; + break; + } + case 2: { + ufvt = 'p'; + name = &((Prefix*) object)->shortName(); + name_length = name->length(); + case_sensitive = true; + break; + } + case 3: { + ufvt = 'q'; + name = &((Prefix*) object)->unicodeName(); + name_length = name->length(); + case_sensitive = true; + break; + } + } + vt3++; + break; + } + vt2 = 1; + vt3 = 0; + } + case 1: { + if(!found_function_name && po.functions_enabled && !p_mode && (!po.limit_implicit_multiplication || ufv_index + 1 == unit_chars_left || ufv_index + 1 == name_chars_left) && vt3 < ufv[vt2][ufv_index].size()) { + object = ufv[vt2][ufv_index][vt3]; + ufvt = 'f'; + name = &((MathFunction*) object)->getName(ufv_i[vt2][ufv_index][vt3]).name; + name_length = name->length(); + case_sensitive = ((MathFunction*) object)->getName(ufv_i[vt2][ufv_index][vt3]).case_sensitive; + vt3++; + break; + } + vt2 = 2; + vt3 = 0; + } + case 2: { + if(po.units_enabled && !p_mode && (!po.limit_implicit_multiplication || ufv_index + 1 == unit_chars_left) && ufv_index < unit_chars_left && vt3 < ufv[vt2][ufv_index].size()) { + object = ufv[vt2][ufv_index][vt3]; + if(ufv_index + 1 == unit_chars_left || !((Unit*) object)->getName(ufv_i[vt2][ufv_index][vt3]).plural) { + ufvt = 'u'; + name = &((Unit*) object)->getName(ufv_i[vt2][ufv_index][vt3]).name; + name_length = name->length(); + case_sensitive = ((Unit*) object)->getName(ufv_i[vt2][ufv_index][vt3]).case_sensitive; + } + vt3++; + break; + } + vt2 = 3; + vt3 = 0; + } + case 3: { + if(po.variables_enabled && !p_mode && (!po.limit_implicit_multiplication || ufv_index + 1 == unit_chars_left || ufv_index + 1 == name_chars_left) && vt3 < ufv[vt2][ufv_index].size()) { + object = ufv[vt2][ufv_index][vt3]; + ufvt = 'v'; + name = &((Variable*) object)->getName(ufv_i[vt2][ufv_index][vt3]).name; + name_length = name->length(); + case_sensitive = ((Variable*) object)->getName(ufv_i[vt2][ufv_index][vt3]).case_sensitive; + vt3++; + break; + } + if(ufv_index == 0 || found_function_name) { + vt2 = 4; + } else { + ufv_index--; + vt3 = 0; + vt2 = 0; + } + } + } + if(name && name_length >= found_function_name_length && ((case_sensitive && compare_name(*name, str, name_length, str_index, base)) || (!case_sensitive && (name_length = compare_name_no_case(*name, str, name_length, str_index, base))))) { + moved_forward = false; + switch(ufvt) { + case 'v': { + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + stmp += i2s(addId(new MathStructure((Variable*) object))); + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + str.replace(str_index, name_length, stmp); + str_index += stmp.length(); + moved_forward = true; + break; + } + case 'f': { + if(((ExpressionItem*) object)->subtype() == SUBTYPE_DATA_SET && str[str_index + name_length] == DOT_CH) { + str[str_index + name_length] = LEFT_PARENTHESIS_CH; + size_t dot2_index = str.find(DOT_CH, str_index + name_length + 1); + str[dot2_index] = COMMA_CH; + size_t end_index = str.find_first_of(NOT_IN_NAMES INTERNAL_OPERATORS, dot2_index + 1); + if(end_index == string::npos) str += RIGHT_PARENTHESIS_CH; + else str.insert(end_index, 1, RIGHT_PARENTHESIS_CH); + } + size_t not_space_index; + if((not_space_index = str.find_first_not_of(SPACES, str_index + name_length)) == string::npos || str[not_space_index] != LEFT_PARENTHESIS_CH) { + found_function = object; + found_function_name = name; + found_function_name_length = name_length; + break; + } + set_function: + MathFunction *f = (MathFunction*) object; + int i4 = -1; + size_t i6; + if(f->args() == 0) { + size_t i7 = str.find_first_not_of(SPACES, str_index + name_length); + if(i7 != string::npos && str[i7] == LEFT_PARENTHESIS_CH) { + i7 = str.find_first_not_of(SPACES, i7 + 1); + if(i7 != string::npos && str[i7] == RIGHT_PARENTHESIS_CH) { + i4 = i7 - str_index + 1; + } + } + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + stmp += i2s(parseAddId(f, empty_string, po)); + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + if(i4 < 0) i4 = name_length; + } else if(po.rpn && f->args() == 1 && str_index > 0 && str[str_index - 1] != LEFT_PARENTHESIS_CH && (str_index + name_length >= str.length() || str[str_index + name_length] != LEFT_PARENTHESIS_CH) && (i6 = str.find_last_not_of(SPACE, str_index - 1)) != string::npos) { + size_t i7 = i6; + int nr_of_p = 0, nr_of_op = 0; + bool b_started = false; + while(i7 != 0) { + if(nr_of_p > 0) { + if(str[i7] == LEFT_PARENTHESIS_CH) { + nr_of_p--; + if(nr_of_p == 0 && nr_of_op == 0) break; + } else if(str[i7] == RIGHT_PARENTHESIS_CH) { + nr_of_p++; + } + } else if(nr_of_p == 0 && is_in(OPERATORS INTERNAL_OPERATORS SPACE RIGHT_PARENTHESIS, str[i7])) { + if(nr_of_op == 0 && b_started) { + i7++; + break; + } else { + if(is_in(OPERATORS INTERNAL_OPERATORS, str[i7])) { + nr_of_op++; + b_started = false; + } else if(str[i7] == RIGHT_PARENTHESIS_CH) { + nr_of_p++; + b_started = true; + } else if(b_started) { + nr_of_op--; + b_started = false; + } + } + } else { + b_started = true; + } + i7--; + } + stmp2 = str.substr(i7, i6 - i7 + 1); + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + if(f->id() == FUNCTION_ID_VECTOR) stmp += i2s(parseAddVectorId(stmp2, po)); + else stmp += i2s(parseAddId(f, stmp2, po)); + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + str.replace(i7, str_index + name_length - i7, stmp); + str_index += name_length; + moved_forward = true; + } else { + bool b = false, b_unended_function = false, b_comma_before = false, b_power_before = false; + //bool b_space_first = false; + size_t i5 = 1; + int arg_i = f->args(); + i6 = 0; + while(!b) { + if(i6 + str_index + name_length >= str.length()) { + b = true; + i5 = 2; + i6++; + b_unended_function = true; + break; + } else { + char c = str[str_index + name_length + i6]; + if(c == LEFT_PARENTHESIS_CH) { + if(i5 < 2) b = true; + else if(i5 == 2 && po.parsing_mode == PARSING_MODE_CONVENTIONAL && !b_power_before) b = true; + else i5++; + } else if(c == RIGHT_PARENTHESIS_CH) { + if(i5 <= 2) b = true; + else i5--; + } else if(c == POWER_CH) { + if(i5 < 2) i5 = 2; + b_power_before = true; + } else if(!b_comma_before && !b_power_before && c == ' ' && arg_i <= 1) { + //if(i5 < 2) b_space_first = true; + if(i5 == 2) b = true; + } else if(!b_comma_before && i5 == 2 && arg_i <= 1 && is_in(OPERATORS INTERNAL_OPERATORS, c) && c != POWER_CH) { + b = true; + } else if(c == COMMA_CH) { + if(i5 == 2) arg_i--; + b_comma_before = true; + if(i5 < 2) i5 = 2; + } else if(i5 < 2) { + i5 = 2; + } + if(c != COMMA_CH && c != ' ') b_comma_before = false; + if(c != POWER_CH && c != ' ') b_power_before = false; + } + i6++; + } + if(b && i5 >= 2) { + stmp2 = str.substr(str_index + name_length, i6 - 1); + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + if(b_unended_function && unended_function) { + po.unended_function = unended_function; + } + if(f->id() == FUNCTION_ID_VECTOR) { + stmp += i2s(parseAddVectorId(stmp2, po)); + } else if((f->id() == FUNCTION_ID_INTERVAL || f->id() == FUNCTION_ID_UNCERTAINTY) && po.read_precision != DONT_READ_PRECISION) { + ParseOptions po2 = po; + po2.read_precision = DONT_READ_PRECISION; + stmp += i2s(parseAddId(f, stmp2, po2)); + } else { + stmp += i2s(parseAddId(f, stmp2, po)); + } + po.unended_function = NULL; + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + i4 = i6 + 1 + name_length - 2; + b = false; + } + size_t i9 = i6; + if(b) { + b = false; + i6 = i6 + 1 + str_index + name_length; + size_t i7 = i6 - 1; + size_t i8 = i7; + while(true) { + i5 = str.find(RIGHT_PARENTHESIS_CH, i7); + if(i5 == string::npos) { + b_unended_function = true; + //str.append(1, RIGHT_PARENTHESIS_CH); + //i5 = str.length() - 1; + i5 = str.length(); + } + if(i5 < (i6 = str.find(LEFT_PARENTHESIS_CH, i8)) || i6 == string::npos) { + i6 = i5; + b = true; + break; + } + i7 = i5 + 1; + i8 = i6 + 1; + } + if(!b) { + b_unended_function = false; + } + } + if(b) { + stmp2 = str.substr(str_index + name_length + i9, i6 - (str_index + name_length + i9)); + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + if(b_unended_function && unended_function) { + po.unended_function = unended_function; + } + if(f->id() == FUNCTION_ID_VECTOR) { + stmp += i2s(parseAddVectorId(stmp2, po)); + } else if((f->id() == FUNCTION_ID_INTERVAL || f->id() == FUNCTION_ID_UNCERTAINTY) && po.read_precision != DONT_READ_PRECISION) { + ParseOptions po2 = po; + po2.read_precision = DONT_READ_PRECISION; + stmp += i2s(parseAddId(f, stmp2, po2)); + } else { + stmp += i2s(parseAddId(f, stmp2, po)); + } + po.unended_function = NULL; + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + i4 = i6 + 1 - str_index; + } + } + if(i4 > 0) { + str.replace(str_index, i4, stmp); + str_index += stmp.length(); + moved_forward = true; + } + break; + } + case 'u': { + replace_text_by_unit_place: + if(str.length() > str_index + name_length && is_in("23", str[str_index + name_length]) && (str.length() == str_index + name_length + 1 || is_not_in(NUMBER_ELEMENTS, str[str_index + name_length + 1])) && *name != SIGN_DEGREE && !((Unit*) object)->isCurrency()) { + str.insert(str_index + name_length, 1, POWER_CH); + } + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + stmp += i2s(addId(new MathStructure((Unit*) object, p))); + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + str.replace(str_index, name_length, stmp); + str_index += stmp.length(); + moved_forward = true; + p = NULL; + break; + } + case 'p': {} + case 'q': {} + case 'P': { + if(str_index + name_length == str.length() || is_in(NOT_IN_NAMES INTERNAL_OPERATORS, str[str_index + name_length])) { + break; + } + p = (Prefix*) object; + str_index += name_length; + unit_chars_left = last_unit_char - str_index + 1; + size_t name_length_old = name_length; + int index = 0; + if(unit_chars_left > UFV_LENGTHS) { + for(size_t ufv_index2 = 0; ufv_index2 < ufvl.size(); ufv_index2++) { + name = NULL; + switch(ufvl_t[ufv_index2]) { + case 'u': { + name = &((Unit*) ufvl[ufv_index2])->getName(ufvl_i[ufv_index2]).name; + case_sensitive = ((Unit*) ufvl[ufv_index2])->getName(ufvl_i[ufv_index2]).case_sensitive; + name_length = name->length(); + if(po.limit_implicit_multiplication || ((Unit*) ufvl[ufv_index2])->getName(ufvl_i[ufv_index2]).plural) { + if(name_length != unit_chars_left) name = NULL; + } else if(name_length > unit_chars_left) { + name = NULL; + } + break; + } + } + if(name && ((case_sensitive && compare_name(*name, str, name_length, str_index, base)) || (!case_sensitive && (name_length = compare_name_no_case(*name, str, name_length, str_index, base))))) { + if((!p_mode && name_length_old > 1) || (p_mode && (name_length + name_length_old > best_pl || ((ufvt != 'P' || !((Unit*) ufvl[ufv_index2])->getName(ufvl_i[ufv_index2]).abbreviation) && name_length + name_length_old == best_pl)))) { + p_mode = true; + best_p = p; + best_p_object = ufvl[ufv_index2]; + best_pl = name_length + name_length_old; + best_pnl = name_length_old; + index = -1; + break; + } + if(!p_mode) { + str.erase(str_index - name_length_old, name_length_old); + str_index -= name_length_old; + object = ufvl[ufv_index2]; + goto replace_text_by_unit_place; + } + } + } + } + if(index < 0) { + } else if(UFV_LENGTHS >= unit_chars_left) { + index = unit_chars_left - 1; + } else if(po.limit_implicit_multiplication) { + index = -1; + } else { + index = UFV_LENGTHS - 1; + } + for(; index >= 0; index--) { + for(size_t ufv_index2 = 0; ufv_index2 < ufv[2][index].size(); ufv_index2++) { + name = &((Unit*) ufv[2][index][ufv_index2])->getName(ufv_i[2][index][ufv_index2]).name; + case_sensitive = ((Unit*) ufv[2][index][ufv_index2])->getName(ufv_i[2][index][ufv_index2]).case_sensitive; + name_length = name->length(); + if(index + 1 == (int) unit_chars_left || !((Unit*) ufv[2][index][ufv_index2])->getName(ufv_i[2][index][ufv_index2]).plural) { + if(name_length <= unit_chars_left && ((case_sensitive && compare_name(*name, str, name_length, str_index, base)) || (!case_sensitive && (name_length = compare_name_no_case(*name, str, name_length, str_index, base))))) { + if((!p_mode && name_length_old > 1) || (p_mode && (name_length + name_length_old > best_pl || ((ufvt != 'P' || !((Unit*) ufv[2][index][ufv_index2])->getName(ufv_i[2][index][ufv_index2]).abbreviation) && name_length + name_length_old == best_pl)))) { + p_mode = true; + best_p = p; + best_p_object = ufv[2][index][ufv_index2]; + best_pl = name_length + name_length_old; + best_pnl = name_length_old; + index = -1; + } + if(!p_mode) { + str.erase(str_index - name_length_old, name_length_old); + str_index -= name_length_old; + object = ufv[2][index][ufv_index2]; + goto replace_text_by_unit_place; + } + } + } + } + if(po.limit_implicit_multiplication || (p_mode && index + 1 + name_length_old < best_pl)) { + break; + } + } + str_index -= name_length_old; + unit_chars_left = last_unit_char - str_index + 1; + break; + } + } + if(moved_forward) { + str_index--; + break; + } + } + } + if(!moved_forward && p_mode) { + object = best_p_object; + p = best_p; + str.erase(str_index, best_pnl); + name_length = best_pl - best_pnl; + goto replace_text_by_unit_place; + } else if(!moved_forward && found_function) { + object = found_function; + name = found_function_name; + name_length = found_function_name_length; + goto set_function; + } + if(!moved_forward) { + bool b = po.unknowns_enabled && is_not_number(str[str_index], base) && !(str_index > 0 && is_in(EXPS, str[str_index]) && str_index + 1 < str.length() && (is_in(NUMBER_ELEMENTS, str[str_index + 1]) || (is_in(PLUS MINUS, str[str_index + 1]) && str_index + 2 < str.length() && is_in(NUMBER_ELEMENTS, str[str_index + 2]))) && is_in(NUMBER_ELEMENTS, str[str_index - 1])); + if(po.limit_implicit_multiplication) { + if(b) { + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + stmp += i2s(addId(new MathStructure(str.substr(str_index, unit_chars_left)))); + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + str.replace(str_index, unit_chars_left, stmp); + str_index += stmp.length() - 1; + } else { + str_index += unit_chars_left - 1; + } + } else if(b) { + size_t i = 1; + if(str[str_index + 1] < 0) { + i++; + while(i <= unit_chars_left && (unsigned char) str[str_index + i] >= 0x80 && (unsigned char) str[str_index + i] <= 0xBF) { + i++; + } + } + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + stmp += i2s(addId(new MathStructure(str.substr(str_index, i)))); + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + str.replace(str_index, i, stmp); + str_index += stmp.length() - 1; + } + } + } + } + + size_t comma_i = str.find(COMMA, 0); + while(comma_i != string::npos) { + int i3 = 1; + size_t left_par_i = comma_i; + while(left_par_i > 0) { + left_par_i = str.find_last_of(LEFT_PARENTHESIS RIGHT_PARENTHESIS, left_par_i - 1); + if(left_par_i == string::npos) break; + if(str[left_par_i] == LEFT_PARENTHESIS_CH) { + i3--; + if(i3 == 0) break; + } else if(str[left_par_i] == RIGHT_PARENTHESIS_CH) { + i3++; + } + } + if(i3 > 0) { + str.insert(0, i3, LEFT_PARENTHESIS_CH); + comma_i += i3; + i3 = 0; + left_par_i = 0; + } + if(i3 == 0) { + i3 = 1; + size_t right_par_i = comma_i; + while(true) { + right_par_i = str.find_first_of(LEFT_PARENTHESIS RIGHT_PARENTHESIS, right_par_i + 1); + if(right_par_i == string::npos) { + for(; i3 > 0; i3--) { + str += RIGHT_PARENTHESIS; + } + right_par_i = str.length() - 1; + } else if(str[right_par_i] == LEFT_PARENTHESIS_CH) { + i3++; + } else if(str[right_par_i] == RIGHT_PARENTHESIS_CH) { + i3--; + } + if(i3 == 0) { + stmp2 = str.substr(left_par_i + 1, right_par_i - left_par_i - 1); + stmp = LEFT_PARENTHESIS ID_WRAP_LEFT; + stmp += i2s(parseAddVectorId(stmp2, po)); + stmp += ID_WRAP_RIGHT RIGHT_PARENTHESIS; + str.replace(left_par_i, right_par_i + 1 - left_par_i, stmp); + comma_i = left_par_i + stmp.length() - 1; + break; + } + } + } + comma_i = str.find(COMMA, comma_i + 1); + } + + if(po.rpn) { + size_t rpn_i = str.find(SPACE, 0); + while(rpn_i != string::npos) { + if(rpn_i == 0 || rpn_i + 1 == str.length() || is_in("~+-*/^\a\b\\\x1c", str[rpn_i - 1]) || (is_in("%&|", str[rpn_i - 1]) && str[rpn_i + 1] != str[rpn_i - 1]) || (is_in("!><=", str[rpn_i - 1]) && is_not_in("=<>", str[rpn_i + 1])) || (is_in(SPACE OPERATORS INTERNAL_OPERATORS, str[rpn_i + 1]) && (str[rpn_i - 1] == SPACE_CH || (str[rpn_i - 1] != str[rpn_i + 1] && is_not_in("!><=", str[rpn_i - 1]))))) { + str.erase(rpn_i, 1); + } else { + rpn_i++; + } + rpn_i = str.find(SPACE, rpn_i); + } + } else if(po.parsing_mode != PARSING_MODE_ADAPTIVE) { + remove_blanks(str); + } else { + //remove spaces between next to operators (except '/') and before/after parentheses + space_i = str.find(SPACE_CH, 0); + while(space_i != string::npos) { + if((str[space_i + 1] != DIVISION_CH && is_in(OPERATORS INTERNAL_OPERATORS RIGHT_PARENTHESIS, str[space_i + 1])) || (str[space_i - 1] != DIVISION_CH && is_in(OPERATORS INTERNAL_OPERATORS LEFT_PARENTHESIS, str[space_i - 1]))) { + str.erase(space_i, 1); + space_i--; + } + space_i = str.find(SPACE_CH, space_i + 1); + } + } + + parseOperators(mstruct, str, po); + +} + +#define BASE_2_10 ((po.base >= 2 && po.base <= 10) || (po.base < BASE_CUSTOM && po.base != BASE_UNICODE && po.base != BASE_BIJECTIVE_26) || (po.base == BASE_CUSTOM && priv->custom_input_base_i <= 10)) + +bool Calculator::parseNumber(MathStructure *mstruct, string str, const ParseOptions &po) { + + mstruct->clear(); + if(str.empty()) return false; + + // check that string contains characters other than operators and whitespace + if(str.find_first_not_of(OPERATORS "\a%\x1c" SPACE) == string::npos && (po.base != BASE_ROMAN_NUMERALS || str.find("|") == string::npos)) { + gsub("\a", str.find_first_of("%" OPERATORS) != string::npos ? " xor " : "xor", str); + gsub("\x1c", "∠", str); + error(false, _("Misplaced operator(s) \"%s\" ignored"), str.c_str(), NULL); + return false; + } + + int minus_count = 0; + bool has_sign = false, had_non_sign = false, b_dot = false, b_exp = false, after_sign_e = false; + int i_colon = 0; + size_t i = 0; + + while(i < str.length()) { + if(!had_non_sign && str[i] == MINUS_CH) { + // count minuses in front of the number + has_sign = true; + minus_count++; + str.erase(i, 1); + } else if(!had_non_sign && str[i] == PLUS_CH) { + // + in front of the number is ignored + has_sign = true; + str.erase(i, 1); + } else if(str[i] == SPACE_CH) { + // ignore whitespace + str.erase(i, 1); + } else if(!b_exp && BASE_2_10 && (str[i] == EXP_CH || str[i] == EXP2_CH)) { + // scientific e-notation + b_exp = true; + had_non_sign = true; + after_sign_e = true; + i++; + } else if(after_sign_e && (str[i] == MINUS_CH || str[i] == PLUS_CH)) { + after_sign_e = false; + i++; + } else if(po.preserve_format && str[i] == DOT_CH) { + b_dot = true; + had_non_sign = true; + after_sign_e = false; + i++; + } else if(po.preserve_format && (!b_dot || i_colon > 0) && str[i] == ':') { + // sexagesimal colon; dots are not allowed in first part of a sexagesimal number + i_colon++; + had_non_sign = true; + after_sign_e = false; + i++; + } else if(str[i] == COMMA_CH && DOT_S == ".") { + // comma is ignored of decimal separator is dot + str.erase(i, 1); + after_sign_e = false; + had_non_sign = true; + } else if(is_in(OPERATORS, str[i]) && (po.base != BASE_ROMAN_NUMERALS || (str[i] != '(' && str[i] != ')' && str[i] != '|'))) { + // ignore operators + error(false, _("Misplaced '%c' ignored"), str[i], NULL); + str.erase(i, 1); + } else if(str[i] == '\a') { + // ignore operators + error(false, _("Misplaced operator(s) \"%s\" ignored"), "xor", NULL); + str.erase(i, 1); + } else if(str[i] == '\x1c') { + // ignore operators + error(false, _("Misplaced operator(s) \"%s\" ignored"), "∠", NULL); + str.erase(i, 1); + } else if(str[i] == '\b') { + // +/- + b_exp = false; + had_non_sign = false; + after_sign_e = false; + i++; + } else { + had_non_sign = true; + after_sign_e = false; + i++; + } + } + if(str.empty()) { + if(minus_count % 2 == 1 && !po.preserve_format) { + mstruct->set(-1, 1, 0); + } else if(has_sign) { + mstruct->set(1, 1, 0); + if(po.preserve_format) { + while(minus_count > 0) { + mstruct->transform(STRUCT_NEGATE); + minus_count--; + } + } + } + return false; + } + // numbers in brackets is an internal reference to a stored MathStructure object + if(str[0] == ID_WRAP_LEFT_CH && str.length() > 2 && str[str.length() - 1] == ID_WRAP_RIGHT_CH) { + int id = s2i(str.substr(1, str.length() - 2)); + MathStructure *m_temp = getId((size_t) id); + if(!m_temp) { + mstruct->setUndefined(); + error(true, _("Internal id %s does not exist."), i2s(id).c_str(), NULL); + return true; + } + mstruct->set_nocopy(*m_temp); + m_temp->unref(); + if(po.preserve_format) { + while(minus_count > 0) { + mstruct->transform(STRUCT_NEGATE); + minus_count--; + } + } else if(minus_count % 2 == 1) { + mstruct->negate(); + } + return true; + } + + // handle non-digits if number base is 2-10 or duodecimal + size_t itmp; + if((BASE_2_10 || po.base == BASE_DUODECIMAL) && (itmp = str.find_first_not_of(po.base == BASE_DUODECIMAL ? NUMBER_ELEMENTS INTERNAL_NUMBER_CHARS MINUS DUODECIMAL_CHARS : NUMBER_ELEMENTS INTERNAL_NUMBER_CHARS EXPS MINUS, 0)) != string::npos) { + if(itmp == 0) { + error(true, _("\"%s\" is not a valid variable/function/unit."), str.c_str(), NULL); + if(minus_count % 2 == 1 && !po.preserve_format) { + mstruct->set(-1, 1, 0); + } else if(has_sign) { + mstruct->set(1, 1, 0); + if(po.preserve_format) { + while(minus_count > 0) { + mstruct->transform(STRUCT_NEGATE); + minus_count--; + } + } + } + return false; + } else { + string stmp = str.substr(itmp, str.length() - itmp); + error(true, _("Trailing characters \"%s\" (not a valid variable/function/unit) in number \"%s\" was ignored."), stmp.c_str(), str.c_str(), NULL); + str.erase(itmp, str.length() - itmp); + } + } + + // replace internal +/- operator + gsub("\b", "±", str); + + // parse number + Number nr(str, po); + + // handle - in front of the number (even number of minuses equals plus, odd number equals a single minus) + if(!po.preserve_format && minus_count % 2 == 1) { + nr.negate(); + } + + if(i_colon && nr.isRational() && !nr.isInteger()) { + // if po.preserve_format is true, parse sexagesimal number as division + Number nr_num(nr.numerator()), nr_den(1, 1, 0); + while(i_colon) { + nr_den *= 60; + i_colon--; + } + nr_num *= nr_den; + nr_num /= nr.denominator(); + mstruct->set(nr_num); + mstruct->transform(STRUCT_DIVISION, nr_den); + } else { + mstruct->set(nr); + } + if(po.preserve_format) { + // handle multiple - in front of the number (treated as a single sign if po.preserve_format is false) + while(minus_count > 0) { + mstruct->transform(STRUCT_NEGATE); + minus_count--; + } + } + return true; + +} + +bool Calculator::parseAdd(string &str, MathStructure *mstruct, const ParseOptions &po) { + if(str.length() > 0) { + size_t i; + if(BASE_2_10) { + i = str.find_first_of(SPACE MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS EXPS ID_WRAP_LEFT, 1); + } else { + i = str.find_first_of(SPACE MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS ID_WRAP_LEFT, 1); + } + if(i == string::npos && str[0] != LOGICAL_NOT_CH && str[0] != BITWISE_NOT_CH && !(str[0] == ID_WRAP_LEFT_CH && str.find(ID_WRAP_RIGHT) < str.length() - 1)) { + return parseNumber(mstruct, str, po); + } else { + return parseOperators(mstruct, str, po); + } + } + return false; +} +bool Calculator::parseAdd(string &str, MathStructure *mstruct, const ParseOptions &po, MathOperation s, bool append) { + if(str.length() > 0) { + size_t i; + if(BASE_2_10) { + i = str.find_first_of(SPACE MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS EXPS ID_WRAP_LEFT, 1); + } else { + i = str.find_first_of(SPACE MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS ID_WRAP_LEFT, 1); + } + if(i == string::npos && str[0] != LOGICAL_NOT_CH && str[0] != BITWISE_NOT_CH && !(str[0] == ID_WRAP_LEFT_CH && str.find(ID_WRAP_RIGHT) < str.length() - 1)) { + if(s == OPERATION_EXP10 && po.read_precision == ALWAYS_READ_PRECISION) { + ParseOptions po2 = po; + po2.read_precision = READ_PRECISION_WHEN_DECIMALS; + MathStructure *mstruct2 = new MathStructure(); + if(!parseNumber(mstruct2, str, po2)) { + mstruct2->unref(); + return false; + } + mstruct->add_nocopy(mstruct2, s, append); + } else { + MathStructure *mstruct2 = new MathStructure(); + if(!parseNumber(mstruct2, str, po)) { + mstruct2->unref(); + return false; + } + if(s == OPERATION_EXP10 && !po.preserve_format && mstruct->isNumber() && mstruct2->isNumber()) { + mstruct->number().exp10(mstruct2->number()); + mstruct->numberUpdated(); + mstruct->mergePrecision(*mstruct2); + } else if(s == OPERATION_DIVIDE && po.preserve_format) { + mstruct->transform_nocopy(STRUCT_DIVISION, mstruct2); + } else if(s == OPERATION_SUBTRACT && po.preserve_format) { + mstruct2->transform(STRUCT_NEGATE); + mstruct->add_nocopy(mstruct2, OPERATION_ADD, append); + } else { + mstruct->add_nocopy(mstruct2, s, append); + } + } + } else { + MathStructure *mstruct2 = new MathStructure(); + if(!parseOperators(mstruct2, str, po)) { + mstruct2->unref(); + return false; + } + if(s == OPERATION_DIVIDE && po.preserve_format) { + mstruct->transform_nocopy(STRUCT_DIVISION, mstruct2); + } else if(s == OPERATION_SUBTRACT && po.preserve_format) { + mstruct2->transform(STRUCT_NEGATE); + mstruct->add_nocopy(mstruct2, OPERATION_ADD, append); + } else { + mstruct->add_nocopy(mstruct2, s, append); + } + } + } + return true; +} + +MathStructure *get_out_of_negate(MathStructure &mstruct, int *i_neg) { + if(mstruct.isNegate() || (mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isMinusOne())) { + (*i_neg)++; + return get_out_of_negate(mstruct.last(), i_neg); + } + return &mstruct; +} + +bool Calculator::parseOperators(MathStructure *mstruct, string str, const ParseOptions &po) { + string save_str = str; + mstruct->clear(); + size_t i = 0, i2 = 0, i3 = 0; + string str2, str3; + bool extended_roman = (po.base == BASE_ROMAN_NUMERALS && (i = str.find("|")) != string::npos && i + 1 < str.length() && str[i + 1] == RIGHT_PARENTHESIS_CH); + while(!extended_roman) { + //find first right parenthesis and then the last left parenthesis before + i2 = str.find(RIGHT_PARENTHESIS_CH); + if(i2 == string::npos) { + i = str.rfind(LEFT_PARENTHESIS_CH); + if(i == string::npos) { + //if no parenthesis break + break; + } else { + //right parenthesis missing -- append + str += RIGHT_PARENTHESIS_CH; + i2 = str.length() - 1; + } + } else { + if(i2 > 0) { + i = str.rfind(LEFT_PARENTHESIS_CH, i2 - 1); + } else { + i = string::npos; + } + if(i == string::npos) { + //left parenthesis missing -- prepend + str.insert(str.begin(), 1, LEFT_PARENTHESIS_CH); + i = 0; + i2++; + } + } + while(true) { + //remove unnecessary double parenthesis and the found parenthesis + if(i > 0 && i2 + 1 < str.length() && str[i - 1] == LEFT_PARENTHESIS_CH && str[i2 + 1] == RIGHT_PARENTHESIS_CH) { + str.erase(str.begin() + (i - 1)); + i--; i2--; + str.erase(str.begin() + (i2 + 1)); + } else { + break; + } + } + if(i > 0 && is_not_in(MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS SPACE, str[i - 1]) && (!BASE_2_10 || (str[i - 1] != EXP_CH && str[i - 1] != EXP2_CH))) { + if(po.rpn) { + str.insert(i2 + 1, MULTIPLICATION); + str.insert(i, SPACE); + i++; + i2++; + } + } + if(i2 + 1 < str.length() && is_not_in(MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS PARENTHESISS SPACE, str[i2 + 1]) && (!BASE_2_10 || (str[i2 + 1] != EXP_CH && str[i2 + 1] != EXP2_CH))) { + if(po.rpn) { + i3 = str.find(SPACE, i2 + 1); + if(i3 == string::npos) { + str += MULTIPLICATION; + } else { + str.replace(i3, 1, MULTIPLICATION); + } + str.insert(i2 + 1, SPACE); + } + } + if(po.rpn && i > 0 && i2 + 1 == str.length() && is_not_in(PARENTHESISS SPACE, str[i - 1])) { + str += MULTIPLICATION_CH; + } + str2 = str.substr(i + 1, i2 - (i + 1)); + MathStructure *mstruct2 = new MathStructure(); + if(str2.empty()) { + error(false, "Empty expression in parentheses interpreted as zero.", NULL); + } else { + parseOperators(mstruct2, str2, po); + } + mstruct2->setInParentheses(true); + str2 = ID_WRAP_LEFT; + str2 += i2s(addId(mstruct2)); + str2 += ID_WRAP_RIGHT; + str.replace(i, i2 - i + 1, str2); + mstruct->clear(); + } + bool b_abs_or = false, b_bit_or = false; + i = 0; + if(!po.rpn) { + // determine if | is used for absolute value + while(po.base != BASE_ROMAN_NUMERALS && (i = str.find('|', i)) != string::npos) { + if(i == 0 || i == str.length() - 1 || is_in(OPERATORS INTERNAL_OPERATORS SPACE, str[i - 1])) {b_abs_or = true; break;} + if(str[i + 1] == '|') { + if(i == str.length() - 2) {b_abs_or = true; break;} + if(b_bit_or) { + b_abs_or = true; + break; + } + i += 2; + } else { + b_bit_or = true; + i++; + } + } + } + if(b_abs_or) { + // |x|=abs(x) + while((i = str.find('|', 0)) != string::npos && i + 1 != str.length()) { + if(str[i + 1] == '|') { + size_t depth = 1; + i2 = i; + while((i2 = str.find("||", i2 + 2)) != string::npos) { + if(is_in(OPERATORS INTERNAL_OPERATORS, str[i2 - 1])) depth++; + else depth--; + if(depth == 0) break; + } + if(i2 == string::npos) str2 = str.substr(i + 2); + else str2 = str.substr(i + 2, i2 - (i + 2)); + str3 = ID_WRAP_LEFT; + str3 += i2s(parseAddId(f_magnitude, str2, po)); + str3 += ID_WRAP_RIGHT; + if(i2 == string::npos) str.replace(i, str.length() - i, str3); + else str.replace(i, i2 - i + 2, str3); + } else { + size_t depth = 1; + i2 = i; + while((i2 = str.find('|', i2 + 1)) != string::npos) { + if(is_in(OPERATORS INTERNAL_OPERATORS, str[i2 - 1])) depth++; + else depth--; + if(depth == 0) break; + } + if(i2 == string::npos) str2 = str.substr(i + 1); + else str2 = str.substr(i + 1, i2 - (i + 1)); + str3 = ID_WRAP_LEFT; + str3 += i2s(parseAddId(f_abs, str2, po)); + str3 += ID_WRAP_RIGHT; + if(i2 == string::npos) str.replace(i, str.length() - i, str3); + else str.replace(i, i2 - i + 1, str3); + } + } + } + if(po.rpn) { + // parse operators with RPN syntax + i = 0; + i3 = 0; + ParseOptions po2 = po; + po2.rpn = false; + vector mstack; + bool b = false; + char last_operator = 0; + char last_operator2 = 0; + while(true) { + i = str.find_first_of(OPERATORS "\a%\x1c" SPACE "\\", i3 + 1); + if(i == string::npos) { + if(!b) { + parseAdd(str, mstruct, po2); + return true; + } + if(i3 != 0) { + str2 = str.substr(i3 + 1, str.length() - i3 - 1); + } else { + str2 = str.substr(i3, str.length() - i3); + } + remove_blank_ends(str2); + if(!str2.empty()) { + error(false, _("RPN syntax error. Values left at the end of the RPN expression."), NULL); + } else if(mstack.size() > 1) { + if(last_operator == 0 && mstack.size() > 1) { + error(false, _("Unused stack values."), NULL); + } else { + while(mstack.size() > 1) { + switch(last_operator) { + case PLUS_CH: { + mstack[mstack.size() - 2]->add_nocopy(mstack.back()); + mstack.pop_back(); + break; + } + case MINUS_CH: { + if(po.preserve_format) { + mstack.back()->transform(STRUCT_NEGATE); + mstack[mstack.size() - 2]->add_nocopy(mstack.back()); + } else { + mstack[mstack.size() - 2]->subtract_nocopy(mstack.back()); + } + mstack.pop_back(); + break; + } + case MULTIPLICATION_CH: { + mstack[mstack.size() - 2]->multiply_nocopy(mstack.back()); + mstack.pop_back(); + break; + } + case DIVISION_CH: { + if(po.preserve_format) { + mstack[mstack.size() - 2]->transform_nocopy(STRUCT_DIVISION, mstack.back()); + } else { + mstack[mstack.size() - 2]->divide_nocopy(mstack.back()); + } + mstack.pop_back(); + break; + } + case POWER_CH: { + mstack[mstack.size() - 2]->raise_nocopy(mstack.back()); + mstack.pop_back(); + break; + } + case AND_CH: { + mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_AND, mstack.back()); + mstack.pop_back(); + break; + } + case OR_CH: { + mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_OR, mstack.back()); + mstack.pop_back(); + break; + } + case GREATER_CH: { + if(last_operator2 == GREATER_CH) { + if(po.preserve_format) mstack.back()->transform(STRUCT_NEGATE); + else mstack.back()->negate(); + mstack[mstack.size() - 2]->transform(f_shift); + mstack[mstack.size() - 2]->addChild_nocopy(mstack.back()); + mstack[mstack.size() - 2]->addChild(m_one); + } else if(last_operator2 == EQUALS_CH) { + mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS_GREATER); + } else { + mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_GREATER); + } + mstack.pop_back(); + break; + } + case LESS_CH: { + if(last_operator2 == LESS_CH) { + mstack[mstack.size() - 2]->transform(f_shift); + mstack[mstack.size() - 2]->addChild_nocopy(mstack.back()); + mstack[mstack.size() - 2]->addChild(m_one); + } else if(last_operator2 == EQUALS_CH) { + mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS_LESS); + } else { + mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_LESS); + } + mstack.pop_back(); + break; + } + case NOT_CH: { + mstack.back()->transform(STRUCT_LOGICAL_NOT); + break; + } + case EQUALS_CH: { + if(last_operator2 == NOT_CH) { + mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_NOT_EQUALS); + } else { + mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS); + } + mstack.pop_back(); + break; + } + case BITWISE_NOT_CH: { + mstack.back()->transform(STRUCT_BITWISE_NOT); + error(false, _("Unused stack values."), NULL); + break; + } + case '\x1c': { + if(po.angle_unit != ANGLE_UNIT_NONE && po.angle_unit != ANGLE_UNIT_RADIANS && mstack.back()->contains(getRadUnit(), false, true, true) <= 0 && mstack.back()->contains(getGraUnit(), false, true, true) <= 0 && mstack.back()->contains(getDegUnit(), false, true, true) <= 0) { + switch(po.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstack.back()->multiply(getDegUnit()); break;} + case ANGLE_UNIT_GRADIANS: {mstack.back()->multiply(getGraUnit()); break;} + default: {} + } + } + mstack.back()->transform(priv->f_cis); + mstack[mstack.size() - 2]->transform_nocopy(STRUCT_MULTIPLICATION, mstack.back()); + mstack.pop_back(); + break; + } + case '\a': { + mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_XOR, mstack.back()); + mstack.pop_back(); + break; + } + case '%': { + if(last_operator2 == '%') { + mstack[mstack.size() - 2]->transform(f_mod); + } else { + mstack[mstack.size() - 2]->transform(f_rem); + } + mstack[mstack.size() - 2]->addChild_nocopy(mstack.back()); + mstack.pop_back(); + break; + } + case '\\': { + if(po.preserve_format) { + mstack[mstack.size() - 2]->transform_nocopy(STRUCT_DIVISION, mstack.back()); + } else { + mstack[mstack.size() - 2]->divide_nocopy(mstack.back()); + } + mstack[mstack.size() - 2]->transform(f_trunc); + mstack.pop_back(); + break; + } + default: { + error(true, _("RPN syntax error. Operator '%c' not supported."), last_operator, NULL); + mstack.pop_back(); + break; + } + } + if(last_operator == NOT_CH || last_operator == BITWISE_NOT_CH) break; + } + } + } else if(mstack.size() == 1) { + if(last_operator == NOT_CH) { + mstack.back()->transform(STRUCT_LOGICAL_NOT); + } else if(last_operator == BITWISE_NOT_CH) { + mstack.back()->transform(STRUCT_BITWISE_NOT); + } + } + mstruct->set_nocopy(*mstack.back()); + while(!mstack.empty()) { + mstack.back()->unref(); + mstack.pop_back(); + } + return true; + } + b = true; + if(i3 != 0) { + str2 = str.substr(i3 + 1, i - i3 - 1); + } else { + str2 = str.substr(i3, i - i3); + } + remove_blank_ends(str2); + if(!str2.empty()) { + mstack.push_back(new MathStructure()); + if((str[i] == GREATER_CH || str[i] == LESS_CH) && po2.base < 10 && po2.base >= 2 && i + 1 < str.length() && str[i + 1] == str[i] && str2.find_first_not_of(NUMBERS SPACE PLUS MINUS) == string::npos) { + for(i = 0; i < str2.size(); i++) { + if(str2[i] >= '0' && str2[i] <= '9' && po.base <= str2[i] - '0') { + po2.base = BASE_DECIMAL; + break; + } + } + parseAdd(str2, mstack.back(), po2); + po2.base = po.base; + } else { + parseAdd(str2, mstack.back(), po2); + } + } + if(str[i] != SPACE_CH) { + if(mstack.size() < 1) { + error(true, _("RPN syntax error. Stack is empty."), NULL); + } else if(mstack.size() < 2) { + if(str[i] == NOT_CH) { + mstack.back()->transform(STRUCT_LOGICAL_NOT); + } else if(str[i] == MINUS_CH) { + if(po.preserve_format) mstack.back()->transform(STRUCT_NEGATE); + else mstack.back()->negate(); + } else if(str[i] == BITWISE_NOT_CH) { + mstack.back()->transform(STRUCT_BITWISE_NOT); + } else if(str[i] == '\x1c') { + if(po.angle_unit != ANGLE_UNIT_NONE && po.angle_unit != ANGLE_UNIT_RADIANS && mstack.back()->contains(getRadUnit(), false, true, true) <= 0 && mstack.back()->contains(getGraUnit(), false, true, true) <= 0 && mstack.back()->contains(getDegUnit(), false, true, true) <= 0) { + switch(po.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstack.back()->multiply(getDegUnit()); break;} + case ANGLE_UNIT_GRADIANS: {mstack.back()->multiply(getGraUnit()); break;} + default: {} + } + } + mstack.back()->transform(priv->f_cis); + mstack.back()->multiply(m_one); + if(po.preserve_format) mstack.back()->swapChildren(1, 2); + } else { + error(false, _("RPN syntax error. Operator ignored as there where only one stack value."), NULL); + } + } else { + switch(str[i]) { + case PLUS_CH: { + mstack[mstack.size() - 2]->add_nocopy(mstack.back()); + mstack.pop_back(); + break; + } + case MINUS_CH: { + if(po.preserve_format) { + mstack.back()->transform(STRUCT_NEGATE); + mstack[mstack.size() - 2]->add_nocopy(mstack.back()); + } else { + mstack[mstack.size() - 2]->subtract_nocopy(mstack.back()); + } + mstack.pop_back(); + break; + } + case MULTIPLICATION_CH: { + mstack[mstack.size() - 2]->multiply_nocopy(mstack.back()); + mstack.pop_back(); + break; + } + case DIVISION_CH: { + if(po.preserve_format) { + mstack[mstack.size() - 2]->transform_nocopy(STRUCT_DIVISION, mstack.back()); + } else { + mstack[mstack.size() - 2]->divide_nocopy(mstack.back()); + } + mstack.pop_back(); + break; + } + case POWER_CH: { + mstack[mstack.size() - 2]->raise_nocopy(mstack.back()); + mstack.pop_back(); + break; + } + case AND_CH: { + if(i + 1 < str.length() && str[i + 1] == AND_CH) { + mstack[mstack.size() - 2]->transform_nocopy(STRUCT_LOGICAL_AND, mstack.back()); + } else { + mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_AND, mstack.back()); + } + mstack.pop_back(); + break; + } + case OR_CH: { + if(i + 1 < str.length() && str[i + 1] == OR_CH) { + mstack[mstack.size() - 2]->transform_nocopy(STRUCT_LOGICAL_OR, mstack.back()); + } else { + mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_OR, mstack.back()); + } + mstack.pop_back(); + break; + } + case GREATER_CH: { + if(i + 1 < str.length() && str[i + 1] == GREATER_CH) { + if(po.preserve_format) mstack.back()->transform(STRUCT_NEGATE); + else mstack.back()->negate(); + mstack[mstack.size() - 2]->transform(f_shift); + mstack[mstack.size() - 2]->addChild_nocopy(mstack.back()); + mstack[mstack.size() - 2]->addChild(m_one); + } else if(i + 1 < str.length() && str[i + 1] == EQUALS_CH) { + mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS_GREATER); + } else { + mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_GREATER); + } + mstack.pop_back(); + break; + } + case LESS_CH: { + if(i + 1 < str.length() && str[i + 1] == LESS_CH) { + mstack[mstack.size() - 2]->transform(f_shift); + mstack[mstack.size() - 2]->addChild_nocopy(mstack.back()); + mstack[mstack.size() - 2]->addChild(m_one); + } else if(i + 1 < str.length() && str[i + 1] == EQUALS_CH) { + mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS_LESS); + } else { + mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_LESS); + } + mstack.pop_back(); + break; + } + case NOT_CH: { + mstack.back()->transform(STRUCT_LOGICAL_NOT); + break; + } + case EQUALS_CH: { + if(i + 1 < str.length() && str[i + 1] == NOT_CH) { + mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_NOT_EQUALS); + mstack.pop_back(); + } else { + mstack[mstack.size() - 2]->add_nocopy(mstack.back(), OPERATION_EQUALS); + } + mstack.pop_back(); + break; + } + case BITWISE_NOT_CH: { + mstack.back()->transform(STRUCT_BITWISE_NOT); + break; + } + case '\x1c': { + if(po.angle_unit != ANGLE_UNIT_NONE && po.angle_unit != ANGLE_UNIT_RADIANS && mstack.back()->contains(getRadUnit(), false, true, true) <= 0 && mstack.back()->contains(getGraUnit(), false, true, true) <= 0 && mstack.back()->contains(getDegUnit(), false, true, true) <= 0) { + switch(po.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstack.back()->multiply(getDegUnit()); break;} + case ANGLE_UNIT_GRADIANS: {mstack.back()->multiply(getGraUnit()); break;} + default: {} + } + } + mstack.back()->transform(priv->f_cis); + mstack[mstack.size() - 2]->transform_nocopy(STRUCT_MULTIPLICATION, mstack.back()); + mstack.pop_back(); + break; + } + case '\a': { + mstack[mstack.size() - 2]->transform_nocopy(STRUCT_BITWISE_XOR, mstack.back()); + mstack.pop_back(); + break; + } + case '%': { + if(i + 1 < str.length() && str[i + 1] == '%') { + mstack[mstack.size() - 2]->transform(f_mod); + } else { + mstack[mstack.size() - 2]->transform(f_rem); + } + mstack[mstack.size() - 2]->addChild_nocopy(mstack.back()); + mstack.pop_back(); + break; + } + case '\\': { + if(po.preserve_format) { + mstack[mstack.size() - 2]->transform_nocopy(STRUCT_DIVISION, mstack.back()); + } else { + mstack[mstack.size() - 2]->divide_nocopy(mstack.back()); + } + mstack[mstack.size() - 2]->transform(f_trunc); + mstack.pop_back(); + break; + } + default: { + error(true, _("RPN syntax error. Operator '%c' not supported."), str[i], NULL); + mstack.pop_back(); + break; + } + } + last_operator = str[i]; + if(i + 1 < str.length()) last_operator2 = str[i + 1]; + else last_operator2 = 0; + if((last_operator2 == EQUALS_CH && (last_operator == GREATER_CH || last_operator == LESS_CH || last_operator == EQUALS_CH)) || (last_operator2 == NOT_CH && last_operator == EQUALS_CH) || (last_operator == last_operator2 && (last_operator == GREATER_CH || last_operator == LESS_CH || last_operator == '%' || last_operator == AND_CH || last_operator == OR_CH))) { + i++; + } + } + } + i3 = i; + } + } + if(po.rpn) remove_blanks(str); + i = 0; + i3 = 0; + // Parse && as logical and + if((i = str.find(LOGICAL_AND, 1)) != string::npos && i + 2 != str.length()) { + bool b = false, append = false; + while(i != string::npos && i + 2 != str.length()) { + str2 = str.substr(0, i); + str = str.substr(i + 2, str.length() - (i + 2)); + if(b) { + parseAdd(str2, mstruct, po, OPERATION_LOGICAL_AND, append); + append = true; + } else { + parseAdd(str2, mstruct, po); + b = true; + } + i = str.find(LOGICAL_AND, 1); + } + if(b) { + parseAdd(str, mstruct, po, OPERATION_LOGICAL_AND, append); + } else { + parseAdd(str, mstruct, po); + } + return true; + } + // Parse || as logical or + if(po.base != BASE_ROMAN_NUMERALS && (i = str.find(LOGICAL_OR, 1)) != string::npos && i + 2 != str.length()) { + bool b = false, append = false; + while(i != string::npos && i + 2 != str.length()) { + str2 = str.substr(0, i); + str = str.substr(i + 2, str.length() - (i + 2)); + if(b) { + parseAdd(str2, mstruct, po, OPERATION_LOGICAL_OR, append); + append = true; + } else { + parseAdd(str2, mstruct, po); + b = true; + } + i = str.find(LOGICAL_OR, 1); + } + if(b) { + parseAdd(str, mstruct, po, OPERATION_LOGICAL_OR, append); + } else { + parseAdd(str, mstruct, po); + } + return true; + } + /*if((i = str.find(LOGICAL_XOR, 1)) != string::npos && i + strlen(LOGICAL_XOR) != str.length()) { + str2 = str.substr(0, i); + str = str.substr(i + strlen(LOGICAL_XOR), str.length() - (i + strlen(LOGICAL_XOR))); + parseAdd(str2, mstruct, po); + parseAdd(str, mstruct, po, OPERATION_LOGICAL_XOR); + return true; + }*/ + // Parse | as bitwise or + if(po.base != BASE_ROMAN_NUMERALS && (i = str.find(BITWISE_OR, 1)) != string::npos && i + 1 != str.length()) { + bool b = false, append = false; + while(i != string::npos && i + 1 != str.length()) { + str2 = str.substr(0, i); + str = str.substr(i + 1, str.length() - (i + 1)); + if(b) { + parseAdd(str2, mstruct, po, OPERATION_BITWISE_OR, append); + append = true; + } else { + parseAdd(str2, mstruct, po); + b = true; + } + i = str.find(BITWISE_OR, 1); + } + if(b) { + parseAdd(str, mstruct, po, OPERATION_BITWISE_OR, append); + } else { + parseAdd(str, mstruct, po); + } + return true; + } + // Parse \a (internal single character substitution for xor operators) as bitwise xor + if((i = str.find('\a', 1)) != string::npos && i + 1 != str.length()) { + str2 = str.substr(0, i); + str = str.substr(i + 1, str.length() - (i + 1)); + parseAdd(str2, mstruct, po); + parseAdd(str, mstruct, po, OPERATION_BITWISE_XOR); + return true; + } + // Parse & as bitwise and + if((i = str.find(BITWISE_AND, 1)) != string::npos && i + 1 != str.length()) { + bool b = false, append = false; + while(i != string::npos && i + 1 != str.length()) { + str2 = str.substr(0, i); + str = str.substr(i + 1, str.length() - (i + 1)); + if(b) { + parseAdd(str2, mstruct, po, OPERATION_BITWISE_AND, append); + append = true; + } else { + parseAdd(str2, mstruct, po); + b = true; + } + i = str.find(BITWISE_AND, 1); + } + if(b) { + parseAdd(str, mstruct, po, OPERATION_BITWISE_AND, append); + } else { + parseAdd(str, mstruct, po); + } + return true; + } + // Parse comparison operators (>, >=, <, <=, =, !=) + if((i = str.find_first_of(LESS GREATER EQUALS NOT, 0)) != string::npos) { + while(i != string::npos && ((str[i] == LOGICAL_NOT_CH && (i + 1 >= str.length() || str[i + 1] != EQUALS_CH)) || (str[i] == LESS_CH && i + 1 < str.length() && str[i + 1] == LESS_CH) || (str[i] == GREATER_CH && i + 1 < str.length() && str[i + 1] == GREATER_CH))) { + i = str.find_first_of(LESS GREATER NOT EQUALS, i + 2); + } + } + if(i != string::npos) { + bool b = false; + bool c = false; + while(i != string::npos && str[i] == NOT_CH && str.length() > i + 1 && str[i + 1] == NOT_CH) { + i++; + if(i + 1 == str.length()) { + c = true; + } + } + MathOperation s = OPERATION_ADD; + while(!c) { + while(i != string::npos && ((str[i] == LOGICAL_NOT_CH && (i + 1 >= str.length() || str[i + 1] != EQUALS_CH)) || (str[i] == LESS_CH && i + 1 < str.length() && str[i + 1] == LESS_CH) || (str[i] == GREATER_CH && i + 1 < str.length() && str[i + 1] == GREATER_CH))) { + i = str.find_first_of(LESS GREATER NOT EQUALS, i + 2); + while(i != string::npos && str[i] == NOT_CH && str.length() > i + 1 && str[i + 1] == NOT_CH) { + i++; + if(i + 1 == str.length()) { + i = string::npos; + } + } + } + if(i == string::npos) { + str2 = str.substr(0, str.length()); + } else { + str2 = str.substr(0, i); + } + if(b) { + switch(i3) { + case EQUALS_CH: {s = OPERATION_EQUALS; break;} + case GREATER_CH: {s = OPERATION_GREATER; break;} + case LESS_CH: {s = OPERATION_LESS; break;} + case GREATER_CH * EQUALS_CH: {s = OPERATION_EQUALS_GREATER; break;} + case LESS_CH * EQUALS_CH: {s = OPERATION_EQUALS_LESS; break;} + case GREATER_CH * LESS_CH: {s = OPERATION_NOT_EQUALS; break;} + } + parseAdd(str2, mstruct, po, s); + } + if(i == string::npos) { + return true; + } + if(!b) { + parseAdd(str2, mstruct, po); + b = true; + } + if(str.length() > i + 1 && is_in(LESS GREATER NOT EQUALS, str[i + 1])) { + if(str[i] == str[i + 1]) { + i3 = str[i]; + } else { + i3 = str[i] * str[i + 1]; + if(i3 == NOT_CH * EQUALS_CH) { + i3 = GREATER_CH * LESS_CH; + } else if(i3 == NOT_CH * LESS_CH) { + i3 = GREATER_CH; + } else if(i3 == NOT_CH * GREATER_CH) { + i3 = LESS_CH; + } + } + i++; + } else { + i3 = str[i]; + } + str = str.substr(i + 1, str.length() - (i + 1)); + i = str.find_first_of(LESS GREATER NOT EQUALS, 0); + while(i != string::npos && str[i] == NOT_CH && str.length() > i + 1 && str[i + 1] == NOT_CH) { + i++; + if(i + 1 == str.length()) { + i = string::npos; + } + } + } + } + // Parse << and >> as bitwise shift + i = str.find(SHIFT_LEFT, 1); + i2 = str.find(SHIFT_RIGHT, 1); + if(i2 != string::npos && (i == string::npos || i2 < i)) i = i2; + if(i != string::npos && i + 2 != str.length()) { + MathStructure mstruct1, mstruct2; + bool b_neg = (str[i] == '>'); + str2 = str.substr(0, i); + str = str.substr(i + 2, str.length() - (i + 2)); + parseAdd(str2, &mstruct1, po); + if(po.base < 10 && po.base >= 2 && str.find_first_not_of(NUMBERS SPACE PLUS MINUS) == string::npos) { + for(i = 0; i < str.size(); i++) { + if(str[i] >= '0' && str[i] <= '9' && po.base <= str[i] - '0') { + ParseOptions po2 = po; + po2.base = BASE_DECIMAL; + parseAdd(str, &mstruct2, po2); + if(b_neg) { + if(po.preserve_format) mstruct2.transform(STRUCT_NEGATE); + else mstruct2.negate(); + } + mstruct->set(f_shift, &mstruct1, &mstruct2, &m_one, NULL); + return true; + } + } + } + parseAdd(str, &mstruct2, po); + if(b_neg) { + if(po.preserve_format) mstruct2.transform(STRUCT_NEGATE); + else mstruct2.negate(); + } + mstruct->set(f_shift, &mstruct1, &mstruct2, &m_one, NULL); + return true; + } + + // Parse addition and subtraction + if((i = str.find_first_of(PLUS MINUS, 1)) != string::npos && i + 1 != str.length()) { + bool b = false, c = false, append = false; + bool min = false; + while(i != string::npos && i + 1 != str.length()) { + if(is_not_in(MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS EXPS, str[i - 1])) { + str2 = str.substr(0, i); + if(!c && b) { + bool b_add; + if(min) { + b_add = parseAdd(str2, mstruct, po, OPERATION_SUBTRACT, append) && mstruct->isAddition(); + } else { + b_add = parseAdd(str2, mstruct, po, OPERATION_ADD, append) && mstruct->isAddition(); + } + append = true; + if(b_add) { + int i_neg = 0; + MathStructure *mstruct_a = get_out_of_negate(mstruct->last(), &i_neg); + MathStructure *mstruct_b = mstruct_a; + if(mstruct_a->isMultiplication() && mstruct_a->size() >= 2) mstruct_b = &mstruct_a->last(); + if(mstruct_b->isVariable() && (mstruct_b->variable() == v_percent || mstruct_b->variable() == v_permille || mstruct_b->variable() == v_permyriad)) { + Variable *v = mstruct_b->variable(); + bool b_neg = (i_neg % 2 == 1); + while(i_neg > 0) { + mstruct->last().setToChild(mstruct->last().size()); + i_neg--; + } + if(mstruct->last().isVariable()) { + mstruct->last().multiply(m_one); + mstruct->last().swapChildren(1, 2); + } + if(mstruct->last().size() > 2) { + mstruct->last().delChild(mstruct->last().size()); + mstruct->last().multiply(v); + } + if(mstruct->last()[0].isNumber()) { + if(b_neg) mstruct->last()[0].number().negate(); + if(v == v_percent) mstruct->last()[0].number().add(100); + else if(v == v_permille) mstruct->last()[0].number().add(1000); + else mstruct->last()[0].number().add(10000); + } else { + if(b_neg && po.preserve_format) mstruct->last()[0].transform(STRUCT_NEGATE); + else if(b_neg) mstruct->last()[0].negate(); + if(v == v_percent) mstruct->last()[0] += Number(100, 1); + else if(v == v_permille) mstruct->last()[0] += Number(1000, 1); + else mstruct->last()[0] += Number(10000, 1); + mstruct->last()[0].swapChildren(1, 2); + } + if(mstruct->size() == 2) { + mstruct->setType(STRUCT_MULTIPLICATION); + } else { + MathStructure *mpercent = &mstruct->last(); + mpercent->ref(); + mstruct->delChild(mstruct->size()); + mstruct->multiply_nocopy(mpercent); + } + } + } + } else { + if(!b && str2.empty()) { + c = true; + } else { + parseAdd(str2, mstruct, po); + if(c && min) { + if(po.preserve_format) mstruct->transform(STRUCT_NEGATE); + else mstruct->negate(); + } + c = false; + } + b = true; + } + min = str[i] == MINUS_CH; + str = str.substr(i + 1, str.length() - (i + 1)); + i = str.find_first_of(PLUS MINUS, 1); + } else { + i = str.find_first_of(PLUS MINUS, i + 1); + } + } + if(b) { + if(c) { + b = parseAdd(str, mstruct, po); + if(min) { + if(po.preserve_format) mstruct->transform(STRUCT_NEGATE); + else mstruct->negate(); + } + return b; + } else { + bool b_add; + if(min) { + b_add = parseAdd(str, mstruct, po, OPERATION_SUBTRACT, append) && mstruct->isAddition(); + } else { + b_add = parseAdd(str, mstruct, po, OPERATION_ADD, append) && mstruct->isAddition(); + } + if(b_add) { + int i_neg = 0; + MathStructure *mstruct_a = get_out_of_negate(mstruct->last(), &i_neg); + MathStructure *mstruct_b = mstruct_a; + if(mstruct_a->isMultiplication() && mstruct_a->size() >= 2) mstruct_b = &mstruct_a->last(); + if(mstruct_b->isVariable() && (mstruct_b->variable() == v_percent || mstruct_b->variable() == v_permille || mstruct_b->variable() == v_permyriad)) { + Variable *v = mstruct_b->variable(); + bool b_neg = (i_neg % 2 == 1); + while(i_neg > 0) { + mstruct->last().setToChild(mstruct->last().size()); + i_neg--; + } + if(mstruct->last().isVariable()) { + mstruct->last().multiply(m_one); + mstruct->last().swapChildren(1, 2); + } + if(mstruct->last().size() > 2) { + mstruct->last().delChild(mstruct->last().size()); + mstruct->last().multiply(v); + } + if(mstruct->last()[0].isNumber()) { + if(b_neg) mstruct->last()[0].number().negate(); + if(v == v_percent) mstruct->last()[0].number().add(100); + else if(v == v_permille) mstruct->last()[0].number().add(1000); + else mstruct->last()[0].number().add(10000); + } else { + if(b_neg && po.preserve_format) mstruct->last()[0].transform(STRUCT_NEGATE); + else if(b_neg) mstruct->last()[0].negate(); + if(v == v_percent) mstruct->last()[0] += Number(100, 1); + else if(v == v_permille) mstruct->last()[0] += Number(1000, 1); + else mstruct->last()[0] += Number(10000, 1); + mstruct->last()[0].swapChildren(1, 2); + } + if(mstruct->size() == 2) { + mstruct->setType(STRUCT_MULTIPLICATION); + } else { + MathStructure *mpercent = &mstruct->last(); + mpercent->ref(); + mstruct->delChild(mstruct->size()); + mstruct->multiply_nocopy(mpercent); + } + } + } + } + return true; + } + } + + // In adaptive parsing mode division might be handled differentiately depending on usage of whitespace characters, e.g. 5/2 m = (5/2)*m, 5/2m=5/(2m) + if(!po.rpn && po.parsing_mode == PARSING_MODE_ADAPTIVE && (i = str.find(DIVISION_CH, 1)) != string::npos && i + 1 != str.length()) { + while(i != string::npos && i + 1 != str.length()) { + bool b = false; + if(i > 2 && i < str.length() - 3 && str[i + 1] == ID_WRAP_LEFT_CH) { + i2 = i; + b = true; + bool had_unit = false, had_nonunit = false; + MathStructure *m_temp = NULL, *m_temp2 = NULL; + while(b) { + b = false; + size_t i4 = i2; + if(i2 > 2 && str[i2 - 1] == ID_WRAP_RIGHT_CH) { + b = true; + } else if(i2 > 4 && str[i2 - 3] == ID_WRAP_RIGHT_CH && str[i2 - 2] == POWER_CH && is_in(NUMBERS, str[i2 - 1])) { + b = true; + i4 -= 2; + } + if(!b) { + if((i2 > 1 && is_not_in(OPERATORS INTERNAL_OPERATORS MULTIPLICATION_2, str[i2 - 1])) || (i2 > 2 && str[i2 - 1] == MULTIPLICATION_2_CH && is_not_in(OPERATORS INTERNAL_OPERATORS, str[i2 - 2]))) had_nonunit = true; + break; + } + i2 = str.rfind(ID_WRAP_LEFT_CH, i4 - 2); + m_temp = NULL; + if(i2 != string::npos) { + int id = s2i(str.substr(i2 + 1, (i4 - 1) - (i2 + 1))); + if(priv->id_structs.find(id) != priv->id_structs.end()) m_temp = priv->id_structs[id]; + } + if(!m_temp || !m_temp->isUnit()) { + had_nonunit = true; + break; + } + had_unit = true; + } + i3 = i; + b = had_unit && had_nonunit; + had_unit = false; + while(b) { + size_t i4 = i3; + i3 = str.find(ID_WRAP_RIGHT_CH, i4 + 2); + m_temp2 = NULL; + if(i3 != string::npos) { + int id = s2i(str.substr(i4 + 2, (i3 - 1) - (i4 + 1))); + if(priv->id_structs.find(id) != priv->id_structs.end()) m_temp2 = priv->id_structs[id]; + } + if(!m_temp2 || !m_temp2->isUnit()) { + b = false; + break; + } + had_unit = true; + b = false; + if(i3 < str.length() - 3 && str[i3 + 1] == ID_WRAP_LEFT_CH) { + b = true; + } else if(i3 < str.length() - 5 && str[i3 + 3] == ID_WRAP_LEFT_CH && str[i3 + 1] == POWER_CH && is_in(NUMBERS, str[i3 + 2])) { + b = true; + i3 += 2; + } + } + b = had_unit; + if(b) { + if(i3 < str.length() - 2 && str[i3 + 1] == POWER_CH && is_in(NUMBERS, str[i3 + 2])) { + i3 += 2; + while(i3 < str.length() - 1 && is_in(NUMBERS, str[i3 + 1])) i3++; + } + if(i3 == str.length() - 1 || (str[i3 + 1] != POWER_CH && str[i3 + 1] != DIVISION_CH)) { + MathStructure *mstruct2 = new MathStructure(); + str2 = str.substr(i2, i - i2); + parseAdd(str2, mstruct2, po); + str2 = str.substr(i + 1, i3 - i); + parseAdd(str2, mstruct2, po, OPERATION_DIVIDE); + str2 = ID_WRAP_LEFT; + str2 += i2s(addId(mstruct2)); + str2 += ID_WRAP_RIGHT; + str.replace(i2, i3 - i2 + 1, str2); + } else { + b = false; + } + } + } + if(!b) { + i2 = str.find_last_not_of(NUMBERS INTERNAL_NUMBER_CHARS PLUS MINUS EXPS, i - 1); + if(i2 == string::npos || (i2 != i - 1 && str[i2] == MULTIPLICATION_2_CH)) b = true; + i2 = str.rfind(MULTIPLICATION_2_CH, i - 1); + if(i2 == string::npos) b = true; + if(b) { + i3 = str.find_first_of(MULTIPLICATION_2 "%" MULTIPLICATION DIVISION, i + 1); + if(i3 == string::npos || i3 == i + 1 || str[i3] != MULTIPLICATION_2_CH) b = false; + if(i3 < str.length() + 1 && (str[i3 + 1] == '%' || str[i3 + 1] == DIVISION_CH || str[i3 + 1] == MULTIPLICATION_CH || str[i3 + 1] == POWER_CH)) b = false; + } + if(b) { + if(i3 != string::npos) str[i3] = MULTIPLICATION_CH; + if(i2 != string::npos) str[i2] = MULTIPLICATION_CH; + } else { + if(str[i + 1] == MULTIPLICATION_2_CH) { + str.erase(i + 1, 1); + } + if(str[i - 1] == MULTIPLICATION_2_CH) { + str.erase(i - 1, 1); + i--; + } + } + } + i = str.find(DIVISION_CH, i + 1); + } + } + if(po.parsing_mode == PARSING_MODE_ADAPTIVE && !po.rpn) remove_blanks(str); + + // In conventional parsing mode there is not difference between implicit and explicit multiplication + if(po.parsing_mode == PARSING_MODE_CONVENTIONAL) { + if((i = str.find(ID_WRAP_RIGHT_CH, 1)) != string::npos && i + 1 != str.length()) { + while(i != string::npos && i + 1 != str.length()) { + if(is_in(NUMBERS ID_WRAP_LEFT, str[i + 1])) { + str.insert(i + 1, 1, MULTIPLICATION_CH); + i++; + } + i = str.find(ID_WRAP_RIGHT_CH, i + 1); + } + } + if((i = str.find(ID_WRAP_LEFT_CH, 1)) != string::npos) { + while(i != string::npos) { + if(is_in(NUMBERS, str[i - 1])) { + str.insert(i, 1, MULTIPLICATION_CH); + i++; + } + i = str.find(ID_WRAP_LEFT_CH, i + 1); + } + } + } + + // Parse explicit multiplication, division, and mod + if((i = str.find_first_of(MULTIPLICATION DIVISION "%", 0)) != string::npos && i + 1 != str.length()) { + bool b = false, append = false; + int type = 0; + while(i != string::npos && i + 1 != str.length()) { + if(i < 1) { + if(i < 1 && str.find_first_not_of(MULTIPLICATION_2 OPERATORS INTERNAL_OPERATORS EXPS) == string::npos) { + gsub("\a", str.find_first_of(OPERATORS "%") != string::npos ? " xor " : "xor", str); + error(false, _("Misplaced operator(s) \"%s\" ignored"), str.c_str(), NULL); + return b; + } + i = 1; + while(i < str.length() && is_in(MULTIPLICATION DIVISION "%", str[i])) { + i++; + } + string errstr = str.substr(0, i); + gsub("\a", str.find_first_of(OPERATORS "%") != string::npos ? " xor " : "xor", errstr); + error(false, _("Misplaced operator(s) \"%s\" ignored"), errstr.c_str(), NULL); + str = str.substr(i, str.length() - i); + i = str.find_first_of(MULTIPLICATION DIVISION "%", 0); + } else { + str2 = str.substr(0, i); + if(b) { + switch(type) { + case 1: { + parseAdd(str2, mstruct, po, OPERATION_DIVIDE, append); + break; + } + case 2: { + MathStructure *mstruct2 = new MathStructure(); + parseAdd(str2, mstruct2, po); + mstruct->transform(f_rem); + mstruct->addChild_nocopy(mstruct2); + break; + } + case 3: { + parseAdd(str2, mstruct, po, OPERATION_DIVIDE, append); + mstruct->transform(f_trunc); + break; + } + case 4: { + MathStructure *mstruct2 = new MathStructure(); + parseAdd(str2, mstruct2, po); + mstruct->transform(f_mod); + mstruct->addChild_nocopy(mstruct2); + break; + } + default: { + parseAdd(str2, mstruct, po, OPERATION_MULTIPLY, append); + } + } + append = true; + } else { + parseAdd(str2, mstruct, po); + b = true; + } + if(str[i] == DIVISION_CH) { + if(str[i + 1] == DIVISION_CH) {type = 3; i++;} + else type = 1; + } else if(str[i] == '%') { + if(str[i + 1] == '%') {type = 4; i++;} + else type = 2; + } else { + type = 0; + } + if(is_in(MULTIPLICATION DIVISION "%", str[i + 1])) { + i2 = 1; + while(i2 + i + 1 != str.length() && is_in(MULTIPLICATION DIVISION "%", str[i2 + i + 1])) { + i2++; + } + string errstr = str.substr(i, i2); + gsub("\a", str.find_first_of(OPERATORS "%") != string::npos ? " xor " : "xor", errstr); + error(false, _("Misplaced operator(s) \"%s\" ignored"), errstr.c_str(), NULL); + i += i2; + } + str = str.substr(i + 1, str.length() - (i + 1)); + i = str.find_first_of(MULTIPLICATION DIVISION "%", 0); + } + } + if(b) { + switch(type) { + case 1: { + parseAdd(str, mstruct, po, OPERATION_DIVIDE, append); + break; + } + case 2: { + MathStructure *mstruct2 = new MathStructure(); + parseAdd(str, mstruct2, po); + mstruct->transform(f_rem); + mstruct->addChild_nocopy(mstruct2); + break; + } + case 3: { + parseAdd(str, mstruct, po, OPERATION_DIVIDE, append); + mstruct->transform(f_trunc); + break; + } + case 4: { + MathStructure *mstruct2 = new MathStructure(); + parseAdd(str, mstruct2, po); + mstruct->transform(f_mod); + mstruct->addChild_nocopy(mstruct2); + break; + } + default: { + parseAdd(str, mstruct, po, OPERATION_MULTIPLY, append); + } + } + return true; + } + } + + // Parse \x1c (internal single substitution character for angle operator) for complex angle format + if((i = str.find('\x1c', 0)) != string::npos && i + 1 != str.length()) { + if(i != 0) str2 = str.substr(0, i); + str = str.substr(i + 1, str.length() - (i + 1)); + if(i != 0) parseAdd(str2, mstruct, po); + else mstruct->set(1, 1, 0); + if(parseAdd(str, mstruct, po, OPERATION_MULTIPLY)) { + if(po.angle_unit != ANGLE_UNIT_NONE && po.angle_unit != ANGLE_UNIT_RADIANS && mstruct->last().contains(getRadUnit(), false, true, true) <= 0 && mstruct->last().contains(getGraUnit(), false, true, true) <= 0 && mstruct->last().contains(getDegUnit(), false, true, true) <= 0) { + switch(po.angle_unit) { + case ANGLE_UNIT_DEGREES: {mstruct->last().multiply(getDegUnit()); break;} + case ANGLE_UNIT_GRADIANS: {mstruct->last().multiply(getGraUnit()); break;} + default: {} + } + } + mstruct->last().transform(priv->f_cis); + } + return true; + } + + if(str.empty()) return false; + + // Check if only operators are left + if(str.find_first_not_of(OPERATORS INTERNAL_OPERATORS SPACE) == string::npos && (po.base != BASE_ROMAN_NUMERALS || str.find_first_of("(|)") == string::npos)) { + gsub("\a", str.find_first_of(OPERATORS "%") != string::npos ? " xor " : "xor", str); + gsub("\x1c", "∠", str); + error(false, _("Misplaced operator(s) \"%s\" ignored"), str.c_str(), NULL); + return false; + } + + // Number signs (+ and - at the beginning of the string) + i = 0; + bool ret = true; + bool has_sign = false; + int minus_count = 0; + while(i < str.length()) { + if(str[i] == MINUS_CH) { + has_sign = true; + minus_count++; + str.erase(i, 1); + } else if(str[i] == PLUS_CH) { + has_sign = true; + str.erase(i, 1); + } else if(str[i] == SPACE_CH) { + str.erase(i, 1); + } else if(str[i] == BITWISE_NOT_CH || str[i] == LOGICAL_NOT_CH) { + break; + } else if(is_in(OPERATORS INTERNAL_OPERATORS, str[i]) && (po.base != BASE_ROMAN_NUMERALS || (str[i] != '(' && str[i] != ')' && str[i] != '|'))) { + if(str[i] == '\a') error(false, _("Misplaced operator(s) \"%s\" ignored"), "xor", NULL); + else if(str[i] == '\x1c') error(false, _("Misplaced operator(s) \"%s\" ignored"), "∠", NULL); + else error(false, _("Misplaced '%c' ignored"), str[i], NULL); + str.erase(i, 1); + } else { + break; + } + } + + // Parse ~ and ! at the beginning of the string as bitwise not and logical not + if(!str.empty() && (str[0] == BITWISE_NOT_CH || str[0] == LOGICAL_NOT_CH)) { + bool bit = (str[0] == BITWISE_NOT_CH); + str.erase(0, 1); + parseAdd(str, mstruct, po); + if(bit) mstruct->setBitwiseNot(); + else mstruct->setLogicalNot(); + if(po.preserve_format) { + while(minus_count > 0) { + mstruct->transform(STRUCT_NEGATE); + minus_count--; + } + } else if(minus_count % 2 == 1) { + mstruct->negate(); + } + return true; + } + + if(str.empty()) { + if(minus_count % 2 == 1 && !po.preserve_format) { + mstruct->set(-1, 1, 0); + } else if(has_sign) { + mstruct->set(1, 1, 0); + if(po.preserve_format) { + while(minus_count > 0) { + mstruct->transform(STRUCT_NEGATE); + minus_count--; + } + } + } + return false; + } + + // Implicit multiplication + if((i = str.find(ID_WRAP_RIGHT_CH, 1)) != string::npos && i + 1 != str.length()) { + bool b = false, append = false; + while(i != string::npos && i + 1 != str.length()) { + if(str[i + 1] != POWER_CH && str[i + 1] != '\b') { + str2 = str.substr(0, i + 1); + str = str.substr(i + 1, str.length() - (i + 1)); + if(b) { + parseAdd(str2, mstruct, po, OPERATION_MULTIPLY, append); + append = true; + } else { + parseAdd(str2, mstruct, po); + b = true; + } + i = str.find(ID_WRAP_RIGHT_CH, 1); + } else { + i = str.find(ID_WRAP_RIGHT_CH, i + 1); + } + } + if(b) { + parseAdd(str, mstruct, po, OPERATION_MULTIPLY, append); + if(po.parsing_mode == PARSING_MODE_ADAPTIVE && mstruct->isMultiplication() && mstruct->size() >= 2 && !(*mstruct)[0].inParentheses()) { + Unit *u1 = NULL; Prefix *p1 = NULL; + bool b_plus = false; + // In adaptive parsing mode, parse 5m 2cm as 5m+2cm, 5ft 2in as 5ft+2in, and similar + if((*mstruct)[0].isMultiplication() && (*mstruct)[0].size() == 2 && (*mstruct)[0][0].isNumber() && (*mstruct)[0][1].isUnit()) {u1 = (*mstruct)[0][1].unit(); p1 = (*mstruct)[0][1].prefix();} + if(u1 && u1->subtype() == SUBTYPE_BASE_UNIT && (u1->referenceName() == "m" || (!p1 && u1->referenceName() == "L")) && (!p1 || (p1->type() == PREFIX_DECIMAL && ((DecimalPrefix*) p1)->exponent() <= 3 && ((DecimalPrefix*) p1)->exponent() > -3))) { + b_plus = true; + for(size_t i2 = 1; i2 < mstruct->size(); i2++) { + if(!(*mstruct)[i2].inParentheses() && (*mstruct)[i2].isMultiplication() && (*mstruct)[i2].size() == 2 && (*mstruct)[i2][0].isNumber() && (*mstruct)[i2][1].isUnit() && (*mstruct)[i2][1].unit() == u1) { + Prefix *p2 = (*mstruct)[i2][1].prefix(); + if(p1 && p2) b_plus = p1->type() == PREFIX_DECIMAL && p2->type() == PREFIX_DECIMAL && ((DecimalPrefix*) p1)->exponent() > ((DecimalPrefix*) p2)->exponent() && ((DecimalPrefix*) p2)->exponent() >= -3; + else if(p2) b_plus = p2->type() == PREFIX_DECIMAL && ((DecimalPrefix*) p2)->exponent() < 0 && ((DecimalPrefix*) p2)->exponent() >= -3; + else if(p1) b_plus = p1->type() == PREFIX_DECIMAL && ((DecimalPrefix*) p1)->exponent() > 1; + else b_plus = false; + if(!b_plus) break; + p1 = p2; + } else { + b_plus = false; + break; + } + } + } else if(u1 && !p1 && u1->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) u1)->mixWithBase()) { + b_plus = true; + for(size_t i2 = 1; i2 < mstruct->size(); i2++) { + if(!(*mstruct)[i2].inParentheses() && (*mstruct)[i2].isMultiplication() && (*mstruct)[i2].size() == 2 && (*mstruct)[i2][0].isNumber() && (*mstruct)[i2][1].isUnit() && u1->isChildOf((*mstruct)[i2][1].unit()) && !(*mstruct)[i2][1].prefix() && (i2 == mstruct->size() - 1 || ((*mstruct)[i2][1].unit()->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) (*mstruct)[i2][1].unit())->mixWithBase()))) { + while(((AliasUnit*) u1)->firstBaseUnit() != (*mstruct)[i2][1].unit()) { + u1 = ((AliasUnit*) u1)->firstBaseUnit(); + if(u1->subtype() != SUBTYPE_ALIAS_UNIT || !((AliasUnit*) u1)->mixWithBase()) { + b_plus = false; + break; + } + } + if(!b_plus) break; + u1 = (*mstruct)[i2][1].unit(); + } else { + b_plus = false; + break; + } + } + } + if(b_plus) mstruct->setType(STRUCT_ADDITION); + } + if(po.preserve_format) { + while(minus_count > 0) { + mstruct->transform(STRUCT_NEGATE); + minus_count--; + } + } else if(minus_count % 2 == 1) { + mstruct->negate(); + } + return true; + } + } + // Implicit multiplication + if((i = str.find(ID_WRAP_LEFT_CH, 1)) != string::npos) { + bool b = false, append = false; + while(i != string::npos) { + if(str[i - 1] != POWER_CH && (i < 2 || str[i - 1] != MINUS_CH || str[i - 2] != POWER_CH) && str[i - 1] != '\b') { + str2 = str.substr(0, i); + str = str.substr(i, str.length() - i); + if(b) { + parseAdd(str2, mstruct, po, OPERATION_MULTIPLY, append); + append = true; + } else { + parseAdd(str2, mstruct, po); + b = true; + } + i = str.find(ID_WRAP_LEFT_CH, 1); + } else { + i = str.find(ID_WRAP_LEFT_CH, i + 1); + } + } + if(b) { + parseAdd(str, mstruct, po, OPERATION_MULTIPLY, append); + if(po.preserve_format) { + while(minus_count > 0) { + mstruct->transform(STRUCT_NEGATE); + minus_count--; + } + } else if(minus_count % 2 == 1) { + mstruct->negate(); + } + return true; + } + } + if((i = str.find(POWER_CH, 1)) != string::npos && i + 1 != str.length()) { + // Parse exponentiation (^) + str2 = str.substr(0, i); + str = str.substr(i + 1, str.length() - (i + 1)); + parseAdd(str2, mstruct, po); + parseAdd(str, mstruct, po, OPERATION_RAISE); + } else if((i = str.find("\b", 1)) != string::npos && i + 1 != str.length()) { + // Parse uncertainty (using \b as internal single substitution character for +/-) + str2 = str.substr(0, i); + str = str.substr(i + 1, str.length() - (i + 1)); + MathStructure *mstruct2 = new MathStructure; + if(po.read_precision != DONT_READ_PRECISION) { + ParseOptions po2 = po; + po2.read_precision = DONT_READ_PRECISION; + parseAdd(str2, mstruct, po2); + parseAdd(str, mstruct2, po2); + } else { + parseAdd(str2, mstruct, po); + parseAdd(str, mstruct2, po); + } + mstruct->transform(f_uncertainty); + mstruct->addChild_nocopy(mstruct2); + mstruct->addChild(m_zero); + } else if(BASE_2_10 && (i = str.find_first_of(EXPS, 1)) != string::npos && i + 1 != str.length() && str.find("\b") == string::npos) { + // Parse scientific e-notation + str2 = str.substr(0, i); + str = str.substr(i + 1, str.length() - (i + 1)); + parseAdd(str2, mstruct, po); + parseAdd(str, mstruct, po, OPERATION_EXP10); + } else if((i = str.find(ID_WRAP_LEFT_CH, 1)) != string::npos && i + 1 != str.length() && str.find(ID_WRAP_RIGHT_CH, i + 1) && str.find_first_not_of(PLUS MINUS, 0) != i) { + // Implicit multiplication + str2 = str.substr(0, i); + str = str.substr(i, str.length() - i); + parseAdd(str2, mstruct, po); + parseAdd(str, mstruct, po, OPERATION_MULTIPLY); + } else if(str.length() > 0 && str[0] == ID_WRAP_LEFT_CH && (i = str.find(ID_WRAP_RIGHT_CH, 1)) != string::npos && i + 1 != str.length()) { + // Implicit multiplication + str2 = str.substr(0, i + 1); + str = str.substr(i + 1, str.length() - (i + 1)); + parseAdd(str2, mstruct, po); + parseAdd(str, mstruct, po, OPERATION_MULTIPLY); + } else { + // Parse as number + ret = parseNumber(mstruct, str, po); + } + if(po.preserve_format) { + while(minus_count > 0) { + mstruct->transform(STRUCT_NEGATE); + minus_count--; + } + } else if(minus_count % 2 == 1) { + mstruct->negate(); + } + return ret; +} + diff -Nru libqalculate-3.6.0/libqalculate/Calculator_p.h libqalculate-3.7.0/libqalculate/Calculator_p.h --- libqalculate-3.6.0/libqalculate/Calculator_p.h 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Calculator_p.h 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,81 @@ +/* + Qalculate + + Copyright (C) 2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#if HAVE_UNORDERED_MAP +# include + using std::unordered_map; +#elif defined(__GNUC__) + +# ifndef __has_include +# define __has_include(x) 0 +# endif + +# if (defined(__clang__) && __has_include()) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 3) +# include + namespace Sgi = std; +# define unordered_map std::tr1::unordered_map +# else +# if __GNUC__ < 3 +# include + namespace Sgi { using ::hash_map; }; // inherit globals +# else +# include +# if __GNUC__ == 3 && __GNUC_MINOR__ == 0 + namespace Sgi = std; // GCC 3.0 +# else + namespace Sgi = ::__gnu_cxx; // GCC 3.1 and later +# endif +# endif +# define unordered_map Sgi::hash_map +# endif +#else // ... there are other compilers, right? + namespace Sgi = std; +# define unordered_map Sgi::hash_map +#endif + +#ifndef CALCULATOR_P_H +#define CALCULATOR_P_H + +enum { + PROC_RPN_ADD, + PROC_RPN_SET, + PROC_RPN_OPERATION_1, + PROC_RPN_OPERATION_2, + PROC_RPN_OPERATION_F, + PROC_NO_COMMAND +}; + +class Calculator_p { + public: + unordered_map id_structs; + unordered_map ids_p; + vector freed_ids; + size_t ids_i; + Number custom_input_base, custom_output_base; + long int custom_input_base_i; + Unit *local_currency; + int use_binary_prefixes; + MathFunction *f_cis, *f_erfi, *f_fresnels, *f_fresnelc; + Unit *u_byn; + unordered_map id_functions; + unordered_map id_variables; + unordered_map id_units; + time_t exchange_rates_time2[1], exchange_rates_check_time2[1]; +}; + +class CalculateThread : public Thread { + protected: + virtual void run(); +}; + +bool is_not_number(char c, int base); + +#endif diff -Nru libqalculate-3.6.0/libqalculate/Calculator-plot.cc libqalculate-3.7.0/libqalculate/Calculator-plot.cc --- libqalculate-3.6.0/libqalculate/Calculator-plot.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Calculator-plot.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,588 @@ +/* + Qalculate + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "Calculator.h" +#include "util.h" +#include "MathStructure.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::string; +using std::vector; +using std::cout; +using std::endl; + +PlotParameters::PlotParameters() { + auto_y_min = true; + auto_x_min = true; + auto_y_max = true; + auto_x_max = true; + y_log = false; + x_log = false; + y_log_base = 10; + x_log_base = 10; + grid = false; + color = true; + linewidth = -1; + show_all_borders = false; + legend_placement = PLOT_LEGEND_TOP_RIGHT; +} +PlotDataParameters::PlotDataParameters() { + yaxis2 = false; + xaxis2 = false; + style = PLOT_STYLE_LINES; + smoothing = PLOT_SMOOTHING_NONE; + test_continuous = false; +} + +bool Calculator::canPlot() { +#ifdef _WIN32 + LPSTR lpFilePart; + char filename[MAX_PATH]; + return SearchPath(NULL, "gnuplot", ".exe", MAX_PATH, filename, &lpFilePart); +#else + FILE *pipe = popen("gnuplot - 2>/dev/null", "w"); + if(!pipe) return false; + return pclose(pipe) == 0; +#endif +} + +void parse_and_precalculate_plot(string &expression, MathStructure &mstruct, const ParseOptions &po, EvaluationOptions &eo) { + eo.approximation = APPROXIMATION_APPROXIMATE; + ParseOptions po2 = po; + po2.read_precision = DONT_READ_PRECISION; + eo.parse_options = po2; + eo.interval_calculation = INTERVAL_CALCULATION_NONE; + mstruct = CALCULATOR->parse(expression, po2); + MathStructure mbak(mstruct); + eo.calculate_functions = false; + eo.expand = false; + CALCULATOR->beginTemporaryStopMessages(); + mstruct.eval(eo); + int im = 0; + if(CALCULATOR->endTemporaryStopMessages(NULL, &im) > 0 || im > 0) mstruct = mbak; + eo.calculate_functions = true; + eo.expand = true; +} + +MathStructure Calculator::expressionToPlotVector(string expression, const MathStructure &min, const MathStructure &max, int steps, MathStructure *x_vector, string x_var, const ParseOptions &po, int msecs) { + Variable *v = getActiveVariable(x_var); + MathStructure x_mstruct; + if(v) x_mstruct = v; + else x_mstruct = x_var; + EvaluationOptions eo; + MathStructure mparse; + if(msecs > 0) startControl(msecs); + beginTemporaryStopIntervalArithmetic(); + parse_and_precalculate_plot(expression, mparse, po, eo); + beginTemporaryStopMessages(); + MathStructure y_vector(mparse.generateVector(x_mstruct, min, max, steps, x_vector, eo)); + endTemporaryStopMessages(); + endTemporaryStopIntervalArithmetic(); + if(msecs > 0) { + if(aborted()) error(true, _("It took too long to generate the plot data."), NULL); + stopControl(); + } + if(y_vector.size() == 0) { + error(true, _("Unable to generate plot data with current min, max and sampling rate."), NULL); + } + return y_vector; +} +MathStructure Calculator::expressionToPlotVector(string expression, float min, float max, int steps, MathStructure *x_vector, string x_var, const ParseOptions &po, int msecs) { + MathStructure min_mstruct(min), max_mstruct(max); + ParseOptions po2 = po; + po2.read_precision = DONT_READ_PRECISION; + MathStructure y_vector(expressionToPlotVector(expression, min_mstruct, max_mstruct, steps, x_vector, x_var, po2, msecs)); + return y_vector; +} +MathStructure Calculator::expressionToPlotVector(string expression, const MathStructure &min, const MathStructure &max, const MathStructure &step, MathStructure *x_vector, string x_var, const ParseOptions &po, int msecs) { + Variable *v = getActiveVariable(x_var); + MathStructure x_mstruct; + if(v) x_mstruct = v; + else x_mstruct = x_var; + EvaluationOptions eo; + MathStructure mparse; + if(msecs > 0) startControl(msecs); + beginTemporaryStopIntervalArithmetic(); + parse_and_precalculate_plot(expression, mparse, po, eo); + beginTemporaryStopMessages(); + MathStructure y_vector(mparse.generateVector(x_mstruct, min, max, step, x_vector, eo)); + endTemporaryStopMessages(); + endTemporaryStopIntervalArithmetic(); + if(msecs > 0) { + if(aborted()) error(true, _("It took too long to generate the plot data."), NULL); + stopControl(); + } + if(y_vector.size() == 0) { + error(true, _("Unable to generate plot data with current min, max and step size."), NULL); + } + return y_vector; +} +MathStructure Calculator::expressionToPlotVector(string expression, float min, float max, float step, MathStructure *x_vector, string x_var, const ParseOptions &po, int msecs) { + MathStructure min_mstruct(min), max_mstruct(max), step_mstruct(step); + ParseOptions po2 = po; + po2.read_precision = DONT_READ_PRECISION; + MathStructure y_vector(expressionToPlotVector(expression, min_mstruct, max_mstruct, step_mstruct, x_vector, x_var, po2, msecs)); + return y_vector; +} +MathStructure Calculator::expressionToPlotVector(string expression, const MathStructure &x_vector, string x_var, const ParseOptions &po, int msecs) { + Variable *v = getActiveVariable(x_var); + MathStructure x_mstruct; + if(v) x_mstruct = v; + else x_mstruct = x_var; + EvaluationOptions eo; + MathStructure mparse; + if(msecs > 0) startControl(msecs); + beginTemporaryStopIntervalArithmetic(); + parse_and_precalculate_plot(expression, mparse, po, eo); + beginTemporaryStopMessages(); + MathStructure y_vector(mparse.generateVector(x_mstruct, x_vector, eo).eval(eo)); + endTemporaryStopMessages(); + endTemporaryStopIntervalArithmetic(); + if(msecs > 0) { + if(aborted()) error(true, _("It took too long to generate the plot data."), NULL); + stopControl(); + } + return y_vector; +} + +bool Calculator::plotVectors(PlotParameters *param, const vector &y_vectors, const vector &x_vectors, vector &pdps, bool persistent, int msecs) { + + string homedir = getLocalTmpDir(); + recursiveMakeDir(homedir); + + string commandline_extra; + string title; + + if(!param) { + PlotParameters pp; + param = &pp; + } + + string plot; + + if(param->filename.empty()) { + if(!param->color) { + commandline_extra += " -mono"; + } + plot += "set terminal pop\n"; + } else { + persistent = true; + if(param->filetype == PLOT_FILETYPE_AUTO) { + size_t i = param->filename.rfind("."); + if(i == string::npos) { + param->filetype = PLOT_FILETYPE_PNG; + error(false, _("No extension in file name. Saving as PNG image."), NULL); + } else { + string ext = param->filename.substr(i + 1, param->filename.length() - (i + 1)); + if(ext == "png") { + param->filetype = PLOT_FILETYPE_PNG; + } else if(ext == "ps") { + param->filetype = PLOT_FILETYPE_PS; + } else if(ext == "pdf") { + param->filetype = PLOT_FILETYPE_PDF; + } else if(ext == "eps") { + param->filetype = PLOT_FILETYPE_EPS; + } else if(ext == "svg") { + param->filetype = PLOT_FILETYPE_SVG; + } else if(ext == "fig") { + param->filetype = PLOT_FILETYPE_FIG; + } else if(ext == "tex") { + param->filetype = PLOT_FILETYPE_LATEX; + } else { + param->filetype = PLOT_FILETYPE_PNG; + error(false, _("Unknown extension in file name. Saving as PNG image."), NULL); + } + } + } + plot += "set terminal "; + switch(param->filetype) { + case PLOT_FILETYPE_FIG: { + plot += "fig "; + if(param->color) { + plot += "color"; + } else { + plot += "monochrome"; + } + break; + } + case PLOT_FILETYPE_SVG: { + plot += "svg"; + break; + } + case PLOT_FILETYPE_LATEX: { + plot += "latex "; + break; + } + case PLOT_FILETYPE_PS: { + plot += "postscript "; + if(param->color) { + plot += "color"; + } else { + plot += "monochrome"; + } + plot += " \"Times\""; + break; + } + case PLOT_FILETYPE_PDF: { + plot += "pdf "; + if(param->color) { + plot += "color"; + } else { + plot += "monochrome"; + } + break; + } + case PLOT_FILETYPE_EPS: { + plot += "postscript eps "; + if(param->color) { + plot += "color"; + } else { + plot += "monochrome"; + } + plot += " \"Times\""; + break; + } + default: { + plot += "png "; + break; + } + + } + plot += "\nset output \""; + plot += param->filename; + plot += "\"\n"; + } + + switch(param->legend_placement) { + case PLOT_LEGEND_NONE: {plot += "set nokey\n"; break;} + case PLOT_LEGEND_TOP_LEFT: {plot += "set key top left\n"; break;} + case PLOT_LEGEND_TOP_RIGHT: {plot += "set key top right\n"; break;} + case PLOT_LEGEND_BOTTOM_LEFT: {plot += "set key bottom left\n"; break;} + case PLOT_LEGEND_BOTTOM_RIGHT: {plot += "set key bottom right\n"; break;} + case PLOT_LEGEND_BELOW: {plot += "set key below\n"; break;} + case PLOT_LEGEND_OUTSIDE: {plot += "set key outside\n"; break;} + } + if(!param->x_label.empty()) { + title = param->x_label; + gsub("\"", "\\\"", title); + plot += "set xlabel \""; + plot += title; + plot += "\"\n"; + } + if(!param->y_label.empty()) { + string title = param->y_label; + gsub("\"", "\\\"", title); + plot += "set ylabel \""; + plot += title; + plot += "\"\n"; + } + if(!param->title.empty()) { + title = param->title; + gsub("\"", "\\\"", title); + plot += "set title \""; + plot += title; + plot += "\"\n"; + } + if(param->grid) { + plot += "set grid\n"; + + } + if(!param->auto_y_min || !param->auto_y_max) { + plot += "set yrange ["; + if(!param->auto_y_min) plot += d2s(param->y_min); + plot += ":"; + if(!param->auto_y_max) plot += d2s(param->y_max); + plot += "]"; + plot += "\n"; + } + if(param->x_log) { + plot += "set logscale x "; + plot += i2s(param->x_log_base); + plot += "\n"; + } + if(param->show_all_borders) { + plot += "set border 15\n"; + } else { + bool xaxis2 = false, yaxis2 = false; + for(size_t i = 0; i < pdps.size(); i++) { + if(pdps[i] && pdps[i]->xaxis2) { + xaxis2 = true; + } + if(pdps[i] && pdps[i]->yaxis2) { + yaxis2 = true; + } + } + if(xaxis2 && yaxis2) { + plot += "set border 15\nset x2tics\nset y2tics\n"; + } else if(xaxis2) { + plot += "set border 7\nset x2tics\n"; + } else if(yaxis2) { + plot += "set border 11\nset y2tics\n"; + } else { + plot += "set border 3\n"; + } + plot += "set xtics nomirror\nset ytics nomirror\n"; + } + size_t samples = 1000; + for(size_t i = 0; i < y_vectors.size(); i++) { + if(!y_vectors[i].isUndefined()) { + if(y_vectors[i].size() > 3000) { + samples = 6000; + break; + } + if(y_vectors[i].size() * 2 > samples) samples = y_vectors[i].size() * 2; + } + } + plot += "set samples "; + plot += i2s(samples); + plot += "\n"; + plot += "plot "; + for(size_t i = 0; i < y_vectors.size(); i++) { + if(!y_vectors[i].isUndefined()) { + if(i != 0) { + plot += ","; + } + string filename = "gnuplot_data"; + filename += i2s(i + 1); + filename = buildPath(homedir, filename); +#ifdef _WIN32 + gsub("\\", "\\\\", filename); +#endif + plot += "\""; + plot += filename; + plot += "\""; + if(i < pdps.size()) { + switch(pdps[i]->smoothing) { + case PLOT_SMOOTHING_UNIQUE: {plot += " smooth unique"; break;} + case PLOT_SMOOTHING_CSPLINES: {plot += " smooth csplines"; break;} + case PLOT_SMOOTHING_BEZIER: {plot += " smooth bezier"; break;} + case PLOT_SMOOTHING_SBEZIER: {plot += " smooth sbezier"; break;} + default: {} + } + if(pdps[i]->xaxis2 && pdps[i]->yaxis2) { + plot += " axis x2y2"; + } else if(pdps[i]->xaxis2) { + plot += " axis x2y1"; + } else if(pdps[i]->yaxis2) { + plot += " axis x1y2"; + } + if(!pdps[i]->title.empty()) { + title = pdps[i]->title; + gsub("\"", "\\\"", title); + plot += " title \""; + plot += title; + plot += "\""; + } + switch(pdps[i]->style) { + case PLOT_STYLE_LINES: {plot += " with lines"; break;} + case PLOT_STYLE_POINTS: {plot += " with points"; break;} + case PLOT_STYLE_POINTS_LINES: {plot += " with linespoints"; break;} + case PLOT_STYLE_BOXES: {plot += " with boxes"; break;} + case PLOT_STYLE_HISTOGRAM: {plot += " with histeps"; break;} + case PLOT_STYLE_STEPS: {plot += " with steps"; break;} + case PLOT_STYLE_CANDLESTICKS: {plot += " with candlesticks"; break;} + case PLOT_STYLE_DOTS: {plot += " with dots"; break;} + } + if(param->linewidth < 1) { + plot += " lw 2"; + } else { + plot += " lw "; + plot += i2s(param->linewidth); + } + } + } + } + plot += "\n"; + + string plot_data; + PrintOptions po; + po.number_fraction_format = FRACTION_DECIMAL; + po.interval_display = INTERVAL_DISPLAY_MIDPOINT; + po.decimalpoint_sign = "."; + po.comma_sign = ","; + for(size_t serie = 0; serie < y_vectors.size(); serie++) { + if(!y_vectors[serie].isUndefined()) { + string filename = "gnuplot_data"; + filename += i2s(serie + 1); + string filepath = buildPath(homedir, filename); + FILE *fdata = fopen(filepath.c_str(), "w+"); + if(!fdata) { + error(true, _("Could not create temporary file %s"), filepath.c_str(), NULL); + return false; + } + plot_data = ""; + int non_numerical = 0, non_real = 0; + //string str = ""; + if(msecs > 0) startControl(msecs); + ComparisonResult ct1 = COMPARISON_RESULT_EQUAL, ct2 = COMPARISON_RESULT_EQUAL; + size_t last_index = string::npos, last_index2 = string::npos; + bool check_continuous = pdps[serie]->test_continuous && (pdps[serie]->style == PLOT_STYLE_LINES || pdps[serie]->style == PLOT_STYLE_POINTS_LINES); + bool prev_failed = false; + for(size_t i = 1; i <= y_vectors[serie].countChildren(); i++) { + ComparisonResult ct = COMPARISON_RESULT_UNKNOWN; + bool invalid_nr = false, b_imagzero_x = false, b_imagzero_y = false; + if(!y_vectors[serie].getChild(i)->isNumber()) { + invalid_nr = true; + non_numerical++; + //if(non_numerical == 1) str = y_vectors[serie].getChild(i)->print(po); + } else if(!y_vectors[serie].getChild(i)->number().isReal()) { + b_imagzero_y = testComplexZero(&y_vectors[serie].getChild(i)->number(), y_vectors[serie].getChild(i)->number().internalImaginary()); + if(!b_imagzero_y) { + invalid_nr = true; + non_real++; + //if(non_numerical + non_real == 1) str = y_vectors[serie].getChild(i)->print(po); + } + } + if(serie < x_vectors.size() && !x_vectors[serie].isUndefined() && x_vectors[serie].countChildren() == y_vectors[serie].countChildren()) { + if(!x_vectors[serie].getChild(i)->isNumber()) { + invalid_nr = true; + non_numerical++; + //if(non_numerical == 1) str = x_vectors[serie].getChild(i)->print(po); + } else if(!x_vectors[serie].getChild(i)->number().isReal()) { + b_imagzero_x = testComplexZero(&x_vectors[serie].getChild(i)->number(), x_vectors[serie].getChild(i)->number().internalImaginary()); + if(!b_imagzero_x) { + invalid_nr = true; + non_real++; + //if(non_numerical + non_real == 1) str = x_vectors[serie].getChild(i)->print(po); + } + } + if(!invalid_nr) { + if(b_imagzero_y) plot_data += x_vectors[serie].getChild(i)->number().realPart().print(po); + else plot_data += x_vectors[serie].getChild(i)->print(po); + plot_data += " "; + } + } + if(!invalid_nr) { + if(check_continuous && !prev_failed) { + if(i == 1 || ct2 == COMPARISON_RESULT_UNKNOWN) ct = COMPARISON_RESULT_EQUAL; + else ct = y_vectors[serie].getChild(i - 1)->number().compare(y_vectors[serie].getChild(i)->number()); + if((ct == COMPARISON_RESULT_GREATER || ct == COMPARISON_RESULT_LESS) && (ct1 == COMPARISON_RESULT_GREATER || ct1 == COMPARISON_RESULT_LESS) && (ct2 == COMPARISON_RESULT_GREATER || ct2 == COMPARISON_RESULT_LESS) && ct1 != ct2 && ct != ct2) { + if(last_index2 != string::npos) plot_data.insert(last_index2 + 1, " \n"); + } + } + if(b_imagzero_x) plot_data += y_vectors[serie].getChild(i)->number().realPart().print(po); + else plot_data += y_vectors[serie].getChild(i)->print(po); + plot_data += "\n"; + prev_failed = false; + } else if(!prev_failed) { + ct = COMPARISON_RESULT_UNKNOWN; + plot_data += " \n"; + prev_failed = true; + } + last_index2 = last_index; + last_index = plot_data.length() - 1; + ct1 = ct2; + ct2 = ct; + if(aborted()) { + fclose(fdata); + if(msecs > 0) { + error(true, _("It took too long to generate the plot data."), NULL); + stopControl(); + } + return false; + } + } + if(msecs > 0) stopControl(); + /*if(non_numerical > 0 || non_real > 0) { + string stitle; + if(serie < pdps.size() && !pdps[serie]->title.empty()) { + stitle = pdps[serie]->title.c_str(); + } else { + stitle = i2s(serie).c_str(); + } + if(non_numerical > 0) { + error(true, _("Series %s contains non-numerical data (\"%s\" first of %s) which can not be properly plotted."), stitle.c_str(), str.c_str(), i2s(non_numerical).c_str(), NULL); + } else { + error(true, _("Series %s contains non-real data (\"%s\" first of %s) which can not be properly plotted."), stitle.c_str(), str.c_str(), i2s(non_real).c_str(), NULL); + } + }*/ + fputs(plot_data.c_str(), fdata); + fflush(fdata); + fclose(fdata); + } + } + + return invokeGnuplot(plot, commandline_extra, persistent); +} +bool Calculator::invokeGnuplot(string commands, string commandline_extra, bool persistent) { + FILE *pipe = NULL; + if(!b_gnuplot_open || !gnuplot_pipe || persistent || commandline_extra != gnuplot_cmdline) { + if(!persistent) { + closeGnuplot(); + } + string commandline = "gnuplot"; + if(persistent) { + commandline += " -persist"; + } + commandline += commandline_extra; +#ifdef _WIN32 + commandline += " - 2>nul"; + pipe = _popen(commandline.c_str(), "w"); +#else + commandline += " - 2>/dev/null"; + pipe = popen(commandline.c_str(), "w"); +#endif + if(!pipe) { + error(true, _("Failed to invoke gnuplot. Make sure that you have gnuplot installed in your path."), NULL); + return false; + } + if(!persistent && pipe) { + gnuplot_pipe = pipe; + b_gnuplot_open = true; + gnuplot_cmdline = commandline_extra; + } + } else { + pipe = gnuplot_pipe; + } + if(!pipe) { + return false; + } + if(!persistent) { + fputs("clear\n", pipe); + fputs("reset\n", pipe); + } + fputs(commands.c_str(), pipe); + fflush(pipe); + if(persistent) { + return pclose(pipe) == 0; + } + return true; +} +bool Calculator::closeGnuplot() { + if(gnuplot_pipe) { +#ifdef _WIN32 + int rv = _pclose(gnuplot_pipe); +#else + int rv = pclose(gnuplot_pipe); +#endif + gnuplot_pipe = NULL; + b_gnuplot_open = false; + return rv == 0; + } + gnuplot_pipe = NULL; + b_gnuplot_open = false; + return true; +} +bool Calculator::gnuplotOpen() { + return b_gnuplot_open && gnuplot_pipe; +} + diff -Nru libqalculate-3.6.0/libqalculate/DataSet.cc libqalculate-3.7.0/libqalculate/DataSet.cc --- libqalculate-3.6.0/libqalculate/DataSet.cc 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/DataSet.cc 2020-01-21 22:54:40.000000000 +0000 @@ -17,6 +17,7 @@ #include "Calculator.h" #include "MathStructure.h" #include "Number.h" +#include "BuiltinFunctions.h" #include #include #include @@ -711,7 +712,7 @@ if(uncertainty) { if(unc_rel) { str.insert(0, "("); - str.insert(0, CALCULATOR->f_uncertainty->referenceName()); + str.insert(0, CALCULATOR->getFunctionById(FUNCTION_ID_UNCERTAINTY)->referenceName()); str += ", "; str += (char*) uncertainty; str += ", 1)"; diff -Nru libqalculate-3.6.0/libqalculate/ExpressionItem.cc libqalculate-3.7.0/libqalculate/ExpressionItem.cc --- libqalculate-3.6.0/libqalculate/ExpressionItem.cc 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/ExpressionItem.cc 2020-01-21 22:54:40.000000000 +0000 @@ -486,3 +486,6 @@ bool ExpressionItem::changeReference(ExpressionItem*, ExpressionItem*) { return false; } +int ExpressionItem::id() const { + return 0; +} diff -Nru libqalculate-3.6.0/libqalculate/ExpressionItem.h libqalculate-3.7.0/libqalculate/ExpressionItem.h --- libqalculate-3.6.0/libqalculate/ExpressionItem.h 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/ExpressionItem.h 2020-01-21 22:54:40.000000000 +0000 @@ -286,6 +286,8 @@ */ virtual int subtype() const = 0; + virtual int id() const; + }; #endif diff -Nru libqalculate-3.6.0/libqalculate/Function.cc libqalculate-3.7.0/libqalculate/Function.cc --- libqalculate-3.6.0/libqalculate/Function.cc 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Function.cc 2020-01-21 22:54:40.000000000 +0000 @@ -18,6 +18,7 @@ #include "Variable.h" #include "Number.h" #include "Unit.h" +#include "BuiltinFunctions.h" #include @@ -52,6 +53,8 @@ # define unordered_map Sgi::hash_map #endif +#include "MathStructure-support.h" + using std::string; using std::vector; using std::iterator; @@ -65,6 +68,7 @@ MathFunction::MathFunction(string name_, int argc_, int max_argc_, string cat_, string title_, string descr_, bool is_active) : ExpressionItem(cat_, name_, title_, descr_, false, true, is_active) { priv = new MathFunction_p; + // arc = min number of arguments, max_argc = max arguments (if max_argc=-1, place additional arguments in vector) argc = argc_; if(max_argc_ < 0 || argc < 0) { if(argc < 0) argc = 0; @@ -73,6 +77,7 @@ max_argc = argc; } else { max_argc = max_argc_; + // arguments not required, must have a default value (by default 0) for(int i = 0; i < max_argc - argc; i++) { default_values.push_back("0"); } @@ -120,11 +125,17 @@ int MathFunction::subtype() const { return SUBTYPE_FUNCTION; } +int MathFunction::id() const { + return 0; +} string MathFunction::example(bool raw_format, string name_string) const { + // example text if(raw_format) return sexample; string str = sexample; + // $name is replaced function name (or provided string) gsub("$name", name_string.empty() ? name() : name_string, str); + // adjust decimal and group separators return CALCULATOR->localizeExpression(str); } void MathFunction::setExample(string new_example) { @@ -157,16 +168,19 @@ remove_blank_ends(scondition); } bool MathFunction::testCondition(const MathStructure &vargs) { + // test condition for arguments if(scondition.empty()) { return true; } + // create a temporary function from the condition expression (for handling av arguments) UserFunction test_function("", "CONDITION_TEST_FUNCTION", scondition, false, argc, "", "", max_argc); MathStructure vargs2(vargs); MathStructure mstruct(test_function.MathFunction::calculate(vargs2)); EvaluationOptions eo; eo.approximation = APPROXIMATION_APPROXIMATE; mstruct.eval(eo); - if(!mstruct.isNumber() || !mstruct.number().isPositive()) { + // check if result is true + if(!mstruct.isNumber() || !mstruct.number().getBoolean()) { if(CALCULATOR->showArgumentErrors() && !CALCULATOR->aborted()) { CALCULATOR->error(true, _("%s() requires that %s"), name().c_str(), printCondition().c_str(), NULL); } @@ -175,7 +189,8 @@ return true; } string MathFunction::printCondition() { - if(scondition.empty() || last_argdef_index == 0) return scondition; + if(scondition.empty()) return scondition; + // replace arguments (represented by \x, \y, \z, \a, etc.) with argument definition names string str = scondition; string svar, argstr; Argument *arg; @@ -224,6 +239,7 @@ return str; } int MathFunction::args(const string &argstr, MathStructure &vargs, const ParseOptions &parseoptions) { + // read arguments from expression (e.g. "52, 2" from expression "sin(52, 2)"); used in Calculator::parse() ParseOptions po = parseoptions; MathStructure *unended_function = po.unended_function; po.unended_function = NULL; @@ -238,10 +254,12 @@ bool last_is_vctr = false, vctr_started = false; if(maxargs() > 0) { arg = getArgumentDefinition(maxargs()); + // if last argument is vector or maximum number of arguments is 1 and the only argument allows vector last_is_vctr = arg && ((arg->type() == ARGUMENT_TYPE_VECTOR) || (maxargs() == 1 && arg->handlesVector())); } for(size_t str_index = 0; str_index < str.length(); str_index++) { switch(str[str_index]) { + // argument does not end within parentheses, brackets or quotes case LEFT_VECTOR_WRAP_CH: {} case LEFT_PARENTHESIS_CH: { if(!in_cit1 && !in_cit2) { @@ -272,18 +290,24 @@ } break; } + // argument separator case COMMA_CH: { if(pars == 0 && !in_cit1 && !in_cit2) { itmp++; + // read one argument if(itmp <= maxargs() || args() < 0) { + // index is <= max number of arguments stmp = str.substr(start_pos, str_index - start_pos); remove_blank_ends(stmp); arg = getArgumentDefinition(itmp); - if(!arg && itmp > argc && args() < 0 && itmp > (int) last_argdef_index && last_argdef_index > 0) { + // index is greater than minimum number of arguments, + // and maximimum number of arguments is unlimited, use the last argument definition + if(!arg && itmp > argc && args() < 0 && itmp > (int) last_argdef_index && (int) last_argdef_index > argc) { arg = priv->argdefs[last_argdef_index]; } if(stmp.empty()) { if(arg) { + // if index has argument definition, use for parsing MathStructure *mstruct = new MathStructure(); arg->parse(mstruct, getDefaultValue(itmp), po); vargs.addChild_nocopy(mstruct); @@ -304,6 +328,7 @@ } } } else if(last_is_vctr) { + // if last argument is a vector, use additional arguments to fill the vector if(!vctr_started) { if(!vargs[vargs.size() - 1].isVector() || vargs[vargs.size() - 1].size() != 1) { vargs[vargs.size() - 1].transform(STRUCT_VECTOR); @@ -331,6 +356,9 @@ } } } + // generate unended function information + // used from Calculator::parse() for display of continuous parsing info + // handling is incomplete if used separately if(!str.empty()) { itmp++; po.unended_function = unended_function; @@ -338,7 +366,7 @@ stmp = str.substr(start_pos, str.length() - start_pos); remove_blank_ends(stmp); arg = getArgumentDefinition(itmp); - if(!arg && itmp > argc && args() < 0 && itmp > (int) last_argdef_index && last_argdef_index > 0) { + if(!arg && itmp > argc && args() < 0 && itmp > (int) last_argdef_index && (int) last_argdef_index > argc) { arg = priv->argdefs[last_argdef_index]; } if(stmp.empty()) { @@ -393,6 +421,7 @@ unended_function->addChild(m_undefined); } } + // append default values if(itmp < maxargs() && itmp >= minargs()) { int itmp2 = itmp; while(itmp2 < maxargs()) { @@ -512,6 +541,7 @@ last = it->first; } if(it->second && it->first > 0 && it->first <= vargs.size()) { + // for symbols arguments with zero or undefined value, search the first argument for a symbol if(it->second->type() == ARGUMENT_TYPE_SYMBOLIC && (vargs[it->first - 1].isZero() || vargs[it->first - 1].isUndefined())) { vargs[it->first - 1] = vargs[0].find_x_var(); if(vargs[it->first - 1].isUndefined() && vargs[0].isVariable() && vargs[0].variable()->isKnown()) vargs[it->first - 1] = ((KnownVariable*) vargs[0].variable())->get().find_x_var(); @@ -523,7 +553,7 @@ CALCULATOR->endTemporaryStopMessages(); } if(vargs[it->first - 1].isUndefined()) { - vargs[it->first - 1].set(CALCULATOR->v_x, true); + vargs[it->first - 1].set(CALCULATOR->getVariableById(VARIABLE_ID_X), true); CALCULATOR->error(false, _("No unknown variable/symbol was found."), NULL); } } @@ -769,6 +799,7 @@ } extern string format_and_print(const MathStructure &mstruct); bool replace_intervals_f(MathStructure &mstruct) { + // replace intervals with temporary variables if(mstruct.isNumber() && (mstruct.number().isInterval(false) || (CALCULATOR->usesIntervalArithmetic() && mstruct.number().precision() >= 0))) { Variable *v = new KnownVariable("", format_and_print(mstruct), mstruct); v->setTitle("\b"); @@ -785,10 +816,9 @@ } return b; } -extern bool set_uncertainty(MathStructure &mstruct, MathStructure &munc, const EvaluationOptions &eo = default_evaluation_options, bool do_eval = false); -extern bool create_interval(MathStructure &mstruct, const MathStructure &m1, const MathStructure &m2); bool replace_f_interval(MathStructure &mstruct, const EvaluationOptions &eo) { - if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_interval && mstruct.size() == 2) { + // replace interval() and uncertainty() with numbers with intervals, if possible + if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_INTERVAL && mstruct.size() == 2) { if(mstruct[0].isNumber() && mstruct[1].isNumber()) { Number nr; if(nr.setInterval(mstruct[0].number(), mstruct[1].number())) { @@ -804,7 +834,7 @@ if(create_interval(mstruct, m1, m2)) return true; } return false; - } else if(eo.interval_calculation != INTERVAL_CALCULATION_NONE && mstruct.isFunction() && mstruct.function() == CALCULATOR->f_uncertainty && mstruct.size() == 3) { + } else if(eo.interval_calculation != INTERVAL_CALCULATION_NONE && mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_UNCERTAINTY && mstruct.size() == 3) { if(mstruct[0].isNumber() && mstruct[1].isNumber()) { Number nr(mstruct[0].number()); if(mstruct[2].number().getBoolean()) { @@ -831,7 +861,7 @@ mstruct.setToChild(1, true); mstruct *= m_one; mstruct.last() -= m2; - mstruct.transform(CALCULATOR->f_interval); + mstruct.transformById(FUNCTION_ID_INTERVAL); m1 *= m_one; m1.last() += m2; mstruct.addChild(m1); @@ -845,13 +875,13 @@ m2 = mstruct[1]; mstruct.setToChild(1); mstruct -= m2; - mstruct.transform(CALCULATOR->f_interval); + mstruct.transformById(FUNCTION_ID_INTERVAL); m1 += m2; mstruct.addChild(m1); } replace_f_interval(mstruct, eo); return true; - + } return false; } @@ -1487,7 +1517,7 @@ str3 = "("; if(!m_temp) { CALCULATOR->error(true, _("Internal id %s does not exist."), i2s(id).c_str(), NULL); - str3 += CALCULATOR->v_undef->preferredInputName(true, false, false, true).name; + str3 += CALCULATOR->getVariableById(VARIABLE_ID_UNDEFINED)->preferredInputName(true, false, false, true).name; } else { str3 += m_temp->print(CALCULATOR->save_printoptions).c_str(); m_temp->unref(); @@ -1518,7 +1548,7 @@ str3 = "("; if(!m_temp) { CALCULATOR->error(true, _("Internal id %s does not exist."), i2s(id).c_str(), NULL); - str3 += CALCULATOR->v_undef->preferredInputName(true, false, false, true).name; + str3 += CALCULATOR->getVariableById(VARIABLE_ID_UNDEFINED)->preferredInputName(true, false, false, true).name; } else { str3 += m_temp->print(CALCULATOR->save_printoptions).c_str(); m_temp->unref(); @@ -1689,6 +1719,10 @@ if(!value.isNumber()) { value.eval(eo); } + /*if(value.isMultiplication() && value.size() == 2 && value[0].isNumber() && value[1].isUnit() && value[1].unit()->baseUnit() == CALCULATOR->getRadUnit()->baseUnit()) { + value /= CALCULATOR->getRadUnit(); + value.eval(eo); + }*/ if(!value.isNumber() || (b_rational_number && !value.number().isRational())) { return false; } @@ -2216,6 +2250,7 @@ if(mstruct->contains(CALCULATOR->getRadUnit(), false, true, true) > 0) return; if(mstruct->contains(CALCULATOR->getDegUnit(), false, true, true) > 0) return; if(mstruct->contains(CALCULATOR->getGraUnit(), false, true, true) > 0) return; + if(contains_angle_unit(*mstruct, po)) return; } switch(po.angle_unit) { case ANGLE_UNIT_DEGREES: { diff -Nru libqalculate-3.6.0/libqalculate/Function.h libqalculate-3.7.0/libqalculate/Function.h --- libqalculate-3.6.0/libqalculate/Function.h 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Function.h 2020-01-21 22:54:40.000000000 +0000 @@ -98,6 +98,8 @@ */ virtual int subtype() const; + virtual int id() const; + std::string example(bool raw_format = false, std::string name_string = "") const; void setExample(std::string new_example); diff -Nru libqalculate-3.6.0/libqalculate/includes.h libqalculate-3.7.0/libqalculate/includes.h --- libqalculate-3.6.0/libqalculate/includes.h 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/includes.h 2020-01-21 22:54:40.000000000 +0000 @@ -31,7 +31,7 @@ #include #define QALCULATE_MAJOR_VERSION (3) -#define QALCULATE_MINOR_VERSION (6) +#define QALCULATE_MINOR_VERSION (7) #define QALCULATE_MICRO_VERSION (0) static std::string empty_string; diff -Nru libqalculate-3.6.0/libqalculate/Makefile.am libqalculate-3.7.0/libqalculate/Makefile.am --- libqalculate-3.6.0/libqalculate/Makefile.am 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Makefile.am 2020-01-21 22:54:43.000000000 +0000 @@ -6,10 +6,20 @@ lib_LTLIBRARIES = libqalculate.la libqalculate_la_SOURCES = \ - Function.cc Calculator.cc DataSet.cc \ - Variable.cc ExpressionItem.cc Number.cc MathStructure.cc \ - Prefix.cc support.h util.cc Unit.cc BuiltinFunctions.cc \ - QalculateDateTime.cc + Function.cc Calculator.cc Calculator-plot.cc Calculator-parse.cc \ + Calculator-definitions.cc Calculator-calculate.cc Calculator-convert.cc \ + DataSet.cc Variable.cc ExpressionItem.cc Number.cc MathStructure.cc \ + Prefix.cc support.h util.cc Unit.cc QalculateDateTime.cc \ + BuiltinFunctions-util.cc BuiltinFunctions-trigonometry.cc BuiltinFunctions-matrixvector.cc \ + BuiltinFunctions-datetime.cc BuiltinFunctions-statistics.cc \ + BuiltinFunctions-explog.cc BuiltinFunctions-special.cc BuiltinFunctions-algebra.cc \ + BuiltinFunctions-calculus.cc BuiltinFunctions-number.cc \ + BuiltinFunctions-combinatorics.cc BuiltinFunctions-logical.cc \ + MathStructure-factor.cc MathStructure-gcd.cc MathStructure-integrate.cc \ + MathStructure-isolatex.cc MathStructure-polynomial.cc \ + MathStructure-matrixvector.cc MathStructure-print.cc \ + MathStructure-differentiate.cc MathStructure-calculate.cc MathStructure-eval.cc \ + MathStructure-convert.cc MathStructure-decompose.cc MathStructure-limit.cc libqalculateincludedir = $(includedir)/libqalculate @@ -19,10 +29,12 @@ util.h includes.h Unit.h BuiltinFunctions.h \ QalculateDateTime.h qalculate.h +noinst_HEADERS = MathStructure-support.h Calculator_p.h bernoulli_numbers.h + libqalculate_la_LDFLAGS = -version-info $(QALCULATE_CURRENT):$(QALCULATE_REVISION):$(QALCULATE_AGE) -no-undefined libqalculate_la_LIBADD = \ - @LIBCURL_LIBS@ @LIBXML_LIBS@ @ICU_LIBS@ @LTLIBINTL@ @LTLIBICONV@ + @LIBCURL_LIBS@ @LIBXML_LIBS@ @ICU_LIBS@ @LTLIBICONV@ AM_CPPFLAGS = \ -I$(top_srcdir) \ diff -Nru libqalculate-3.6.0/libqalculate/MathStructure-calculate.cc libqalculate-3.7.0/libqalculate/MathStructure-calculate.cc --- libqalculate-3.6.0/libqalculate/MathStructure-calculate.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure-calculate.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,6914 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "MathStructure.h" +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "Number.h" +#include "Function.h" +#include "Variable.h" +#include "Unit.h" +#include "Prefix.h" +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +bool warn_test_interval(MathStructure &mnonzero, const EvaluationOptions &eo2) { + if(mnonzero.isComparison() && mnonzero[0].isVariable() && !mnonzero[0].variable()->isKnown() && !((UnknownVariable*) mnonzero[0].variable())->interval().isUndefined()) { + /*if(((UnknownVariable*) mnonzero[0].variable())->interval().isNumber() && mnonzero[1].isNumber()) { + MathStructure mbak(mnonzero); + mnonzero[0] = ((UnknownVariable*) mnonzero[0].variable())->interval(); + mnonzero.eval(eo2); + if(!mnonzero.isNumber()) mnonzero.clear(); + return true; + } else*/ if(((UnknownVariable*) mnonzero[0].variable())->interval().containsInterval(true)) { + MathStructure mbak(mnonzero); + mnonzero[0] = ((UnknownVariable*) mnonzero[0].variable())->interval(); + mnonzero.eval(eo2); + if(mnonzero.isComparison()) mnonzero = mbak; + else return true; + } else { + mnonzero[0] = ((UnknownVariable*) mnonzero[0].variable())->interval(); + mnonzero.eval(eo2); + return true; + } + } else if(mnonzero.isLogicalAnd() || mnonzero.isLogicalOr()) { + bool b_ret = false; + for(size_t i = 0; i < mnonzero.size(); i++) { + if(warn_test_interval(mnonzero[i], eo2)) b_ret = true; + } + if(b_ret) { + mnonzero.calculatesub(eo2, eo2, false); + return true; + } + } + return false; +} +bool warn_about_assumed_not_value(const MathStructure &mstruct, const MathStructure &mvalue, const EvaluationOptions &eo) { + CALCULATOR->beginTemporaryStopMessages(); + EvaluationOptions eo2 = eo; + eo2.assume_denominators_nonzero = false; + eo2.test_comparisons = true; + eo2.isolate_x = true; + eo2.expand = true; + eo2.approximation = APPROXIMATION_APPROXIMATE; + MathStructure mnonzero(mstruct); + mnonzero.add(mvalue, OPERATION_NOT_EQUALS); + mnonzero.eval(eo2); + warn_test_interval(mnonzero, eo2); + if(CALCULATOR->endTemporaryStopMessages()) return false; + if(mnonzero.isZero()) return false; + if(mnonzero.isOne()) return true; + if(mvalue.isZero() && mnonzero.isComparison() && mnonzero.comparisonType() == COMPARISON_NOT_EQUALS && mnonzero[1].isZero() && mnonzero[0].representsApproximatelyZero(true)) return false; + CALCULATOR->error(false, _("Required assumption: %s."), format_and_print(mnonzero).c_str(), NULL); + return true; +} +bool warn_about_denominators_assumed_nonzero(const MathStructure &mstruct, const EvaluationOptions &eo) { + CALCULATOR->beginTemporaryStopMessages(); + EvaluationOptions eo2 = eo; + eo2.assume_denominators_nonzero = false; + eo2.test_comparisons = true; + eo2.isolate_x = true; + eo2.expand = true; + eo2.approximation = APPROXIMATION_APPROXIMATE; + MathStructure mnonzero(mstruct); + mnonzero.add(m_zero, OPERATION_NOT_EQUALS); + mnonzero.eval(eo2); + warn_test_interval(mnonzero, eo2); + if(CALCULATOR->endTemporaryStopMessages()) return false; + if(mnonzero.isZero()) return false; + if(mnonzero.isOne()) return true; + if(mnonzero.isComparison() && mnonzero.comparisonType() == COMPARISON_NOT_EQUALS && mnonzero[1].isZero() && mnonzero[0].representsApproximatelyZero(true)) return false; + CALCULATOR->error(false, _("To avoid division by zero, the following must be true: %s."), format_and_print(mnonzero).c_str(), NULL); + return true; +} +bool warn_about_denominators_assumed_nonzero_or_positive(const MathStructure &mstruct, const MathStructure &mstruct2, const EvaluationOptions &eo) { + CALCULATOR->beginTemporaryStopMessages(); + EvaluationOptions eo2 = eo; + eo2.assume_denominators_nonzero = false; + eo2.test_comparisons = true; + eo2.isolate_x = true; + eo2.expand = true; + eo2.approximation = APPROXIMATION_APPROXIMATE; + MathStructure mnonzero(mstruct); + mnonzero.add(m_zero, OPERATION_NOT_EQUALS); + MathStructure *mpos = new MathStructure(mstruct2); + mpos->add(m_zero, OPERATION_EQUALS_GREATER); + mnonzero.add_nocopy(mpos, OPERATION_LOGICAL_OR); + mnonzero.eval(eo2); + warn_test_interval(mnonzero, eo2); + if(CALCULATOR->endTemporaryStopMessages()) return false; + if(mnonzero.isZero()) return false; + if(mnonzero.isOne()) return true; + if(mnonzero.isComparison() && mnonzero.comparisonType() == COMPARISON_NOT_EQUALS && mnonzero[1].isZero() && mnonzero[0].representsApproximatelyZero(true)) return false; + CALCULATOR->error(false, _("To avoid division by zero, the following must be true: %s."), format_and_print(mnonzero).c_str(), NULL); + return true; +} +bool warn_about_denominators_assumed_nonzero_llgg(const MathStructure &mstruct, const MathStructure &mstruct2, const MathStructure &mstruct3, const EvaluationOptions &eo) { + CALCULATOR->beginTemporaryStopMessages(); + EvaluationOptions eo2 = eo; + eo2.assume_denominators_nonzero = false; + eo2.test_comparisons = true; + eo2.isolate_x = true; + eo2.expand = true; + eo2.approximation = APPROXIMATION_APPROXIMATE; + MathStructure mnonzero(mstruct); + mnonzero.add(m_zero, OPERATION_NOT_EQUALS); + MathStructure *mpos = new MathStructure(mstruct2); + mpos->add(m_zero, OPERATION_EQUALS_GREATER); + MathStructure *mpos2 = new MathStructure(mstruct3); + mpos2->add(m_zero, OPERATION_EQUALS_GREATER); + mpos->add_nocopy(mpos2, OPERATION_LOGICAL_AND); + mnonzero.add_nocopy(mpos, OPERATION_LOGICAL_OR); + MathStructure *mneg = new MathStructure(mstruct2); + mneg->add(m_zero, OPERATION_LESS); + MathStructure *mneg2 = new MathStructure(mstruct3); + mneg2->add(m_zero, OPERATION_LESS); + mneg->add_nocopy(mneg2, OPERATION_LOGICAL_AND); + mnonzero.add_nocopy(mneg, OPERATION_LOGICAL_OR); + mnonzero.eval(eo2); + warn_test_interval(mnonzero, eo2); + if(CALCULATOR->endTemporaryStopMessages()) return false; + if(mnonzero.isZero()) return false; + if(mnonzero.isOne()) return true; + if(mnonzero.isComparison() && mnonzero.comparisonType() == COMPARISON_NOT_EQUALS && mnonzero[1].isZero() && mnonzero[0].representsApproximatelyZero(true)) return false; + CALCULATOR->error(false, _("To avoid division by zero, the following must be true: %s."), format_and_print(mnonzero).c_str(), NULL); + return true; +} + +int MathStructure::merge_addition(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool reversed) { + // test if two terms can be merged + if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { + // both terms are numbers try Number::add() (might never fail for infinite values) + Number nr(o_number); + if(nr.add(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate())) { + if(o_number == nr) { + o_number = nr; + numberUpdated(); + return 2; + } + o_number = nr; + numberUpdated(); + return 1; + } + return -1; + } + if(isZero()) { + // 0+a=a + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + if(mstruct.isZero()) { + // a+0=a + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + if(m_type == STRUCT_NUMBER && o_number.isInfinite()) { + if(mstruct.representsReal(false)) { + // infinity+a=infinity + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + } else if(mstruct.isNumber() && mstruct.number().isInfinite()) { + if(representsReal(false)) { + // a+infinity=infinity + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + clear(true); + o_number = mstruct.number(); + MERGE_APPROX_AND_PREC(mstruct) + } + return 3; + } + } + if(representsUndefined() || mstruct.representsUndefined()) return -1; + switch(m_type) { + case STRUCT_VECTOR: { + switch(mstruct.type()) { + case STRUCT_ADDITION: { + // try again with reversed order + return 0; + } + case STRUCT_VECTOR: { + if(SIZE == mstruct.size()) { + // [a1,a2,a3,...]+[b1,b2,b3,...]=[a1+b1,a2+b2,a3+b3,...] + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).calculateAdd(mstruct[i], eo, this, i); + } + MERGE_APPROX_AND_PREC(mstruct) + CHILDREN_UPDATED + return 1; + } + } + default: { + if(mstruct.representsScalar()) { + // [a1,a2,a3,...]+b=[a1+b,a2+b,a3+b,...] + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).calculateAdd(mstruct, eo, this, i); + } + CHILDREN_UPDATED + return 1; + } + return -1; + } + } + return -1; + } + case STRUCT_ADDITION: { + switch(mstruct.type()) { + case STRUCT_ADDITION: { + // (a1+a2+a3+...)+(b1+b2+b3+...)=a1+a2+a3+...+b1+b2+b3+... + for(size_t i = 0; i < mstruct.size(); i++) { + if(reversed) { + INSERT_REF(&mstruct[i], i) + calculateAddIndex(i, eo, false); + } else { + APPEND_REF(&mstruct[i]); + calculateAddLast(eo, false); + } + } + MERGE_APPROX_AND_PREC(mstruct) + if(SIZE == 1) { + setToChild(1, false, mparent, index_this + 1); + } else if(SIZE == 0) { + clear(true); + } else { + evalSort(); + } + return 1; + } + default: { + // (a1+a2+a3+...)+b=a1+a2+a3+...+b + MERGE_APPROX_AND_PREC(mstruct) + if(reversed) { + PREPEND_REF(&mstruct); + calculateAddIndex(0, eo, true, mparent, index_this); + } else { + APPEND_REF(&mstruct); + calculateAddLast(eo, true, mparent, index_this); + } + return 1; + } + } + break; + } + case STRUCT_MULTIPLICATION: { + switch(mstruct.type()) { + case STRUCT_VECTOR: {} + case STRUCT_ADDITION: { + // try again with reversed order + return 0; + } + case STRUCT_MULTIPLICATION: { + size_t i1 = 0, i2 = 0; + bool b = true; + if(CHILD(0).isNumber()) i1 = 1; + if(mstruct[0].isNumber()) i2 = 1; + if(SIZE - i1 == mstruct.size() - i2) { + for(size_t i = i1; i < SIZE; i++) { + if(CHILD(i) != mstruct[i + i2 - i1]) { + b = false; + break; + } + } + if(b) { + // ax+bx=(a+b)x, axy+xy=(a+1)xy, xy+xy=2xy (when a and b are numbers) + if(i1 == 0) { + PREPEND(m_one); + } + if(i2 == 0) { + CHILD(0).number()++; + } else { + if(!CHILD(0).number().add(mstruct[0].number())) return -1; + } + MERGE_APPROX_AND_PREC(mstruct) + calculateMultiplyIndex(0, eo, true, mparent, index_this); + return 1; + } + } + + for(size_t i2 = 0; i2 < SIZE; i2++) { + if(eo.transform_trigonometric_functions && CHILD(i2).isPower() && CHILD(i2)[0].isFunction() && (CHILD(i2)[0].function()->id() == FUNCTION_ID_COS || CHILD(i2)[0].function()->id() == FUNCTION_ID_SIN) && CHILD(i2)[0].size() == 1 && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isTwo() && mstruct.size() > 0) { + if(!FUNCTION_PROTECTED(eo, CHILD(i2)[0].function()->id() == FUNCTION_ID_SIN ? FUNCTION_ID_COS : FUNCTION_ID_SIN)) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isPower() && mstruct[i][0].isFunction() && mstruct[i][0].function()->id() == (CHILD(i2)[0].function()->id() == FUNCTION_ID_SIN ? FUNCTION_ID_COS : FUNCTION_ID_SIN) && mstruct[i][0].size() == 1 && mstruct[i][1].isNumber() && mstruct[i][1].number().isTwo() && CHILD(i2)[0][0] == mstruct[i][0][0]) { + // a*sin(x)^2+b*cos(x)^2=(a-b)*sin(x)^2+b + MathStructure madd1(*this); + MathStructure madd2(mstruct); + MathStructure madd; + madd1.delChild(i2 + 1, true); + madd2.delChild(i + 1, true); + if(CHILD(i2)[0].function()->id() == FUNCTION_ID_SIN) {madd = madd2; madd2.calculateNegate(eo);} + else {madd = madd1; madd1.calculateNegate(eo);} + if(madd1.calculateAdd(madd2, eo)) { + SET_CHILD_MAP(i2); + CHILD(0).setFunctionId(FUNCTION_ID_SIN); + calculateMultiply(madd1, eo); + EvaluationOptions eo2 = eo; + eo2.transform_trigonometric_functions = false; + calculateAdd(madd, eo2); + return 1; + } + } + } + } + if(eo.protected_function != CHILD(i2)[0].function()) { + // ay*sin(x)^2-ay=-ay*cos(x)^2, ay*cos(x)^2-ay=-ay*sin(x)^2 + bool b = false; + if(mstruct[0].isNumber()) { + if(CHILD(0).isNumber()) { + if(mstruct.size() == SIZE - 1 && CHILD(0).number() == -mstruct[0].number()) { + b = true; + for(size_t i = 1; i < mstruct.size(); i++) { + if(!mstruct[i].equals(CHILD(i2 > i ? i : i + 1))) {b = false; break;} + } + } + } else if(mstruct.size() == SIZE && mstruct[0].isMinusOne()) { + b = true; + for(size_t i = 1; i < mstruct.size(); i++) { + if(!mstruct[i].equals(CHILD(i2 >= i ? i - 1 : i))) {b = false; break;} + } + } + } else if(mstruct.size() == SIZE - 2 && CHILD(0).isMinusOne()) { + b = true; + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct[i].equals(CHILD(i2 - 1 >= i ? i + 1 : i + 2))) {b = false; break;} + } + } + if(b) { + CHILD(i2)[0].setFunctionId(CHILD(i2)[0].function()->id() == FUNCTION_ID_COS ? FUNCTION_ID_SIN : FUNCTION_ID_COS); + MERGE_APPROX_AND_PREC(mstruct) + calculateNegate(eo, mparent, index_this); + return 1; + } + } + } else if(eo.transform_trigonometric_functions && CHILD(i2).isPower() && CHILD(i2)[0].isFunction() && (CHILD(i2)[0].function()->id() == FUNCTION_ID_COSH || CHILD(i2)[0].function()->id() == FUNCTION_ID_SINH) && CHILD(i2)[0].size() == 1 && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isTwo() && mstruct.size() > 0) { + if(!FUNCTION_PROTECTED(eo, CHILD(i2)[0].function()->id() == FUNCTION_ID_SINH ? FUNCTION_ID_COSH : FUNCTION_ID_SINH)) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isPower() && mstruct[i][0].isFunction() && mstruct[i][0].function()->id() == (CHILD(i2)[0].function()->id() == FUNCTION_ID_SINH ? FUNCTION_ID_COSH : FUNCTION_ID_SINH) && mstruct[i][0].size() == 1 && mstruct[i][1].isNumber() && mstruct[i][1].number().isTwo() && CHILD(i2)[0][0] == mstruct[i][0][0]) { + // a*sinh(x)^2+b*cosh(x)^2=(a+b)*sinh(x)^2+b + MathStructure madd1(*this); + MathStructure madd2(mstruct); + MathStructure madd; + madd1.delChild(i2 + 1, true); + madd2.delChild(i + 1, true); + if(mstruct[i][0].function()->id() == FUNCTION_ID_SINH) madd = madd1; + else madd = madd2; + if(madd1.calculateAdd(madd2, eo)) { + SET_CHILD_MAP(i2); + CHILD(0).setFunctionId(FUNCTION_ID_SINH); + calculateMultiply(madd1, eo); + EvaluationOptions eo2 = eo; + eo2.transform_trigonometric_functions = false; + calculateAdd(madd, eo2); + return 1; + } + } + } + } + if(eo.protected_function != CHILD(i2)[0].function()) { + if(CHILD(i2)[0].function()->id() == FUNCTION_ID_SINH && mstruct.size() == SIZE - 1) { + // ay*sinh(x)^2+ay=ay*cosh(x)^2 + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct[i].equals(CHILD(i2 > i ? i : i + 1))) break; + if(i == mstruct.size() - 1) { + CHILD(i2)[0].setFunctionId(FUNCTION_ID_COSH); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } else if(CHILD(i2)[0].function()->id() == FUNCTION_ID_COSH) { + // ay*cosh(x)^2-ay=ay*sinh(x)^2 + bool b = false; + if(mstruct[0].isNumber()) { + if(CHILD(0).isNumber()) { + if(mstruct.size() == SIZE - 1 && CHILD(0).number() == -mstruct[0].number()) { + b = true; + for(size_t i = 1; i < mstruct.size(); i++) { + if(!mstruct[i].equals(CHILD(i2 > i ? i : i + 1))) {b = false; break;} + } + } + } else if(mstruct.size() == SIZE && mstruct[0].isMinusOne()) { + b = true; + for(size_t i = 1; i < mstruct.size(); i++) { + if(!mstruct[i].equals(CHILD(i2 >= i ? i - 1 : i))) {b = false; break;} + } + } + } else if(mstruct.size() == SIZE - 2 && CHILD(0).isMinusOne()) { + b = true; + for(size_t i = 1; i < mstruct.size(); i++) { + if(!mstruct[i].equals(CHILD(i2 - 1 >= i ? i + 1 : i + 2))) {b = false; break;} + } + } + if(b) { + CHILD(i2)[0].setFunctionId(FUNCTION_ID_SINH); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } + } else if(CHILD(i2).isFunction()) { + if(CHILD(i2).function()->id() == FUNCTION_ID_SIGNUM && !FUNCTION_PROTECTED(eo, FUNCTION_ID_SIGNUM) && CHILD(i2).size() == 2 && CHILD(i2)[0].isAddition() && CHILD(i2)[0].size() == 2 && CHILD(i2)[0].representsReal(true)) { + // x*sgn(x+y)+y*sgn(x+y)=abs(x+y) + for(size_t im = 0; im < mstruct.size(); im++) { + if(mstruct[im] == CHILD(i2)) { + MathStructure m1(*this), m2(mstruct); + m1.delChild(i2 + 1, true); + m2.delChild(im + 1, true); + if((m1 == CHILD(i2)[0][0] && m2 == CHILD(i2)[0][1]) || (m2 == CHILD(i2)[0][0] && m1 == CHILD(i2)[0][1])) { + SET_CHILD_MAP(i2) + setFunctionId(FUNCTION_ID_ABS); + ERASE(1) + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } + } else if(CHILD(i2).function()->id() == FUNCTION_ID_ASIN || CHILD(i2).function()->id() == FUNCTION_ID_ACOS) { + CHILD(i2).setFunctionId(CHILD(i2).function()->id() == FUNCTION_ID_ASIN ? FUNCTION_ID_ACOS : FUNCTION_ID_ASIN); + if(equals(mstruct) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_ASIN) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_ACOS)) { + // asin(x)+acos(x)=pi/2 + delChild(i2 + 1, true); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {calculateMultiply(Number(90, 1, 0), eo); break;} + case ANGLE_UNIT_GRADIANS: {calculateMultiply(Number(100, 1, 0), eo); break;} + case ANGLE_UNIT_RADIANS: {calculateMultiply(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo); calculateMultiply(nr_half, eo); break;} + default: {calculateMultiply(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo); calculateMultiply(nr_half, eo); if(CALCULATOR->getRadUnit()) {calculateMultiply(CALCULATOR->getRadUnit(), eo);} break;} + } + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + CHILD(i2).setFunctionId(CHILD(i2).function()->id() == FUNCTION_ID_ASIN ? FUNCTION_ID_ACOS : FUNCTION_ID_ASIN); + } else if(CHILD(i2).function()->id() == FUNCTION_ID_SINH || CHILD(i2).function()->id() == FUNCTION_ID_COSH) { + CHILD(i2).setFunctionId(CHILD(i2).function()->id() == FUNCTION_ID_SINH ? FUNCTION_ID_COSH : FUNCTION_ID_SINH); + if(equals(mstruct) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_SINH) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_COSH)) { + // sinh(x)+cosh(x)=e^x + MathStructure *mexp = &CHILD(i2)[0]; + mexp->ref(); + delChild(i2 + 1, true); + MathStructure *mmul = new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_E)); + mmul->raise_nocopy(mexp); + mmul->calculateRaiseExponent(eo); + MERGE_APPROX_AND_PREC(mstruct) + multiply_nocopy(mmul); + calculateMultiplyLast(eo, true, mparent, index_this); + return 1; + } + CHILD(i2).setFunctionId(CHILD(i2).function()->id() == FUNCTION_ID_SINH ? FUNCTION_ID_COSH : FUNCTION_ID_SINH); + } + } + } + + if(eo.transform_trigonometric_functions) { + for(size_t i2 = 0; i2 < mstruct.size(); i2++) { + if(mstruct[i2].isPower() && mstruct[i2][0].isFunction() && (mstruct[i2][0].function()->id() == FUNCTION_ID_COS || mstruct[i2][0].function()->id() == FUNCTION_ID_SIN) && mstruct[i2][0].size() == 1 && mstruct[i2][1].isNumber() && mstruct[i2][1].number().isTwo() && SIZE > 0) { + // ay*sin(x)^2-ay=-ay*cos(x)^2, ay*cos(x)^2-ay=-ay*sin(x)^2 + if(eo.protected_function != mstruct[i2][0].function()) { + bool b = false; + if(CHILD(0).isNumber()) { + if(mstruct[0].isNumber()) { + if(mstruct.size() - 1 == SIZE && CHILD(0).number() == -mstruct[0].number()) { + b = true; + for(size_t i = 1; i < SIZE; i++) { + if(!CHILD(i).equals(mstruct[i2 > i ? i : i + 1])) {b = false; break;} + } + } + } else if(mstruct.size() == SIZE && CHILD(0).isMinusOne()) { + b = true; + for(size_t i = 1; i < SIZE; i++) { + if(!CHILD(i).equals(mstruct[i2 >= i ? i - 1 : i])) {b = false; break;} + } + } + } else if(mstruct.size() - 2 == SIZE && mstruct[0].isMinusOne()) { + b = true; + for(size_t i = 0; i < SIZE; i++) { + if(!CHILD(i).equals(mstruct[i2 - 1 >= i ? i + 1 : i + 2])) {b = false; break;} + } + } + if(b) { + mstruct[i2][0].setFunctionId(mstruct[i2][0].function()->id() == FUNCTION_ID_COS ? FUNCTION_ID_SIN : FUNCTION_ID_COS); + mstruct.calculateNegate(eo); + if(mparent) mparent->swapChildren(index_this + 1, index_mstruct + 1); + else set_nocopy(mstruct, true); + return 1; + } + } + } else if(mstruct[i2].isPower() && mstruct[i2][0].isFunction() && (mstruct[i2][0].function()->id() == FUNCTION_ID_COSH || mstruct[i2][0].function()->id() == FUNCTION_ID_SINH) && mstruct[i2][0].size() == 1 && mstruct[i2][1].isNumber() && mstruct[i2][1].number().isTwo() && SIZE > 0) { + if(eo.protected_function != mstruct[i2][0].function()) { + if(mstruct[i2][0].function()->id() == FUNCTION_ID_SINH && mstruct.size() - 1 == SIZE) { + // ay*sinh(x)^2+ay=ay*cosh(x)^2 + for(size_t i = 0; i < SIZE; i++) { + if(!CHILD(i).equals(mstruct[i2 > i ? i : i + 1])) break; + if(i == SIZE - 1) { + mstruct[i2][0].setFunctionId(FUNCTION_ID_COSH); + if(mparent) mparent->swapChildren(index_this + 1, index_mstruct + 1); + else set_nocopy(mstruct, true); + return 1; + } + } + } else if(mstruct[i2][0].function()->id() == FUNCTION_ID_COSH) { + // ay*cosh(x)^2-ay=ay*sinh(x)^2 + bool b = false; + if(CHILD(0).isNumber()) { + if(mstruct[0].isNumber()) { + if(mstruct.size() - 1 == SIZE && CHILD(0).number() == -mstruct[0].number()) { + b = true; + for(size_t i = 1; i < SIZE; i++) { + if(!CHILD(i).equals(mstruct[i2 > i ? i : i + 1])) {b = false; break;} + } + } + } else if(mstruct.size() == SIZE && CHILD(0).isMinusOne()) { + b = true; + for(size_t i = 1; i < SIZE; i++) { + if(!CHILD(i).equals(mstruct[i2 >= i ? i - 1 : i])) {b = false; break;} + } + } + } else if(mstruct.size() - 2 == SIZE && mstruct[0].isMinusOne()) { + b = true; + for(size_t i = 1; i < SIZE; i++) { + if(!CHILD(i).equals(mstruct[i2 - 1 >= i ? i + 1 : i + 2])) {b = false; break;} + } + } + if(b) { + mstruct[i2][0].setFunctionId(FUNCTION_ID_SINH); + if(mparent) mparent->swapChildren(index_this + 1, index_mstruct + 1); + else set_nocopy(mstruct, true); + return 1; + } + } + } + } + } + } + + if(!eo.combine_divisions) break; + // y/x+z/x=(y+z)/x (eo.combine_divisions is not used anymore) + b = true; size_t divs = 0; + for(; b && i1 < SIZE; i1++) { + if(CHILD(i1).isPower() && CHILD(i1)[1].hasNegativeSign()) { + divs++; + b = false; + for(; i2 < mstruct.size(); i2++) { + if(mstruct[i2].isPower() && mstruct[i2][1].hasNegativeSign()) { + if(mstruct[i2] == CHILD(i1)) { + b = true; + } + i2++; + break; + } + } + } + } + if(b && divs > 0) { + for(; i2 < mstruct.size(); i2++) { + if(mstruct[i2].isPower() && mstruct[i2][1].hasNegativeSign()) { + b = false; + break; + } + } + } + if(b && divs > 0) { + if(SIZE - divs == 0) { + if(mstruct.size() - divs == 0) { + calculateMultiply(nr_two, eo); + } else if(mstruct.size() - divs == 1) { + PREPEND(m_one); + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct[i].isPower() || !mstruct[i][1].hasNegativeSign()) { + mstruct[i].ref(); + CHILD(0).add_nocopy(&mstruct[i], true); + CHILD(0).calculateAddLast(eo, true, this, 0); + break; + } + } + calculateMultiplyIndex(0, eo, true, mparent, index_this); + } else { + for(size_t i = 0; i < mstruct.size();) { + if(mstruct[i].isPower() && mstruct[i][1].hasNegativeSign()) { + mstruct.delChild(i + 1); + } else { + i++; + } + } + PREPEND(m_one); + mstruct.ref(); + CHILD(0).add_nocopy(&mstruct, true); + CHILD(0).calculateAddLast(eo, true, this, 0); + calculateMultiplyIndex(0, eo, true, mparent, index_this); + } + } else if(SIZE - divs == 1) { + size_t index = 0; + for(; index < SIZE; index++) { + if(!CHILD(index).isPower() || !CHILD(index)[1].hasNegativeSign()) { + break; + } + } + if(mstruct.size() - divs == 0) { + if(IS_REAL(CHILD(index))) { + CHILD(index).number()++; + } else { + CHILD(index).calculateAdd(m_one, eo, this, index); + } + calculateMultiplyIndex(index, eo, true, mparent, index_this); + } else if(mstruct.size() - divs == 1) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct[i].isPower() || !mstruct[i][1].hasNegativeSign()) { + mstruct[i].ref(); + CHILD(index).add_nocopy(&mstruct[i], true); + CHILD(index).calculateAddLast(eo, true, this, index); + break; + } + } + calculateMultiplyIndex(index, eo, true, mparent, index_this); + } else { + for(size_t i = 0; i < mstruct.size();) { + if(mstruct[i].isPower() && mstruct[i][1].hasNegativeSign()) { + mstruct.delChild(i + 1); + } else { + i++; + } + } + mstruct.ref(); + CHILD(index).add_nocopy(&mstruct, true); + CHILD(index).calculateAddLast(eo, true, this, index); + calculateMultiplyIndex(index, eo, true, mparent, index_this); + } + } else { + for(size_t i = 0; i < SIZE;) { + if(CHILD(i).isPower() && CHILD(i)[1].hasNegativeSign()) { + ERASE(i); + } else { + i++; + } + } + if(mstruct.size() - divs == 0) { + calculateAdd(m_one, eo); + } else if(mstruct.size() - divs == 1) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct[i].isPower() || !mstruct[i][1].hasNegativeSign()) { + mstruct[i].ref(); + add_nocopy(&mstruct[i], true); + calculateAddLast(eo); + break; + } + } + } else { + MathStructure *mstruct2 = new MathStructure(); + mstruct2->setType(STRUCT_MULTIPLICATION); + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct[i].isPower() || !mstruct[i][1].hasNegativeSign()) { + mstruct[i].ref(); + mstruct2->addChild_nocopy(&mstruct[i]); + } + } + add_nocopy(mstruct2, true); + calculateAddLast(eo, true, mparent, index_this); + } + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isPower() && mstruct[i][1].hasNegativeSign()) { + mstruct[i].ref(); + multiply_nocopy(&mstruct[i], true); + calculateMultiplyLast(eo); + } + } + } + return 1; + } + + break; + } + case STRUCT_POWER: { + if(eo.combine_divisions && mstruct[1].hasNegativeSign()) { + // y/x+1/x=(y+1)/x (eo.combine_divisions is not used anymore) + bool b = false; + size_t index = 0; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isPower() && CHILD(i)[1].hasNegativeSign()) { + if(b) { + b = false; + break; + } + if(mstruct == CHILD(i)) { + index = i; + b = true; + } + if(!b) break; + } + } + if(b) { + if(SIZE == 2) { + if(index == 0) setToChild(2, true); + else setToChild(1, true); + } else { + ERASE(index); + } + calculateAdd(m_one, eo); + mstruct.ref(); + multiply_nocopy(&mstruct, false); + calculateMultiplyLast(eo, true, mparent, index_this); + return 1; + } + } + if(eo.transform_trigonometric_functions && SIZE == 2 && CHILD(0).isNumber() && mstruct[0].isFunction()) { + if((mstruct[0].function()->id() == FUNCTION_ID_COS || mstruct[0].function()->id() == FUNCTION_ID_SIN) && !FUNCTION_PROTECTED(eo, mstruct[0].function()->id() == FUNCTION_ID_SIN ? FUNCTION_ID_COS : FUNCTION_ID_SIN) && mstruct[0].size() == 1 && mstruct[1].isNumber() && mstruct[1].number().isTwo()) { + if(CHILD(1).isPower() && CHILD(1)[0].isFunction() && CHILD(1)[0].function()->id() == (mstruct[0].function()->id() == FUNCTION_ID_SIN ? FUNCTION_ID_COS : FUNCTION_ID_SIN) && CHILD(1)[0].size() == 1 && CHILD(1)[1].isNumber() && CHILD(1)[1].number().isTwo() && mstruct[0][0] == CHILD(1)[0][0]) { + // a*sin(x)^2+cos(x)^2=1+(a-1)*sin(x), a*cos(x)^2+sin(x)^2=1+(a-1)*cos(x) + if(CHILD(0).calculateSubtract(m_one, eo)) { + add(m_one); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } else if((mstruct[0].function()->id() == FUNCTION_ID_COSH || mstruct[0].function()->id() == FUNCTION_ID_SINH) && !FUNCTION_PROTECTED(eo, mstruct[0].function()->id() == FUNCTION_ID_SINH ? FUNCTION_ID_COSH : FUNCTION_ID_SINH) && mstruct[0].size() == 1 && mstruct[1].isNumber() && mstruct[1].number().isTwo()) { + if(CHILD(1).isPower() && CHILD(1)[0].isFunction() && CHILD(1)[0].function()->id() == (mstruct[0].function()->id() == FUNCTION_ID_SINH ? FUNCTION_ID_COSH : FUNCTION_ID_SINH) && CHILD(1)[0].size() == 1 && CHILD(1)[1].isNumber() && CHILD(1)[1].number().isTwo() && mstruct[0][0] == CHILD(1)[0][0]) { + // a*sinh(x)^2+cosh(x)^2=1+(a+1)*sinh(x), a*cosh(x)^2+sinh(x)^2=(a+1)*cosh(x)-1 + if(CHILD(0).calculateAdd(m_one, eo)) { + add(CHILD(1)[0].function()->id() == FUNCTION_ID_SINH ? m_one : m_minus_one); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } + } + } + default: { + if(SIZE == 2 && CHILD(0).isNumber() && CHILD(1) == mstruct) { + // ax+x=(a+1)x + CHILD(0).number()++; + MERGE_APPROX_AND_PREC(mstruct) + calculateMultiplyIndex(0, eo, true, mparent, index_this); + return 1; + } + if(eo.transform_trigonometric_functions && SIZE == 2 && CHILD(1).isPower() && CHILD(1)[0].isFunction() && CHILD(1)[0].function() != eo.protected_function && CHILD(1)[1] == nr_two && CHILD(1)[0].size() == 1) { + if(mstruct.isNumber() && CHILD(0).isNumber()) { + if(CHILD(1)[0].function()->id() == FUNCTION_ID_SIN && mstruct.number() == -CHILD(0).number()) { + // a*sin(x)^2-a=a*cos(x)^2 + CHILD(1)[0].setFunctionId(FUNCTION_ID_COS); + MERGE_APPROX_AND_PREC(mstruct) + calculateNegate(eo, mparent, index_this); + return 1; + } else if(CHILD(1)[0].function()->id() == FUNCTION_ID_COS && mstruct.number() == -CHILD(0).number()) { + // a*cos(x)^2-a=a*sin(x)^2 + CHILD(1)[0].setFunctionId(FUNCTION_ID_SIN); + MERGE_APPROX_AND_PREC(mstruct) + calculateNegate(eo, mparent, index_this); + return 1; + } else if(CHILD(1)[0].function()->id() == FUNCTION_ID_COSH && mstruct.number() == -CHILD(0).number()) { + // a*cosh(x)^2-a=a*sinh(x)^2 + MERGE_APPROX_AND_PREC(mstruct) + CHILD(1)[0].setFunctionId(FUNCTION_ID_SINH); + return 1; + } else if(CHILD(1)[0].function()->id() == FUNCTION_ID_SINH && mstruct == CHILD(0)) { + // a*sinh(x)^2+a=a*cosh(x)^2 + CHILD(1)[0].setFunctionId(FUNCTION_ID_COSH); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } else if(eo.transform_trigonometric_functions && SIZE == 3 && CHILD(0).isMinusOne()) { + size_t i = 0; + if(CHILD(1).isPower() && CHILD(1)[0].isFunction() && (CHILD(1)[0].function()->id() == FUNCTION_ID_SIN || CHILD(1)[0].function()->id() == FUNCTION_ID_COS || CHILD(1)[0].function()->id() == FUNCTION_ID_COSH) && CHILD(1)[0].function() != eo.protected_function && CHILD(1)[1] == nr_two && CHILD(1)[0].size() == 1 && CHILD(2) == mstruct) i = 1; + if(CHILD(2).isPower() && CHILD(2)[0].isFunction() && (CHILD(2)[0].function()->id() == FUNCTION_ID_SIN || CHILD(2)[0].function()->id() == FUNCTION_ID_COS || CHILD(2)[0].function()->id() == FUNCTION_ID_COSH) && CHILD(2)[0].function() != eo.protected_function && CHILD(2)[1] == nr_two && CHILD(2)[0].size() == 1 && CHILD(1) == mstruct) i = 2; + if(i > 0) { + if(CHILD(i)[0].function()->id() == FUNCTION_ID_SIN) { + // -y*sin(x)^2+y=y*cos(x)^2 + CHILD(i)[0].setFunctionId(FUNCTION_ID_COS); + MERGE_APPROX_AND_PREC(mstruct) + calculateNegate(eo, mparent, index_this); + return 1; + } else if(CHILD(i)[0].function()->id() == FUNCTION_ID_COS) { + // -y*cos(x)^2+y=y*sin(x)^2 + CHILD(i)[0].setFunctionId(FUNCTION_ID_SIN); + MERGE_APPROX_AND_PREC(mstruct) + calculateNegate(eo, mparent, index_this); + return 1; + } else if(CHILD(i)[0].function()->id() == FUNCTION_ID_COSH) { + // -y*cosh(x)^2+y=y*sinh(x)^2 + MERGE_APPROX_AND_PREC(mstruct) + CHILD(i)[0].setFunctionId(FUNCTION_ID_SINH); + return 1; + } + } + } + if(mstruct.isDateTime() || (mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_SIGNUM && !FUNCTION_PROTECTED(eo, FUNCTION_ID_SIGNUM))) { + // try again with reversed order + return 0; + } + } + } + break; + } + case STRUCT_POWER: { + if(CHILD(0).isFunction() && (CHILD(0).function()->id() == FUNCTION_ID_COS || CHILD(0).function()->id() == FUNCTION_ID_SIN) && eo.protected_function != CHILD(0).function() && CHILD(0).size() == 1 && CHILD(1).isNumber() && CHILD(1).number().isTwo()) { + if(eo.transform_trigonometric_functions && mstruct.isMinusOne()) { + // sin(x)^2-1=-cos(x)^2, cos(x)^2-1=-sin(x)^2 + CHILD(0).setFunctionId(CHILD(0).function()->id() == FUNCTION_ID_SIN ? FUNCTION_ID_COS : FUNCTION_ID_SIN); + negate(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mstruct.isPower() && mstruct[0].isFunction() && mstruct[0].function()->id() == (CHILD(0).function()->id() == FUNCTION_ID_SIN ? FUNCTION_ID_COS : FUNCTION_ID_SIN) && eo.protected_function != mstruct[0].function() && mstruct[0].size() == 1 && mstruct[1].isNumber() && mstruct[1].number().isTwo() && CHILD(0)[0] == mstruct[0][0]) { + // cos(x)^2+sin(x)^2=1 + set(1, 1, 0, true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(eo.transform_trigonometric_functions && CHILD(0).isFunction() && (CHILD(0).function()->id() == FUNCTION_ID_COSH || CHILD(0).function()->id() == FUNCTION_ID_SINH) && eo.protected_function != CHILD(0).function() && CHILD(0).size() == 1 && CHILD(1).isNumber() && CHILD(1).number().isTwo()) { + if(CHILD(0).function()->id() == FUNCTION_ID_SINH && mstruct.isOne()) { + // sinh(x)^2+1=cosh(x)^2 + CHILD(0).setFunctionId(FUNCTION_ID_COSH); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(CHILD(0).function()->id() == FUNCTION_ID_COSH && mstruct.isMinusOne()) { + // cosh(x)^2-1=sinh(x)^2 + CHILD(0).setFunctionId(FUNCTION_ID_SINH); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mstruct.isPower() && mstruct[0].isFunction() && mstruct[0].function()->id() == (CHILD(0).function()->id() == FUNCTION_ID_SINH ? FUNCTION_ID_COSH : FUNCTION_ID_SINH) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_COSH) && mstruct[0].size() == 1 && mstruct[1].isNumber() && mstruct[1].number().isTwo() && CHILD(0)[0] == mstruct[0][0]) { + // sinh(x)^2+cosh(x)^2=2*sinh(x)^2+1 + CHILD(0).setFunctionId(FUNCTION_ID_SINH); + multiply(nr_two); + add(m_one); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + goto default_addition_merge; + } + case STRUCT_FUNCTION: { + if(o_function->id() == FUNCTION_ID_SIGNUM && mstruct.isMultiplication() && !FUNCTION_PROTECTED(eo, FUNCTION_ID_SIGNUM)) { + if((SIZE == 1 || SIZE == 2) && CHILD(0).isAddition() && CHILD(0).size() == 2 && (CHILD(0)[0].isOne() || CHILD(0)[1].isOne()) && CHILD(0).representsReal(true)) { + // sgn(x+1)+sgn(x+1)x=abs(x+1) + for(size_t im = 0; im < mstruct.size(); im++) { + if(mstruct[im] == *this) { + MathStructure *mchild = &mstruct[im]; + mchild->ref(); + mstruct.delChild(im + 1); + if((mstruct.size() == 1 && mstruct[0] == CHILD(0)[CHILD(0)[0].isOne() ? 1 : 0]) || (mstruct.size() > 1 && mstruct == CHILD(0)[CHILD(0)[0].isOne() ? 1 : 0])) { + mchild->unref(); + setFunctionId(FUNCTION_ID_ABS); + if(SIZE == 2) {ERASE(1);} + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + mstruct.insertChild_nocopy(mchild, im + 1); + } + } + } + } else if(mstruct.isFunction() && ((o_function->id() == FUNCTION_ID_ASIN && mstruct.function()->id() == FUNCTION_ID_ACOS) || (o_function->id() == FUNCTION_ID_ACOS && mstruct.function()->id() == FUNCTION_ID_ASIN)) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_ACOS) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_ASIN) && SIZE == 1 && mstruct.size() == 1 && CHILD(0) == mstruct[0]) { + // asin(x)+acos(x)=pi/2 + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {set(90, 1, 0, true); break;} + case ANGLE_UNIT_GRADIANS: {set(100, 1, 0, true); break;} + case ANGLE_UNIT_RADIANS: {set(CALCULATOR->getVariableById(VARIABLE_ID_PI), true); multiply(nr_half); calculatesub(eo, eo, true); break;} + default: {set(CALCULATOR->getVariableById(VARIABLE_ID_PI), true); multiply(nr_half); if(CALCULATOR->getRadUnit()) {multiply(CALCULATOR->getRadUnit(), true);} calculatesub(eo, eo, true); break;} + } + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mstruct.isFunction() && ((o_function->id() == FUNCTION_ID_SINH && mstruct.function()->id() == FUNCTION_ID_COSH) || (o_function->id() == FUNCTION_ID_COSH && mstruct.function()->id() == FUNCTION_ID_SINH)) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_COSH) && !FUNCTION_PROTECTED(eo, FUNCTION_ID_SINH) && SIZE == 1 && mstruct.size() == 1 && CHILD(0) == mstruct[0]) { + // sinh(x)+cosh(x)=e^x + MathStructure *mexp = &CHILD(0); + mexp->ref(); + set(CALCULATOR->getVariableById(VARIABLE_ID_E), true); + calculatesub(eo, eo, true); + raise_nocopy(mexp); + MERGE_APPROX_AND_PREC(mstruct) + calculateRaiseExponent(eo, mparent, index_this); + return 1; + } else if(mstruct.isFunction() && o_function->id() == FUNCTION_ID_STRIP_UNITS && mstruct.function()->id() == FUNCTION_ID_STRIP_UNITS && mstruct.size() == 1 && SIZE == 1) { + // nounit(x)+nounit(y)=nounit(x+y) + mstruct[0].ref(); + CHILD(0).add_nocopy(&mstruct[0]); + return 1; + } + goto default_addition_merge; + } + case STRUCT_DATETIME: { + if(mstruct.isDateTime()) { + // date/time + date/time + if(o_datetime->add(*mstruct.datetime())) { + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isMinusOne() && mstruct[1].isDateTime() && (CALCULATOR->getUnitById(UNIT_ID_SECOND) || CALCULATOR->getUnitById(UNIT_ID_DAY))) { + if(CALCULATOR->getUnitById(UNIT_ID_DAY) && !mstruct[1].datetime()->timeIsSet() && !o_datetime->timeIsSet()) { + // date1 - date2 = date2.daysTo(date1) + Number ndays = mstruct[1].datetime()->daysTo(*o_datetime); + set(ndays, true); + multiply(CALCULATOR->getUnitById(UNIT_ID_DAY)); + } else { + // time1 - time2 = time2.secondsTo(time1) + Number nsecs = mstruct[1].datetime()->secondsTo(*o_datetime, true); + set(nsecs, true); + multiply(CALCULATOR->getUnitById(UNIT_ID_SECOND), true); + } + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(CALCULATOR->getUnitById(UNIT_ID_SECOND) && ((mstruct.isUnit() && mstruct.unit()->baseUnit() == CALCULATOR->getUnitById(UNIT_ID_SECOND) && mstruct.unit()->baseExponent() == 1 && !mstruct.unit()->hasNonlinearRelationTo(CALCULATOR->getUnitById(UNIT_ID_SECOND))) || (mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[0].number().isReal() && !mstruct[0].number().isInterval() && mstruct[1].isUnit() && mstruct[1].unit()->baseUnit() == CALCULATOR->getUnitById(UNIT_ID_SECOND) && mstruct[1].unit()->baseExponent() == 1 && !mstruct[1].unit()->hasNonlinearRelationTo(CALCULATOR->getUnitById(UNIT_ID_SECOND))))) { + MathStructure mmul(1, 1, 0); + Unit *u; + if(mstruct.isMultiplication()) { + mmul = mstruct[0]; + u = mstruct[1].unit(); + } else { + u = mstruct.unit(); + } + if(CALCULATOR->getUnitById(UNIT_ID_MONTH) && u != CALCULATOR->getUnitById(UNIT_ID_YEAR) && (u == CALCULATOR->getUnitById(UNIT_ID_MONTH) || u->isChildOf(CALCULATOR->getUnitById(UNIT_ID_MONTH)))) { + // date + a*month + if(u != CALCULATOR->getUnitById(UNIT_ID_MONTH)) { + CALCULATOR->getUnitById(UNIT_ID_MONTH)->convert(u, mmul); + mmul.eval(eo); + } + if(mmul.isNumber() && o_datetime->addMonths(mmul.number())) { + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(CALCULATOR->getUnitById(UNIT_ID_YEAR) && (u == CALCULATOR->getUnitById(UNIT_ID_YEAR) || u->isChildOf(CALCULATOR->getUnitById(UNIT_ID_YEAR)))) { + // date + a*year + if(u != CALCULATOR->getUnitById(UNIT_ID_YEAR)) { + CALCULATOR->getUnitById(UNIT_ID_YEAR)->convert(u, mmul); + mmul.eval(eo); + } + if(mmul.isNumber() && o_datetime->addYears(mmul.number())) { + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(CALCULATOR->getUnitById(UNIT_ID_DAY) && (u == CALCULATOR->getUnitById(UNIT_ID_DAY) || u->isChildOf(CALCULATOR->getUnitById(UNIT_ID_DAY)))) { + // date + a*day + if(u != CALCULATOR->getUnitById(UNIT_ID_DAY)) { + CALCULATOR->getUnitById(UNIT_ID_DAY)->convert(u, mmul); + mmul.eval(eo); + } + if(mmul.isNumber() && o_datetime->addDays(mmul.number())) { + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(CALCULATOR->getUnitById(UNIT_ID_HOUR) && (u == CALCULATOR->getUnitById(UNIT_ID_HOUR) || u->isChildOf(CALCULATOR->getUnitById(UNIT_ID_HOUR)))) { + // date + a*hour + if(u != CALCULATOR->getUnitById(UNIT_ID_HOUR)) { + CALCULATOR->getUnitById(UNIT_ID_HOUR)->convert(u, mmul); + mmul.eval(eo); + } + if(mmul.isNumber() && o_datetime->addHours(mmul.number())) { + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(CALCULATOR->getUnitById(UNIT_ID_MINUTE) && (u == CALCULATOR->getUnitById(UNIT_ID_MINUTE) || u->isChildOf(CALCULATOR->getUnitById(UNIT_ID_MINUTE)))) { + // date + a*minute + if(u != CALCULATOR->getUnitById(UNIT_ID_MINUTE)) { + CALCULATOR->getUnitById(UNIT_ID_MINUTE)->convert(u, mmul); + mmul.eval(eo); + } + if(mmul.isNumber() && o_datetime->addMinutes(mmul.number())) { + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else { + // date + a*second + MathStructure mmulb(mmul); + if(u != CALCULATOR->getUnitById(UNIT_ID_SECOND)) { + u->convertToBaseUnit(mmul); + mmul.eval(eo); + } + if(mmul.isNumber() && o_datetime->addSeconds(mmul.number(), true)) { + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } + } + default: { + default_addition_merge: + switch(mstruct.type()) { + case STRUCT_VECTOR: {} + case STRUCT_DATETIME: {} + case STRUCT_ADDITION: {} + case STRUCT_MULTIPLICATION: { + // try again with reversed order + return 0; + } + default: { + if(equals(mstruct)) { + // x+x=2x + multiply_nocopy(new MathStructure(2, 1, 0), true); + MERGE_APPROX_AND_PREC(mstruct) + calculateMultiplyLast(eo, true, mparent, index_this); + return 1; + } + } + } + } + } + return -1; +} + +bool reducable(const MathStructure &mnum, const MathStructure &mden, Number &nr) { + switch(mnum.type()) { + case STRUCT_NUMBER: {} + case STRUCT_ADDITION: { + break; + } + default: { + bool reduce = true; + for(size_t i = 0; i < mden.size() && reduce; i++) { + switch(mden[i].type()) { + case STRUCT_MULTIPLICATION: { + reduce = false; + for(size_t i2 = 0; i2 < mden[i].size(); i2++) { + if(mnum == mden[i][i2]) { + reduce = true; + if(!nr.isOne() && !nr.isFraction()) nr.set(1, 1, 0); + break; + } else if(mden[i][i2].isPower() && mden[i][i2][1].isNumber() && mden[i][i2][1].number().isReal() && mnum == mden[i][i2][0]) { + if(!mden[i][i2][1].number().isPositive()) { + break; + } + if(mden[i][i2][1].number().isLessThan(nr)) nr = mden[i][i2][1].number(); + reduce = true; + break; + } + } + break; + } + case STRUCT_POWER: { + if(mden[i][1].isNumber() && mden[i][1].number().isReal() && mnum == mden[i][0]) { + if(!mden[i][1].number().isPositive()) { + reduce = false; + break; + } + if(mden[i][1].number().isLessThan(nr)) nr = mden[i][1].number(); + break; + } + } + default: { + if(mnum != mden[i]) { + reduce = false; + break; + } + if(!nr.isOne() && !nr.isFraction()) nr.set(1, 1, 0); + } + } + } + return reduce; + } + } + return false; +} +void reduce(const MathStructure &mnum, MathStructure &mden, Number &nr, const EvaluationOptions &eo) { + switch(mnum.type()) { + case STRUCT_NUMBER: {} + case STRUCT_ADDITION: { + break; + } + default: { + for(size_t i = 0; i < mden.size(); i++) { + switch(mden[i].type()) { + case STRUCT_MULTIPLICATION: { + for(size_t i2 = 0; i2 < mden[i].size(); i2++) { + if(mden[i][i2] == mnum) { + if(!nr.isOne()) { + MathStructure *mexp = new MathStructure(1, 1, 0); + mexp->number() -= nr; + mden[i][i2].raise_nocopy(mexp); + mden[i][i2].calculateRaiseExponent(eo); + if(mden[i][i2].isOne() && mden[i].size() > 1) { + mden[i].delChild(i2 + 1); + if(mden[i].size() == 1) { + mden[i].setToChild(1, true, &mden, i + 1); + } + } + } else { + if(mden[i].size() == 1) { + mden[i].set(m_one); + } else { + mden[i].delChild(i2 + 1); + if(mden[i].size() == 1) { + mden[i].setToChild(1, true, &mden, i + 1); + } + } + } + break; + } else if(mden[i][i2].isPower() && mden[i][i2][1].isNumber() && mden[i][i2][1].number().isReal() && mnum.equals(mden[i][i2][0])) { + mden[i][i2][1].number() -= nr; + if(mden[i][i2][1].number().isOne()) { + mden[i][i2].setToChild(1, true, &mden[i], i2 + 1); + } else { + mden[i][i2].calculateRaiseExponent(eo); + if(mden[i][i2].isOne() && mden[i].size() > 1) { + mden[i].delChild(i2 + 1); + if(mden[i].size() == 1) { + mden[i].setToChild(1, true, &mden, i + 1); + } + } + } + break; + } + } + break; + } + case STRUCT_POWER: { + if(mden[i][1].isNumber() && mden[i][1].number().isReal() && mnum.equals(mden[i][0])) { + mden[i][1].number() -= nr; + if(mden[i][1].number().isOne()) { + mden[i].setToChild(1, true, &mden, i + 1); + } else { + mden[i].calculateRaiseExponent(eo, &mden, i); + } + break; + } + } + default: { + if(!nr.isOne()) { + MathStructure *mexp = new MathStructure(1, 1, 0); + mexp->number() -= nr; + mden[i].raise_nocopy(mexp); + mden[i].calculateRaiseExponent(eo, &mden, 1); + } else { + mden[i].set(m_one); + } + } + } + } + mden.calculatesub(eo, eo, false); + } + } +} + +bool addablePower(const MathStructure &mstruct, const EvaluationOptions &eo) { + if(mstruct[0].representsNonNegative(true)) return true; + if(mstruct[1].representsInteger()) return true; + //return eo.allow_complex && mstruct[0].representsNegative(true) && mstruct[1].isNumber() && mstruct[1].number().isRational() && mstruct[1].number().denominatorIsEven(); + return eo.allow_complex && mstruct[1].isNumber() && mstruct[1].number().isRational() && mstruct[1].number().denominatorIsEven(); +} + +int MathStructure::merge_multiplication(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool reversed, bool do_append) { + // test if two factors can be merged + if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { + // both factors are numbers try Number::multiply() (might never fail for infinite values) + Number nr(o_number); + if(nr.multiply(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) { + if(o_number == nr) { + o_number = nr; + numberUpdated(); + return 2; + } + o_number = nr; + numberUpdated(); + return 1; + } + return -1; + } + if(mstruct.isOne()) { + // x*1=x + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } else if(isOne()) { + // 1*x=x + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + if(m_type == STRUCT_NUMBER && o_number.isInfinite()) { + if(o_number.isMinusInfinity(false)) { + if(mstruct.representsPositive(false)) { + // (-infinity)*x=-infinity if x is positive + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } else if(mstruct.representsNegative(false)) { + // (-infinity)*x=infinity if x is negative + o_number.setPlusInfinity(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(o_number.isPlusInfinity(false)) { + if(mstruct.representsPositive(false)) { + // infinity*x=infinity if x is negative + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } else if(mstruct.representsNegative(false)) { + // infinity*x=-infinity if x is negative + o_number.setMinusInfinity(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + if(eo.approximation == APPROXIMATION_EXACT) { + // test approximate value + MathStructure mtest(mstruct); + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(CALCULATOR->usesIntervalArithmetic()) { + CALCULATOR->beginTemporaryStopMessages(); + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + if(eo2.interval_calculation == INTERVAL_CALCULATION_NONE) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; + mtest.calculateFunctions(eo2); + mtest.calculatesub(eo2, eo2); + CALCULATOR->endTemporaryStopMessages(); + } + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + if(o_number.isMinusInfinity(false)) { + if(mtest.representsPositive(false)) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } else if(mtest.representsNegative(false)) { + o_number.setPlusInfinity(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(o_number.isPlusInfinity(false)) { + if(mtest.representsPositive(false)) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } else if(mtest.representsNegative(false)) { + o_number.setMinusInfinity(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } + } else if(mstruct.isNumber() && mstruct.number().isInfinite()) { + if(mstruct.number().isMinusInfinity(false)) { + if(representsPositive(false)) { + // x*(-infinity)=-infinity if x is positive + clear(true); + o_number.setMinusInfinity(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(representsNegative(false)) { + // x*(-infinity)=infinity if x is negative + clear(true); + o_number.setPlusInfinity(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(mstruct.number().isPlusInfinity(false)) { + if(representsPositive(false)) { + // x*infinity=infinity if x is positive + clear(true); + o_number.setPlusInfinity(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(representsNegative(false)) { + // x*infinity=-infinity if x is negative + clear(true); + o_number.setMinusInfinity(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + if(eo.approximation == APPROXIMATION_EXACT) { + // test approximate value + MathStructure mtest(*this); + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(CALCULATOR->usesIntervalArithmetic()) { + CALCULATOR->beginTemporaryStopMessages(); + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + if(eo2.interval_calculation == INTERVAL_CALCULATION_NONE) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; + mtest.calculateFunctions(eo2); + mtest.calculatesub(eo2, eo2); + CALCULATOR->endTemporaryStopMessages(); + } + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + if(mstruct.number().isMinusInfinity(false)) { + if(mtest.representsPositive(false)) { + clear(true); + o_number.setMinusInfinity(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mtest.representsNegative(false)) { + clear(true); + o_number.setPlusInfinity(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(mstruct.number().isPlusInfinity(false)) { + if(mtest.representsPositive(false)) { + clear(true); + o_number.setPlusInfinity(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mtest.representsNegative(false)) { + clear(true); + o_number.setMinusInfinity(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } + } + + if(representsUndefined() || mstruct.representsUndefined()) return -1; + + // check if factors are numerator and denominator, and denominator is polynomial + const MathStructure *mnum = NULL, *mden = NULL; + bool b_nonzero = false; + if(eo.reduce_divisions) { + if(!isNumber() && mstruct.isPower() && mstruct[0].isAddition() && mstruct[0].size() > 1 && mstruct[1].isNumber() && mstruct[1].number().isMinusOne()) { + // second factor is denominator (exponent = -1) + if((!isPower() || !CHILD(1).hasNegativeSign()) && representsNumber() && mstruct[0].representsNumber()) { + if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !mstruct[0].representsZero(true)) || mstruct[0].representsNonZero(true)) { + // denominator is not zero + b_nonzero = true; + } + if(b_nonzero || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !mstruct[0].representsZero(true))) { + mnum = this; + mden = &mstruct[0]; + } + } + } else if(!mstruct.isNumber() && isPower() && CHILD(0).isAddition() && CHILD(0).size() > 1 && CHILD(1).isNumber() && CHILD(1).number().isMinusOne()) { + // first factor is denominator (exponent = -1) + if((!mstruct.isPower() || !mstruct[1].hasNegativeSign()) && mstruct.representsNumber() && CHILD(0).representsNumber()) { + if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true)) || CHILD(0).representsNonZero(true)) { + // denominator is not zero + b_nonzero = true; + } + if(b_nonzero || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true))) { + mnum = &mstruct; + mden = &CHILD(0); + } + } + } + } + + // look for common factors in numerator and denominator + if(mnum && mden && eo.reduce_divisions) { + switch(mnum->type()) { + case STRUCT_ADDITION: { + // polynomial division is not handled here + break; + } + case STRUCT_MULTIPLICATION: { + Number nr; + vector nrs; + vector reducables; + for(size_t i = 0; i < mnum->size(); i++) { + switch((*mnum)[i].type()) { + case STRUCT_ADDITION: {break;} + case STRUCT_POWER: { + if((*mnum)[i][1].isNumber() && (*mnum)[i][1].number().isReal()) { + if((*mnum)[i][1].number().isPositive()) { + nr.set((*mnum)[i][1].number()); + if(reducable((*mnum)[i][0], *mden, nr)) { + nrs.push_back(nr); + reducables.push_back(i); + } + } + break; + } + } + default: { + nr.set(1, 1, 0); + if(reducable((*mnum)[i], *mden, nr)) { + nrs.push_back(nr); + reducables.push_back(i); + } + } + } + } + if(reducables.size() > 0) { + if(!b_nonzero && eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(*mden, eo)) break; + if(mnum == this) { + mstruct.ref(); + transform_nocopy(STRUCT_MULTIPLICATION, &mstruct); + } else { + transform(STRUCT_MULTIPLICATION); + PREPEND_REF(&mstruct); + } + size_t i_erased = 0; + for(size_t i = 0; i < reducables.size(); i++) { + switch(CHILD(0)[reducables[i] - i_erased].type()) { + case STRUCT_POWER: { + if(CHILD(0)[reducables[i] - i_erased][1].isNumber() && CHILD(0)[reducables[i] - i_erased][1].number().isReal()) { + reduce(CHILD(0)[reducables[i] - i_erased][0], CHILD(1)[0], nrs[i], eo); + if(nrs[i] == CHILD(0)[reducables[i] - i_erased][1].number()) { + CHILD(0).delChild(reducables[i] - i_erased + 1); + i_erased++; + } else { + CHILD(0)[reducables[i] - i_erased][1].number() -= nrs[i]; + if(CHILD(0)[reducables[i] - i_erased][1].number().isOne()) { + CHILD(0)[reducables[i] - i_erased].setToChild(1, true, &CHILD(0), reducables[i] - i_erased + 1); + } else { + CHILD(0)[reducables[i] - i_erased].calculateRaiseExponent(eo); + } + CHILD(0).calculateMultiplyIndex(reducables[i] - i_erased, eo, true); + } + break; + } + } + default: { + reduce(CHILD(0)[reducables[i] - i_erased], CHILD(1)[0], nrs[i], eo); + if(nrs[i].isOne()) { + CHILD(0).delChild(reducables[i] - i_erased + 1); + i_erased++; + } else { + MathStructure mexp(1, 1); + mexp.number() -= nrs[i]; + CHILD(0)[reducables[i] - i_erased].calculateRaise(mexp, eo); + CHILD(0).calculateMultiplyIndex(reducables[i] - i_erased, eo, true); + } + } + } + } + if(CHILD(0).size() == 0) { + setToChild(2, true, mparent, index_this + 1); + } else if(CHILD(0).size() == 1) { + CHILD(0).setToChild(1, true, this, 1); + calculateMultiplyIndex(0, eo, true, mparent, index_this); + } else { + calculateMultiplyIndex(0, eo, true, mparent, index_this); + } + return 1; + } + break; + } + case STRUCT_POWER: { + if((*mnum)[1].isNumber() && (*mnum)[1].number().isReal()) { + if((*mnum)[1].number().isPositive()) { + Number nr((*mnum)[1].number()); + if(reducable((*mnum)[0], *mden, nr)) { + if(!b_nonzero && eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(*mden, eo)) break; + if(nr != (*mnum)[1].number()) { + MathStructure mnum2((*mnum)[0]); + if(mnum == this) { + CHILD(1).number() -= nr; + if(CHILD(1).number().isOne()) { + set(mnum2); + } else { + calculateRaiseExponent(eo); + } + mstruct.ref(); + transform_nocopy(STRUCT_MULTIPLICATION, &mstruct); + reduce(mnum2, CHILD(1)[0], nr, eo); + calculateMultiplyLast(eo); + } else { + transform(STRUCT_MULTIPLICATION); + PREPEND(mstruct); + CHILD(0)[1].number() -= nr; + if(CHILD(0)[1].number().isOne()) { + CHILD(0) = mnum2; + } else { + CHILD(0).calculateRaiseExponent(eo); + } + reduce(mnum2, CHILD(1)[0], nr, eo); + calculateMultiplyIndex(0, eo); + } + } else { + if(mnum == this) { + MathStructure mnum2((*mnum)[0]); + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + reduce(mnum2, (*mparent)[index_this][0], nr, eo); + } else { + set_nocopy(mstruct, true); + reduce(mnum2, CHILD(0), nr, eo); + } + } else { + reduce((*mnum)[0], CHILD(0), nr, eo); + } + } + return 1; + } + } + break; + } + } + default: { + Number nr(1, 1); + if(reducable(*mnum, *mden, nr)) { + if(!b_nonzero && eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(*mden, eo)) break; + if(mnum == this) { + MathStructure mnum2(*mnum); + if(!nr.isOne()) { + reduce(*mnum, mstruct[0], nr, eo); + mstruct.calculateRaiseExponent(eo); + nr.negate(); + nr++; + calculateRaise(nr, eo); + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo, true, mparent, index_this); + } else if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + reduce(mnum2, (*mparent)[index_this][0], nr, eo); + (*mparent)[index_this].calculateRaiseExponent(eo, mparent, index_this); + } else { + set_nocopy(mstruct, true); + reduce(mnum2, CHILD(0), nr, eo); + calculateRaiseExponent(eo, mparent, index_this); + } + } else { + reduce(*mnum, CHILD(0), nr, eo); + if(!nr.isOne()) { + calculateRaiseExponent(eo); + nr.negate(); + nr++; + mstruct.calculateRaise(nr, eo); + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo, true, mparent, index_this); + } else { + calculateRaiseExponent(eo, mparent, index_this); + } + } + return 1; + } + } + } + } + + if(mstruct.isFunction() && eo.protected_function != mstruct.function()) { + if(((mstruct.function()->id() == FUNCTION_ID_ABS && mstruct.size() == 1 && mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_SIGNUM && mstruct[0].size() == 2) || (mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2 && mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ABS && mstruct[0].size() == 1)) && (equals(mstruct[0][0]) || (isFunction() && o_function->id() == FUNCTION_ID_ABS && SIZE == 1 && CHILD(0) == mstruct[0][0]) || (isPower() && CHILD(0) == mstruct[0][0]) || (isPower() && CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_ABS && CHILD(0).size() == 1 && CHILD(0)[0] == mstruct[0][0]))) { + // sgn(abs(x))*x^y=x^y + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } else if(mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2) { + if(equals(mstruct[0]) && representsReal(true)) { + // sgn(x)*x=abs(x) + transformById(FUNCTION_ID_ABS); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(isPower() && CHILD(1).representsOdd() && mstruct[0] == CHILD(0) && CHILD(0).representsReal(true)) { + //sgn(x)*x^3=abs(x)^3 + CHILD(0).transformById(FUNCTION_ID_ABS); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(mstruct.function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(mstruct)) { + if(equals(mstruct[0]) && mstruct[0].representsReal(true) && mstruct[1].number().isOdd()) { + // root(x, 3)*x=abs(x)^(1/3)*x + mstruct[0].transformById(FUNCTION_ID_ABS); + mstruct[1].number().recip(); + mstruct.setType(STRUCT_POWER); + transform(STRUCT_FUNCTION); + setFunctionId(FUNCTION_ID_ABS); + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } else if(isPower() && CHILD(1).representsOdd() && CHILD(0) == mstruct[0] && CHILD(0).representsReal(true) && mstruct[1].number().isOdd()) { + // root(x, 3)*x^3=abs(x)^(1/3)*x^3 + mstruct[0].transformById(FUNCTION_ID_ABS); + mstruct[1].number().recip(); + mstruct.setType(STRUCT_POWER); + CHILD(0).transformById(FUNCTION_ID_ABS); + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } else if(isPower() && CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_ABS && CHILD(0).size() == 1 && CHILD(0)[0].equals(mstruct[0]) && CHILD(1).isNumber() && CHILD(1).number().isRational() && CHILD(1).number().isFraction() && CHILD(1).number().denominator() == mstruct[1].number() && CHILD(0).representsReal(true) && CHILD(1).number().numerator() == mstruct[1].number() - 1) { + // root(x, 3)*abs(x)^(2/3)=x + SET_CHILD_MAP(0) + SET_CHILD_MAP(0) + return 1; + } + } else if(eo.transform_trigonometric_functions && mstruct.function()->id() == FUNCTION_ID_SINC && mstruct.size() == 1 && equals(mstruct[0])) { + // sinc(x)*x=sin(x) + calculateMultiply(CALCULATOR->getRadUnit(), eo); + transformById(FUNCTION_ID_SIN); + if(eo.calculate_functions) calculateFunctions(eo, false); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + if(isZero()) { + if(mstruct.isFunction()) { + if((mstruct.function()->id() == FUNCTION_ID_LOG || mstruct.function()->id() == FUNCTION_ID_EXPINT) && mstruct.size() == 1) { + if(mstruct[0].representsNonZero() || warn_about_assumed_not_value(mstruct[0], m_zero, eo)) { + // 0*ln(x)=0 and 0*Ei(x)=0 if x is assumed non-zero + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + } else if(mstruct.function()->id() == FUNCTION_ID_LOGINT && mstruct.size() == 1) { + if(mstruct.representsNumber(true) || warn_about_assumed_not_value(mstruct[0], m_one, eo)) { + // 0*li(x)=0 if x is assumed not one + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + } else if(mstruct.function()->id() == FUNCTION_ID_TAN && mstruct.size() == 1) { + mstruct.setFunctionId(FUNCTION_ID_COS); + if(warn_about_assumed_not_value(mstruct, m_zero, eo)) { + // 0*tan(x)=0 if cos(x) != 0 + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + mstruct.setFunctionId(FUNCTION_ID_TAN); + } + } else if(mstruct.isPower() && mstruct[0].isFunction() && mstruct[1].representsNumber()) { + if((mstruct[0].function()->id() == FUNCTION_ID_LOG || mstruct[0].function()->id() == FUNCTION_ID_EXPINT) && mstruct[0].size() == 1) { + if(mstruct[0][0].representsNonZero() || warn_about_assumed_not_value(mstruct[0][0], m_zero, eo)) { + // ln(x)^a*0=0 and Ei(x)*0=0 if x is assumed non-zero + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + } else if(mstruct[0].function()->id() == FUNCTION_ID_LOGINT && mstruct[0].size() == 1) { + if(mstruct[0].representsNumber(true) || warn_about_assumed_not_value(mstruct[0][0], m_one, eo)) { + // li(x)^a*0=0 if x is assumed not one + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + } else if(mstruct[0].function()->id() == FUNCTION_ID_TAN && mstruct[0].size() == 1) { + mstruct[0].setFunctionId(FUNCTION_ID_COS); + if(warn_about_assumed_not_value(mstruct[0], m_zero, eo)) { + // 0*tan(x)^a=0 if cos(x) != 0 + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + mstruct[0].setFunctionId(FUNCTION_ID_TAN); + } + } + } + + switch(m_type) { + case STRUCT_VECTOR: { + switch(mstruct.type()) { + case STRUCT_ADDITION: { + return 0; + } + case STRUCT_VECTOR: { + if(isMatrix() && mstruct.isMatrix()) { + // matrix multiplication + // the number of columns in the first matrix must be equal to the number of rows in the second matrix + if(CHILD(0).size() != mstruct.size()) { + CALCULATOR->error(true, _("The second matrix must have as many rows (was %s) as the first has columns (was %s) for matrix multiplication."), i2s(mstruct.size()).c_str(), i2s(CHILD(0).size()).c_str(), NULL); + return -1; + } + MathStructure msave(*this); + size_t rows = SIZE; + clearMatrix(true); + resizeMatrix(rows, mstruct[0].size(), m_zero); + MathStructure mtmp; + for(size_t index_r = 0; index_r < SIZE; index_r++) { + for(size_t index_c = 0; index_c < CHILD(0).size(); index_c++) { + for(size_t index = 0; index < msave[0].size(); index++) { + mtmp = msave[index_r][index]; + mtmp.calculateMultiply(mstruct[index][index_c], eo); + CHILD(index_r)[index_c].calculateAdd(mtmp, eo, &CHILD(index_r), index_c); + } + } + } + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(isMatrix() && mstruct.isVector()) { + // matrix multiplication (vector is treated as matrix with 1 row) + if(SIZE != mstruct.size() || CHILD(0).size() != 1) { + CALCULATOR->error(true, _("The second matrix must have as many rows (was %s) as the first has columns (was %s) for matrix multiplication."), i2s(1).c_str(), i2s(CHILD(0).size()).c_str(), NULL); + return -1; + } + MathStructure msave(*this); + size_t rows = SIZE; + clearMatrix(true); + resizeMatrix(rows, mstruct.size(), m_zero); + MathStructure mtmp; + for(size_t index_r = 0; index_r < SIZE; index_r++) { + for(size_t index_c = 0; index_c < CHILD(0).size(); index_c++) { + CHILD(index_r)[index_c].set(msave[index_r][0]); + CHILD(index_r)[index_c].calculateMultiply(mstruct[index_c], eo); + } + } + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else { + // dot product of two vectors: [a1, a2, a3, ..]*[b1, b2, b3, ...]=a1*b1+a2*b2+a3*b3+... + // dimension of the vectors must be equal + if(SIZE == mstruct.size()) { + for(size_t i = 0; i < SIZE; i++) { + mstruct[i].ref(); + CHILD(i).multiply_nocopy(&mstruct[i], true); + CHILD(i).calculateMultiplyLast(eo, true); + } + m_type = STRUCT_ADDITION; + MERGE_APPROX_AND_PREC(mstruct) + calculatesub(eo, eo, false, mparent, index_this); + return 1; + } + } + return -1; + } + default: { + // matrix/vector multiplied by scalar: multiply each element + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).calculateMultiply(mstruct, eo); + } + MERGE_APPROX_AND_PREC(mstruct) + calculatesub(eo, eo, false, mparent, index_this); + return 1; + } + } + } + case STRUCT_ADDITION: { + if(eo.expand != 0 && containsType(STRUCT_DATETIME, false, true, false) > 0) return -1; + switch(mstruct.type()) { + case STRUCT_ADDITION: { + // multiplication of polynomials + // avoid multiplication of very long polynomials + if(eo.expand != 0 && SIZE < 1000 && mstruct.size() < 1000 && (SIZE * mstruct.size() < (eo.expand == -1 ? 50 : 500))) { + // avoid multiplication of polynomials with intervals (if factors might be negitive) + if(eo.expand > -2 || (!containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) && !mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0)) || (representsNonNegative(true) && mstruct.representsNonNegative(true))) { + MathStructure msave(*this); + CLEAR; + for(size_t i = 0; i < mstruct.size(); i++) { + if(CALCULATOR->aborted()) { + set(msave); + return -1; + } + APPEND(msave); + mstruct[i].ref(); + LAST.multiply_nocopy(&mstruct[i], true); + if(reversed) { + LAST.swapChildren(1, LAST.size()); + LAST.calculateMultiplyIndex(0, eo, true, this, SIZE - 1); + } else { + LAST.calculateMultiplyLast(eo, true, this, SIZE - 1); + } + } + MERGE_APPROX_AND_PREC(mstruct) + calculatesub(eo, eo, false, mparent, index_this); + return 1; + } else if(eo.expand <= -2 && (!mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) || representsNonNegative(true))) { + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).calculateMultiply(mstruct, eo, this, i); + } + calculatesub(eo, eo, false, mparent, index_this); + return 1; + } else if(eo.expand <= -2 && (!containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) || mstruct.representsNonNegative(true))) { + return 0; + } + } + if(equals(mstruct)) { + // x*x=x^2 + raise_nocopy(new MathStructure(2, 1, 0)); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + break; + } + case STRUCT_POWER: { + if(mstruct[1].isNumber() && *this == mstruct[0]) { + // (x+y)(x+y)^a=(x+y)^(a+1) + // check if a might be -1 and (x+y) might be zero + if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !representsZero(true)) + || (mstruct[1].isNumber() && mstruct[1].number().isReal() && !mstruct[1].number().isMinusOne()) + || representsNonZero(true) + || mstruct[1].representsPositive() + || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !representsZero(true) && warn_about_denominators_assumed_nonzero_or_positive(*this, mstruct[1], eo))) { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + (*mparent)[index_this][1].number()++; + (*mparent)[index_this].calculateRaiseExponent(eo, mparent, index_this); + } else { + set_nocopy(mstruct, true); + CHILD(1).number()++; + calculateRaiseExponent(eo, mparent, index_this); + } + return 1; + } + } + if(eo.expand == 0 && mstruct[0].isAddition()) return -1; + // eo.combine_divisions is not used anymore + if(eo.combine_divisions && mstruct[1].hasNegativeSign()) { + int ret; + vector merged; + merged.resize(SIZE, false); + size_t merges = 0; + MathStructure *mstruct2 = new MathStructure(mstruct); + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isOne()) ret = -1; + else ret = CHILD(i).merge_multiplication(*mstruct2, eo, NULL, 0, 0, false, false); + if(ret == 0) { + ret = mstruct2->merge_multiplication(CHILD(i), eo, NULL, 0, 0, true, false); + if(ret >= 1) { + mstruct2->ref(); + setChild_nocopy(mstruct2, i + 1); + } + } + if(ret >= 1) { + mstruct2->unref(); + if(i + 1 != SIZE) mstruct2 = new MathStructure(mstruct); + merged[i] = true; + merges++; + } else { + if(i + 1 == SIZE) mstruct2->unref(); + merged[i] = false; + } + } + if(merges == 0) { + return -1; + } else if(merges == SIZE) { + calculatesub(eo, eo, false, mparent, index_this); + return 1; + } else if(merges == SIZE - 1) { + for(size_t i = 0; i < SIZE; i++) { + if(!merged[i]) { + mstruct.ref(); + CHILD(i).multiply_nocopy(&mstruct, true); + break; + } + } + calculatesub(eo, eo, false, mparent, index_this); + } else { + MathStructure *mdiv = new MathStructure(); + merges = 0; + for(size_t i = 0; i - merges < SIZE; i++) { + if(!merged[i]) { + CHILD(i - merges).ref(); + if(merges > 0) { + (*mdiv)[0].add_nocopy(&CHILD(i - merges), merges > 1); + } else { + mdiv->multiply(mstruct); + mdiv->setChild_nocopy(&CHILD(i - merges), 1); + } + ERASE(i - merges); + merges++; + } + } + add_nocopy(mdiv, true); + calculatesub(eo, eo, false); + } + return 1; + } + if(eo.expand == 0 || (eo.expand < -1 && mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) && !representsNonNegative(true))) return -1; + } + case STRUCT_MULTIPLICATION: { + if(do_append && (eo.expand == 0 || (eo.expand < -1 && mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) && !representsNonNegative(true)))) { + transform(STRUCT_MULTIPLICATION); + for(size_t i = 0; i < mstruct.size(); i++) { + APPEND_REF(&mstruct[i]); + } + return 1; + } + } + default: { + if(eo.expand == 0 || (eo.expand < -1 && mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) && !representsNonNegative(true))) return -1; + // (a1+a2+...)*b=(ba1+ba2+...) + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).multiply(mstruct, true); + if(reversed) { + CHILD(i).swapChildren(1, CHILD(i).size()); + CHILD(i).calculateMultiplyIndex(0, eo, true, this, i); + } else { + CHILD(i).calculateMultiplyLast(eo, true, this, i); + } + } + MERGE_APPROX_AND_PREC(mstruct) + calculatesub(eo, eo, false, mparent, index_this); + return 1; + } + } + return -1; + } + case STRUCT_MULTIPLICATION: { + switch(mstruct.type()) { + case STRUCT_VECTOR: {} + case STRUCT_ADDITION: { + if(eo.expand == 0 || containsType(STRUCT_DATETIME, false, true, false) > 0) { + if(!do_append) return -1; + APPEND_REF(&mstruct); + return 1; + } + // try again with reversed order + return 0; + } + case STRUCT_MULTIPLICATION: { + // (a1*a2*...)(b1*b2*...)=a1*a2*...*b1*b2*... + for(size_t i = 0; i < mstruct.size(); i++) { + if(reversed) { + PREPEND_REF(&mstruct[i]); + calculateMultiplyIndex(0, eo, false); + } else { + APPEND_REF(&mstruct[i]); + calculateMultiplyLast(eo, false); + } + } + MERGE_APPROX_AND_PREC(mstruct) + if(SIZE == 1) { + setToChild(1, false, mparent, index_this + 1); + } else if(SIZE == 0) { + clear(true); + } else { + evalSort(); + } + return 1; + } + case STRUCT_POWER: { + if(mstruct[1].isNumber() && equals(mstruct[0])) { + // xy(xy)^a=(xy)^(a+1) + // check if a might be -1 and xy might be zero + if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !representsZero(true)) + || (mstruct[1].isNumber() && mstruct[1].number().isReal() && !mstruct[1].number().isMinusOne()) + || representsNonZero(true) + || mstruct[1].representsPositive() + || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !representsZero(true) && warn_about_denominators_assumed_nonzero_or_positive(*this, mstruct[1], eo))) { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + (*mparent)[index_this][1].number()++; + (*mparent)[index_this].calculateRaiseExponent(eo, mparent, index_this); + } else { + set_nocopy(mstruct, true); + CHILD(1).number()++; + calculateRaiseExponent(eo, mparent, index_this); + } + return 1; + } + } + } + default: { + if(do_append) { + MERGE_APPROX_AND_PREC(mstruct) + if(reversed) { + PREPEND_REF(&mstruct); + calculateMultiplyIndex(0, eo, true, mparent, index_this); + } else { + APPEND_REF(&mstruct); + calculateMultiplyLast(eo, true, mparent, index_this); + } + return 1; + } else { + for(size_t i = 0; i < SIZE; i++) { + int ret = CHILD(i).merge_multiplication(mstruct, eo, NULL, 0, 0, false, false); + if(ret == 0) { + ret = mstruct.merge_multiplication(CHILD(i), eo, NULL, 0, 0, true, false); + if(ret >= 1) { + if(ret == 2) ret = 3; + else if(ret == 3) ret = 2; + mstruct.ref(); + setChild_nocopy(&mstruct, i + 1); + } + } + if(ret >= 1) { + if(ret != 2) calculateMultiplyIndex(i, eo, true, mparent, index_this); + return 1; + } + } + } + } + } + return -1; + } + case STRUCT_POWER: { + switch(mstruct.type()) { + case STRUCT_VECTOR: {} + case STRUCT_ADDITION: {} + case STRUCT_MULTIPLICATION: { + // try again with reversed order + return 0; + } + case STRUCT_POWER: { + if(CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_ABS && mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ROOT && mstruct[1].isMinusOne() && CHILD(0).size() == 1 && VALID_ROOT(mstruct[0]) && CHILD(0)[0].equals(mstruct[0][0]) && CHILD(1).isNumber() && CHILD(1).number().isRational() && CHILD(1).number().isFraction() && CHILD(1).number().denominator() == mstruct[0][1].number() && CHILD(0)[0].representsReal(true) && CHILD(1).number().numerator() == -(mstruct[0][1].number() - 1)) { + // root(x, 3)^-1*abs(x)^(-2/3)=1/x + SET_CHILD_MAP(0) + SET_CHILD_MAP(0) + raise(m_minus_one); + return 1; + } + if(mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ABS && CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_ROOT && CHILD(1).isMinusOne() && mstruct[0].size() == 1 && VALID_ROOT(CHILD(0)) && CHILD(0)[0].equals(mstruct[0][0]) && mstruct[1].isNumber() && mstruct[1].number().isRational() && mstruct[1].number().isFraction() && mstruct[1].number().denominator() == CHILD(0)[1].number() && mstruct[0][0].representsReal(true) && mstruct[1].number().numerator() == -(CHILD(0)[1].number() - 1)) { + // root(x, 3)^-1*abs(x)^(-2/3)=1/x + SET_CHILD_MAP(0) + SET_CHILD_MAP(0) + raise(m_minus_one); + return 1; + } + if(mstruct[0] == CHILD(0) || (CHILD(0).isMultiplication() && CHILD(0).size() == 2 && CHILD(0)[0].isMinusOne() && CHILD(0)[1] == mstruct[0] && (mstruct[1].representsEven() || mstruct[1].representsOdd()))) { + // x^a*x^b=x^(a+b) + // (-x)^a*x^b=(-x)^(a+b) if b is even + // (-x)^a*x^b=-(-x)^(a+b) if b is odd + if(mstruct[0].isUnit() && mstruct[0].prefix()) { + if(CHILD(0).isMultiplication()) CHILD(0)[0].setPrefix(mstruct[0].prefix()); + else CHILD(0).setPrefix(mstruct[0].prefix()); + } + bool b = eo.allow_complex || CHILD(0).representsNonNegative(true), b2 = true, b_warn = false; + if(!b) { + // if complex not allowed and base might be negative, exponents must be integers + b = CHILD(1).representsInteger() && mstruct[1].representsInteger(); + } + bool b_neg = mstruct[1].representsOdd() && !(mstruct[0] == CHILD(0)); + if(b) { + b = false; + bool b2test = false; + if(IS_REAL(mstruct[1]) && IS_REAL(CHILD(1))) { + if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) { + b2 = true; + b = true; + } else if(!mstruct[1].number().isMinusOne() && !CHILD(1).number().isMinusOne()) { + b2 = (mstruct[1].number() + CHILD(1).number()).isNegative(); + b = true; + if(!b2) { + // sign of exponent changes: test if base is non-zero + b2test = true; + } + } + } + if(!b || b2test) { + b = (!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true)) + || CHILD(0).representsNonZero(true) + || (CHILD(1).representsPositive() && mstruct[1].representsPositive()) + || (CHILD(1).representsNegative() && mstruct[1].representsNegative()); + if(!b && eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true)) { + b = true; + b_warn = true; + } + if(b2test) { + b2 = b; + if(!b_neg) b = true; + } else if(b_neg) { + b = false; + } + } + } + if(b) { + if(IS_REAL(CHILD(1)) && IS_REAL(mstruct[1])) { + // exponents are real numbers + if(!b2 && !do_append) return -1; + // test if base is non-zero (if exponent is negative) + if(b_warn && !warn_about_denominators_assumed_nonzero(CHILD(0), eo)) return -1; + if(b2) { + // exponents can safely be combined + CHILD(1).number() += mstruct[1].number(); + if(b_neg) { + calculateRaiseExponent(eo); + calculateNegate(eo, mparent, index_this); + } else { + calculateRaiseExponent(eo, mparent, index_this); + } + } else { + // a and b have different signs and a+b is not negative: x^a/x^b=x^(a-b+1)/x + if(CHILD(1).number().isNegative()) { + CHILD(1).number()++; + mstruct[1].number() += CHILD(1).number(); + CHILD(1).number().set(-1, 1, 0); + } else { + mstruct[1].number()++; + CHILD(1).number() += mstruct[1].number(); + mstruct[1].number().set(-1, 1, 0); + } + MERGE_APPROX_AND_PREC(mstruct) + transform(STRUCT_MULTIPLICATION); + CHILD(0).calculateRaiseExponent(eo, this, 0); + if(reversed) { + PREPEND_REF(&mstruct); + CHILD(0).calculateRaiseExponent(eo, this, 0); + calculateMultiplyIndex(0, eo, true, mparent, index_this); + } else { + APPEND_REF(&mstruct); + CHILD(1).calculateRaiseExponent(eo, this, 1); + calculateMultiplyLast(eo, true, mparent, index_this); + } + } + return 1; + } else { + MathStructure mstruct2(CHILD(1)); + if(mstruct2.calculateAdd(mstruct[1], eo)) { + // test and warn for possible division by zero (test both base and exponents) + if(b_warn && !warn_about_denominators_assumed_nonzero_llgg(CHILD(0), CHILD(1), mstruct[1], eo)) return -1; + CHILD(1) = mstruct2; + calculateRaiseExponent(eo, mparent, index_this); + return 1; + } + } + } + } else if(mstruct[1] == CHILD(1)) { + if(!CHILD(0).isMultiplication() && !mstruct[0].isMultiplication() && (mstruct[1].representsInteger() || CHILD(0).representsPositive(true) || mstruct[0].representsPositive(true))) { + // x^a*y^a=(xy)^a if x and y is positive, or a is integer + MathStructure mstruct2(CHILD(0)); + if(mstruct2.calculateMultiply(mstruct[0], eo)) { + CHILD(0) = mstruct2; + MERGE_APPROX_AND_PREC(mstruct) + calculateRaiseExponent(eo, mparent, index_this); + return 1; + } + } else if(eo.transform_trigonometric_functions && CHILD(1).representsInteger() && CHILD(0).isFunction() && mstruct[0].isFunction() && eo.protected_function != mstruct[0].function() && eo.protected_function != CHILD(0).function() && CHILD(0).size() == 1 && mstruct[0].size() == 1 && CHILD(0)[0] == mstruct[0][0]) { + if((CHILD(0).function()->id() == FUNCTION_ID_COS && mstruct[0].function()->id() == FUNCTION_ID_SIN) || (CHILD(0).function()->id() == FUNCTION_ID_SIN && mstruct[0].function()->id() == FUNCTION_ID_COS) || (CHILD(0).function()->id() == FUNCTION_ID_COSH && mstruct[0].function()->id() == FUNCTION_ID_SINH) || (CHILD(0).function()->id() == FUNCTION_ID_SINH && mstruct[0].function()->id() == FUNCTION_ID_COSH)) { + // cos(x)^n*sin(x)^n=sin(2x)^n/2^n + if(CHILD(0).function()->id() == FUNCTION_ID_COSH) CHILD(0).setFunctionId(FUNCTION_ID_SINH); + else if(CHILD(0).function()->id() == FUNCTION_ID_COS) CHILD(0).setFunctionId(FUNCTION_ID_SIN); + CHILD(0)[0].calculateMultiply(nr_two, eo); + CHILD(0).childUpdated(1); + CHILD_UPDATED(0) + MathStructure *mdiv = new MathStructure(2, 1, 0); + mdiv->calculateRaise(CHILD(1), eo); + mdiv->calculateInverse(eo); + multiply_nocopy(mdiv); + calculateMultiplyLast(eo); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if((CHILD(0).function()->id() == FUNCTION_ID_TAN && mstruct[0].function()->id() == FUNCTION_ID_COS) || (CHILD(0).function()->id() == FUNCTION_ID_COS && mstruct[0].function()->id() == FUNCTION_ID_TAN)) { + // tan(x)^n*cos(x)^n=sin(x)^n + CHILD(0).setFunctionId(FUNCTION_ID_SIN); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if((CHILD(0).function()->id() == FUNCTION_ID_TANH && mstruct[0].function()->id() == FUNCTION_ID_COSH) || (CHILD(0).function()->id() == FUNCTION_ID_COSH && mstruct[0].function()->id() == FUNCTION_ID_TANH)) { + // tanh(x)^n*cosh(x)^n=sinh(x)^n + CHILD(0).setFunctionId(FUNCTION_ID_SIN); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } else if(eo.transform_trigonometric_functions && CHILD(1).isInteger() && mstruct[1].isInteger() && CHILD(0).isFunction() && mstruct[0].isFunction() && eo.protected_function != mstruct[0].function() && eo.protected_function != CHILD(0).function() && mstruct[0].size() == 1 && CHILD(0).size() == 1 && CHILD(0)[0] == mstruct[0][0]) { + if(CHILD(1).number().isNonNegative() != mstruct[1].number().isNonNegative()) { + if(CHILD(0).function()->id() == FUNCTION_ID_SIN) { + if(mstruct[0].function()->id() == FUNCTION_ID_COS) { + // sin(x)^n/cos(x)^m=tan(x)^n if n=m + // sin(x)^n/cos(x)^m=tan(x)^m*sin(x)^(n-m) if n>m + // sin(x)^n/cos(x)^m=tan(x)^m/cos(x)^(m-n) if nm + mstruct[0].setFunctionId(FUNCTION_ID_SIN); + CHILD(1).number() -= mstruct[1].number(); + } + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } else if(mstruct[0].function()->id() == FUNCTION_ID_TAN) { + // sin(x)^n/tan(x)^m=cos(x)^n if n=m + // sin(x)^n/tan(x)^m=cos(x)^m*sin(x)^(n-m) if n>m + // sin(x)^n/tan(x)^m=cos(x)^m/tan(x)^(m-n) if nm + mstruct[0].setFunctionId(FUNCTION_ID_SIN); + CHILD(1).number() -= mstruct[1].number(); + } + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_COS) { + if(mstruct[0].function()->id() == FUNCTION_ID_SIN) { + // sin(x)^n/cos(x)^m=tan(x)^n if n=m + // sin(x)^n/cos(x)^m=tan(x)^m*sin(x)^(n-m) if n>m + // sin(x)^n/cos(x)^m=tan(x)^m/cos(x)^(m-n) if nm + CHILD(0).setFunctionId(FUNCTION_ID_SIN); + mstruct[1].number() -= CHILD(1).number(); + } + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_TAN) { + if(mstruct[0].function()->id() == FUNCTION_ID_SIN) { + // sin(x)^n/tan(x)^m=cos(x)^n if n=m + // sin(x)^n/tan(x)^m=cos(x)^m*sin(x)^(n-m) if n>m + // sin(x)^n/tan(x)^m=cos(x)^m/tan(x)^(m-n) if nm + CHILD(0).setFunctionId(FUNCTION_ID_SIN); + mstruct[1].number() -= CHILD(1).number(); + } + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_SINH) { + if(mstruct[0].function()->id() == FUNCTION_ID_COSH) { + // sinh(x)^n/cosh(x)^m=tanh(x)^n if n=m + // sinh(x)^n/cosh(x)^m=tanh(x)^m*sinh(x)^(n-m) if n>m + // sinh(x)^n/cosh(x)^m=tanh(x)^m/cosh(x)^(m-n) if nm + mstruct[0].setFunctionId(FUNCTION_ID_SINH); + CHILD(1).number() -= mstruct[1].number(); + } + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } else if(mstruct[0].function()->id() == FUNCTION_ID_TANH) { + // sinh(x)^n/tanh(x)^m=cosh(x)^n if n=m + // sinh(x)^n/tanh(x)^m=cosh(x)^m*sinh(x)^(n-m) if n>m + // sinh(x)^n/tanh(x)^m=cosh(x)^m/tanh(x)^(m-n) if nm + mstruct[0].setFunctionId(FUNCTION_ID_SINH); + CHILD(1).number() -= mstruct[1].number(); + } + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_COSH) { + if(mstruct[0].function()->id() == FUNCTION_ID_SINH) { + // sinh(x)^n/cosh(x)^m=tanh(x)^n if n=m + // sinh(x)^n/cosh(x)^m=tanh(x)^m*sinh(x)^(n-m) if n>m + // sinh(x)^n/cosh(x)^m=tanh(x)^m/cosh(x)^(m-n) if nm + CHILD(0).setFunctionId(FUNCTION_ID_SINH); + mstruct[1].number() -= CHILD(1).number(); + } + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_TANH) { + if(mstruct[0].function()->id() == FUNCTION_ID_SINH) { + // sinh(x)^n/tanh(x)^m=cosh(x)^n if n=m + // sinh(x)^n/tanh(x)^m=cosh(x)^m*sinh(x)^(n-m) if n>m + // sinh(x)^n/tanh(x)^m=cosh(x)^m/tanh(x)^(m-n) if nm + CHILD(0).setFunctionId(FUNCTION_ID_SINH); + mstruct[1].number() -= CHILD(1).number(); + } + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } + } else { + if((CHILD(0).function()->id() == FUNCTION_ID_TAN && mstruct[0].function()->id() == FUNCTION_ID_COS)) { + // tan(x)^n*cos(x)^m=sin(x)^n*cos(x)^(m-n) + CHILD(0).setFunctionId(FUNCTION_ID_SIN); + mstruct[1].number() -= CHILD(1).number(); + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } else if((CHILD(0).function()->id() == FUNCTION_ID_COS && mstruct[0].function()->id() == FUNCTION_ID_TAN)) { + // tan(x)^n*cos(x)^m=sin(x)^n*cos(x)^(m-n) + mstruct[0].setFunctionId(FUNCTION_ID_SIN); + CHILD(1).number() -= mstruct[1].number(); + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } else if((CHILD(0).function()->id() == FUNCTION_ID_TANH && mstruct[0].function()->id() == FUNCTION_ID_COSH)) { + // tanh(x)^n*cosh(x)^m=sinh(x)^n*cosh(x)^(m-n) + CHILD(0).setFunctionId(FUNCTION_ID_SINH); + mstruct[1].number() -= CHILD(1).number(); + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } else if((CHILD(0).function()->id() == FUNCTION_ID_COSH && mstruct[0].function()->id() == FUNCTION_ID_TANH)) { + // tanh(x)^n*cosh(x)^m=sinh(x)^n*cosh(x)^(m-n) + mstruct[0].setFunctionId(FUNCTION_ID_SINH); + CHILD(1).number() -= mstruct[1].number(); + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } + } else if(mstruct[0].isMultiplication() && mstruct[0].size() == 2 && mstruct[0][0].isMinusOne() && mstruct[0][1] == CHILD(0) && CHILD(1).representsEven()) { + return 0; + } + break; + } + case STRUCT_FUNCTION: { + if(!FUNCTION_PROTECTED(eo, FUNCTION_ID_SIGNUM) && mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2 && CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_ABS && CHILD(0).size() == 1 && mstruct[0] == CHILD(0)[0] && CHILD(1).isNumber() && CHILD(1).number().isRational() && CHILD(1).number().numeratorIsOne() && !CHILD(1).number().denominatorIsEven() && CHILD(0)[0].representsReal(true)) { + // sgn(x)*abs(x)^(1/n)=root(x,n) if x is real + setType(STRUCT_FUNCTION); + setFunctionId(FUNCTION_ID_ROOT); + CHILD(0).setToChild(1, true); + CHILD(1).number().recip(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + if(eo.transform_trigonometric_functions && CHILD(0).isFunction() && CHILD(0).size() == 1 && mstruct.size() == 1 && CHILD(1).isInteger() && CHILD(1).number().isNegative() && eo.protected_function != mstruct.function() && eo.protected_function != CHILD(0).function()) { + if(CHILD(0).function()->id() == FUNCTION_ID_SIN) { + if(mstruct.function()->id() == FUNCTION_ID_COS && CHILD(0)[0] == mstruct[0]) { + if(CHILD(1).number().isMinusOne()) { + // cos(x)/sin(x)=1/tan(x) + CHILD(0).setFunctionId(FUNCTION_ID_TAN); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + // cos(x)/sin(x)^n=1/(sin(x)^(n-1)*tan(x)) + mstruct.setFunctionId(FUNCTION_ID_TAN); + mstruct.raise(nr_minus_one); + CHILD(1).number()++; + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } else if(mstruct.function()->id() == FUNCTION_ID_TAN && CHILD(0)[0] == mstruct[0]) { + if(CHILD(1).number().isMinusOne()) { + // tan(x)/sin(x)=1/cos(x) + CHILD(0).setFunctionId(FUNCTION_ID_COS); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + // tan(x)/sin(x)^n=1/(cos(x)*sin(x)^(n-1)) + mstruct.setFunctionId(FUNCTION_ID_COS); + mstruct.raise(nr_minus_one); + CHILD(1).number()++; + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_COS) { + if(mstruct.function()->id() == FUNCTION_ID_SIN && CHILD(0)[0] == mstruct[0]) { + if(CHILD(1).number().isMinusOne()) { + // sin(x)/cos(x)=tan(x) + CHILD(0).setFunctionId(FUNCTION_ID_TAN); + SET_CHILD_MAP(0) + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + // sin(x)/cos(x)^n=tan(x)/(cos(x)^(n-1)) + mstruct.setFunctionId(FUNCTION_ID_TAN); + CHILD(1).number()++; + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_TAN) { + if(mstruct.function()->id() == FUNCTION_ID_SIN && CHILD(0)[0] == mstruct[0]) { + if(CHILD(1).number().isMinusOne()) { + // sin(x)/tan(x)=cos(x) + CHILD(0).setFunctionId(FUNCTION_ID_COS); + SET_CHILD_MAP(0) + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + // sin(x)/tan(x)^n=cos(x)/(tan(x)^(n-1)) + mstruct.setFunctionId(FUNCTION_ID_COS); + CHILD(1).number()++; + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_SINH) { + if(mstruct.function()->id() == FUNCTION_ID_COSH && CHILD(0)[0] == mstruct[0]) { + if(CHILD(1).number().isMinusOne()) { + // cosh(x)/sinh(x)=1/tanh(x) + CHILD(0).setFunctionId(FUNCTION_ID_TANH); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + // cosh(x)/sinh(x)^n=1/(sinh(x)^(n-1)*tanh(x)) + mstruct.setFunctionId(FUNCTION_ID_TANH); + mstruct.raise(nr_minus_one); + CHILD(1).number()++; + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } else if(mstruct.function()->id() == FUNCTION_ID_TANH && CHILD(0)[0] == mstruct[0]) { + if(CHILD(1).number().isMinusOne()) { + // tanh(x)/sinh(x)=1/cosh(x) + CHILD(0).setFunctionId(FUNCTION_ID_COSH); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + // tanh(x)/sinh(x)^n=1/(cosh(x)*sinh(x)^(n-1)) + mstruct.setFunctionId(FUNCTION_ID_COSH); + mstruct.raise(nr_minus_one); + CHILD(1).number()++; + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_COSH) { + if(mstruct.function()->id() == FUNCTION_ID_SINH && CHILD(0)[0] == mstruct[0]) { + if(CHILD(1).number().isMinusOne()) { + // sinh(x)/cosh(x)=tanh(x) + CHILD(0).setFunctionId(FUNCTION_ID_TANH); + SET_CHILD_MAP(0) + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + // sinh(x)/cosh(x)^n=tanh(x)/(cosh(x)^(n-1)) + mstruct.setFunctionId(FUNCTION_ID_TANH); + CHILD(1).number()++; + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_TANH) { + if(mstruct.function()->id() == FUNCTION_ID_SINH && CHILD(0)[0] == mstruct[0]) { + if(CHILD(1).number().isMinusOne()) { + // sinh(x)/tanh(x)=cosh(x) + CHILD(0).setFunctionId(FUNCTION_ID_COSH); + SET_CHILD_MAP(0) + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + // sinh(x)/tanh(x)^n=cosh(x)/(tanh(x)^(n-1)) + mstruct.setFunctionId(FUNCTION_ID_COSH); + CHILD(1).number()++; + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } + } + if(mstruct.function()->id() == FUNCTION_ID_STRIP_UNITS && mstruct.size() == 1) { + if(m_type == STRUCT_POWER && CHILD(0).isVariable() && CHILD(0).variable()->isKnown() && mstruct[0].contains(CHILD(0), false) > 0) { + // v^a*nounit(v)=nounit(v)*(nounit(v)*(units in v))^a + // try extracting units from variable + if(separate_unit_vars(CHILD(0), eo, false)) { + calculateRaiseExponent(eo); + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } + } + } + default: { + if(!mstruct.isNumber() && CHILD(1).isNumber() && CHILD(0) == mstruct) { + // x*x^a=x^(a+1) + // test if x is non-zero or a is non-negative + if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true)) + || (CHILD(1).isNumber() && CHILD(1).number().isReal() && !CHILD(1).number().isMinusOne()) + || CHILD(0).representsNonZero(true) + || CHILD(1).representsPositive() + || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true) && warn_about_denominators_assumed_nonzero_or_positive(CHILD(0), CHILD(1), eo))) { + CHILD(1).number()++; + MERGE_APPROX_AND_PREC(mstruct) + calculateRaiseExponent(eo, mparent, index_this); + return 1; + } + } + if(mstruct.isNumber() && CHILD(1).isNumber() && !CHILD(1).number().includesInfinity() && CHILD(0).isNumber() && CHILD(0).number().isRational() && !CHILD(0).number().isZero() && mstruct.number().isRational()) { + if(CHILD(0).isInteger() && mstruct.number().denominator() == CHILD(0).number().numerator()) { + // n^a*m/n=n^(a-1)*m + CHILD(1).number()--; + MERGE_APPROX_AND_PREC(mstruct) + calculateRaiseExponent(eo); + if(!mstruct.number().numeratorIsOne()) calculateMultiply(mstruct.number().numerator(), eo, mparent, index_this); + return 1; + } else if(mstruct.number().denominator() == CHILD(0).number().numerator() && mstruct.number().numerator() == CHILD(0).number().denominator()) { + // (n/m)^a*m/n=(n/m)^(a-1) + CHILD(1).number()--; + MERGE_APPROX_AND_PREC(mstruct) + calculateRaiseExponent(eo); + return 1; + } + } + // x^a*0=0 (keep units and check if not matrix and not undefined) + if(mstruct.isZero() && (!eo.keep_zero_units || containsType(STRUCT_UNIT, false, true, true) <= 0 || (CHILD(0).isUnit() && CHILD(0).unit() == CALCULATOR->getRadUnit()) || (CHILD(0).isFunction() && CHILD(0).representsNumber(false))) && !representsUndefined(true, true, !eo.assume_denominators_nonzero) && representsNonMatrix()) { + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + if(CHILD(0).isFunction() && mstruct.isZero() && CHILD(1).representsNumber()) { + if((CHILD(0).function()->id() == FUNCTION_ID_LOG || CHILD(0).function()->id() == FUNCTION_ID_EXPINT) && SIZE == 1) { + if(CHILD(0)[0].representsNonZero() || warn_about_assumed_not_value(CHILD(0)[0], m_zero, eo)) { + // ln(x)^a*0=0 and Ei(x)*0=0 if x is assumed non-zero + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 3; + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_LOGINT && SIZE == 1) { + if(CHILD(0).representsNumber(true) || warn_about_assumed_not_value(CHILD(0)[0], m_one, eo)) { + // li(x)^a*0=0 if x is assumed not one + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 3; + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_TAN && CHILD(0).size() == 1) { + CHILD(0).setFunctionId(FUNCTION_ID_COS); + if(warn_about_assumed_not_value(CHILD(0), m_zero, eo)) { + // tan(x)^a*0=0 if cos(x) is assumed non-zero + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 3; + } + CHILD(0).setFunctionId(FUNCTION_ID_TAN); + } + } + break; + } + } + return -1; + } + case STRUCT_FUNCTION: { + if(eo.protected_function != o_function) { + if(((o_function->id() == FUNCTION_ID_ABS && SIZE == 1 && CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_SIGNUM && CHILD(0).size() == 2) || (o_function->id() == FUNCTION_ID_SIGNUM && SIZE == 2 && CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_ABS && CHILD(0).size() == 1)) && (CHILD(0)[0] == mstruct || (mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_ABS && mstruct.size() == 1 && CHILD(0)[0] == mstruct[0]) || (mstruct.isPower() && mstruct[0] == CHILD(0)[0]) || (mstruct.isPower() && mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ABS && mstruct[0].size() == 1 && CHILD(0)[0] == mstruct[0][0]))) { + // sgn(abs(x))*x^y=x^y + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } else if(o_function->id() == FUNCTION_ID_ABS && SIZE == 1) { + if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_ABS && mstruct.size() == 1 && mstruct[0] == CHILD(0) && CHILD(0).representsReal(true)) { + // abs(x)*abs(x)=x^2 + SET_CHILD_MAP(0) + MERGE_APPROX_AND_PREC(mstruct) + calculateRaise(nr_two, eo); + return 1; + } else if(mstruct.isFunction() && eo.protected_function != mstruct.function() && mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2 && mstruct[0] == CHILD(0) && CHILD(0).representsScalar()) { + // sgn(x)*abs(x)=x + SET_CHILD_MAP(0) + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(o_function->id() == FUNCTION_ID_SIGNUM && SIZE == 2) { + if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2 && mstruct[0] == CHILD(0) && CHILD(0).representsReal(true)) { + if(mstruct[1].isOne() && CHILD(1).isOne()) { + set(1, 1, 0, true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mstruct[1] == CHILD(1)) { + // sgn(x)*sgn(x)=sgn(abs(x)) + CHILD(0).transformById(FUNCTION_ID_ABS); + CHILD_UPDATED(0) + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(mstruct.isFunction() && eo.protected_function != mstruct.function() && mstruct.function()->id() == FUNCTION_ID_ABS && mstruct.size() == 1 && mstruct[0] == CHILD(0) && CHILD(0).representsScalar()) { + // sgn(x)*abs(x)=x + SET_CHILD_MAP(0) + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mstruct == CHILD(0) && CHILD(0).representsReal(true)) { + // sgn(x)*x=abs(x) + setFunctionId(FUNCTION_ID_ABS); + ERASE(1) + return 1; + } else if(mstruct.isPower() && mstruct[1].representsOdd() && mstruct[0] == CHILD(0) && CHILD(0).representsReal(true)) { + //sgn(x)*x^3=abs(x)^3 + mstruct[0].transformById(FUNCTION_ID_ABS); + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 1; + } + } else if(o_function->id() == FUNCTION_ID_ROOT && THIS_VALID_ROOT) { + if(CHILD(0) == mstruct && CHILD(0).representsReal(true) && CHILD(1).number().isOdd()) { + // root(x, 3)*x=abs(x)^(1/3)*x + CHILD(0).transformById(FUNCTION_ID_ABS); + CHILD(1).number().recip(); + m_type = STRUCT_POWER; + mstruct.transformById(FUNCTION_ID_ABS); + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } else if(mstruct.isPower() && mstruct[1].representsOdd() && CHILD(0) == mstruct[0] && CHILD(0).representsReal(true) && CHILD(1).number().isOdd()) { + // root(x, 3)*x^3=abs(x)^(1/3)*x^3 + CHILD(0).transformById(FUNCTION_ID_ABS); + CHILD(1).number().recip(); + m_type = STRUCT_POWER; + mstruct[0].transformById(FUNCTION_ID_ABS); + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } else if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(mstruct) && CHILD(0) == mstruct[0] && CHILD(0).representsReal(true) && CHILD(1).number().isOdd() && mstruct[1].number().isOdd()) { + // root(x, y)*root(x, z)=abs(x)^(1/y)*abs(x)^(1/z) + CHILD(0).transformById(FUNCTION_ID_ABS); + CHILD(1).number().recip(); + m_type = STRUCT_POWER; + mstruct[0].transformById(FUNCTION_ID_ABS); + mstruct[1].number().recip(); + mstruct.setType(STRUCT_POWER); + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } else if(mstruct.isPower() && mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ABS && mstruct[0].size() == 1 && mstruct[0][0].equals(CHILD(0)) && mstruct[1].isNumber() && mstruct[1].number().isRational() && mstruct[1].number().isFraction() && mstruct[0].number().denominator() == CHILD(1).number() && CHILD(0).representsReal(true) && mstruct[1].number().numerator() == CHILD(1).number() - 1) { + // root(x, 3)*abs(x)^(2/3)=x + SET_CHILD_MAP(0) + return 1; + } + } else if((o_function->id() == FUNCTION_ID_LOG || o_function->id() == FUNCTION_ID_EXPINT) && SIZE == 1 && mstruct.isZero()) { + // Ei(x)*0=0 if x is assumed non-zero + if(CHILD(0).representsNonZero() || warn_about_assumed_not_value(CHILD(0), m_zero, eo)) { + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 3; + } + } else if(o_function->id() == FUNCTION_ID_LOGINT && SIZE == 1 && mstruct.isZero()) { + // li(x)*0=0 if x is assumed not one + if(representsNumber(true) || warn_about_assumed_not_value(CHILD(0), m_one, eo)) { + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 3; + } + } else if(o_function->id() == FUNCTION_ID_TAN && SIZE == 1 && mstruct.isZero()) { + setFunctionId(FUNCTION_ID_COS); + if(warn_about_assumed_not_value(*this, m_zero, eo)) { + // 0*tan(x)=0 if cos(x) is assume non-zero + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 3; + } + setFunctionId(FUNCTION_ID_TAN); + } else if(eo.transform_trigonometric_functions && o_function->id() == FUNCTION_ID_SINC && SIZE == 1 && CHILD(0) == mstruct) { + // sinc(x)*x=sin(x) + CHILD(0).calculateMultiply(CALCULATOR->getRadUnit(), eo); + CHILD_UPDATED(0) + setFunctionId(FUNCTION_ID_SIN); + if(eo.calculate_functions) calculateFunctions(eo, false); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(eo.transform_trigonometric_functions && mstruct.isFunction() && mstruct.size() == 1 && eo.protected_function != mstruct.function()) { + if(o_function->id() == FUNCTION_ID_TAN && SIZE == 1) { + if(mstruct.function()->id() == FUNCTION_ID_COS && mstruct[0] == CHILD(0)) { + // tan(x)*cos(x)=sin(x) + setFunctionId(FUNCTION_ID_SIN); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(o_function->id() == FUNCTION_ID_COS && SIZE == 1) { + if(mstruct.function()->id() == FUNCTION_ID_TAN && mstruct[0] == CHILD(0)) { + // tan(x)*cos(x)=sin(x) + setFunctionId(FUNCTION_ID_SIN); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mstruct.function()->id() == FUNCTION_ID_SIN && mstruct[0] == CHILD(0)) { + // cos(x)*sin(x)=sin(2x)/2 + setFunctionId(FUNCTION_ID_SIN); + CHILD(0).calculateMultiply(nr_two, eo); + CHILD_UPDATED(0) + calculateDivide(nr_two, eo); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(o_function->id() == FUNCTION_ID_SIN && SIZE == 1) { + if(mstruct.function()->id() == FUNCTION_ID_COS && mstruct[0] == CHILD(0)) { + // cos(x)*sin(x)=sin(2x)/2 + setFunctionId(FUNCTION_ID_SIN); + CHILD(0).calculateMultiply(nr_two, eo); + CHILD_UPDATED(0) + calculateDivide(nr_two, eo); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(o_function->id() == FUNCTION_ID_TANH && SIZE == 1) { + if(mstruct.function()->id() == FUNCTION_ID_COSH && mstruct[0] == CHILD(0)) { + // tanh(x)*cosh(x)=sinh(x) + setFunctionId(FUNCTION_ID_SINH); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(o_function->id() == FUNCTION_ID_SINH && SIZE == 1) { + if(mstruct.function()->id() == FUNCTION_ID_COSH && mstruct[0] == CHILD(0)) { + // cosh(x)*sinh(x)=sinh(2x)/2 + setFunctionId(FUNCTION_ID_SINH); + CHILD(0).calculateMultiply(nr_two, eo); + CHILD_UPDATED(0) + calculateDivide(nr_two, eo); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(o_function->id() == FUNCTION_ID_COSH && SIZE == 1) { + if(mstruct.function()->id() == FUNCTION_ID_TANH && mstruct[0] == CHILD(0)) { + // tanh(x)*cosh(x)=sinh(x) + setFunctionId(FUNCTION_ID_SINH); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mstruct.function()->id() == FUNCTION_ID_SINH && mstruct[0] == CHILD(0)) { + // cosh(x)*sinh(x)=sinh(2x)/2 + setFunctionId(FUNCTION_ID_SINH); + CHILD(0).calculateMultiply(nr_two, eo); + CHILD_UPDATED(0) + calculateDivide(nr_two, eo); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } + } + if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) { + if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_STRIP_UNITS && mstruct.size() == 1) { + // nounit(x)*nounit(y)=nounit(x*y) + mstruct[0].ref(); + CHILD(0).multiply_nocopy(&mstruct[0]); + return 1; + } else if(mstruct.isVariable() && mstruct.variable()->isKnown() && CHILD(0).contains(mstruct, false) > 0) { + // nounit(v)*v=nounit(v)*nounit(v)*(units in v) + // try extracting units from variable + if(separate_unit_vars(mstruct, eo, false)) { + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } else if(mstruct.isPower() && mstruct[0].isVariable() && mstruct[0].variable()->isKnown() && CHILD(0).contains(mstruct[0], false) > 0) { + // nounit(v)*v^a=nounit(v)*(nounit(v)*(units in v))^a + // try extracting units from variable + if(separate_unit_vars(mstruct[0], eo, false)) { + mstruct.calculateRaiseExponent(eo); + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } + } + } + default: { + switch(mstruct.type()) { + case STRUCT_VECTOR: {} + case STRUCT_ADDITION: {} + case STRUCT_MULTIPLICATION: {} + case STRUCT_POWER: { + // try again with reversed order + return 0; + } + case STRUCT_COMPARISON: { + if(isComparison()) { + // use logical and for multiplication of comparisons (logical and equals multiplication) + mstruct.ref(); + transform_nocopy(STRUCT_LOGICAL_AND, &mstruct); + return 1; + } + } + default: { + if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_STRIP_UNITS && mstruct.size() == 1) { + if(m_type == STRUCT_VARIABLE && o_variable->isKnown() && mstruct[0].contains(*this, false) > 0) { + // v*nounit(v)=nounit(v)*nounit(v)*(units in v) + // try extracting units from variable + if(separate_unit_vars(*this, eo, false)) { + mstruct.ref(); + multiply_nocopy(&mstruct); + calculateMultiplyLast(eo); + return 1; + } + } + } + // x*0=0 (keep units and check if not matrix and not undefined) + if(mstruct.isZero() && (!eo.keep_zero_units || containsType(STRUCT_UNIT, false, true, true) <= 0 || (isUnit() && unit() == CALCULATOR->getRadUnit()) || (isFunction() && representsNumber(false))) && !representsUndefined(true, true, !eo.assume_denominators_nonzero) && representsNonMatrix()) { + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 3; + } + // 0*x=0 (keep units and check if not matrix and not undefined) + if(isZero() && !mstruct.representsUndefined(true, true, !eo.assume_denominators_nonzero) && (!eo.keep_zero_units || mstruct.containsType(STRUCT_UNIT, false, true, true) <= 0 || (mstruct.isUnit() && mstruct.unit() == CALCULATOR->getRadUnit())) && mstruct.representsNonMatrix()) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + if(equals(mstruct)) { + // x*x=x^2 + if(mstruct.isUnit() && mstruct.prefix()) o_prefix = mstruct.prefix(); + raise_nocopy(new MathStructure(2, 1, 0)); + MERGE_APPROX_AND_PREC(mstruct) + calculateRaiseExponent(eo, mparent, index_this); + return 1; + } + break; + } + } + break; + } + } + return -1; +} + +bool test_if_numerator_not_too_large(Number &vb, Number &ve) { + if(!vb.isRational()) return false; + if(!mpz_fits_slong_p(mpq_numref(ve.internalRational()))) return false; + long int exp = labs(mpz_get_si(mpq_numref(ve.internalRational()))); + if(vb.isRational()) { + if((long long int) exp * mpz_sizeinbase(mpq_numref(vb.internalRational()), 10) <= 1000000LL && (long long int) exp * mpz_sizeinbase(mpq_denref(vb.internalRational()), 10) <= 1000000LL) return true; + } + return false; +} + +bool is_negation(const MathStructure &m1, const MathStructure &m2) { + if(m1.isAddition() && m2.isAddition() && m1.size() == m2.size()) { + for(size_t i = 0; i < m1.size(); i++) { + if(!is_negation(m1[i], m2[i])) return false; + } + return true; + } + if(m1.isNumber() && m2.isNumber()) { + return m1.number() == -m2.number(); + } + if(m1.isMultiplication() && m1.size() > 1) { + if(m1[0].isNumber()) { + if(m1[0].number().isMinusOne()) { + if(m1.size() == 2) return m1[1] == m2; + if(m2.isMultiplication() && m2.size() == m1.size() - 1) { + for(size_t i = 1; i < m1.size(); i++) { + if(!m1[i].equals(m2[i - 1], true, true)) return false; + } + return true; + } + return false; + } else { + if(m2.isMultiplication() && m2.size() == m1.size() && m2[0].isNumber()) { + for(size_t i = 1; i < m1.size(); i++) { + if(!m1[i].equals(m2[i], true, true)) return false; + } + return m1[0].number().equals(-m2[0].number(), true, true); + } + return false; + } + } + } + if(m2.isMultiplication() && m2.size() > 1) { + if(m2[0].isNumber()) { + if(m2[0].number().isMinusOne()) { + if(m2.size() == 2) return m2[1] == m1; + if(m1.isMultiplication() && m1.size() == m2.size() - 1) { + for(size_t i = 1; i < m2.size(); i++) { + if(!m2[i].equals(m1[i - 1], true, true)) return false; + } + return true; + } + return false; + } + } + } + return false; +} + +int MathStructure::merge_power(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool) { + // test if base and exponent can be merged + if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { + // base and exponent are numbers try Number::raise() + Number nr(o_number); + if(nr.raise(mstruct.number(), eo.approximation < APPROXIMATION_APPROXIMATE) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) { + // Exponentiation succeeded without inappropriate change in approximation status + if(o_number == nr) { + o_number = nr; + numberUpdated(); + return 2; + } + o_number = nr; + numberUpdated(); + return 1; + } + if(!o_number.isMinusOne() && !o_number.isOne() && mstruct.number().isRational() && !mstruct.isInteger()) { + if(o_number.isNegative()) { + // (-a)^b=(-1)^b*a^b + MathStructure mtest(*this); + if(mtest.number().negate() && mtest.calculateRaise(mstruct, eo)) { + set(mtest); + MathStructure *mmul = new MathStructure(-1, 1, 0); + mmul->calculateRaise(mstruct, eo); + multiply_nocopy(mmul); + calculateMultiplyLast(eo); + return 1; + } + } else { + Number exp_num(mstruct.number().numerator()); + if(!exp_num.isOne() && !exp_num.isMinusOne() && o_number.isPositive() && test_if_numerator_not_too_large(o_number, exp_num)) { + // a^(n/d)=(a^n)^(1/d) + nr = o_number; + if(nr.raise(exp_num, eo.approximation < APPROXIMATION_APPROXIMATE) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) { + o_number = nr; + numberUpdated(); + nr.set(mstruct.number().denominator()); + nr.recip(); + calculateRaise(nr, eo, mparent, index_this); + return 1; + } + } + if(o_number.isPositive()) { + Number nr_root(mstruct.number().denominator()); + if(eo.split_squares && o_number.isInteger() && o_number.integerLength() < 100000L && nr_root.isLessThanOrEqualTo(LARGEST_RAISED_PRIME_EXPONENT)) { + // a^(1/d)=b^(1/d)*(a/b)^(1/d) + // search list of primes raised by the exponent denominator for value which can divide the base without remainder + int root = nr_root.intValue(); + nr.set(1, 1, 0); + bool b = true, overflow; + long int val; + while(b) { + if(CALCULATOR->aborted()) break; + b = false; + overflow = false; + val = o_number.lintValue(&overflow); + if(overflow) { + mpz_srcptr cval = mpq_numref(o_number.internalRational()); + for(size_t i = 0; root == 2 ? (i < NR_OF_SQUARE_PRIMES) : (RAISED_PRIMES[root - 3][i] != 0); i++) { + if(CALCULATOR->aborted()) break; + if(mpz_divisible_ui_p(cval, (unsigned long int) (root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]))) { + nr *= PRIMES[i]; + o_number /= (root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]); + b = true; + break; + } + } + } else { + for(size_t i = 0; root == 2 ? (i < NR_OF_SQUARE_PRIMES) : (RAISED_PRIMES[root - 3][i] != 0); i++) { + if(CALCULATOR->aborted()) break; + if((root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]) > val) { + break; + } else if(val % (root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]) == 0) { + nr *= PRIMES[i]; + o_number /= (root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]); + b = true; + break; + } + } + } + } + if(!nr.isOne()) { + transform(STRUCT_MULTIPLICATION); + CHILD(0).calculateRaise(mstruct, eo, this, 0); + PREPEND(nr); + if(!mstruct.number().numeratorIsOne()) { + CHILD(0).calculateRaise(mstruct.number().numerator(), eo, this, 0); + } + calculateMultiplyIndex(0, eo, true, mparent, index_this); + return 1; + } + } + if(eo.split_squares && nr_root != 2) { + // partial roots, e.g. 9^(1/4)=3^(1/2) + // if denominator is even try square root + if(nr_root.isEven()) { + Number nr(o_number); + if(nr.sqrt() && !nr.isApproximate()) { + o_number = nr; + mstruct.number().multiply(2); + mstruct.ref(); + raise_nocopy(&mstruct); + calculateRaiseExponent(eo, mparent, index_this); + return 1; + } + } + // test if denominator is divisible with prime number (each from PRIMES array) and try calculating root + for(size_t i = 1; i < NR_OF_PRIMES; i++) { + if(nr_root.isLessThanOrEqualTo(PRIMES[i])) break; + if(nr_root.isIntegerDivisible(PRIMES[i])) { + Number nr(o_number); + if(nr.root(Number(PRIMES[i], 1)) && !nr.isApproximate()) { + o_number = nr; + mstruct.number().multiply(PRIMES[i]); + mstruct.ref(); + raise_nocopy(&mstruct); + calculateRaiseExponent(eo, mparent, index_this); + return 1; + } + } + } + } + } + } + } + if(o_number.isMinusOne() && mstruct.number().isRational()) { + if(mstruct.number().isInteger()) { + // (-1)^n equals 1 if n is even, -1 if n is odd (is normally handled above) + if(mstruct.number().isEven()) set(m_one, true); + else set(m_minus_one, true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else { + Number nr_floor(mstruct.number()); + nr_floor.floor(); + if(mstruct.number().denominatorIsTwo()) { + // (-1)^(n/2) equals i if floor(n/2) is even and -i if floor(n/2) is odd + if(nr_floor.isEven()) set(nr_one_i, true); + else set(nr_minus_i, true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else { + mstruct.number() -= nr_floor; + mstruct.numberUpdated(); + if(mstruct.number().denominator() == 3) { + // (-1)^(n/3) equals (1+sqrt(3)*i)/2; negate if floor(n/3) is odd + set(3, 1, 0, true); + calculateRaise(nr_half, eo); + if(nr_floor.isEven()) calculateMultiply(nr_one_i, eo); + else calculateMultiply(nr_minus_i, eo); + calculateMultiply(nr_half, eo); + if(nr_floor.isEven() == mstruct.number().numeratorIsOne()) calculateAdd(nr_half, eo); + else calculateAdd(nr_minus_half, eo); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mstruct.number().denominator() == 4) { + // (-1)^(n/4) equals (1+i)*1/sqrt(2) if floor(n/4) is even and (-1-i)*1/sqrt(2) if floor(n/4) is odd + if(nr_floor.isEven() == mstruct.number().numeratorIsOne()) set(1, 1, 0, true); + else set(-1, 1, 0, true); + if(nr_floor.isEven()) calculateAdd(nr_one_i, eo); + else calculateAdd(nr_minus_i, eo); + multiply(nr_two); + LAST.calculateRaise(nr_minus_half, eo); + calculateMultiplyLast(eo); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(!nr_floor.isZero()) { + // (-1)^(n/d)=(-1)^(n/d-floor(n/d)); negate if floor(n/d) is odd + // e.g. (-1)^(7/5)=-(-1)^(2/5) + mstruct.ref(); + raise_nocopy(&mstruct); + calculateRaiseExponent(eo); + if(nr_floor.isOdd()) calculateNegate(eo); + return 1; + } + } + } + } + if(o_number.isRational() && !o_number.isInteger() && !o_number.numeratorIsOne() && mstruct.number().isRational()) { + // (n/d)^a=n^a*1/d^a + Number num(o_number.numerator()); + Number den(o_number.denominator()); + if(den.integerLength() < 100000L && num.integerLength() < 100000L) { + set(num, true); + calculateRaise(mstruct, eo); + multiply(den); + LAST.calculateRaise(mstruct, eo); + LAST.calculateInverse(eo); + calculateMultiplyLast(eo); + return 1; + } + } + // If base numerator is larger than denominator, invert base and negate exponent + if(o_number.isRational() && !o_number.isInteger() && !o_number.isZero() && ((o_number.isNegative() && o_number.isGreaterThan(nr_minus_one) && mstruct.number().isInteger()) || (o_number.isPositive() && o_number.isLessThan(nr_one)))) { + mstruct.number().negate(); + o_number.recip(); + return 0; + } + return -1; + } + + if(mstruct.isOne()) { + // x^1=x + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } else if(isOne() && mstruct.representsNumber()) { + // 1^x=1 + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + if(m_type == STRUCT_NUMBER && o_number.isInfinite(false)) { + if(mstruct.representsNegative(false)) { + // infinity^(-a)=0 + o_number.clear(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mstruct.representsPositive(false)) { + if(o_number.isMinusInfinity()) { + if(mstruct.representsEven(false)) { + // (-infinity)^a=infinity if a is even + o_number.setPlusInfinity(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mstruct.representsOdd(false)) { + // (-infinity)^a=-infinity if a is odd + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(o_number.isPlusInfinity()) { + // infinity^a=infinity + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + MathStructure mtest(mstruct); + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(CALCULATOR->usesIntervalArithmetic()) { + CALCULATOR->beginTemporaryStopMessages(); + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + if(eo2.interval_calculation == INTERVAL_CALCULATION_NONE) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; + mtest.calculateFunctions(eo2); + mtest.calculatesub(eo2, eo2); + CALCULATOR->endTemporaryStopMessages(); + } + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + if(mtest.representsNegative(false)) { + // infinity^(-a)=0 + o_number.clear(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mtest.representsNonZero(false) && mtest.representsPositive(false)) { + if(o_number.isMinusInfinity()) { + if(mstruct.representsEven(false)) { + // (-infinity)^a=infinity if a is even + o_number.setPlusInfinity(); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mstruct.representsOdd(false)) { + // (-infinity)^a=-infinity if a is odd + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(o_number.isPlusInfinity()) { + // infinity^a=infinity + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } else if(mstruct.isNumber() && mstruct.number().isInfinite(false)) { + // test calculation of base when exponent is infinite + MathStructure mtest(*this); + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(CALCULATOR->usesIntervalArithmetic()) { + CALCULATOR->beginTemporaryStopMessages(); + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + if(eo2.interval_calculation == INTERVAL_CALCULATION_NONE) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; + mtest.calculateFunctions(eo2); + mtest.calculatesub(eo2, eo2); + CALCULATOR->endTemporaryStopMessages(); + } + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + if(mtest.isNumber()) { + if(mtest.merge_power(mstruct, eo) > 0 && mtest.isNumber()) { + if(mtest.number().isPlusInfinity()) { + set(nr_plus_inf, true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mtest.number().isMinusInfinity()) { + set(nr_minus_inf, true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mtest.number().isZero()) { + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } + } + + if(representsUndefined() || mstruct.representsUndefined()) return -1; + if(isZero() && mstruct.representsPositive()) { + // 0^a=0 if a is positive + return 1; + } + if(mstruct.isZero() && !representsUndefined(true, true)) { + // x^0=1 + set(m_one); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + + switch(m_type) { + case STRUCT_VECTOR: { + if(mstruct.isNumber() && mstruct.number().isInteger()) { + if(isMatrix()) { + // matrix multiplication: m^n=m*m*m... + // requires equal number of columns and rows (columns of 1st matrix must be equal to rows in 2nd matrix) + if(matrixIsSquare()) { + Number nr(mstruct.number()); + // handle matrix inversion after multiplication + bool b_neg = false; + if(nr.isNegative()) { + nr.setNegative(false); + b_neg = true; + } + if(!nr.isOne()) { + MathStructure msave(*this); + nr--; + while(nr.isPositive()) { + if(CALCULATOR->aborted()) { + set(msave); + return -1; + } + calculateMultiply(msave, eo); + nr--; + } + } + if(b_neg) { + // exponent is negative: invert matrix + if(!invertMatrix(eo)) { + if(mstruct.number().isMinusOne()) return -1; + raise(nr_minus_one); + } + } + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + return -1; + } else { + // vector multiplication: do v^n=v^(n-1)*v + if(mstruct.number().isMinusOne()) { + return -1; + } + Number nr(mstruct.number()); + if(nr.isNegative()) { + nr++; + } else { + nr--; + } + MathStructure msave(*this); + calculateMultiply(msave, eo); + calculateRaise(nr, eo); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + + } + goto default_power_merge; + } + case STRUCT_ADDITION: { + if(mstruct.isNumber() && mstruct.number().isInteger() && containsType(STRUCT_DATETIME, false, true, false) <= 0) { + if(eo.reduce_divisions && mstruct.number().isMinusOne()) { + // 1/(a1+a2+...) + int bnum = -1, bden = -1; + // count difference between number of negative and positive terms + int inegs = 0; + bool b_break = false; + for(size_t i = 0; i < SIZE && !b_break; i++) { + switch(CHILD(i).type()) { + case STRUCT_NUMBER: { + if(!CHILD(i).number().isRational() || CHILD(i).number().numeratorIsGreaterThan(1000000L) || CHILD(i).number().numeratorIsLessThan(-1000000L) || CHILD(i).number().denominatorIsGreaterThan(1000L)) { + bnum = 0; bden = 0; inegs = 0; b_break = true; + } + if(bden != 0 && !CHILD(i).number().isInteger()) bden = 1; + if(bnum != 0 && !CHILD(i).isZero()) { + if(CHILD(i).number().numeratorIsOne() || CHILD(i).number().numeratorIsMinusOne()) bnum = 0; + else bnum = 1; + } + if(CHILD(i).number().hasNegativeSign()) { + //negative term + inegs++; + // negative first term counts double + // (for predictable result when number of negative and positive terms are equal) + if(i == 0) inegs++; + } else if(!CHILD(i).number().isZero()) { + // positive term + inegs--; + } + break; + } + case STRUCT_MULTIPLICATION: { + if(CHILD(i).size() > 0 && CHILD(i)[0].isNumber()) { + if(!CHILD(i)[0].number().isRational() || CHILD(i)[0].number().numeratorIsGreaterThan(1000000L) || CHILD(i)[0].number().numeratorIsLessThan(-1000000L) || CHILD(i)[0].number().denominatorIsGreaterThan(1000L)) { + bnum = 0; bden = 0; inegs = 0; b_break = true; + } + if(bden != 0 && !CHILD(i)[0].number().isInteger()) bden = 1; + if(bnum != 0 && !CHILD(i)[0].isZero()) { + if(CHILD(i)[0].number().numeratorIsOne() || CHILD(i)[0].number().numeratorIsMinusOne()) bnum = 0; + else bnum = 1; + } + if(CHILD(i)[0].number().hasNegativeSign()) { + //negative term + inegs++; + // negative first term counts double + if(i == 0) inegs++; + } else if(!CHILD(i)[0].number().isZero()) { + // positive term + inegs--; + } + break; + } + } + default: { + bnum = 0; + inegs--; + break; + } + } + } + if(bden < 0) bden = 0; + if(bnum < 0) bnum = 0; + if(bnum || bden) { + // denominator only contains rational multipliers (non-numerical values excluded) + // if bnum is true, denonimator contains multiplier with numerator > 1: + // determine the greater common divisor of multiplier numerators + // if bden is true, denominator contains non-integer multipliers: + // determine least common multiplier of multiplier denominators + Number nr_num, nr_den(1, 1, 0); + for(size_t i = 0; i < SIZE && !nr_den.isZero(); i++) { + switch(CHILD(i).type()) { + case STRUCT_NUMBER: { + if(CHILD(i).number().isInteger()) { + if(bnum && !nr_num.isOne() && !CHILD(i).number().isZero()) { + if(nr_num.isZero()) nr_num = CHILD(i).number(); + else nr_num.gcd(CHILD(i).number()); + } + } else { + if(bnum && !nr_num.isOne() && !CHILD(i).number().isZero()) { + if(nr_num.isZero()) nr_num = CHILD(i).number().numerator(); + else nr_num.gcd(CHILD(i).number().numerator()); + } + if(bden) { + nr_den.lcm(CHILD(i).number().denominator()); + if(nr_den.isGreaterThan(1000000L)) nr_den.clear(); + } + } + break; + } + case STRUCT_MULTIPLICATION: { + if(CHILD(i).size() > 0 && CHILD(i)[0].isNumber()) { + if(CHILD(i)[0].number().isInteger()) { + if(bnum && !nr_num.isOne() && !CHILD(i)[0].number().isZero()) { + if(nr_num.isZero()) nr_num = CHILD(i)[0].number(); + else nr_num.gcd(CHILD(i)[0].number()); + } + } else { + if(bnum && !nr_num.isOne() && !CHILD(i)[0].number().isZero()) { + if(nr_num.isZero()) nr_num = CHILD(i)[0].number().numerator(); + else nr_num.gcd(CHILD(i)[0].number().numerator()); + } + if(bden) { + nr_den.lcm(CHILD(i)[0].number().denominator()); + if(nr_den.isGreaterThan(1000000L)) nr_den.clear(); + } + } + break; + } + } + default: { + break; + } + } + } + if(!nr_den.isZero() && (!nr_den.isOne() || !nr_num.isOne())) { + Number nr(nr_den); + nr.divide(nr_num); + nr.setNegative(inegs > 0); + // multiply each term by lcm/gcd + // if the number of negative terms is greater than the number of positive terms, negate all terms + for(size_t i = 0; i < SIZE; i++) { + switch(CHILD(i).type()) { + case STRUCT_NUMBER: { + CHILD(i).number() *= nr; + break; + } + case STRUCT_MULTIPLICATION: { + if(CHILD(i).size() > 0 && CHILD(i)[0].isNumber()) { + CHILD(i)[0].number() *= nr; + CHILD(i).calculateMultiplyIndex(0, eo, true, this, i); + break; + } + } + default: { + CHILD(i).calculateMultiply(nr, eo); + } + } + } + calculatesub(eo, eo, false); + mstruct.ref(); + raise_nocopy(&mstruct); + calculateRaiseExponent(eo); + calculateMultiply(nr, eo, mparent, index_this); + return 1; + } + } + if(inegs > 0) { + // if the number of negative terms is greater than the number of positive terms: 1/(a1+a2+...)=-1/(-a1-a2-...) + // this makes it easier the handle expressions such as 1/(a1-a2-a3+a4)+1/(-a1+a2+a3-a4) (=0) + for(size_t i = 0; i < SIZE; i++) { + switch(CHILD(i).type()) { + case STRUCT_NUMBER: {CHILD(i).number().negate(); break;} + case STRUCT_MULTIPLICATION: { + if(CHILD(i).size() > 0 && CHILD(i)[0].isNumber()) { + CHILD(i)[0].number().negate(); + CHILD(i).calculateMultiplyIndex(0, eo, true, this, i); + break; + } + } + default: { + CHILD(i).calculateNegate(eo); + } + } + } + mstruct.ref(); + raise_nocopy(&mstruct); + negate(); + return 1; + } + } else if(eo.expand != 0 && !mstruct.number().isZero() && (eo.expand > -2 || !containsInterval())) { + // (a1+a2+a3...)^b + bool b = true; + bool neg = mstruct.number().isNegative(); + Number m(mstruct.number()); + m.setNegative(false); + if(SIZE > 1) { + // determine if addition exponentiation should be expanded + // if number of terms and exponent is small enough to allow reasonably fast calculation + if(eo.expand == -1) { + // use more conservative values + switch(SIZE) { + case 4: {if(m.isGreaterThan(3)) {b = false;} break;} + case 3: {if(m.isGreaterThan(4)) {b = false;} break;} + case 2: {if(m.isGreaterThan(10)) {b = false;} break;} + default: { + if(SIZE > 8 || m.isGreaterThan(2)) b = false; + } + } + } else { + b = false; + long int i_pow = m.lintValue(&b); + if(b || i_pow > 300) { + b = false; + } else { + Number num_terms; + if(num_terms.binomial(i_pow + (long int) SIZE - 1, (long int) SIZE - 1)) { + size_t tc = countTotalChildren() / SIZE; + if(tc <= 4) tc = 0; + else tc -= 4; + b = num_terms.isLessThanOrEqualTo(tc > 1 ? 300 / tc : 300); + } + } + } + } + if(b) { + if(!representsNonMatrix()) { + // use simple expansion for base which might be/inlcude matrix(es): (a+b)^n=(a+b)(a+b)... + MathStructure mthis(*this); + while(!m.isOne()) { + if(CALCULATOR->aborted()) { + set(mthis); + goto default_power_merge; + } + calculateMultiply(mthis, eo); + m--; + } + } else { + // use binomial theorem + MathStructure mstruct1(CHILD(0)); + MathStructure mstruct2(CHILD(1)); + for(size_t i = 2; i < SIZE; i++) { + if(CALCULATOR->aborted()) goto default_power_merge; + mstruct2.add(CHILD(i), true); + } + Number k(1); + Number p1(m); + Number p2(1); + p1--; + Number bn; + MathStructure msave(*this); + CLEAR + APPEND(mstruct1); + CHILD(0).calculateRaise(m, eo); + while(k.isLessThan(m)) { + if(CALCULATOR->aborted() || !bn.binomial(m, k)) { + set(msave); + goto default_power_merge; + } + APPEND_NEW(bn); + LAST.multiply(mstruct1); + if(!p1.isOne()) { + LAST[1].raise_nocopy(new MathStructure(p1)); + LAST[1].calculateRaiseExponent(eo); + } + LAST.multiply(mstruct2, true); + if(!p2.isOne()) { + LAST[2].raise_nocopy(new MathStructure(p2)); + LAST[2].calculateRaiseExponent(eo); + } + LAST.calculatesub(eo, eo, false); + k++; + p1--; + p2++; + } + APPEND(mstruct2); + LAST.calculateRaise(m, eo); + calculatesub(eo, eo, false); + } + // negative exponent: inverse after expansion (using absolute exponent) + if(neg) calculateInverse(eo); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } + goto default_power_merge; + } + case STRUCT_MULTIPLICATION: { + if(mstruct.representsInteger()) { + // (xy)^a=x^a*y^a + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).calculateRaise(mstruct, eo); + } + MERGE_APPROX_AND_PREC(mstruct) + calculatesub(eo, eo, false, mparent, index_this); + return 1; + } else if(!mstruct.isInfinite()) { + // (-5xy)^z=5^z*x^z*(-y)^z && x >= 0 && y<0 + MathStructure mnew; + mnew.setType(STRUCT_MULTIPLICATION); + for(size_t i = 0; i < SIZE;) { + if(CHILD(i).representsNonNegative(true)) { + CHILD(i).ref(); + mnew.addChild_nocopy(&CHILD(i)); + ERASE(i); + } else if(CHILD(i).isNumber() && CHILD(i).number().isNegative() && !CHILD(i).number().isMinusOne()) { + // (-5)^z=5^z*(-1)^z + CHILD(i).number().negate(); + mnew.addChild(CHILD(i)); + CHILD(i).number().set(-1, 1, 0); + i++; + } else { + i++; + } + } + if(mnew.size() > 0) { + if(SIZE > 0) { + if(SIZE == 1) SET_CHILD_MAP(0) + mnew.addChild(*this); + } + set_nocopy(mnew, true); + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).calculateRaise(mstruct, eo); + } + MERGE_APPROX_AND_PREC(mstruct) + calculatesub(eo, eo, false, mparent, index_this); + return 1; + } + } + goto default_power_merge; + } + case STRUCT_POWER: { + // (x^y)^z + if((eo.allow_complex && CHILD(1).representsFraction()) || (mstruct.representsInteger() && (eo.allow_complex || CHILD(0).representsInteger())) || representsNonNegative(true)) { + // (x^a)^b=x^(a*b) if x>=0 or -1getFunctionById(FUNCTION_ID_ABS), &mstruct_base, NULL); + } + } else if(!CHILD(1).representsOdd() && !CHILD(0).representsNonNegative(true)) { + // it is not known if a is even or odd (and x might be negative) + goto default_power_merge; + } + } + mstruct.ref(); + MERGE_APPROX_AND_PREC(mstruct) + CHILD(1).multiply_nocopy(&mstruct, true); + CHILD(1).calculateMultiplyLast(eo, true, this, 1); + calculateRaiseExponent(eo, mparent, index_this); + return 1; + } + if(mstruct.isNumber() && CHILD(0).isVariable() && CHILD(0).variable()->id() == VARIABLE_ID_E && CHILD(1).isNumber() && CHILD(1).number().hasImaginaryPart() && !CHILD(1).number().hasRealPart() && mstruct.number().isReal()) { + // (e^(a*i))^b + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(CALCULATOR->usesIntervalArithmetic()) { + // calculate floor((a+pi)/pi/2) and make sure that upper and lower value is equal + CALCULATOR->beginTemporaryStopMessages(); + Number nr(*CHILD(1).number().internalImaginary()); + Number nrpi; nrpi.pi(); + nr.add(nrpi); + nr.divide(nrpi); + nr.divide(2); + Number nr_u(nr.upperEndPoint()); + nr = nr.lowerEndPoint(); + nr_u.floor(); + nr.floor(); + if(!CALCULATOR->endTemporaryStopMessages() && nr == nr_u) { + // (e^(a*i))^b = e^((a-2i*floor((a+pi)/pi/2))*b) + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + nr.setApproximate(false); + nr *= 2; + nr.negate(); + nr *= nr_one_i; + if(!nr.isZero()) { + CHILD(1) += nr; + CHILD(1).last() *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + } + mstruct.ref(); + CHILD(1).multiply_nocopy(&mstruct, true); + CHILD(1).calculateMultiplyLast(eo, true, this, 1); + calculateRaiseExponent(eo, mparent, index_this); + return true; + } + } + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + } + goto default_power_merge; + } + case STRUCT_VARIABLE: { + if(o_variable->id() == VARIABLE_ID_E) { + if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber()) { + if(mstruct[1].isVariable() && mstruct[1].variable()->id() == VARIABLE_ID_PI) { + if(mstruct[0].number().isI() || mstruct[0].number().isMinusI()) { + //e^(i*pi)=-1 + set(m_minus_one, true); + return 1; + } else if(mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().hasRealPart() && mstruct[0].number().internalImaginary()->isRational()) { + // e^(a*i*pi)=(-1)^(a) + set(-1, 1, 0, true); + calculateRaise(*mstruct[0].number().internalImaginary(), eo); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(mstruct[0].number().isI() && mstruct[1].isFunction() && mstruct[1].function()->id() == FUNCTION_ID_ATAN && mstruct[1].size() == 1 && !mstruct[1][0].containsUnknowns() && ((eo.expand != 0 && eo.expand > -2) || !mstruct[1][0].containsInterval(true, false, false, eo.expand == -2 ? 1 : 0))) { + //e^(i*atan(x))=(x*i+1)/sqrt(x^2+1) + set(mstruct[1][0], true); + calculateRaise(nr_two, eo); + calculateAdd(m_one, eo); + calculateRaise(nr_half, eo); + calculateInverse(eo); + multiply(mstruct[1][0]); + LAST.calculateMultiply(nr_one_i, eo); + LAST.calculateAdd(m_one, eo); + calculateMultiplyLast(eo); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } else if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_LOG && mstruct.size() == 1) { + if(mstruct[0].representsNumber() && (eo.allow_infinite || mstruct[0].representsNonZero())) { + // e^ln(x)=x; x!=0 + set_nocopy(mstruct[0], true); + return 1; + } + } + } + goto default_power_merge; + } + case STRUCT_FUNCTION: { + if(eo.protected_function != o_function) { + if(o_function->id() == FUNCTION_ID_ABS && SIZE == 1) { + if(mstruct.representsEven() && CHILD(0).representsReal(true)) { + // abs(x)^2=x^2 + SET_CHILD_MAP(0); + mstruct.ref(); + raise_nocopy(&mstruct); + calculateRaiseExponent(eo); + return 1; + } + } else if(o_function->id() == FUNCTION_ID_SIGNUM && CHILD(0).representsReal(true) && SIZE == 2 && ((CHILD(1).isZero() && mstruct.representsPositive()) || CHILD(1).isOne())) { + if(mstruct.representsOdd()) { + // sgn(x)^3=sgn(x) + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mstruct.representsEven()) { + if(CHILD(1).isOne() && CHILD(0).representsReal(true)) { + SET_CHILD_MAP(0) + return 1; + } else { + // sgn(x)^2=sgn(abs(x)) + CHILD(0).transformById(FUNCTION_ID_ABS); + CHILD_UPDATED(0) + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } else if(o_function->id() == FUNCTION_ID_ROOT && THIS_VALID_ROOT) { + if(mstruct.representsEven() && CHILD(0).representsReal(true) && CHILD(1).number().isOdd()) { + // root(x, 3)^2=abs(x)^(3/2) + CHILD(0).transformById(FUNCTION_ID_ABS); + CHILD(1).number().recip(); + m_type = STRUCT_POWER; + mstruct.ref(); + raise_nocopy(&mstruct); + calculateRaiseExponent(eo); + return 1; + } else if(mstruct.isNumber() && mstruct.number().isInteger() && !mstruct.number().isMinusOne()) { + if(mstruct == CHILD(1)) { + // root(x, a)^a=x + SET_CHILD_MAP(0) + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(mstruct.number().isIntegerDivisible(CHILD(1).number())) { + // root(x, a)^(2a)=x^2 + mstruct.calculateDivide(CHILD(1).number(), eo); + mstruct.ref(); + SET_CHILD_MAP(0) + raise_nocopy(&mstruct); + return 1; + } else if(CHILD(1).number().isIntegerDivisible(mstruct.number())) { + // root(x, 3a)^(a)=root(x, 3) + Number nr(CHILD(1).number()); + if(nr.divide(mstruct.number())) { + CHILD(1) = nr; + CHILD_UPDATED(1) + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } + } + } + if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1 && mstruct.containsType(STRUCT_UNIT, false, true, true) == 0) { + // nounit(x)^y=nounit(x^y) + mstruct.ref(); + CHILD(0).raise_nocopy(&mstruct); + return 1; + } + goto default_power_merge; + } + default: { + default_power_merge: + + if(mstruct.isAddition()) { + // x^(a+b+...) + bool b = representsNonNegative(true); + if(!b) { + // if x is not >= 0 each term of the exponent must be either an integer + // or, if x<0, a rational number with an even denominator + b = true; + bool bneg = representsNegative(true); + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct[i].representsInteger() && (!bneg || !eo.allow_complex || !mstruct[i].isNumber() || !mstruct[i].number().isRational() || !mstruct[i].number().denominatorIsEven())) { + b = false; + break; + } + } + } + if(b) { + // x^(a+b+...)=x^a*x^b*... + MathStructure msave(*this); + clear(true); + m_type = STRUCT_MULTIPLICATION; + MERGE_APPROX_AND_PREC(mstruct) + for(size_t i = 0; i < mstruct.size(); i++) { + APPEND(msave); + mstruct[i].ref(); + LAST.raise_nocopy(&mstruct[i]); + LAST.calculateRaiseExponent(eo); + calculateMultiplyLast(eo, false); + } + if(SIZE == 1) { + setToChild(1, false, mparent, index_this + 1); + } else if(SIZE == 0) { + clear(true); + } else { + evalSort(); + } + return 1; + } + } else if(mstruct.isMultiplication() && mstruct.size() > 1) { + // x^(a*b*...) + bool b = representsNonNegative(true); + if(!b) { + // all factors of the exponent must be integers + b = true; + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct[i].representsInteger()) { + b = false; + break; + } + } + } + if(b) { + // try raising the base by each factor separately: x^(a*b*c*...)=(x^a)^(b*c*...)) + MathStructure mthis(*this); + for(size_t i = 0; i < mstruct.size(); i++) { + if(i == 0) mthis.raise(mstruct[i]); + // exponent factor must be real and, if base is zero, positive + if(!mstruct[i].representsReal(true) || (isZero() && !mstruct[i].representsPositive(true))) continue; + if(i > 0) mthis[1] = mstruct[i]; + EvaluationOptions eo2 = eo; + eo2.split_squares = false; + // avoid abs(x)^(2a) loop + if(mthis.calculateRaiseExponent(eo2) && (!mthis.isPower() || ((!isFunction() || o_function->id() != FUNCTION_ID_ABS || SIZE != 1 || !CHILD(0).equals(mthis[0], true, true)) && (!is_negation(mthis[0], *this))))) { + set(mthis); + if(mstruct.size() == 2) { + if(i == 0) { + mstruct[1].ref(); + raise_nocopy(&mstruct[1]); + } else { + mstruct[0].ref(); + raise_nocopy(&mstruct[0]); + } + } else { + mstruct.ref(); + raise_nocopy(&mstruct); + CHILD(1).delChild(i + 1); + } + calculateRaiseExponent(eo); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + } + } else if(mstruct.isNumber() && mstruct.number().isRational() && !mstruct.number().isInteger() && !mstruct.number().numeratorIsOne() && !mstruct.number().numeratorIsMinusOne()) { + // x^(n/d) + if(representsNonNegative(true) && (m_type != STRUCT_FUNCTION || o_function->id() != FUNCTION_ID_ABS)) { + // x>0 + if(isMultiplication() && SIZE == 2 && CHILD(0).isMinusOne() && mstruct.number().numeratorIsEven()) { + // (-x)^(n/d), n is even + bool b; + if(mstruct.number().isNegative()) { + // n<0: test x^(-n) + MathStructure mtest(CHILD(1)); + b = mtest.calculateRaise(-mstruct.number().numerator(), eo); + if(b && mtest.isPower() && mtest[1] == -mstruct.number().numerator()) b = false; + if(!b) break; + // (-x)^(-n/d)=(x^n)^(-1/d) + set(mtest, true); + raise(m_minus_one); + CHILD(1).number() /= mstruct.number().denominator(); + } else { + // n>0: test x^n + MathStructure mtest(CHILD(1)); + b = mtest.calculateRaise(mstruct.number().numerator(), eo); + if(b && mtest.isPower() && mtest[1] == mstruct.number().numerator()) b = false; + if(!b) break; + // (-x)^(n/d)=(x^n)^(1/d) + set(mtest, true); + raise(m_one); + CHILD(1).number() /= mstruct.number().denominator(); + } + if(b) calculateRaiseExponent(eo); + return 1; + } + bool b; + if(mstruct.number().isNegative()) { + // try x^(-n/d)=(x^n)^(-1/d) + b = calculateRaise(-mstruct.number().numerator(), eo); + if(!b) { + setToChild(1); + break; + } + raise(m_minus_one); + CHILD(1).number() /= mstruct.number().denominator(); + } else { + // try x^(n/d)=(x^n)^(1/d) + b = calculateRaise(mstruct.number().numerator(), eo); + if(!b) { + setToChild(1); + break; + } + raise(m_one); + CHILD(1).number() /= mstruct.number().denominator(); + } + if(b) calculateRaiseExponent(eo); + return 1; + } + } + break; + } + } + + return -1; +} + +int MathStructure::merge_logical_and(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool) { + if(equals(mstruct, true, true)) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + if(mstruct.representsNonZero()) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + if(mstruct.isZero()) { + if(isZero()) return 2; + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 3; + } + if(representsNonZero()) { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + if(isZero()) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + + if(CALCULATOR->aborted()) return -1; + + if(eo.test_comparisons && isLogicalOr()) { + if(SIZE > 50) return -1; + if(mstruct.isLogicalOr()) { + if(mstruct.size() * SIZE > 50) return -1; + for(size_t i = 0; i < SIZE; ) { + MathStructure msave(CHILD(i)); + for(size_t i2 = 0; i2 < mstruct.size(); i2++) { + if(i2 > 0) { + insertChild(msave, i + 1); + } + CHILD(i).calculateLogicalAnd(mstruct[i2], eo, this, i); + i++; + } + } + } else { + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).calculateLogicalAnd(mstruct, eo, this, i); + } + } + MERGE_APPROX_AND_PREC(mstruct) + calculatesub(eo, eo, false); + return 1; + } else if(eo.test_comparisons && mstruct.isLogicalOr()) { + return 0; + } else if(isComparison() && mstruct.isComparison()) { + if(CHILD(0) == mstruct[0]) { + ComparisonResult cr = mstruct[1].compare(CHILD(1)); + ComparisonType ct1 = ct_comp, ct2 = mstruct.comparisonType(); + switch(cr) { + case COMPARISON_RESULT_NOT_EQUAL: { + if(ct_comp == COMPARISON_EQUALS && ct2 == COMPARISON_EQUALS) { + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(ct_comp == COMPARISON_EQUALS && ct2 == COMPARISON_NOT_EQUALS) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } else if(ct_comp == COMPARISON_NOT_EQUALS && ct2 == COMPARISON_EQUALS) { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + return -1; + } + case COMPARISON_RESULT_EQUAL: { + MERGE_APPROX_AND_PREC(mstruct) + if(ct_comp == ct2) return 1; + if(ct_comp == COMPARISON_NOT_EQUALS) { + if(ct2 == COMPARISON_LESS || ct2 == COMPARISON_EQUALS_LESS) { + ct_comp = COMPARISON_LESS; + if(ct2 == COMPARISON_LESS) return 3; + return 1; + } else if(ct2 == COMPARISON_GREATER || ct2 == COMPARISON_EQUALS_GREATER) { + ct_comp = COMPARISON_GREATER; + if(ct2 == COMPARISON_GREATER) return 3; + return 1; + } + } else if(ct2 == COMPARISON_NOT_EQUALS) { + if(ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) { + if(ct_comp == COMPARISON_LESS) return 2; + ct_comp = COMPARISON_LESS; + return 1; + } else if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) { + if(ct_comp == COMPARISON_GREATER) return 2; + ct_comp = COMPARISON_GREATER; + return 1; + } + } else if((ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_EQUALS) && (ct2 == COMPARISON_EQUALS_LESS || ct2 == COMPARISON_EQUALS_GREATER || ct2 == COMPARISON_EQUALS)) { + if(ct_comp == COMPARISON_EQUALS) return 2; + ct_comp = COMPARISON_EQUALS; + if(ct2 == COMPARISON_EQUALS) return 3; + return 1; + } else if((ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) && (ct2 == COMPARISON_LESS || ct2 == COMPARISON_EQUALS_LESS)) { + if(ct_comp == COMPARISON_LESS) return 2; + ct_comp = COMPARISON_LESS; + if(ct2 == COMPARISON_LESS) return 3; + return 1; + } else if((ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) && (ct2 == COMPARISON_GREATER || ct2 == COMPARISON_EQUALS_GREATER)) { + if(ct_comp == COMPARISON_GREATER) return 2; + ct_comp = COMPARISON_GREATER; + if(ct2 == COMPARISON_GREATER) return 3; + return 1; + } + clear(true); + return 1; + } + case COMPARISON_RESULT_EQUAL_OR_GREATER: { + switch(ct1) { + case COMPARISON_GREATER: {ct1 = COMPARISON_LESS; break;} + case COMPARISON_EQUALS_GREATER: {ct1 = COMPARISON_EQUALS_LESS; break;} + case COMPARISON_LESS: {ct1 = COMPARISON_GREATER; break;} + case COMPARISON_EQUALS_LESS: {ct1 = COMPARISON_EQUALS_GREATER; break;} + default: {} + } + switch(ct2) { + case COMPARISON_GREATER: {ct2 = COMPARISON_LESS; break;} + case COMPARISON_EQUALS_GREATER: {ct2 = COMPARISON_EQUALS_LESS; break;} + case COMPARISON_LESS: {ct2 = COMPARISON_GREATER; break;} + case COMPARISON_EQUALS_LESS: {ct2 = COMPARISON_EQUALS_GREATER; break;} + default: {} + } + } + case COMPARISON_RESULT_EQUAL_OR_LESS: { + switch(ct1) { + case COMPARISON_LESS: { + if(ct2 == COMPARISON_GREATER || ct2 == COMPARISON_EQUALS) { + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(ct2 == COMPARISON_LESS || ct2 == COMPARISON_EQUALS_LESS || ct2 == COMPARISON_NOT_EQUALS) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + break; + } + case COMPARISON_GREATER: { + if(ct2 == COMPARISON_GREATER) { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + break; + } + case COMPARISON_EQUALS_LESS: { + if(ct2 == COMPARISON_EQUALS_LESS) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + break; + } + case COMPARISON_EQUALS_GREATER: { + if(ct2 == COMPARISON_EQUALS_GREATER || ct2 == COMPARISON_EQUALS) { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + break; + } + case COMPARISON_EQUALS: { + if(ct2 == COMPARISON_GREATER) { + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + break; + } + case COMPARISON_NOT_EQUALS: { + if(ct2 == COMPARISON_GREATER) { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + break; + } + } + break; + } + case COMPARISON_RESULT_GREATER: { + switch(ct1) { + case COMPARISON_GREATER: {ct1 = COMPARISON_LESS; break;} + case COMPARISON_EQUALS_GREATER: {ct1 = COMPARISON_EQUALS_LESS; break;} + case COMPARISON_LESS: {ct1 = COMPARISON_GREATER; break;} + case COMPARISON_EQUALS_LESS: {ct1 = COMPARISON_EQUALS_GREATER; break;} + default: {} + } + switch(ct2) { + case COMPARISON_GREATER: {ct2 = COMPARISON_LESS; break;} + case COMPARISON_EQUALS_GREATER: {ct2 = COMPARISON_EQUALS_LESS; break;} + case COMPARISON_LESS: {ct2 = COMPARISON_GREATER; break;} + case COMPARISON_EQUALS_LESS: {ct2 = COMPARISON_EQUALS_GREATER; break;} + default: {} + } + } + case COMPARISON_RESULT_LESS: { + switch(ct1) { + case COMPARISON_EQUALS: { + switch(ct2) { + case COMPARISON_EQUALS: {} + case COMPARISON_EQUALS_GREATER: {} + case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) clear(true); return 1;} + case COMPARISON_NOT_EQUALS: {} + case COMPARISON_EQUALS_LESS: {} + case COMPARISON_LESS: {MERGE_APPROX_AND_PREC(mstruct) return 2;} + default: {} + } + break; + } + case COMPARISON_NOT_EQUALS: { + switch(ct2) { + case COMPARISON_EQUALS: {} + case COMPARISON_EQUALS_GREATER: {} + case COMPARISON_GREATER: { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + default: {} + } + break; + } + case COMPARISON_EQUALS_LESS: {} + case COMPARISON_LESS: { + switch(ct2) { + case COMPARISON_EQUALS: {} + case COMPARISON_EQUALS_GREATER: {} + case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) clear(true); return 1;} + case COMPARISON_NOT_EQUALS: {} + case COMPARISON_EQUALS_LESS: {} + case COMPARISON_LESS: {MERGE_APPROX_AND_PREC(mstruct) return 2;} + } + break; + } + case COMPARISON_EQUALS_GREATER: {} + case COMPARISON_GREATER: { + switch(ct2) { + case COMPARISON_EQUALS: {} + case COMPARISON_EQUALS_GREATER: {} + case COMPARISON_GREATER: { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + default: {} + } + break; + } + } + break; + } + default: { + if(!eo.test_comparisons) return -1; + if(comparisonType() == COMPARISON_EQUALS && !CHILD(1).contains(mstruct[0])) { + mstruct.calculateReplace(CHILD(0), CHILD(1), eo); + if(eo.isolate_x) {mstruct.isolate_x(eo, eo); mstruct.calculatesub(eo, eo, true);} + mstruct.ref(); + add_nocopy(&mstruct, OPERATION_LOGICAL_AND); + calculateLogicalAndLast(eo); + return 1; + } else if(mstruct.comparisonType() == COMPARISON_EQUALS && !mstruct[1].contains(CHILD(0))) { + calculateReplace(mstruct[0], mstruct[1], eo); + if(eo.isolate_x) {isolate_x(eo, eo); calculatesub(eo, eo, true);} + mstruct.ref(); + add_nocopy(&mstruct, OPERATION_LOGICAL_AND); + calculateLogicalAndLast(eo); + return 1; + } + return -1; + } + } + } else if(eo.test_comparisons && comparisonType() == COMPARISON_EQUALS && !CHILD(0).isNumber() && !CHILD(0).containsInterval() && CHILD(1).isNumber() && mstruct.contains(CHILD(0))) { + mstruct.calculateReplace(CHILD(0), CHILD(1), eo); + if(eo.isolate_x) {mstruct.isolate_x(eo, eo); mstruct.calculatesub(eo, eo, true);} + mstruct.ref(); + add_nocopy(&mstruct, OPERATION_LOGICAL_AND); + calculateLogicalAndLast(eo); + return 1; + } else if(eo.test_comparisons && mstruct.comparisonType() == COMPARISON_EQUALS && !mstruct[0].isNumber() && !mstruct[0].containsInterval() && mstruct[1].isNumber() && contains(mstruct[0])) { + calculateReplace(mstruct[0], mstruct[1], eo); + if(eo.isolate_x) {isolate_x(eo, eo); calculatesub(eo, eo, true);} + mstruct.ref(); + add_nocopy(&mstruct, OPERATION_LOGICAL_AND); + calculateLogicalAndLast(eo); + return 1; + } + } else if(isLogicalAnd()) { + if(mstruct.isLogicalAnd()) { + for(size_t i = 0; i < mstruct.size(); i++) { + APPEND_REF(&mstruct[i]); + } + MERGE_APPROX_AND_PREC(mstruct) + calculatesub(eo, eo, false); + } else { + APPEND_REF(&mstruct); + MERGE_APPROX_AND_PREC(mstruct) + calculatesub(eo, eo, false); + } + return 1; + } else if(mstruct.isLogicalAnd()) { + transform(STRUCT_LOGICAL_AND); + for(size_t i = 0; i < mstruct.size(); i++) { + APPEND_REF(&mstruct[i]); + } + MERGE_APPROX_AND_PREC(mstruct) + calculatesub(eo, eo, false); + return 1; + } + return -1; + +} + +int MathStructure::merge_logical_or(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool) { + + if(mstruct.representsNonZero()) { + if(isOne()) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + set(1, 1, 0, true); + MERGE_APPROX_AND_PREC(mstruct) + return 3; + } + if(mstruct.isZero()) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + if(representsNonZero()) { + if(!isOne()) set(1, 1, 0, true); + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + if(isZero()) { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + if(equals(mstruct, true, true)) { + return 2; + } + if(isLogicalAnd()) { + if(mstruct.isLogicalAnd()) { + if(SIZE < mstruct.size()) { + bool b = true; + for(size_t i = 0; i < SIZE; i++) { + b = false; + for(size_t i2 = 0; i2 < mstruct.size(); i2++) { + if(CHILD(i) == mstruct[i2]) { + b = true; + break; + } + } + if(!b) break; + } + if(b) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + } else if(SIZE > mstruct.size()) { + bool b = true; + for(size_t i = 0; i < mstruct.size(); i++) { + b = false; + for(size_t i2 = 0; i2 < SIZE; i2++) { + if(mstruct[i] == CHILD(i2)) { + b = true; + break; + } + } + if(!b) break; + } + if(b) { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + } + } else { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i) == mstruct) { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + } + } + } else if(mstruct.isLogicalAnd()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(equals(mstruct[i])) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + } + } + + if(isComparison() && mstruct.isComparison()) { + if(CHILD(0) == mstruct[0]) { + ComparisonResult cr = mstruct[1].compare(CHILD(1)); + ComparisonType ct1 = ct_comp, ct2 = mstruct.comparisonType(); + switch(cr) { + case COMPARISON_RESULT_NOT_EQUAL: { + return -1; + } + case COMPARISON_RESULT_EQUAL: { + if(ct_comp == ct2) return 1; + switch(ct_comp) { + case COMPARISON_EQUALS: { + switch(ct2) { + case COMPARISON_NOT_EQUALS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} + case COMPARISON_EQUALS_LESS: {} + case COMPARISON_EQUALS_GREATER: {ct_comp = ct2; MERGE_APPROX_AND_PREC(mstruct) return 3;} + case COMPARISON_LESS: {ct_comp = COMPARISON_EQUALS_LESS; MERGE_APPROX_AND_PREC(mstruct) return 1;} + case COMPARISON_GREATER: {ct_comp = COMPARISON_EQUALS_GREATER; MERGE_APPROX_AND_PREC(mstruct) return 1;} + default: {} + } + break; + } + case COMPARISON_NOT_EQUALS: { + switch(ct2) { + case COMPARISON_EQUALS_LESS: {} + case COMPARISON_EQUALS_GREATER: {} + case COMPARISON_EQUALS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} + case COMPARISON_LESS: {} + case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) return 2;} + default: {} + } + break; + } + case COMPARISON_EQUALS_LESS: { + switch(ct2) { + case COMPARISON_NOT_EQUALS: {} + case COMPARISON_GREATER: {} + case COMPARISON_EQUALS_GREATER: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} + case COMPARISON_EQUALS: {} + case COMPARISON_LESS: {MERGE_APPROX_AND_PREC(mstruct) return 2;} + default: {} + } + break; + } + case COMPARISON_LESS: { + switch(ct2) { + case COMPARISON_NOT_EQUALS: {} + case COMPARISON_EQUALS_LESS: {ct_comp = ct2; MERGE_APPROX_AND_PREC(mstruct) return 3;} + case COMPARISON_EQUALS_GREATER: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} + case COMPARISON_EQUALS: {ct_comp = COMPARISON_EQUALS_LESS; MERGE_APPROX_AND_PREC(mstruct) return 1;} + case COMPARISON_GREATER: {ct_comp = COMPARISON_NOT_EQUALS; MERGE_APPROX_AND_PREC(mstruct) return 1;} + default: {} + } + break; + } + case COMPARISON_EQUALS_GREATER: { + switch(ct2) { + case COMPARISON_NOT_EQUALS: {} + case COMPARISON_LESS: {} + case COMPARISON_EQUALS_LESS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} + case COMPARISON_EQUALS: {} + case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) return 2;} + default: {} + } + break; + } + case COMPARISON_GREATER: { + switch(ct2) { + case COMPARISON_NOT_EQUALS: {} + case COMPARISON_EQUALS_GREATER: {ct_comp = ct2; MERGE_APPROX_AND_PREC(mstruct) return 3;} + case COMPARISON_EQUALS_LESS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} + case COMPARISON_EQUALS: {ct_comp = COMPARISON_EQUALS_GREATER; MERGE_APPROX_AND_PREC(mstruct) return 1;} + case COMPARISON_LESS: {ct_comp = COMPARISON_NOT_EQUALS; MERGE_APPROX_AND_PREC(mstruct) return 1;} + default: {} + } + break; + } + } + break; + } + case COMPARISON_RESULT_EQUAL_OR_GREATER: { + switch(ct1) { + case COMPARISON_GREATER: {ct1 = COMPARISON_LESS; break;} + case COMPARISON_EQUALS_GREATER: {ct1 = COMPARISON_EQUALS_LESS; break;} + case COMPARISON_LESS: {ct1 = COMPARISON_GREATER; break;} + case COMPARISON_EQUALS_LESS: {ct1 = COMPARISON_EQUALS_GREATER; break;} + default: {} + } + switch(ct2) { + case COMPARISON_GREATER: {ct2 = COMPARISON_LESS; break;} + case COMPARISON_EQUALS_GREATER: {ct2 = COMPARISON_EQUALS_LESS; break;} + case COMPARISON_LESS: {ct2 = COMPARISON_GREATER; break;} + case COMPARISON_EQUALS_LESS: {ct2 = COMPARISON_EQUALS_GREATER; break;} + default: {} + } + } + case COMPARISON_RESULT_EQUAL_OR_LESS: { + switch(ct1) { + case COMPARISON_LESS: { + if(ct2 == COMPARISON_LESS || ct2 == COMPARISON_EQUALS_LESS || ct2 == COMPARISON_NOT_EQUALS) { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + break; + } + case COMPARISON_GREATER: { + if(ct2 == COMPARISON_GREATER) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + break; + } + case COMPARISON_EQUALS_LESS: { + if(ct2 == COMPARISON_EQUALS_LESS) { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + break; + } + case COMPARISON_EQUALS_GREATER: { + if(ct2 == COMPARISON_EQUALS_GREATER || ct2 == COMPARISON_EQUALS) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + break; + } + case COMPARISON_NOT_EQUALS: { + if(ct2 == COMPARISON_GREATER) { + MERGE_APPROX_AND_PREC(mstruct) + return 2; + } + break; + } + default: {} + } + break; + } + case COMPARISON_RESULT_GREATER: { + switch(ct1) { + case COMPARISON_GREATER: {ct1 = COMPARISON_LESS; break;} + case COMPARISON_EQUALS_GREATER: {ct1 = COMPARISON_EQUALS_LESS; break;} + case COMPARISON_LESS: {ct1 = COMPARISON_GREATER; break;} + case COMPARISON_EQUALS_LESS: {ct1 = COMPARISON_EQUALS_GREATER; break;} + default: {} + } + switch(ct2) { + case COMPARISON_GREATER: {ct2 = COMPARISON_LESS; break;} + case COMPARISON_EQUALS_GREATER: {ct2 = COMPARISON_EQUALS_LESS; break;} + case COMPARISON_LESS: {ct2 = COMPARISON_GREATER; break;} + case COMPARISON_EQUALS_LESS: {ct2 = COMPARISON_EQUALS_GREATER; break;} + default: {} + } + } + case COMPARISON_RESULT_LESS: { + switch(ct1) { + case COMPARISON_EQUALS: { + switch(ct2) { + case COMPARISON_NOT_EQUALS: {} + case COMPARISON_EQUALS_LESS: {} + case COMPARISON_LESS: { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + default: {} + } + break; + } + case COMPARISON_NOT_EQUALS: { + switch(ct2) { + case COMPARISON_EQUALS: {} + case COMPARISON_EQUALS_GREATER: {} + case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) return 2;} + case COMPARISON_EQUALS_LESS: {} + case COMPARISON_LESS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} + default: {} + } + break; + } + case COMPARISON_EQUALS_LESS: {} + case COMPARISON_LESS: { + switch(ct2) { + case COMPARISON_NOT_EQUALS: {} + case COMPARISON_EQUALS_LESS: {} + case COMPARISON_LESS: { + if(mparent) { + mparent->swapChildren(index_this + 1, index_mstruct + 1); + } else { + set_nocopy(mstruct, true); + } + return 3; + } + default: {} + } + break; + } + case COMPARISON_EQUALS_GREATER: {} + case COMPARISON_GREATER: { + switch(ct2) { + case COMPARISON_NOT_EQUALS: {} + case COMPARISON_EQUALS_LESS: {} + case COMPARISON_LESS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} + case COMPARISON_EQUALS: {} + case COMPARISON_EQUALS_GREATER: {} + case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) return 2;} + } + break; + } + } + break; + } + default: { + return -1; + } + } + } else if(eo.test_comparisons && comparisonType() == COMPARISON_NOT_EQUALS && !CHILD(0).isNumber() && !CHILD(0).containsInterval() && CHILD(1).isNumber() && mstruct.contains(CHILD(0))) { + mstruct.calculateReplace(CHILD(0), CHILD(1), eo); + if(eo.isolate_x) {mstruct.isolate_x(eo, eo); mstruct.calculatesub(eo, eo, true);} + mstruct.ref(); + add_nocopy(&mstruct, OPERATION_LOGICAL_OR); + calculateLogicalOrLast(eo); + return 1; + } else if(eo.test_comparisons && mstruct.comparisonType() == COMPARISON_NOT_EQUALS && !mstruct[0].isNumber() && !mstruct[0].containsInterval() && mstruct[1].isNumber() && contains(mstruct[0])) { + calculateReplace(mstruct[0], mstruct[1], eo); + if(eo.isolate_x) {isolate_x(eo, eo); calculatesub(eo, eo, true);} + mstruct.ref(); + add_nocopy(&mstruct, OPERATION_LOGICAL_OR); + calculateLogicalOrLast(eo); + return 1; + } + } else if(isLogicalOr()) { + if(mstruct.isLogicalOr()) { + for(size_t i = 0; i < mstruct.size(); i++) { + APPEND_REF(&mstruct[i]); + } + MERGE_APPROX_AND_PREC(mstruct) + calculatesub(eo, eo, false); + } else { + APPEND_REF(&mstruct); + MERGE_APPROX_AND_PREC(mstruct) + calculatesub(eo, eo, false); + } + return 1; + } else if(mstruct.isLogicalOr()) { + transform(STRUCT_LOGICAL_OR); + for(size_t i = 0; i < mstruct.size(); i++) { + APPEND_REF(&mstruct[i]); + } + MERGE_APPROX_AND_PREC(mstruct) + calculatesub(eo, eo, false); + return 1; + } + return -1; + +} + +int MathStructure::merge_logical_xor(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure*, size_t, size_t, bool) { + + if(equals(mstruct)) { + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + bool bp1 = representsNonZero(); + bool bp2 = mstruct.representsNonZero(); + if(bp1 && bp2) { + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + bool bn1 = isZero(); + bool bn2 = mstruct.isZero(); + if(bn1 && bn2) { + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + if((bn1 && bp2) || (bp1 && bn2)) { + set(1, 1, 0, true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + return -1; + + /*int b0, b1; + if(isZero()) { + b0 = 0; + } else if(representsNonZero(true)) { + b0 = 1; + } else { + b0 = -1; + } + if(mstruct.isZero()) { + b1 = 0; + } else if(mstruct.representsNonZero(true)) { + b1 = 1; + } else { + b1 = -1; + } + + if((b0 == 1 && b1 == 0) || (b0 == 0 && b1 == 1)) { + set(1, 1, 0, true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(b0 >= 0 && b1 >= 0) { + clear(true); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(b0 == 0) { + set(mstruct, true); + add(m_zero, OPERATION_NOT_EQUALS); + calculatesub(eo, eo, false); + return 1; + } else if(b0 == 1) { + set(mstruct, true); + add(m_zero, OPERATION_EQUALS); + calculatesub(eo, eo, false); + return 1; + } else if(b1 == 0) { + add(m_zero, OPERATION_NOT_EQUALS); + calculatesub(eo, eo, false); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } else if(b1 == 1) { + add(m_zero, OPERATION_EQUALS); + calculatesub(eo, eo, false); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + MathStructure *mstruct2 = new MathStructure(*this); + add(mstruct, OPERATION_LOGICAL_AND); + LAST.calculateLogicalNot(eo); + LAST.calculatesub(eo, eo, false); + calculatesub(eo, eo, false); + mstruct2->setLogicalNot(); + mstruct2->calculatesub(eo, eo, false); + mstruct2->add(mstruct, OPERATION_LOGICAL_AND); + mstruct2->calculatesub(eo, eo, false); + add_nocopy(mstruct2, OPERATION_LOGICAL_OR); + calculatesub(eo, eo, false); + + return 1;*/ + +} + + +int MathStructure::merge_bitwise_and(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure*, size_t, size_t, bool) { + if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { + Number nr(o_number); + if(nr.bitAnd(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) { + if(o_number == nr) { + o_number = nr; + numberUpdated(); + return 2; + } + o_number = nr; + numberUpdated(); + return 1; + } + return -1; + } + switch(m_type) { + case STRUCT_VECTOR: { + switch(mstruct.type()) { + case STRUCT_VECTOR: { + if(SIZE < mstruct.size()) return 0; + for(size_t i = 0; i < mstruct.size(); i++) { + mstruct[i].ref(); + CHILD(i).add_nocopy(&mstruct[i], OPERATION_LOGICAL_AND); + CHILD(i).calculatesub(eo, eo, false); + } + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + default: { + return -1; + } + } + return -1; + } + case STRUCT_BITWISE_AND: { + switch(mstruct.type()) { + case STRUCT_VECTOR: { + return -1; + } + case STRUCT_BITWISE_AND: { + for(size_t i = 0; i < mstruct.size(); i++) { + APPEND_REF(&mstruct[i]); + } + calculatesub(eo, eo, false); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + default: { + APPEND_REF(&mstruct); + calculatesub(eo, eo, false); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + break; + } + default: { + switch(mstruct.type()) { + case STRUCT_BITWISE_AND: { + return 0; + } + default: {} + } + } + } + return -1; +} +int MathStructure::merge_bitwise_or(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure*, size_t, size_t, bool) { + if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { + Number nr(o_number); + if(nr.bitOr(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) { + if(o_number == nr) { + o_number = nr; + numberUpdated(); + return 2; + } + o_number = nr; + numberUpdated(); + return 1; + } + return -1; + } + switch(m_type) { + case STRUCT_VECTOR: { + switch(mstruct.type()) { + case STRUCT_VECTOR: { + if(SIZE < mstruct.size()) return 0; + for(size_t i = 0; i < mstruct.size(); i++) { + mstruct[i].ref(); + CHILD(i).add_nocopy(&mstruct[i], OPERATION_LOGICAL_OR); + CHILD(i).calculatesub(eo, eo, false); + } + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + default: { + return -1; + } + } + return -1; + } + case STRUCT_BITWISE_OR: { + switch(mstruct.type()) { + case STRUCT_VECTOR: { + return -1; + } + case STRUCT_BITWISE_OR: { + for(size_t i = 0; i < mstruct.size(); i++) { + APPEND_REF(&mstruct[i]); + } + calculatesub(eo, eo, false); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + default: { + APPEND_REF(&mstruct); + calculatesub(eo, eo, false); + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + } + break; + } + default: { + switch(mstruct.type()) { + case STRUCT_BITWISE_OR: { + return 0; + } + default: {} + } + } + } + return -1; +} +int MathStructure::merge_bitwise_xor(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure*, size_t, size_t, bool) { + if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { + Number nr(o_number); + if(nr.bitXor(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) { + if(o_number == nr) { + o_number = nr; + numberUpdated(); + return 2; + } + o_number = nr; + numberUpdated(); + return 1; + } + return -1; + } + switch(m_type) { + case STRUCT_VECTOR: { + switch(mstruct.type()) { + case STRUCT_VECTOR: { + if(SIZE < mstruct.size()) return 0; + for(size_t i = 0; i < mstruct.size(); i++) { + mstruct[i].ref(); + CHILD(i).add_nocopy(&mstruct[i], OPERATION_LOGICAL_XOR); + CHILD(i).calculatesub(eo, eo, false); + } + MERGE_APPROX_AND_PREC(mstruct) + return 1; + } + default: { + return -1; + } + } + return -1; + } + default: {} + } + return -1; +} + +#define MERGE_RECURSE if(recursive) {\ + for(size_t i = 0; i < SIZE; i++) {\ + if(CALCULATOR->aborted()) break;\ + if(!CHILD(i).isNumber()) CHILD(i).calculatesub(eo, feo, true, this, i);\ + }\ + CHILDREN_UPDATED;\ + } + +#define MERGE_ALL(FUNC, TRY_LABEL) size_t i2, i3 = SIZE;\ + bool do_abort = false; \ + for(size_t i = 0; i < SIZE - 1; i++) {\ + i2 = i + 1;\ + TRY_LABEL:\ + for(; i2 < i; i2++) {\ + if(CALCULATOR->aborted()) break;\ + int r = CHILD(i2).FUNC(CHILD(i), eo, this, i2, i);\ + if(r == 0) {\ + SWAP_CHILDREN(i2, i);\ + r = CHILD(i2).FUNC(CHILD(i), eo, this, i2, i, true);\ + if(r < 1) {\ + SWAP_CHILDREN(i2, i);\ + }\ + }\ + if(r >= 1) {\ + ERASE(i);\ + b = true;\ + i3 = i;\ + i = i2;\ + i2 = 0;\ + goto TRY_LABEL;\ + }\ + }\ + for(i2 = i + 1; i2 < SIZE; i2++) {\ + if(CALCULATOR->aborted()) break;\ + int r = CHILD(i).FUNC(CHILD(i2), eo, this, i, i2);\ + if(r == 0) {\ + SWAP_CHILDREN(i, i2);\ + r = CHILD(i).FUNC(CHILD(i2), eo, this, i, i2, true);\ + if(r < 1) {\ + SWAP_CHILDREN(i, i2);\ + } else if(r == 2) {\ + r = 3;\ + } else if(r == 3) {\ + r = 2;\ + }\ + }\ + if(r >= 1) {\ + ERASE(i2);\ + b = true;\ + if(r != 2) {\ + i2 = 0;\ + goto TRY_LABEL;\ + }\ + i2--;\ + } else if(CHILD(i).isDateTime()) {\ + do_abort = true;\ + break;\ + }\ + }\ + if(do_abort) break;\ + if(i3 < SIZE) {\ + if(i3 == SIZE - 1) break;\ + i = i3;\ + i3 = SIZE;\ + i2 = i + 1;\ + goto TRY_LABEL;\ + }\ + } + +#define MERGE_ALL2 if(SIZE == 1) {\ + setToChild(1, false, mparent, index_this + 1);\ + } else if(SIZE == 0) {\ + clear(true);\ + } else {\ + evalSort();\ + } + +bool fix_intervals(MathStructure &mstruct, const EvaluationOptions &eo, bool *failed, long int min_precision, bool function_middle) { + if(mstruct.type() == STRUCT_NUMBER) { + if(eo.interval_calculation != INTERVAL_CALCULATION_NONE) { + if(!mstruct.number().isInterval(false) && mstruct.number().precision() >= 0 && (CALCULATOR->usesIntervalArithmetic() || mstruct.number().precision() <= PRECISION + 10)) { + mstruct.number().precisionToInterval(); + mstruct.setPrecision(-1); + mstruct.numberUpdated(); + return true; + } + } else if(mstruct.number().isInterval(false)) { + if(!mstruct.number().intervalToPrecision(min_precision)) { + if(failed) *failed = true; + return false; + } + mstruct.numberUpdated(); + return true; + } + } else if(mstruct.type() == STRUCT_FUNCTION && (mstruct.function()->id() == FUNCTION_ID_INTERVAL || mstruct.function()->id() == FUNCTION_ID_UNCERTAINTY)) { + if(eo.interval_calculation == INTERVAL_CALCULATION_NONE) { + bool b = mstruct.calculateFunctions(eo, false); + if(b) { + fix_intervals(mstruct, eo, failed, function_middle); + return true; + } else if(function_middle && mstruct.type() == STRUCT_FUNCTION && mstruct.function()->id() == FUNCTION_ID_INTERVAL && mstruct.size() == 2) { + mstruct.setType(STRUCT_ADDITION); + mstruct.divide(nr_two); + return true; + } else if(function_middle && mstruct.type() == STRUCT_FUNCTION && mstruct.function()->id() == FUNCTION_ID_UNCERTAINTY && mstruct.size() >= 1) { + mstruct.setToChild(1, true); + return true; + } + } + } else { + bool b = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(fix_intervals(mstruct[i], eo, failed, function_middle)) { + mstruct.childUpdated(i + 1); + b = true; + } + } + return b; + } + return false; +} + +bool contains_zero_unit(const MathStructure &mstruct); +bool contains_zero_unit(const MathStructure &mstruct) { + if(mstruct.isMultiplication() && mstruct.size() > 1 && mstruct[0].isZero()) { + bool b = true; + for(size_t i = 1; i < mstruct.size(); i++) { + if(!mstruct[i].isUnit_exp()) { + b = false; + break; + } + } + if(b) return true; + } + for(size_t i = 0; i < mstruct.size(); i++) { + if(contains_zero_unit(mstruct[i])) return true; + } + return false; +} + +bool test_var_int(const MathStructure &mstruct, bool *v = NULL) { + if(mstruct.isVariable() && (mstruct.variable()->id() == VARIABLE_ID_E || mstruct.variable()->id() == VARIABLE_ID_PI)) { + if(!v) return true; + if(*v) return false; + else *v = true; + return true; + } + if(mstruct.isNumber() && mstruct.number().isReal()) { + if(!v) { + if(mstruct.number().isInterval()) { + Number nr_int(mstruct.number()); + nr_int.round(); + return mstruct.number() < nr_int || mstruct.number() > nr_int; + } + if(mstruct.isApproximate()) { + Number nr_f = mstruct.number(); + nr_f.floor(); + Number nr_c(nr_f); + nr_c++; + return COMPARISON_IS_NOT_EQUAL(mstruct.number().compareApproximately(nr_f)) && COMPARISON_IS_NOT_EQUAL(mstruct.number().compareApproximately(nr_c)); + } + return !mstruct.number().isInterval() && !mstruct.number().isInteger(); + } + if(mstruct.isApproximate()) return false; + return mstruct.number().isRational(); + } + if(mstruct.isMultiplication() || mstruct.isAddition() || (mstruct.isPower() && mstruct[1].isInteger())) { + bool v2 = false; + if(!v) v = &v2; + for(size_t i = 0; i < mstruct.size(); i++) { + if(!test_var_int(mstruct[i], v)) return false; + } + if(*v) return true; + } + return false; +} + +bool test_non_integer(const MathStructure &mstruct, const EvaluationOptions&) { + if(test_var_int(mstruct)) return true; + if(!mstruct.isApproximate()) { + if((mstruct.isMultiplication() || mstruct.isAddition()) && mstruct.size() >= 2 && mstruct[0].isNumber() && mstruct[0].number().isReal() && !mstruct[0].number().isInterval() && !mstruct[0].number().isInteger()) { + for(size_t i = 1; i < mstruct.size(); i++) { + if(!mstruct[i].representsInteger()) return false; + } + return true; + } + } + return false; +} +bool MathStructure::factorizeUnits() { + switch(m_type) { + case STRUCT_ADDITION: { + if(containsType(STRUCT_DATETIME, false, true, false) > 0) return false; + bool b = false; + MathStructure mstruct_units(*this); + MathStructure mstruct_new(*this); + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(CALCULATOR->aborted()) break; + if(mstruct_units[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct_units[i].size();) { + if(CALCULATOR->aborted()) break; + if(!mstruct_units[i][i2].isUnit_exp()) { + mstruct_units[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); + else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); + for(size_t i2 = 0; i2 < mstruct_new[i].size();) { + if(CALCULATOR->aborted()) break; + if(mstruct_new[i][i2].isUnit_exp()) { + mstruct_new[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); + else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); + } else if(mstruct_units[i].isUnit_exp()) { + mstruct_new[i].set(1, 1, 0); + } else { + mstruct_units[i].setUndefined(); + } + } + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(CALCULATOR->aborted()) break; + if(!mstruct_units[i].isUndefined()) { + for(size_t i2 = i + 1; i2 < mstruct_units.size();) { + if(mstruct_units[i2] == mstruct_units[i]) { + mstruct_new[i].add(mstruct_new[i2], true); + mstruct_new.delChild(i2 + 1); + mstruct_units.delChild(i2 + 1); + b = true; + } else { + i2++; + } + } + if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); + else mstruct_new[i].multiply(mstruct_units[i], true); + } + } + if(b) { + if(mstruct_new.size() == 1) set(mstruct_new[0], true); + else set(mstruct_new, true); + return true; + } + } + default: { + bool b = false; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) break; + if(CHILD(i).factorizeUnits()) { + CHILD_UPDATED(i); + b = true; + } + } + return b; + } + } +} + +bool MathStructure::calculatesub(const EvaluationOptions &eo, const EvaluationOptions &feo, bool recursive, MathStructure *mparent, size_t index_this) { + + // do not modify MathStructure marked as protected + if(b_protected) return false; + + bool b = false; + + // the normal process here is the first calculate all children (if recursive) and try merging every child with every other child + + switch(m_type) { + case STRUCT_VARIABLE: { + if(eo.calculate_variables && o_variable->isKnown()) { + // replace variable with value of calculation is approximate or variable is exact (variable is approximate if marked as approximate or value contains interval) + if((eo.approximation == APPROXIMATION_APPROXIMATE || (!o_variable->isApproximate() && !((KnownVariable*) o_variable)->get().containsInterval(true, false, false, 0, true))) && !((KnownVariable*) o_variable)->get().isAborted()) { + set(((KnownVariable*) o_variable)->get()); + unformat(eo); + if(eo.calculate_functions) { + // calculate any functions in the variable value + calculateFunctions(feo); + } + // replace precision with interval and vice versa depending on interval calculation mode (foremost relevant for INTERVAL_CALCULATION_NONE) + fix_intervals(*this, feo, NULL, PRECISION); + b = true; + calculatesub(eo, feo, true, mparent, index_this); + } + } + break; + } + case STRUCT_POWER: { + if(recursive) { + CHILD(0).calculatesub(eo, feo, true, this, 0); + CHILD(1).calculatesub(eo, feo, true, this, 1); + CHILDREN_UPDATED; + } + if(CHILD(0).merge_power(CHILD(1), eo) >= 1) { + b = true; + setToChild(1, false, mparent, index_this + 1); + } + break; + } + case STRUCT_ADDITION: { + MERGE_RECURSE + bool found_nonlinear_relations = false; + // convert units with nonlinear relation (to units in other terms) first + if(eo.sync_units && (syncUnits(false, &found_nonlinear_relations, true, feo) || (found_nonlinear_relations && eo.sync_nonlinear_unit_relations))) { + if(found_nonlinear_relations && eo.sync_nonlinear_unit_relations) { + EvaluationOptions eo2 = eo; + eo2.expand = -3; + eo2.combine_divisions = false; + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).calculatesub(eo2, feo, true, this, i); + CHILD(i).factorizeUnits(); + } + CHILDREN_UPDATED; + syncUnits(true, NULL, true, feo); + } + unformat(eo); + MERGE_RECURSE + } + MERGE_ALL(merge_addition, try_add) + MERGE_ALL2 + break; + } + case STRUCT_MULTIPLICATION: { + + MERGE_RECURSE + if(eo.sync_units && syncUnits(eo.sync_nonlinear_unit_relations, NULL, true, feo)) { + unformat(eo); + MERGE_RECURSE + } + + if(representsNonMatrix()) { + + if(SIZE > 2) { + int nonintervals = 0, had_interval = false; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isNumber()) { + if(CHILD(i).number().isInterval(false)) { + had_interval = true; + if(nonintervals >= 2) break; + } else if(nonintervals < 2) { + nonintervals++; + if(nonintervals == 2 && had_interval) break; + } + } + } + if(had_interval && nonintervals >= 2) evalSort(false); + } + + MERGE_ALL(merge_multiplication, try_multiply) + + } else { + // matrix factors are not reorderable + size_t i2, i3 = SIZE; + for(size_t i = 0; i < SIZE - 1; i++) { + i2 = i + 1; + try_multiply_matrix: + bool b_matrix = !CHILD(i).representsNonMatrix(); + if(i2 < i) { + for(; ; i2--) { + int r = CHILD(i2).merge_multiplication(CHILD(i), eo, this, i2, i); + if(r == 0) { + SWAP_CHILDREN(i2, i); + r = CHILD(i2).merge_multiplication(CHILD(i), eo, this, i2, i, true); + if(r < 1) { + SWAP_CHILDREN(i2, i); + } + } + if(r >= 1) { + ERASE(i); + b = true; + i3 = i; + i = i2; + i2 = 0; + goto try_multiply_matrix; + } + if(i2 == 0) break; + if(b_matrix && !CHILD(i2).representsNonMatrix()) break; + } + } + bool had_matrix = false; + for(i2 = i + 1; i2 < SIZE; i2++) { + if(had_matrix && !CHILD(i2).representsNonMatrix()) continue; + int r = CHILD(i).merge_multiplication(CHILD(i2), eo, this, i, i2); + if(r == 0) { + SWAP_CHILDREN(i, i2); + r = CHILD(i).merge_multiplication(CHILD(i2), eo, this, i, i2, true); + if(r < 1) { + SWAP_CHILDREN(i, i2); + } else if(r == 2) { + r = 3; + } else if(r == 3) { + r = 2; + } + } + if(r >= 1) { + ERASE(i2); + b = true; + if(r != 2) { + i2 = 0; + goto try_multiply_matrix; + } + i2--; + } + if(i == SIZE - 1) break; + if(b_matrix && !CHILD(i2).representsNonMatrix()) had_matrix = true; + } + if(i3 < SIZE) { + if(i3 == SIZE - 1) break; + i = i3; + i3 = SIZE; + i2 = i + 1; + goto try_multiply_matrix; + } + } + } + + MERGE_ALL2 + + break; + } + case STRUCT_BITWISE_AND: { + MERGE_RECURSE + MERGE_ALL(merge_bitwise_and, try_bitand) + MERGE_ALL2 + break; + } + case STRUCT_BITWISE_OR: { + MERGE_RECURSE + MERGE_ALL(merge_bitwise_or, try_bitor) + MERGE_ALL2 + break; + } + case STRUCT_BITWISE_XOR: { + MERGE_RECURSE + MERGE_ALL(merge_bitwise_xor, try_bitxor) + MERGE_ALL2 + break; + } + case STRUCT_BITWISE_NOT: { + if(recursive) { + CHILD(0).calculatesub(eo, feo, true, this, 0); + CHILDREN_UPDATED; + } + switch(CHILD(0).type()) { + case STRUCT_NUMBER: { + Number nr(CHILD(0).number()); + if(nr.bitNot() && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || CHILD(0).number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || CHILD(0).number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || CHILD(0).number().includesInfinity())) { + set(nr, true); + } + break; + } + case STRUCT_VECTOR: { + SET_CHILD_MAP(0); + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).setLogicalNot(); + } + break; + } + case STRUCT_BITWISE_NOT: { + //~(~a)=a + setToChild(1); + setToChild(1); + break; + } + default: {} + } + break; + } + case STRUCT_LOGICAL_AND: { + if(recursive) { + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).calculatesub(eo, feo, true, this, i); + CHILD_UPDATED(i) + if(CHILD(i).isZero()) { + clear(true); + b = true; + break; + } + } + if(b) break; + } + MERGE_ALL(merge_logical_and, try_logand) + if(SIZE == 1) { + if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) { + setToChild(1, false, mparent, index_this + 1); + } else if(CHILD(0).representsNonZero()) { + set(1, 1, 0, true); + } else if(CHILD(0).isZero()) { + clear(true); + } else { + APPEND(m_zero); + m_type = STRUCT_COMPARISON; + ct_comp = COMPARISON_NOT_EQUALS; + } + } else if(SIZE == 0) { + clear(true); + } else { + evalSort(); + } + break; + } + case STRUCT_LOGICAL_OR: { + bool isResistance = false; + // calculate resistance || resistance as parallel resistor (?) + switch(CHILD(0).type()) { + case STRUCT_MULTIPLICATION: { + if(CHILD(0)[1] != 0 && CHILD(0)[1].unit() && CHILD(0)[1].unit()->name().find("ohm") != string::npos) { + isResistance = true; + } + break; + } + case STRUCT_UNIT: { + if (CHILD(0).unit() && CHILD(0).unit()->name().find("ohm") != string::npos) { + isResistance = true; + } + break; + } + default: {} + } + if(isResistance) { + MathStructure mstruct; + for (size_t i = 0; i < SIZE; i++) { + MathStructure mtemp(CHILD(i)); + mtemp.inverse(); + mstruct += mtemp; + } + mstruct.inverse(); + clear(); + set(mstruct); + break; + } + if(recursive) { + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).calculatesub(eo, feo, true, this, i); + CHILD_UPDATED(i) + if(CHILD(i).representsNonZero()) { + set(1, 1, 0, true); + b = true; + break; + } + } + if(b) break; + } + MERGE_ALL(merge_logical_or, try_logor) + if(SIZE == 1) { + if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) { + setToChild(1, false, mparent, index_this + 1); + } else if(CHILD(0).representsNonZero()) { + set(1, 1, 0, true); + } else if(CHILD(0).isZero()) { + clear(true); + } else { + APPEND(m_zero); + m_type = STRUCT_COMPARISON; + ct_comp = COMPARISON_NOT_EQUALS; + } + } else if(SIZE == 0) { + clear(true); + } else { + evalSort(); + } + break; + } + case STRUCT_LOGICAL_XOR: { + if(recursive) { + CHILD(0).calculatesub(eo, feo, true, this, 0); + CHILD(1).calculatesub(eo, feo, true, this, 1); + CHILDREN_UPDATED; + } + if(CHILD(0).merge_logical_xor(CHILD(1), eo) >= 1) { + b = true; + setToChild(1, false, mparent, index_this + 1); + } + break; + } + case STRUCT_LOGICAL_NOT: { + if(recursive) { + CHILD(0).calculatesub(eo, feo, true, this, 0); + CHILDREN_UPDATED; + } + if(CHILD(0).representsNonZero()) { + clear(true); + b = true; + } else if(CHILD(0).isZero()) { + set(1, 1, 0, true); + b = true; + } else if(CHILD(0).isLogicalNot()) { + // !(!a)=a + setToChild(1); + setToChild(1); + if(!representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) { + add(m_zero, OPERATION_NOT_EQUALS); + calculatesub(eo, feo, false); + } + b = true; + } + break; + } + case STRUCT_COMPARISON: { + EvaluationOptions eo2 = eo; + if(eo2.assume_denominators_nonzero == 1) eo2.assume_denominators_nonzero = false; + if(recursive) { + CHILD(0).calculatesub(eo2, feo, true, this, 0); + CHILD(1).calculatesub(eo2, feo, true, this, 1); + CHILDREN_UPDATED; + } + if(eo.sync_units && syncUnits(eo.sync_nonlinear_unit_relations, NULL, true, feo)) { + unformat(eo); + if(recursive) { + CHILD(0).calculatesub(eo2, feo, true, this, 0); + CHILD(1).calculatesub(eo2, feo, true, this, 1); + CHILDREN_UPDATED; + } + } + if(CHILD(0).isAddition() || CHILD(1).isAddition()) { + size_t i2 = 0; + for(size_t i = 0; !CHILD(0).isAddition() || i < CHILD(0).size(); i++) { + if(CHILD(1).isAddition()) { + for(; i2 < CHILD(1).size(); i2++) { + if(CHILD(0).isAddition() && CHILD(0)[i] == CHILD(1)[i2]) { + CHILD(0).delChild(i + 1); + CHILD(1).delChild(i2 + 1); + break; + } else if(!CHILD(0).isAddition() && CHILD(0) == CHILD(1)[i2]) { + CHILD(0).clear(true); + CHILD(1).delChild(i2 + 1); + break; + } + } + } else if(CHILD(0)[i] == CHILD(1)) { + CHILD(1).clear(true); + CHILD(0).delChild(i + 1); + break; + } + if(!CHILD(0).isAddition()) break; + } + if(CHILD(0).isAddition()) { + if(CHILD(0).size() == 1) CHILD(0).setToChild(1, true); + else if(CHILD(0).size() == 0) CHILD(0).clear(true); + } + if(CHILD(1).isAddition()) { + if(CHILD(1).size() == 1) CHILD(1).setToChild(1, true); + else if(CHILD(1).size() == 0) CHILD(1).clear(true); + } + } + if(CHILD(0).isMultiplication() && CHILD(1).isMultiplication()) { + size_t i1 = 0, i2 = 0; + if(CHILD(0)[0].isNumber()) i1++; + if(CHILD(1)[0].isNumber()) i2++; + while(i1 < CHILD(0).size() && i2 < CHILD(1).size()) { + if(CHILD(0)[i1] == CHILD(1)[i2] && CHILD(0)[i1].representsPositive(true)) { + CHILD(0).delChild(i1 + 1); + CHILD(1).delChild(i2 + 1); + } else { + break; + } + } + if(CHILD(0).size() == 1) CHILD(0).setToChild(1, true); + else if(CHILD(0).size() == 0) CHILD(0).set(1, 1, 0, true); + if(CHILD(1).size() == 1) CHILD(1).setToChild(1, true); + else if(CHILD(1).size() == 0) CHILD(1).set(1, 1, 0, true); + } + if(((CHILD(0).isNumber() || (CHILD(0).isVariable() && !CHILD(0).variable()->isKnown() && ((UnknownVariable*) CHILD(0).variable())->interval().isNumber())) && (CHILD(1).isNumber() || ((CHILD(1).isVariable() && !CHILD(1).variable()->isKnown() && ((UnknownVariable*) CHILD(1).variable())->interval().isNumber())))) || (CHILD(0).isDateTime() && CHILD(1).isDateTime())) { + ComparisonResult cr; + if(CHILD(0).isNumber()) { + if(CHILD(1).isNumber()) cr = CHILD(1).number().compareApproximately(CHILD(0).number()); + else cr = ((UnknownVariable*) CHILD(1).variable())->interval().number().compareApproximately(CHILD(0).number()); + } else if(CHILD(1).isNumber()) { + cr = CHILD(1).number().compareApproximately(((UnknownVariable*) CHILD(0).variable())->interval().number()); + } else if(CHILD(1).isVariable()) { + cr = ((UnknownVariable*) CHILD(1).variable())->interval().number().compareApproximately(((UnknownVariable*) CHILD(0).variable())->interval().number()); + } else { + cr = CHILD(1).compare(CHILD(0)); + } + if(cr >= COMPARISON_RESULT_UNKNOWN) { + break; + } + switch(ct_comp) { + case COMPARISON_EQUALS: { + if(cr == COMPARISON_RESULT_EQUAL) { + set(1, 1, 0, true); + b = true; + } else if(COMPARISON_IS_NOT_EQUAL(cr)) { + clear(true); + b = true; + } + break; + } + case COMPARISON_NOT_EQUALS: { + if(cr == COMPARISON_RESULT_EQUAL) { + clear(true); + b = true; + } else if(COMPARISON_IS_NOT_EQUAL(cr)) { + set(1, 1, 0, true); + b = true; + } + break; + } + case COMPARISON_LESS: { + if(cr == COMPARISON_RESULT_LESS) { + set(1, 1, 0, true); + b = true; + } else if(cr != COMPARISON_RESULT_EQUAL_OR_LESS && cr != COMPARISON_RESULT_NOT_EQUAL) { + clear(true); + b = true; + } + break; + } + case COMPARISON_EQUALS_LESS: { + if(COMPARISON_IS_EQUAL_OR_LESS(cr)) { + set(1, 1, 0, true); + b = true; + } else if(cr != COMPARISON_RESULT_EQUAL_OR_GREATER && cr != COMPARISON_RESULT_NOT_EQUAL) { + clear(true); + b = true; + } + break; + } + case COMPARISON_GREATER: { + if(cr == COMPARISON_RESULT_GREATER) { + set(1, 1, 0, true); + b = true; + } else if(cr != COMPARISON_RESULT_EQUAL_OR_GREATER && cr != COMPARISON_RESULT_NOT_EQUAL) { + clear(true); + b = true; + } + break; + } + case COMPARISON_EQUALS_GREATER: { + if(COMPARISON_IS_EQUAL_OR_GREATER(cr)) { + set(1, 1, 0, true); + b = true; + } else if(cr != COMPARISON_RESULT_EQUAL_OR_LESS && cr != COMPARISON_RESULT_NOT_EQUAL) { + clear(true); + b = true; + } + break; + } + } + break; + } + if(!eo.test_comparisons) { + break; + } + + if(eo2.keep_zero_units && contains_zero_unit(*this)) { + eo2.keep_zero_units = false; + MathStructure mtest(*this); + CALCULATOR->beginTemporaryStopMessages(); + mtest.calculatesub(eo2, feo, true); + if(mtest.isNumber()) { + CALCULATOR->endTemporaryStopMessages(true); + set(mtest); + b = true; + break; + } + CALCULATOR->endTemporaryStopMessages(); + } + if((CHILD(0).representsUndefined() && !CHILD(1).representsUndefined(true, true, true)) || (CHILD(1).representsUndefined() && !CHILD(0).representsUndefined(true, true, true))) { + if(ct_comp == COMPARISON_EQUALS) { + clear(true); + b = true; + break; + } else if(ct_comp == COMPARISON_NOT_EQUALS) { + set(1, 1, 0, true); + b = true; + break; + } + } + if((ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_GREATER) && CHILD(1).isZero()) { + if(CHILD(0).isLogicalNot() || CHILD(0).isLogicalAnd() || CHILD(0).isLogicalOr() || CHILD(0).isLogicalXor() || CHILD(0).isComparison()) { + if(ct_comp == COMPARISON_EQUALS_LESS) { + ERASE(1); + m_type = STRUCT_LOGICAL_NOT; + calculatesub(eo, feo, false, mparent, index_this); + } else { + setToChild(1, false, mparent, index_this + 1); + } + b = true; + } + } else if((ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_LESS) && CHILD(0).isZero()) { + if(CHILD(1).isLogicalNot() || CHILD(1).isLogicalAnd() || CHILD(1).isLogicalOr() || CHILD(1).isLogicalXor() || CHILD(1).isComparison()) { + if(ct_comp == COMPARISON_EQUALS_GREATER) { + ERASE(0); + m_type = STRUCT_LOGICAL_NOT; + calculatesub(eo, feo, false, mparent, index_this); + } else { + setToChild(2, false, mparent, index_this + 1); + } + b = true; + } + } + if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { + if((CHILD(0).representsReal(true) && CHILD(1).representsComplex(true)) || (CHILD(1).representsReal(true) && CHILD(0).representsComplex(true))) { + if(ct_comp == COMPARISON_EQUALS) { + clear(true); + } else { + set(1, 1, 0, true); + } + b = true; + } else if((CHILD(0).representsZero(true) && CHILD(1).representsZero(true))) { + if(ct_comp != COMPARISON_EQUALS) { + clear(true); + } else { + set(1, 1, 0, true); + } + b = true; + } else if(CHILD(0).isVariable() && !CHILD(0).variable()->isKnown() && CHILD(0).representsInteger() && test_non_integer(CHILD(1), eo)) { + if(ct_comp == COMPARISON_EQUALS) clear(true); + else set(1, 1, 0, true); + b = true; + } + } + if(b) break; + if(CHILD(1).isNumber() && CHILD(0).isVariable() && !CHILD(0).variable()->isKnown()) { + Assumptions *ass = ((UnknownVariable*) CHILD(0).variable())->assumptions(); + if(ass && ass->min()) { + bool b_inc = ass->includeEqualsMin(); + switch(ct_comp) { + case COMPARISON_EQUALS: { + if((b_inc && CHILD(1).number() < *ass->min()) || (!b_inc && CHILD(1).number() <= *ass->min())) {clear(true); b = true;} + break; + } + case COMPARISON_NOT_EQUALS: { + if((b_inc && CHILD(1).number() < *ass->min()) || (!b_inc && CHILD(1).number() <= *ass->min())) {set(1, 1, 0, true); b = true;} + break; + } + case COMPARISON_LESS: { + if(CHILD(1).number() <= *ass->min()) {clear(true); b = true;} + + break; + } + case COMPARISON_GREATER: { + if((b_inc && CHILD(1).number() < *ass->min()) || (!b_inc && CHILD(1).number() <= *ass->min())) {set(1, 1, 0, true); b = true;} + break; + } + case COMPARISON_EQUALS_LESS: { + if(b_inc && CHILD(1).number() == *ass->min()) {ct_comp = COMPARISON_EQUALS; b = true;} + else if((b_inc && CHILD(1).number() < *ass->min()) || (!b_inc && CHILD(1).number() <= *ass->min())) {clear(true); b = true;} + break; + } + case COMPARISON_EQUALS_GREATER: { + if(CHILD(1).number() <= *ass->min()) {set(1, 1, 0, true); b = true;} + break; + } + } + } + if(ass && ass->max() && isComparison()) { + bool b_inc = ass->includeEqualsMax(); + switch(ct_comp) { + case COMPARISON_EQUALS: { + if((b_inc && CHILD(1).number() > *ass->max()) || (!b_inc && CHILD(1).number() >= *ass->max())) {clear(true); b = true;} + break; + } + case COMPARISON_NOT_EQUALS: { + if((b_inc && CHILD(1).number() > *ass->max()) || (!b_inc && CHILD(1).number() >= *ass->max())) {set(1, 1, 0, true); b = true;} + break; + } + case COMPARISON_LESS: { + if((b_inc && CHILD(1).number() > *ass->max()) || (!b_inc && CHILD(1).number() >= *ass->max())) {set(1, 1, 0, true); b = true;} + break; + } + case COMPARISON_GREATER: { + if(CHILD(1).number() >= *ass->max()) {clear(true); b = true;} + break; + } + case COMPARISON_EQUALS_LESS: { + if(CHILD(1).number() >= *ass->max()) {set(1, 1, 0, true); b = true;} + break; + } + case COMPARISON_EQUALS_GREATER: { + if(b_inc && CHILD(1).number() == *ass->max()) {ct_comp = COMPARISON_EQUALS; b = true;} + else if((b_inc && CHILD(1).number() > *ass->max()) || (!b_inc && CHILD(1).number() >= *ass->max())) {clear(true); b = true;} + break; + } + } + } + } + if(b) break; + if(eo.approximation == APPROXIMATION_EXACT && eo.test_comparisons > 0) { + bool b_intval = CALCULATOR->usesIntervalArithmetic(); + bool b_failed = false; + EvaluationOptions eo3 = feo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + eo3.approximation = APPROXIMATION_APPROXIMATE; + eo2.test_comparisons = false; + MathStructure mtest(*this); + for(int i = 0; i < 2; i++) { + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + int b_ass = (i == 0 ? 2 : contains_ass_intval(mtest)); + if(b_ass == 0 || !CALCULATOR->usesIntervalArithmetic()) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); break;} + replace_interval_unknowns(mtest, i > 0); + if(i == 0 && !b_intval) fix_intervals(mtest, eo2, &b_failed); + if(!b_failed) { + if(i == 0 && mtest[0].isAddition() && mtest[0].size() > 1 && mtest[1].isZero()) { + mtest[1] = mtest[0][0]; + mtest[1].negate(); + mtest[0].delChild(1, true); + } + CALCULATOR->beginTemporaryStopMessages(); + if(b_ass == 2) mtest[0].calculateFunctions(eo3); + mtest[0].calculatesub(eo2, eo3, true); + if(b_ass == 2) mtest[1].calculateFunctions(eo3); + mtest[1].calculatesub(eo2, eo3, true); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + mtest.childrenUpdated(); + if(CALCULATOR->endTemporaryStopMessages(NULL, NULL, MESSAGE_ERROR) == 0) { + eo2.approximation = eo.approximation; + eo2.test_comparisons = -1; + mtest.calculatesub(eo2, feo, false); + if(mtest.isNumber()) { + if(mtest.isZero()) clear(true); + else set(1, 1, 0, true); + b = true; + return b; + } + } + } else { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + break; + } + } + } + eo2 = eo; + if(eo2.assume_denominators_nonzero == 1) eo2.assume_denominators_nonzero = false; + bool mtest_new = false; + MathStructure *mtest; + if(!CHILD(1).isZero()) { + if(!eo.isolate_x || find_x_var().isUndefined()) { + CHILD(0).calculateSubtract(CHILD(1), eo2); + CHILD(1).clear(); + mtest = &CHILD(0); + mtest->ref(); + } else { + mtest = new MathStructure(CHILD(0)); + mtest->calculateSubtract(CHILD(1), eo2); + remove_rad_unit(*mtest, eo2); + mtest_new = true; + } + } else { + mtest = &CHILD(0); + mtest->ref(); + } + int incomp = 0; + if(mtest->isAddition()) { + mtest->evalSort(true); + incomp = compare_check_incompability(mtest); + if(incomp == 1 && !mtest_new) { + mtest->unref(); + mtest = new MathStructure(CHILD(0)); + if(remove_rad_unit(*mtest, eo2)) { + mtest_new = true; + if(mtest->isAddition()) { + mtest->evalSort(true); + incomp = compare_check_incompability(mtest); + } + } + } + } + if(incomp <= 0) { + if(mtest_new && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { + bool a_pos = CHILD(0).representsPositive(true); + bool a_nneg = a_pos || CHILD(0).representsNonNegative(true); + bool a_neg = !a_nneg && CHILD(0).representsNegative(true); + bool a_npos = !a_pos && (a_neg || CHILD(0).representsNonPositive(true)); + bool b_pos = CHILD(1).representsPositive(true); + bool b_nneg = b_pos || CHILD(1).representsNonNegative(true); + bool b_neg = !b_nneg && CHILD(1).representsNegative(true); + bool b_npos = !b_pos && (b_neg || CHILD(1).representsNonPositive(true)); + if(isApproximate()) { + if((a_pos && b_neg) || (a_neg && b_pos)) { + incomp = 1; + } + } else { + if((a_pos && b_npos) || (a_npos && b_pos) || (a_nneg && b_neg) || (a_neg && b_nneg)) { + incomp = 1; + } + } + } else if(incomp < 0) { + mtest->unref(); + break; + } + } + + switch(ct_comp) { + case COMPARISON_EQUALS: { + if(incomp > 0) { + clear(true); + b = true; + } else if(mtest->representsZero(true)) { + set(1, 1, 0, true); + b = true; + } else if(mtest->representsNonZero(true)) { + clear(true); + b = true; + } + break; + } + case COMPARISON_NOT_EQUALS: { + if(incomp > 0) { + set(1, 1, 0, true); + b = true; + } else if(mtest->representsNonZero(true)) { + set(1, 1, 0, true); + b = true; + } else if(mtest->representsZero(true)) { + clear(true); + b = true; + } + break; + } + case COMPARISON_LESS: { + if(incomp > 0) { + } else if(mtest->representsNegative(true)) { + set(1, 1, 0, true); + b = true; + } else if(mtest->representsNonNegative(true)) { + clear(true); + b = true; + } + break; + } + case COMPARISON_GREATER: { + if(incomp > 0) { + } else if(mtest->representsPositive(true)) { + set(1, 1, 0, true); + b = true; + } else if(mtest->representsNonPositive(true)) { + clear(true); + b = true; + } + break; + } + case COMPARISON_EQUALS_LESS: { + if(incomp > 0) { + } else if(mtest->representsNonPositive(true)) { + set(1, 1, 0, true); + b = true; + } else if(mtest->representsPositive(true)) { + clear(true); + b = true; + } + break; + } + case COMPARISON_EQUALS_GREATER: { + if(incomp > 0) { + } else if(mtest->representsNonNegative(true)) { + set(1, 1, 0, true); + b = true; + } else if(mtest->representsNegative(true)) { + clear(true); + b = true; + } + break; + } + } + mtest->unref(); + break; + } + case STRUCT_FUNCTION: { + // always calculate certain functions (introduced by operations outside of functions) + if(o_function->id() == FUNCTION_ID_ABS || o_function->id() == FUNCTION_ID_ROOT || o_function->id() == FUNCTION_ID_INTERVAL || o_function->id() == FUNCTION_ID_UNCERTAINTY || o_function->id() == FUNCTION_ID_SIGNUM || o_function->id() == FUNCTION_ID_DIRAC || o_function->id() == FUNCTION_ID_HEAVISIDE) { + b = calculateFunctions(eo, false); + if(b) { + calculatesub(eo, feo, true, mparent, index_this); + break; + } + } else if(o_function->id() == FUNCTION_ID_STRIP_UNITS) { + b = calculateFunctions(eo, false); + if(b) calculatesub(eo, feo, true, mparent, index_this); + break; + } + } + default: { + if(recursive) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).calculatesub(eo, feo, true, this, i)) b = true; + } + CHILDREN_UPDATED; + } + if(eo.sync_units && syncUnits(eo.sync_nonlinear_unit_relations, NULL, true, feo)) { + unformat(eo); + if(recursive) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).calculatesub(eo, feo, true, this, i)) b = true; + } + CHILDREN_UPDATED; + } + } + } + } + return b; +} + +#define MERGE_INDEX(FUNC, TRY_LABEL) bool b = false;\ + TRY_LABEL:\ + for(size_t i = 0; i < index; i++) {\ + if(CALCULATOR->aborted()) break; \ + int r = CHILD(i).FUNC(CHILD(index), eo, this, i, index);\ + if(r == 0) {\ + SWAP_CHILDREN(i, index);\ + r = CHILD(i).FUNC(CHILD(index), eo, this, i, index, true);\ + if(r < 1) {\ + SWAP_CHILDREN(i, index);\ + } else if(r == 2) {\ + r = 3;\ + } else if(r == 3) {\ + r = 2;\ + }\ + }\ + if(r >= 1) {\ + ERASE(index);\ + if(!b && r == 2) {\ + b = true;\ + index = SIZE;\ + break;\ + } else {\ + b = true;\ + index = i;\ + goto TRY_LABEL;\ + }\ + }\ + }\ + for(size_t i = index + 1; i < SIZE; i++) {\ + if(CALCULATOR->aborted()) break; \ + int r = CHILD(index).FUNC(CHILD(i), eo, this, index, i);\ + if(r == 0) {\ + SWAP_CHILDREN(index, i);\ + r = CHILD(index).FUNC(CHILD(i), eo, this, index, i, true);\ + if(r < 1) {\ + SWAP_CHILDREN(index, i);\ + } else if(r == 2) {\ + r = 3;\ + } else if(r == 3) {\ + r = 2;\ + }\ + }\ + if(r >= 1) {\ + ERASE(i);\ + if(!b && r == 3) {\ + b = true;\ + break;\ + }\ + b = true;\ + if(r != 2) {\ + goto TRY_LABEL;\ + }\ + i--;\ + }\ + } + +#define MERGE_INDEX2 if(b && check_size) {\ + if(SIZE == 1) {\ + setToChild(1, false, mparent, index_this + 1);\ + } else if(SIZE == 0) {\ + clear(true);\ + } else {\ + evalSort();\ + }\ + return true;\ + } else {\ + evalSort();\ + return b;\ + } + + +bool MathStructure::calculateMergeIndex(size_t index, const EvaluationOptions &eo, const EvaluationOptions &feo, MathStructure *mparent, size_t index_this) { + switch(m_type) { + case STRUCT_MULTIPLICATION: { + return calculateMultiplyIndex(index, eo, true, mparent, index_this); + } + case STRUCT_ADDITION: { + return calculateAddIndex(index, eo, true, mparent, index_this); + } + case STRUCT_POWER: { + return calculateRaiseExponent(eo, mparent, index_this); + } + case STRUCT_LOGICAL_AND: { + return calculateLogicalAndIndex(index, eo, true, mparent, index_this); + } + case STRUCT_LOGICAL_OR: { + return calculateLogicalOrIndex(index, eo, true, mparent, index_this); + } + case STRUCT_LOGICAL_XOR: { + return calculateLogicalXorLast(eo, mparent, index_this); + } + case STRUCT_BITWISE_AND: { + return calculateBitwiseAndIndex(index, eo, true, mparent, index_this); + } + case STRUCT_BITWISE_OR: { + return calculateBitwiseOrIndex(index, eo, true, mparent, index_this); + } + case STRUCT_BITWISE_XOR: { + return calculateBitwiseXorIndex(index, eo, true, mparent, index_this); + } + default: {} + } + return calculatesub(eo, feo, false, mparent, index_this); +} +bool MathStructure::calculateLogicalOrLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { + return calculateLogicalOrIndex(SIZE - 1, eo, check_size, mparent, index_this); +} +bool MathStructure::calculateLogicalOrIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { + + if(index >= SIZE || !isLogicalOr()) { + CALCULATOR->error(true, "calculateLogicalOrIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); + return false; + } + + MERGE_INDEX(merge_logical_or, try_logical_or_index) + + if(b && check_size) { + if(SIZE == 1) { + if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) { + setToChild(1, false, mparent, index_this + 1); + } else if(CHILD(0).representsPositive()) { + clear(true); + o_number.setTrue(); + } else if(CHILD(0).representsNonPositive()) { + clear(true); + o_number.setFalse(); + } else { + APPEND(m_zero); + m_type = STRUCT_COMPARISON; + ct_comp = COMPARISON_GREATER; + } + } else if(SIZE == 0) { + clear(true); + } else { + evalSort(); + } + return true; + } else { + evalSort(); + return false; + } + +} +bool MathStructure::calculateLogicalOr(const MathStructure &mor, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + add(mor, OPERATION_LOGICAL_OR, true); + LAST.evalSort(); + return calculateLogicalOrIndex(SIZE - 1, eo, true, mparent, index_this); +} +bool MathStructure::calculateLogicalXorLast(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + + if(!isLogicalXor()) { + CALCULATOR->error(true, "calculateLogicalXorLast() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); + return false; + } + if(CHILD(0).merge_logical_xor(CHILD(1), eo, this, 0, 1) >= 1) { + if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) { + setToChild(1, false, mparent, index_this + 1); + } else if(CHILD(0).representsPositive()) { + clear(true); + o_number.setTrue(); + } else if(CHILD(0).representsNonPositive()) { + clear(true); + o_number.setFalse(); + } else { + APPEND(m_zero); + m_type = STRUCT_COMPARISON; + ct_comp = COMPARISON_GREATER; + } + return true; + } + return false; + +} +bool MathStructure::calculateLogicalXor(const MathStructure &mxor, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + add(mxor, OPERATION_LOGICAL_XOR); + LAST.evalSort(); + return calculateLogicalXorLast(eo, mparent, index_this); +} +bool MathStructure::calculateLogicalAndLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { + return calculateLogicalAndIndex(SIZE - 1, eo, check_size, mparent, index_this); +} +bool MathStructure::calculateLogicalAndIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { + + if(index >= SIZE || !isLogicalAnd()) { + CALCULATOR->error(true, "calculateLogicalAndIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); + return false; + } + + MERGE_INDEX(merge_logical_and, try_logical_and_index) + + if(b && check_size) { + if(SIZE == 1) { + if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) { + setToChild(1, false, mparent, index_this + 1); + } else if(CHILD(0).representsPositive()) { + clear(true); + o_number.setTrue(); + } else if(CHILD(0).representsNonPositive()) { + clear(true); + o_number.setFalse(); + } else { + APPEND(m_zero); + m_type = STRUCT_COMPARISON; + ct_comp = COMPARISON_GREATER; + } + } else if(SIZE == 0) { + clear(true); + } else { + evalSort(); + } + return true; + } else { + evalSort(); + return false; + } + +} +bool MathStructure::calculateLogicalAnd(const MathStructure &mand, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + add(mand, OPERATION_LOGICAL_AND, true); + LAST.evalSort(); + return calculateLogicalAndIndex(SIZE - 1, eo, true, mparent, index_this); +} +bool MathStructure::calculateInverse(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + return calculateRaise(m_minus_one, eo, mparent, index_this); +} +bool MathStructure::calculateNegate(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + if(m_type == STRUCT_NUMBER) { + Number nr(o_number); + if(nr.negate() && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate())) { + o_number = nr; + numberUpdated(); + return true; + } + if(!isMultiplication()) transform(STRUCT_MULTIPLICATION); + PREPEND(m_minus_one); + return false; + } + if(!isMultiplication()) transform(STRUCT_MULTIPLICATION); + PREPEND(m_minus_one); + return calculateMultiplyIndex(0, eo, true, mparent, index_this); +} +bool MathStructure::calculateBitwiseNot(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + transform(STRUCT_LOGICAL_NOT); + return calculatesub(eo, eo, false, mparent, index_this); +} +bool MathStructure::calculateLogicalNot(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + transform(STRUCT_BITWISE_NOT); + return calculatesub(eo, eo, false, mparent, index_this); +} +bool MathStructure::calculateRaiseExponent(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + if(!isPower()) { + CALCULATOR->error(true, "calculateRaiseExponent() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); + return false; + } + if(CHILD(0).merge_power(CHILD(1), eo, this, 0, 1) >= 1) { + setToChild(1, false, mparent, index_this + 1); + return true; + } + return false; +} +bool MathStructure::calculateRaise(const MathStructure &mexp, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + if(mexp.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { + Number nr(o_number); + if(nr.raise(mexp.number(), eo.approximation < APPROXIMATION_APPROXIMATE) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mexp.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mexp.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mexp.number().includesInfinity())) { + o_number = nr; + numberUpdated(); + return true; + } + } + raise(mexp); + LAST.evalSort(); + return calculateRaiseExponent(eo, mparent, index_this); +} +bool MathStructure::calculateBitwiseAndLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { + return calculateBitwiseAndIndex(SIZE - 1, eo, check_size, mparent, index_this); +} +bool MathStructure::calculateBitwiseAndIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { + + if(index >= SIZE || !isBitwiseAnd()) { + CALCULATOR->error(true, "calculateBitwiseAndIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); + return false; + } + + MERGE_INDEX(merge_bitwise_and, try_bitwise_and_index) + MERGE_INDEX2 + +} +bool MathStructure::calculateBitwiseAnd(const MathStructure &mand, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + add(mand, OPERATION_BITWISE_AND, true); + LAST.evalSort(); + return calculateBitwiseAndIndex(SIZE - 1, eo, true, mparent, index_this); +} +bool MathStructure::calculateBitwiseOrLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { + return calculateBitwiseOrIndex(SIZE - 1, eo, check_size, mparent, index_this); +} +bool MathStructure::calculateBitwiseOrIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { + + if(index >= SIZE || !isBitwiseOr()) { + CALCULATOR->error(true, "calculateBitwiseOrIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); + return false; + } + + MERGE_INDEX(merge_bitwise_or, try_bitwise_or_index) + MERGE_INDEX2 + +} +bool MathStructure::calculateBitwiseOr(const MathStructure &mor, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + add(mor, OPERATION_BITWISE_OR, true); + LAST.evalSort(); + return calculateBitwiseOrIndex(SIZE - 1, eo, true, mparent, index_this); +} +bool MathStructure::calculateBitwiseXorLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { + return calculateBitwiseXorIndex(SIZE - 1, eo, check_size, mparent, index_this); +} +bool MathStructure::calculateBitwiseXorIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { + + if(index >= SIZE || !isBitwiseXor()) { + CALCULATOR->error(true, "calculateBitwiseXorIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); + return false; + } + + MERGE_INDEX(merge_bitwise_xor, try_bitwise_xor_index) + MERGE_INDEX2 + +} +bool MathStructure::calculateBitwiseXor(const MathStructure &mxor, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + add(mxor, OPERATION_BITWISE_XOR, true); + LAST.evalSort(); + return calculateBitwiseXorIndex(SIZE - 1, eo, true, mparent, index_this); +} +bool MathStructure::calculateMultiplyLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { + return calculateMultiplyIndex(SIZE - 1, eo, check_size, mparent, index_this); +} +bool MathStructure::calculateMultiplyIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { + + if(index >= SIZE || !isMultiplication()) { + CALCULATOR->error(true, "calculateMultiplyIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); + return false; + } + + bool b = false; + try_multiply_matrix_index: + bool b_matrix = !CHILD(index).representsNonMatrix(); + if(index > 0) { + for(size_t i = index - 1; ; i--) { + if(CALCULATOR->aborted()) break; + int r = CHILD(i).merge_multiplication(CHILD(index), eo, this, i, index); + if(r == 0) { + SWAP_CHILDREN(i, index); + r = CHILD(i).merge_multiplication(CHILD(index), eo, this, i, index, true); + if(r < 1) { + SWAP_CHILDREN(i, index); + } else if(r == 2) { + r = 3; + } else if(r == 3) { + r = 2; + } + } + if(r >= 1) { + ERASE(index); + if(!b && r == 2) { + b = true; + index = SIZE; + break; + } else { + b = true; + index = i; + goto try_multiply_matrix_index; + } + } + if(i == 0) break; + if(b_matrix && !CHILD(i).representsNonMatrix()) break; + } + } + + bool had_matrix = false; + for(size_t i = index + 1; i < SIZE; i++) { + if(had_matrix && !CHILD(i).representsNonMatrix()) continue; + if(CALCULATOR->aborted()) break; + int r = CHILD(index).merge_multiplication(CHILD(i), eo, this, index, i); + if(r == 0) { + SWAP_CHILDREN(index, i); + r = CHILD(index).merge_multiplication(CHILD(i), eo, this, index, i, true); + if(r < 1) { + SWAP_CHILDREN(index, i); + } else if(r == 2) { + r = 3; + } else if(r == 3) { + r = 2; + } + } + if(r >= 1) { + ERASE(i); + if(!b && r == 3) { + b = true; + break; + } + b = true; + if(r != 2) { + goto try_multiply_matrix_index; + } + i--; + } + if(i == SIZE - 1) break; + if(b_matrix && !CHILD(i).representsNonMatrix()) had_matrix = true; + } + + MERGE_INDEX2 + +} +bool MathStructure::calculateMultiply(const MathStructure &mmul, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + if(mmul.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { + Number nr(o_number); + if(nr.multiply(mmul.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mmul.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mmul.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mmul.number().includesInfinity())) { + o_number = nr; + numberUpdated(); + return true; + } + } + multiply(mmul, true); + LAST.evalSort(); + return calculateMultiplyIndex(SIZE - 1, eo, true, mparent, index_this); +} +bool MathStructure::calculateDivide(const MathStructure &mdiv, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + if(mdiv.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { + Number nr(o_number); + if(nr.divide(mdiv.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mdiv.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mdiv.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mdiv.number().includesInfinity())) { + o_number = nr; + numberUpdated(); + return true; + } + } + MathStructure *mmul = new MathStructure(mdiv); + mmul->evalSort(); + multiply_nocopy(mmul, true); + LAST.calculateInverse(eo, this, SIZE - 1); + return calculateMultiplyIndex(SIZE - 1, eo, true, mparent, index_this); +} +bool MathStructure::calculateAddLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { + return calculateAddIndex(SIZE - 1, eo, check_size, mparent, index_this); +} +bool MathStructure::calculateAddIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { + + if(index >= SIZE || !isAddition()) { + CALCULATOR->error(true, "calculateAddIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); + return false; + } + + MERGE_INDEX(merge_addition, try_add_index) + MERGE_INDEX2 + +} +bool MathStructure::calculateAdd(const MathStructure &madd, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + if(madd.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { + Number nr(o_number); + if(nr.add(madd.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || madd.number().isApproximate())) { + o_number = nr; + numberUpdated(); + return true; + } + } + add(madd, true); + LAST.evalSort(); + return calculateAddIndex(SIZE - 1, eo, true, mparent, index_this); +} +bool MathStructure::calculateSubtract(const MathStructure &msub, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { + if(msub.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { + Number nr(o_number); + if(nr.subtract(msub.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || msub.number().isApproximate())) { + o_number = nr; + numberUpdated(); + return true; + } + } + MathStructure *madd = new MathStructure(msub); + madd->evalSort(); + add_nocopy(madd, true); + LAST.calculateNegate(eo, this, SIZE - 1); + return calculateAddIndex(SIZE - 1, eo, true, mparent, index_this); +} + +bool MathStructure::calculateFunctions(const EvaluationOptions &eo, bool recursive, bool do_unformat) { + + if(m_type == STRUCT_FUNCTION && o_function != eo.protected_function) { + + if(function_value) { + // clear stored function value (presently not used) + function_value->unref(); + function_value = NULL; + } + + // test if the number of arguments (children) is appropriate for the function + if(!o_function->testArgumentCount(SIZE)) { + return false; + } + + if(o_function->maxargs() > -1 && (long int) SIZE > o_function->maxargs()) { + if(o_function->maxargs() == 1 && o_function->getArgumentDefinition(1) && o_function->getArgumentDefinition(1)->handlesVector()) { + // for functions which takes exactly one argument: if there are additional children calculate the function separately for each child and place results in vector + bool b = false; + for(size_t i2 = 0; i2 < CHILD(0).size(); i2++) { + CHILD(0)[i2].transform(o_function); + if(CHILD(0)[i2].calculateFunctions(eo, recursive, do_unformat)) b = true; + CHILD(0).childUpdated(i2 + 1); + } + SET_CHILD_MAP(0) + return b; + } + // remove unused arguments/children + REDUCE(o_function->maxargs()); + } + m_type = STRUCT_VECTOR; + Argument *arg = NULL, *last_arg = NULL; + int last_i = 0; + + for(size_t i = 0; i < SIZE; i++) { + arg = o_function->getArgumentDefinition(i + 1); + if(arg) { + last_arg = arg; + last_i = i; + if(i > 0 && arg->type() == ARGUMENT_TYPE_SYMBOLIC && (CHILD(i).isZero() || CHILD(i).isUndefined())) { + // argument type is symbol and value is zero or undefined, search the first argument/child for symbols + CHILD(i).set(CHILD(0).find_x_var(), true); + if(CHILD(i).isUndefined() && CHILD(0).isVariable() && CHILD(0).variable()->isKnown()) CHILD(i).set(((KnownVariable*) CHILD(0).variable())->get().find_x_var(), true); + if(CHILD(i).isUndefined()) { + // no symbol found: calculate the argument/child and try again + CALCULATOR->beginTemporaryStopMessages(); + MathStructure mtest(CHILD(0)); + mtest.eval(eo); + CHILD(i).set(mtest.find_x_var(), true); + CALCULATOR->endTemporaryStopMessages(); + } + if(CHILD(i).isUndefined()) { + CALCULATOR->error(false, _("No unknown variable/symbol was found."), NULL); + CHILD(i).set(CALCULATOR->getVariableById(VARIABLE_ID_X), true); + } + } + // test if argument/child can be used by function + if(!arg->test(CHILD(i), i + 1, o_function, eo)) { + if(arg->handlesVector() && CHILD(i).isVector()) { + // calculate the function separately for each child of vector + bool b = false; + for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { + CHILD(i)[i2].transform(o_function); + for(size_t i3 = 0; i3 < SIZE; i3++) { + if(i3 < i) CHILD(i)[i2].insertChild(CHILD(i3), i3 + 1); + else if(i3 > i) CHILD(i)[i2].addChild(CHILD(i3)); + } + if(CHILD(i)[i2].calculateFunctions(eo, recursive, do_unformat)) b = true; + CHILD(i).childUpdated(i2 + 1); + } + SET_CHILD_MAP(i); + return b; + } + // argument/child did not fulfil criteria + m_type = STRUCT_FUNCTION; + CHILD_UPDATED(i); + return false; + } else { + CHILD_UPDATED(i); + } + if(arg->handlesVector()) { + if(arg->tests() && !CHILD(i).isVector() && !CHILD(i).representsScalar()) { + CHILD(i).eval(eo); + CHILD_UPDATED(i); + } + if(CHILD(i).isVector()) { + bool b = false; + // calculate the function separately for each child of vector + for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { + CHILD(i)[i2].transform(o_function); + for(size_t i3 = 0; i3 < SIZE; i3++) { + if(i3 < i) CHILD(i)[i2].insertChild(CHILD(i3), i3 + 1); + else if(i3 > i) CHILD(i)[i2].addChild(CHILD(i3)); + } + if(CHILD(i)[i2].calculateFunctions(eo, recursive, do_unformat)) b = true; + CHILD(i).childUpdated(i2 + 1); + } + SET_CHILD_MAP(i); + return b; + } + } + } + } + + if(last_arg && o_function->maxargs() < 0 && last_i >= o_function->minargs()) { + // use the last argument to test additional arguments (if number of arguments is unlimited and last argument was above minimum number of arguments) + for(size_t i = last_i + 1; i < SIZE; i++) { + if(!last_arg->test(CHILD(i), i + 1, o_function, eo)) { + m_type = STRUCT_FUNCTION; + CHILD_UPDATED(i); + return false; + } else { + CHILD_UPDATED(i); + } + } + } + + if(!o_function->testCondition(*this)) { + m_type = STRUCT_FUNCTION; + return false; + } + MathStructure *mstruct = new MathStructure(); + int ret = o_function->calculate(*mstruct, *this, eo); + if(ret > 0) { + // function calculation was successful + set_nocopy(*mstruct, true); + if(recursive) calculateFunctions(eo); + mstruct->unref(); + if(do_unformat) unformat(eo); + return true; + } else { + // function calculation failed + if(ret < 0) { + // updated argument/child was returned + ret = -ret; + if(o_function->maxargs() > 0 && ret > o_function->maxargs()) { + if(mstruct->isVector()) { + if(do_unformat) mstruct->unformat(eo); + for(size_t arg_i = 1; arg_i <= SIZE && arg_i <= mstruct->size(); arg_i++) { + mstruct->getChild(arg_i)->ref(); + setChild_nocopy(mstruct->getChild(arg_i), arg_i); + } + } + } else if(ret <= (long int) SIZE) { + if(do_unformat) mstruct->unformat(eo); + mstruct->ref(); + setChild_nocopy(mstruct, ret); + } + } + /*if(eo.approximation == APPROXIMATION_EXACT) { + mstruct->clear(); + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + CALCULATOR->beginTemporaryStopMessages(); + if(o_function->calculate(*mstruct, *this, eo2) > 0) { + function_value = mstruct; + function_value->ref(); + function_value->calculateFunctions(eo2); + } + if(CALCULATOR->endTemporaryStopMessages() > 0 && function_value) { + function_value->unref(); + function_value = NULL; + } + }*/ + m_type = STRUCT_FUNCTION; + mstruct->unref(); + for(size_t i = 0; i < SIZE; i++) { + arg = o_function->getArgumentDefinition(i + 1); + if(arg && arg->handlesVector()) { + if(!CHILD(i).isVector()) { + CHILD(i).calculatesub(eo, eo, false); + if(!CHILD(i).isVector()) return false; + } + // calculate the function separately for each child of vector + bool b = false; + for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { + CHILD(i)[i2].transform(o_function); + for(size_t i3 = 0; i3 < SIZE; i3++) { + if(i3 < i) CHILD(i)[i2].insertChild(CHILD(i3), i3 + 1); + else if(i3 > i) CHILD(i)[i2].addChild(CHILD(i3)); + } + if(CHILD(i)[i2].calculateFunctions(eo, recursive, do_unformat)) b = true; + CHILD(i).childUpdated(i2 + 1); + } + SET_CHILD_MAP(i); + return b; + } + } + return false; + } + } + bool b = false; + if(recursive) { + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) break; + if(CHILD(i).calculateFunctions(eo, recursive, do_unformat)) { + CHILD_UPDATED(i); + b = true; + } + } + } + return b; + +} + +int evalSortCompare(const MathStructure &mstruct1, const MathStructure &mstruct2, const MathStructure &parent, bool b_abs = false); +int evalSortCompare(const MathStructure &mstruct1, const MathStructure &mstruct2, const MathStructure &parent, bool b_abs) { + if(parent.isMultiplication()) { + if((!mstruct1.representsNonMatrix() && !mstruct2.representsScalar()) || (!mstruct2.representsNonMatrix() && !mstruct1.representsScalar())) { + return 0; + } + } + if(b_abs || parent.isAddition()) { + if(mstruct1.isMultiplication() && mstruct1.size() > 0) { + size_t start = 0; + while(mstruct1[start].isNumber() && mstruct1.size() > start + 1) { + start++; + } + int i2; + if(mstruct2.isMultiplication()) { + if(mstruct2.size() < 1) return -1; + size_t start2 = 0; + while(mstruct2[start2].isNumber() && mstruct2.size() > start2 + 1) { + start2++; + } + for(size_t i = 0; ; i++) { + if(i + start2 >= mstruct2.size()) { + if(i + start >= mstruct1.size()) { + if(start2 == start) { + for(size_t i3 = 0; i3 < start; i3++) { + i2 = evalSortCompare(mstruct1[i3], mstruct2[i3], parent, b_abs); + if(i2 != 0) return i2; + } + return 0; + } + if(start2 > start) return -1; + } + return 1; + } + if(i + start >= mstruct1.size()) return -1; + i2 = evalSortCompare(mstruct1[i + start], mstruct2[i + start2], parent, b_abs); + if(i2 != 0) return i2; + } + if(mstruct1.size() - start == mstruct2.size() - start2) return 0; + return -1; + } else { + i2 = evalSortCompare(mstruct1[start], mstruct2, parent, b_abs); + if(i2 != 0) return i2; + if(b_abs && start == 1 && (mstruct1[0].isMinusOne() || mstruct1[0].isOne())) return 0; + return 1; + } + } else if(mstruct2.isMultiplication() && mstruct2.size() > 0) { + size_t start = 0; + while(mstruct2[start].isNumber() && mstruct2.size() > start + 1) { + start++; + } + int i2; + if(mstruct1.isMultiplication()) { + return 1; + } else { + i2 = evalSortCompare(mstruct1, mstruct2[start], parent, b_abs); + if(i2 != 0) return i2; + if(b_abs && start == 1 && (mstruct2[0].isMinusOne() || mstruct2[0].isOne())) return 0; + return -1; + } + } + } + if(mstruct1.type() != mstruct2.type()) { + if(!parent.isMultiplication()) { + if(mstruct2.isNumber()) return -1; + if(mstruct1.isNumber()) return 1; + } + if(!parent.isMultiplication() || (!mstruct1.isNumber() && !mstruct2.isNumber())) { + if(mstruct2.isPower()) { + int i = evalSortCompare(mstruct1, mstruct2[0], parent, b_abs); + if(i == 0) { + return evalSortCompare(m_one, mstruct2[1], parent, b_abs); + } + return i; + } + if(mstruct1.isPower()) { + int i = evalSortCompare(mstruct1[0], mstruct2, parent, b_abs); + if(i == 0) { + return evalSortCompare(mstruct1[1], m_one, parent, b_abs); + } + return i; + } + } + if(mstruct2.isAborted()) return -1; + if(mstruct1.isAborted()) return 1; + if(mstruct2.isInverse()) return -1; + if(mstruct1.isInverse()) return 1; + if(mstruct2.isDivision()) return -1; + if(mstruct1.isDivision()) return 1; + if(mstruct2.isNegate()) return -1; + if(mstruct1.isNegate()) return 1; + if(mstruct2.isLogicalAnd()) return -1; + if(mstruct1.isLogicalAnd()) return 1; + if(mstruct2.isLogicalOr()) return -1; + if(mstruct1.isLogicalOr()) return 1; + if(mstruct2.isLogicalXor()) return -1; + if(mstruct1.isLogicalXor()) return 1; + if(mstruct2.isLogicalNot()) return -1; + if(mstruct1.isLogicalNot()) return 1; + if(mstruct2.isComparison()) return -1; + if(mstruct1.isComparison()) return 1; + if(mstruct2.isBitwiseOr()) return -1; + if(mstruct1.isBitwiseOr()) return 1; + if(mstruct2.isBitwiseXor()) return -1; + if(mstruct1.isBitwiseXor()) return 1; + if(mstruct2.isBitwiseAnd()) return -1; + if(mstruct1.isBitwiseAnd()) return 1; + if(mstruct2.isBitwiseNot()) return -1; + if(mstruct1.isBitwiseNot()) return 1; + if(mstruct2.isUndefined()) return -1; + if(mstruct1.isUndefined()) return 1; + if(mstruct2.isFunction()) return -1; + if(mstruct1.isFunction()) return 1; + if(mstruct2.isAddition()) return -1; + if(mstruct1.isAddition()) return 1; + if(mstruct2.isMultiplication()) return -1; + if(mstruct1.isMultiplication()) return 1; + if(mstruct2.isPower()) return -1; + if(mstruct1.isPower()) return 1; + if(mstruct2.isUnit()) return -1; + if(mstruct1.isUnit()) return 1; + if(mstruct2.isSymbolic()) return -1; + if(mstruct1.isSymbolic()) return 1; + if(mstruct2.isVariable()) return -1; + if(mstruct1.isVariable()) return 1; + if(mstruct2.isDateTime()) return -1; + if(mstruct1.isDateTime()) return 1; + if(parent.isMultiplication()) { + if(mstruct2.isNumber()) return -1; + if(mstruct1.isNumber()) return 1; + } + return -1; + } + switch(mstruct1.type()) { + case STRUCT_NUMBER: { + if(CALCULATOR->aborted()) return 0; + if(b_abs) { + ComparisonResult cmp = mstruct1.number().compareAbsolute(mstruct2.number()); + if(cmp == COMPARISON_RESULT_LESS) return -1; + else if(cmp == COMPARISON_RESULT_GREATER) return 1; + return 0; + } + if(!mstruct1.number().hasImaginaryPart() && !mstruct2.number().hasImaginaryPart()) { + if(mstruct1.number().isFloatingPoint()) { + if(!mstruct2.number().isFloatingPoint()) return 1; + if(mstruct1.number().isInterval()) { + if(!mstruct2.number().isInterval()) return 1; + } else if(mstruct2.number().isInterval()) return -1; + } else if(mstruct2.number().isFloatingPoint()) return -1; + ComparisonResult cmp = mstruct1.number().compare(mstruct2.number()); + if(cmp == COMPARISON_RESULT_LESS) return -1; + else if(cmp == COMPARISON_RESULT_GREATER) return 1; + return 0; + } else { + if(!mstruct1.number().hasRealPart()) { + if(mstruct2.number().hasRealPart()) { + return 1; + } else { + ComparisonResult cmp = mstruct1.number().compareImaginaryParts(mstruct2.number()); + if(cmp == COMPARISON_RESULT_LESS) return -1; + else if(cmp == COMPARISON_RESULT_GREATER) return 1; + return 0; + } + } else if(mstruct2.number().hasRealPart()) { + ComparisonResult cmp = mstruct1.number().compareRealParts(mstruct2.number()); + if(cmp == COMPARISON_RESULT_EQUAL) { + cmp = mstruct1.number().compareImaginaryParts(mstruct2.number()); + } + if(cmp == COMPARISON_RESULT_LESS) return -1; + else if(cmp == COMPARISON_RESULT_GREATER) return 1; + return 0; + } else { + return -1; + } + } + return -1; + } + case STRUCT_UNIT: { + if(mstruct1.unit() < mstruct2.unit()) return -1; + if(mstruct1.unit() == mstruct2.unit()) return 0; + return 1; + } + case STRUCT_SYMBOLIC: { + if(mstruct1.symbol() < mstruct2.symbol()) return -1; + else if(mstruct1.symbol() == mstruct2.symbol()) return 0; + return 1; + } + case STRUCT_VARIABLE: { + if(mstruct1.variable() < mstruct2.variable()) return -1; + else if(mstruct1.variable() == mstruct2.variable()) return 0; + return 1; + } + case STRUCT_FUNCTION: { + if(mstruct1.function() < mstruct2.function()) return -1; + if(mstruct1.function() == mstruct2.function()) { + for(size_t i = 0; i < mstruct2.size(); i++) { + if(i >= mstruct1.size()) { + return -1; + } + int i2 = evalSortCompare(mstruct1[i], mstruct2[i], parent, b_abs); + if(i2 != 0) return i2; + } + return 0; + } + return 1; + } + case STRUCT_POWER: { + int i = evalSortCompare(mstruct1[0], mstruct2[0], parent, b_abs); + if(i == 0) { + return evalSortCompare(mstruct1[1], mstruct2[1], parent, b_abs); + } + return i; + } + default: { + if(mstruct2.size() < mstruct1.size()) return -1; + else if(mstruct2.size() > mstruct1.size()) return 1; + int ie; + for(size_t i = 0; i < mstruct1.size(); i++) { + ie = evalSortCompare(mstruct1[i], mstruct2[i], parent, b_abs); + if(ie != 0) { + return ie; + } + } + } + } + return 0; +} + +void MathStructure::evalSort(bool recursive, bool b_abs) { + if(recursive) { + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).evalSort(true, b_abs); + } + } + //if(m_type != STRUCT_ADDITION && m_type != STRUCT_MULTIPLICATION && m_type != STRUCT_LOGICAL_AND && m_type != STRUCT_LOGICAL_OR && m_type != STRUCT_LOGICAL_XOR && m_type != STRUCT_BITWISE_AND && m_type != STRUCT_BITWISE_OR && m_type != STRUCT_BITWISE_XOR) return; + if(m_type != STRUCT_ADDITION && m_type != STRUCT_MULTIPLICATION && m_type != STRUCT_BITWISE_AND && m_type != STRUCT_BITWISE_OR && m_type != STRUCT_BITWISE_XOR) return; + if(m_type == STRUCT_ADDITION && containsType(STRUCT_DATETIME, false, true, false) > 0) return; + vector sorted; + sorted.reserve(SIZE); + for(size_t i = 0; i < SIZE; i++) { + if(i == 0) { + sorted.push_back(v_order[i]); + } else { + if(evalSortCompare(CHILD(i), *v_subs[sorted.back()], *this, b_abs) >= 0) { + sorted.push_back(v_order[i]); + } else if(sorted.size() == 1) { + sorted.insert(sorted.begin(), v_order[i]); + } else { + for(size_t i2 = sorted.size() - 2; ; i2--) { + if(evalSortCompare(CHILD(i), *v_subs[sorted[i2]], *this, b_abs) >= 0) { + sorted.insert(sorted.begin() + i2 + 1, v_order[i]); + break; + } + if(i2 == 0) { + sorted.insert(sorted.begin(), v_order[i]); + break; + } + } + } + } + } + for(size_t i2 = 0; i2 < sorted.size(); i2++) { + v_order[i2] = sorted[i2]; + } +} + + diff -Nru libqalculate-3.6.0/libqalculate/MathStructure.cc libqalculate-3.7.0/libqalculate/MathStructure.cc --- libqalculate-3.6.0/libqalculate/MathStructure.cc 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure.cc 2020-01-21 22:54:40.000000000 +0000 @@ -11,8 +11,9 @@ #include "support.h" -#include "MathStructure.h" #include "Calculator.h" +#include "MathStructure.h" +#include "BuiltinFunctions.h" #include "Number.h" #include "Function.h" #include "Variable.h" @@ -20,342 +21,13 @@ #include "Prefix.h" #include #include - -#if HAVE_UNORDERED_MAP -# include - using std::unordered_map; -#elif defined(__GNUC__) - -# ifndef __has_include -# define __has_include(x) 0 -# endif - -# if (defined(__clang__) && __has_include()) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 3) -# include - namespace Sgi = std; -# define unordered_map std::tr1::unordered_map -# else -# if __GNUC__ < 3 -# include - namespace Sgi { using ::hash_map; }; // inherit globals -# else -# include -# if __GNUC__ == 3 && __GNUC_MINOR__ == 0 - namespace Sgi = std; // GCC 3.0 -# else - namespace Sgi = ::__gnu_cxx; // GCC 3.1 and later -# endif -# endif -# define unordered_map Sgi::hash_map -# endif -#else // ... there are other compilers, right? - namespace Sgi = std; -# define unordered_map Sgi::hash_map -#endif +#include "MathStructure-support.h" using std::string; using std::cout; using std::vector; -using std::ostream; using std::endl; -#define SWAP_CHILDREN(i1, i2) {MathStructure *swap_mstruct = v_subs[v_order[i1]]; v_subs[v_order[i1]] = v_subs[v_order[i2]]; v_subs[v_order[i2]] = swap_mstruct;} -#define CHILD_TO_FRONT(i) v_order.insert(v_order.begin(), v_order[i]); v_order.erase(v_order.begin() + (i + 1)); -#define SET_CHILD_MAP(i) setToChild(i + 1, true); -#define SET_MAP(o) set(o, true); -#define SET_MAP_NOCOPY(o) set_nocopy(o, true); -#define MERGE_APPROX_AND_PREC(o) if(!b_approx && o.isApproximate()) b_approx = true; if(o.precision() > 0 && (i_precision < 1 || o.precision() < i_precision)) i_precision = o.precision(); -#define CHILD_UPDATED(i) if(!b_approx && CHILD(i).isApproximate()) b_approx = true; if(CHILD(i).precision() > 0 && (i_precision < 1 || CHILD(i).precision() < i_precision)) i_precision = CHILD(i).precision(); -#define CHILDREN_UPDATED for(size_t child_i = 0; child_i < SIZE; child_i++) {if(!b_approx && CHILD(child_i).isApproximate()) b_approx = true; if(CHILD(child_i).precision() > 0 && (i_precision < 1 || CHILD(child_i).precision() < i_precision)) i_precision = CHILD(child_i).precision();} - -#define APPEND(o) v_order.push_back(v_subs.size()); v_subs.push_back(new MathStructure(o)); if(!b_approx && o.isApproximate()) b_approx = true; if(o.precision() > 0 && (i_precision < 1 || o.precision() < i_precision)) i_precision = o.precision(); -#define APPEND_NEW(o) {v_order.push_back(v_subs.size()); MathStructure *m_append_new = new MathStructure(o); v_subs.push_back(m_append_new); if(!b_approx && m_append_new->isApproximate()) b_approx = true; if(m_append_new->precision() > 0 && (i_precision < 1 || m_append_new->precision() < i_precision)) i_precision = m_append_new->precision();} -#define APPEND_COPY(o) v_order.push_back(v_subs.size()); v_subs.push_back(new MathStructure(*(o))); if(!b_approx && (o)->isApproximate()) b_approx = true; if((o)->precision() > 0 && (i_precision < 1 || (o)->precision() < i_precision)) i_precision = (o)->precision(); -#define APPEND_POINTER(o) v_order.push_back(v_subs.size()); v_subs.push_back(o); if(!b_approx && (o)->isApproximate()) b_approx = true; if((o)->precision() > 0 && (i_precision < 1 || (o)->precision() < i_precision)) i_precision = (o)->precision(); -#define APPEND_REF(o) v_order.push_back(v_subs.size()); v_subs.push_back(o); (o)->ref(); if(!b_approx && (o)->isApproximate()) b_approx = true; if((o)->precision() > 0 && (i_precision < 1 || (o)->precision() < i_precision)) i_precision = (o)->precision(); -#define PREPEND(o) v_order.insert(v_order.begin(), v_subs.size()); v_subs.push_back(new MathStructure(o)); if(!b_approx && o.isApproximate()) b_approx = true; if(o.precision() > 0 && (i_precision < 1 || o.precision() < i_precision)) i_precision = o.precision(); -#define PREPEND_REF(o) v_order.insert(v_order.begin(), v_subs.size()); v_subs.push_back(o); (o)->ref(); if(!b_approx && (o)->isApproximate()) b_approx = true; if((o)->precision() > 0 && (i_precision < 1 || (o)->precision() < i_precision)) i_precision = (o)->precision(); -#define INSERT_REF(o, i) v_order.insert(v_order.begin() + i, v_subs.size()); v_subs.push_back(o); (o)->ref(); if(!b_approx && (o)->isApproximate()) b_approx = true; if((o)->precision() > 0 && (i_precision < 1 || (o)->precision() < i_precision)) i_precision = (o)->precision(); -#define CLEAR v_order.clear(); for(size_t i = 0; i < v_subs.size(); i++) {v_subs[i]->unref();} v_subs.clear(); -//#define REDUCE(v_size) for(size_t v_index = v_size; v_index < v_order.size(); v_index++) {v_subs[v_order[v_index]]->unref(); v_subs.erase(v_subs.begin() + v_order[v_index]);} v_order.resize(v_size); -#define REDUCE(v_size) {vector v_tmp; v_tmp.resize(SIZE, 0); for(size_t v_index = v_size; v_index < v_order.size(); v_index++) {v_subs[v_order[v_index]]->unref(); v_subs[v_order[v_index]] = NULL; v_tmp[v_order[v_index]] = 1;} v_order.resize(v_size); for(vector::iterator v_it = v_subs.begin(); v_it != v_subs.end();) {if(*v_it == NULL) v_it = v_subs.erase(v_it); else ++v_it;} size_t i_change = 0; for(size_t v_index = 0; v_index < v_tmp.size(); v_index++) {if(v_tmp[v_index] == 1) i_change++; v_tmp[v_index] = i_change;} for(size_t v_index = 0; v_index < v_order.size(); v_index++) v_order[v_index] -= v_tmp[v_index];} -#define CHILD(v_index) (*v_subs[v_order[v_index]]) -#define SIZE v_order.size() -#define LAST (*v_subs[v_order[v_order.size() - 1]]) -#define ERASE(v_index) v_subs[v_order[v_index]]->unref(); v_subs.erase(v_subs.begin() + v_order[v_index]); for(size_t v_index2 = 0; v_index2 < v_order.size(); v_index2++) {if(v_order[v_index2] > v_order[v_index]) v_order[v_index2]--;} v_order.erase(v_order.begin() + (v_index)); - -#define IS_REAL(o) (o.isNumber() && o.number().isReal()) -#define IS_RATIONAL(o) (o.isNumber() && o.number().isRational()) - -#define IS_A_SYMBOL(o) ((o.isSymbolic() || o.isVariable() || o.isFunction()) && o.representsScalar()) - -#define POWER_CLEAN(o) if(o[1].isOne()) {o.setToChild(1);} else if(o[1].isZero()) {o.set(1, 1, 0);} - -#define VALID_ROOT(o) (o.size() == 2 && o[1].isNumber() && o[1].number().isInteger() && o[1].number().isPositive()) -#define THIS_VALID_ROOT (SIZE == 2 && CHILD(1).isNumber() && CHILD(1).number().isInteger() && CHILD(1).number().isPositive()) - -void printRecursive(const MathStructure &mstruct) { - std::cout << "RECURSIVE " << mstruct.print() << std::endl; - for(size_t i = 0; i < mstruct.size(); i++) { - std::cout << i << ": " << mstruct[i].print() << std::endl; - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - std::cout << i << "-" << i2 << ": " << mstruct[i][i2].print() << std::endl; - for(size_t i3 = 0; i3 < mstruct[i][i2].size(); i3++) { - std::cout << i << "-" << i2 << "-" << i3 << ": " << mstruct[i][i2][i3].print() << std::endl; - for(size_t i4 = 0; i4 < mstruct[i][i2][i3].size(); i4++) { - std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << ": " << mstruct[i][i2][i3][i4].print() << std::endl; - for(size_t i5 = 0; i5 < mstruct[i][i2][i3][i4].size(); i5++) { - std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << ": " << mstruct[i][i2][i3][i4][i5].print() << std::endl; - for(size_t i6 = 0; i6 < mstruct[i][i2][i3][i4][i5].size(); i6++) { - std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << "-" << i6 << ": " << mstruct[i][i2][i3][i4][i5][i6].print() << std::endl; - for(size_t i7 = 0; i7 < mstruct[i][i2][i3][i4][i5][i6].size(); i7++) { - std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << "-" << i6 << "-" << i7 << ": " << mstruct[i][i2][i3][i4][i5][i6][i7].print() << std::endl; - for(size_t i8 = 0; i8 < mstruct[i][i2][i3][i4][i5][i6][i7].size(); i8++) { - std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << "-" << i6 << "-" << i7 << "-" << i8 << ": " << mstruct[i][i2][i3][i4][i5][i6][i7][i8].print() << std::endl; - for(size_t i9 = 0; i9 < mstruct[i][i2][i3][i4][i5][i6][i7][i8].size(); i9++) { - std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << "-" << i6 << "-" << i7 << "-" << i8 << "-" << i9 << ": " << mstruct[i][i2][i3][i4][i5][i6][i7][i8][i9].print() << std::endl; - } - } - } - } - } - } - } - } - } -} - -string format_and_print(const MathStructure &mstruct) { - MathStructure m_print(mstruct); - if(CALCULATOR) { - m_print.sort(CALCULATOR->messagePrintOptions()); - m_print.formatsub(CALCULATOR->messagePrintOptions(), NULL, 0, true, &m_print); - return m_print.print(CALCULATOR->messagePrintOptions()); - } else { - PrintOptions po; - po.interval_display = INTERVAL_DISPLAY_PLUSMINUS; - po.spell_out_logical_operators = true; - po.number_fraction_format = FRACTION_FRACTIONAL; - m_print.sort(po); - m_print.formatsub(po, NULL, 0, true, &m_print); - return m_print.print(po); - } -} - -struct sym_desc { - MathStructure sym; - Number deg_a; - Number deg_b; - Number ldeg_a; - Number ldeg_b; - Number max_deg; - size_t max_lcnops; - bool operator<(const sym_desc &x) const { - if (max_deg == x.max_deg) return max_lcnops < x.max_lcnops; - else return max_deg.isLessThan(x.max_deg); - } -}; -typedef std::vector sym_desc_vec; - -bool polynomial_long_division(const MathStructure &mnum, const MathStructure &mden, const MathStructure &xvar_pre, MathStructure &mquotient, MathStructure &mrem, const EvaluationOptions &eo, bool check_args = false, bool for_newtonraphson = false); -void integer_content(const MathStructure &mpoly, Number &icontent); -bool interpolate(const MathStructure &gamma, const Number &xi, const MathStructure &xvar, MathStructure &minterp, const EvaluationOptions &eo); -bool get_first_symbol(const MathStructure &mpoly, MathStructure &xvar); -bool divide_in_z(const MathStructure &mnum, const MathStructure &mden, MathStructure &mquotient, const sym_desc_vec &sym_stats, size_t var_i, const EvaluationOptions &eo); -bool prem(const MathStructure &mnum, const MathStructure &mden, const MathStructure &xvar, MathStructure &mrem, const EvaluationOptions &eo, bool check_args = true); -bool sr_gcd(const MathStructure &m1, const MathStructure &m2, MathStructure &mgcd, const sym_desc_vec &sym_stats, size_t var_i, const EvaluationOptions &eo); -void polynomial_smod(const MathStructure &mpoly, const Number &xi, MathStructure &msmod, const EvaluationOptions &eo, MathStructure *mparent = NULL, size_t index_smod = 0); -bool heur_gcd(const MathStructure &m1, const MathStructure &m2, MathStructure &mgcd, const EvaluationOptions &eo, MathStructure *ca, MathStructure *cb, const sym_desc_vec &sym_stats, size_t var_i); -void add_symbol(const MathStructure &mpoly, sym_desc_vec &v); -void collect_symbols(const MathStructure &mpoly, sym_desc_vec &v); -void add_symbol(const MathStructure &mpoly, vector &v); -void collect_symbols(const MathStructure &mpoly, vector &v); -void get_symbol_stats(const MathStructure &m1, const MathStructure &m2, sym_desc_vec &v); -bool sqrfree(MathStructure &mpoly, const EvaluationOptions &eo); -bool sqrfree(MathStructure &mpoly, const vector &symbols, const EvaluationOptions &eo); -bool simplify_functions(MathStructure &mstruct, const EvaluationOptions &eo, const EvaluationOptions &feo, const MathStructure &x_var = m_undefined); -bool factorize_find_multiplier(const MathStructure &mstruct, MathStructure &mnew, MathStructure &factor_mstruct, bool only_units = false); -bool is_unit_multiexp(const MathStructure &mstruct); -bool has_approximate_relation_to_base(Unit *u, bool do_intervals = true); -bool contains_approximate_relation_to_base(const MathStructure &m, bool do_intervals = true); -bool contains_diff_for(const MathStructure &m, const MathStructure &x_var); -bool separate_unit_vars(MathStructure &m, const EvaluationOptions &eo, bool only_approximate, bool dry_run = false); -void lcm_of_coefficients_denominators(const MathStructure &e, Number &nlcm); -void multiply_lcm(const MathStructure &e, const Number &lcm, MathStructure &mmul, const EvaluationOptions &eo); - -bool flattenMultiplication(MathStructure &mstruct) { - bool retval = false; - for(size_t i = 0; i < mstruct.size();) { - if(mstruct[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - mstruct[i][i2].ref(); - mstruct.insertChild_nocopy(&mstruct[i][i2], i + i2 + 2); - } - mstruct.delChild(i + 1); - retval = true; - } else { - i++; - } - } - return retval; -} -bool flattenAddition(MathStructure &mstruct) { - bool retval = false; - for(size_t i = 0; i < mstruct.size();) { - if(mstruct[i].isAddition()) { - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - mstruct[i][i2].ref(); - mstruct.insertChild_nocopy(&mstruct[i][i2], i + i2 + 2); - } - mstruct.delChild(i + 1); - retval = true; - } else { - i++; - } - } - return retval; -} -bool warn_test_interval(MathStructure &mnonzero, const EvaluationOptions &eo2) { - if(mnonzero.isComparison() && mnonzero[0].isVariable() && !mnonzero[0].variable()->isKnown() && !((UnknownVariable*) mnonzero[0].variable())->interval().isUndefined()) { - /*if(((UnknownVariable*) mnonzero[0].variable())->interval().isNumber() && mnonzero[1].isNumber()) { - MathStructure mbak(mnonzero); - mnonzero[0] = ((UnknownVariable*) mnonzero[0].variable())->interval(); - mnonzero.eval(eo2); - if(!mnonzero.isNumber()) mnonzero.clear(); - return true; - } else*/ if(((UnknownVariable*) mnonzero[0].variable())->interval().containsInterval(true)) { - MathStructure mbak(mnonzero); - mnonzero[0] = ((UnknownVariable*) mnonzero[0].variable())->interval(); - mnonzero.eval(eo2); - if(mnonzero.isComparison()) mnonzero = mbak; - else return true; - } else { - mnonzero[0] = ((UnknownVariable*) mnonzero[0].variable())->interval(); - mnonzero.eval(eo2); - return true; - } - } else if(mnonzero.isLogicalAnd() || mnonzero.isLogicalOr()) { - bool b_ret = false; - for(size_t i = 0; i < mnonzero.size(); i++) { - if(warn_test_interval(mnonzero[i], eo2)) b_ret = true; - } - if(b_ret) { - mnonzero.calculatesub(eo2, eo2, false); - return true; - } - } - return false; -} -bool warn_about_assumed_not_value(const MathStructure &mstruct, const MathStructure &mvalue, const EvaluationOptions &eo) { - CALCULATOR->beginTemporaryStopMessages(); - EvaluationOptions eo2 = eo; - eo2.assume_denominators_nonzero = false; - eo2.test_comparisons = true; - eo2.isolate_x = true; - eo2.expand = true; - eo2.approximation = APPROXIMATION_APPROXIMATE; - MathStructure mnonzero(mstruct); - mnonzero.add(mvalue, OPERATION_NOT_EQUALS); - mnonzero.eval(eo2); - warn_test_interval(mnonzero, eo2); - if(CALCULATOR->endTemporaryStopMessages()) return false; - if(mnonzero.isZero()) return false; - if(mnonzero.isOne()) return true; - if(mvalue.isZero() && mnonzero.isComparison() && mnonzero.comparisonType() == COMPARISON_NOT_EQUALS && mnonzero[1].isZero() && mnonzero[0].representsApproximatelyZero(true)) return false; - CALCULATOR->error(false, _("Required assumption: %s."), format_and_print(mnonzero).c_str(), NULL); - return true; -} -bool warn_about_denominators_assumed_nonzero(const MathStructure &mstruct, const EvaluationOptions &eo) { - CALCULATOR->beginTemporaryStopMessages(); - EvaluationOptions eo2 = eo; - eo2.assume_denominators_nonzero = false; - eo2.test_comparisons = true; - eo2.isolate_x = true; - eo2.expand = true; - eo2.approximation = APPROXIMATION_APPROXIMATE; - MathStructure mnonzero(mstruct); - mnonzero.add(m_zero, OPERATION_NOT_EQUALS); - mnonzero.eval(eo2); - warn_test_interval(mnonzero, eo2); - if(CALCULATOR->endTemporaryStopMessages()) return false; - if(mnonzero.isZero()) return false; - if(mnonzero.isOne()) return true; - if(mnonzero.isComparison() && mnonzero.comparisonType() == COMPARISON_NOT_EQUALS && mnonzero[1].isZero() && mnonzero[0].representsApproximatelyZero(true)) return false; - CALCULATOR->error(false, _("To avoid division by zero, the following must be true: %s."), format_and_print(mnonzero).c_str(), NULL); - return true; -} -bool warn_about_denominators_assumed_nonzero_or_positive(const MathStructure &mstruct, const MathStructure &mstruct2, const EvaluationOptions &eo) { - CALCULATOR->beginTemporaryStopMessages(); - EvaluationOptions eo2 = eo; - eo2.assume_denominators_nonzero = false; - eo2.test_comparisons = true; - eo2.isolate_x = true; - eo2.expand = true; - eo2.approximation = APPROXIMATION_APPROXIMATE; - MathStructure mnonzero(mstruct); - mnonzero.add(m_zero, OPERATION_NOT_EQUALS); - MathStructure *mpos = new MathStructure(mstruct2); - mpos->add(m_zero, OPERATION_EQUALS_GREATER); - mnonzero.add_nocopy(mpos, OPERATION_LOGICAL_OR); - mnonzero.eval(eo2); - warn_test_interval(mnonzero, eo2); - if(CALCULATOR->endTemporaryStopMessages()) return false; - if(mnonzero.isZero()) return false; - if(mnonzero.isOne()) return true; - if(mnonzero.isComparison() && mnonzero.comparisonType() == COMPARISON_NOT_EQUALS && mnonzero[1].isZero() && mnonzero[0].representsApproximatelyZero(true)) return false; - CALCULATOR->error(false, _("To avoid division by zero, the following must be true: %s."), format_and_print(mnonzero).c_str(), NULL); - return true; -} -bool warn_about_denominators_assumed_nonzero_llgg(const MathStructure &mstruct, const MathStructure &mstruct2, const MathStructure &mstruct3, const EvaluationOptions &eo) { - CALCULATOR->beginTemporaryStopMessages(); - EvaluationOptions eo2 = eo; - eo2.assume_denominators_nonzero = false; - eo2.test_comparisons = true; - eo2.isolate_x = true; - eo2.expand = true; - eo2.approximation = APPROXIMATION_APPROXIMATE; - MathStructure mnonzero(mstruct); - mnonzero.add(m_zero, OPERATION_NOT_EQUALS); - MathStructure *mpos = new MathStructure(mstruct2); - mpos->add(m_zero, OPERATION_EQUALS_GREATER); - MathStructure *mpos2 = new MathStructure(mstruct3); - mpos2->add(m_zero, OPERATION_EQUALS_GREATER); - mpos->add_nocopy(mpos2, OPERATION_LOGICAL_AND); - mnonzero.add_nocopy(mpos, OPERATION_LOGICAL_OR); - MathStructure *mneg = new MathStructure(mstruct2); - mneg->add(m_zero, OPERATION_LESS); - MathStructure *mneg2 = new MathStructure(mstruct3); - mneg2->add(m_zero, OPERATION_LESS); - mneg->add_nocopy(mneg2, OPERATION_LOGICAL_AND); - mnonzero.add_nocopy(mneg, OPERATION_LOGICAL_OR); - mnonzero.eval(eo2); - warn_test_interval(mnonzero, eo2); - if(CALCULATOR->endTemporaryStopMessages()) return false; - if(mnonzero.isZero()) return false; - if(mnonzero.isOne()) return true; - if(mnonzero.isComparison() && mnonzero.comparisonType() == COMPARISON_NOT_EQUALS && mnonzero[1].isZero() && mnonzero[0].representsApproximatelyZero(true)) return false; - CALCULATOR->error(false, _("To avoid division by zero, the following must be true: %s."), format_and_print(mnonzero).c_str(), NULL); - return true; -} - -void unnegate_sign(MathStructure &mstruct) { - if(mstruct.isNumber()) { - mstruct.number().negate(); - } else if(mstruct.isMultiplication() && mstruct.size() > 0) { - if(mstruct[0].isMinusOne()) { - if(mstruct.size() > 2) { - mstruct.delChild(1); - } else if(mstruct.size() == 2) { - mstruct.setToChild(2); - } else { - mstruct.set(1, 1, 0); - } - } else { - unnegate_sign(mstruct[0]); - } - } -} - void MathStructure::mergePrecision(const MathStructure &o) {MERGE_APPROX_AND_PREC(o)} void MathStructure::mergePrecision(bool approx, int prec) { if(!b_approx && approx) setApproximate(); @@ -364,10 +36,6 @@ } } -void idm1(const MathStructure &mnum, bool &bfrac, bool &bint); -void idm2(const MathStructure &mnum, bool &bfrac, bool &bint, Number &nr); -int idm3(MathStructure &mnum, Number &nr, bool expand); - void MathStructure::ref() { i_ref++; } @@ -880,13 +548,6 @@ bool MathStructure::operator != (const MathStructure &o) const {return !equals(o);} -/*MathStructure& MathStructure::CHILD(size_t v_index) const { - if(v_index < v_order.size() && v_order[v_index] < v_subs.size()) return *v_subs[v_order[v_index]]; - MathStructure* m = new MathStructure;//(new UnknownVariable("x","x")); - m->setUndefined(true); - return *m; -}*/ - const MathStructure &MathStructure::operator [] (size_t index) const {return CHILD(index);} MathStructure &MathStructure::operator [] (size_t index) {return CHILD(index);} @@ -1014,6 +675,9 @@ if(o_function) o_function->unref(); o_function = f; } +void MathStructure::setFunctionId(int id) { + setFunction(CALCULATOR->getFunctionById(id)); +} void MathStructure::setUnit(Unit *u) { if(u) u->ref(); if(o_unit) o_unit->unref(); @@ -1066,7 +730,7 @@ bool MathStructure::isDivision() const {return m_type == STRUCT_DIVISION;} bool MathStructure::isNegate() const {return m_type == STRUCT_NEGATE;} bool MathStructure::isInfinity() const {return m_type == STRUCT_NUMBER && o_number.isInfinite(true);} -bool MathStructure::isUndefined() const {return m_type == STRUCT_UNDEFINED || (m_type == STRUCT_NUMBER && o_number.isUndefined()) || (m_type == STRUCT_VARIABLE && o_variable == CALCULATOR->v_undef);} +bool MathStructure::isUndefined() const {return m_type == STRUCT_UNDEFINED || (m_type == STRUCT_NUMBER && o_number.isUndefined()) || (m_type == STRUCT_VARIABLE && o_variable == CALCULATOR->getVariableById(VARIABLE_ID_UNDEFINED));} bool MathStructure::isInteger() const {return m_type == STRUCT_NUMBER && o_number.isInteger();} bool MathStructure::isInfinite(bool ignore_imag) const {return m_type == STRUCT_NUMBER && o_number.isInfinite(ignore_imag);} bool MathStructure::isNumber() const {return m_type == STRUCT_NUMBER;} @@ -1178,7 +842,7 @@ case STRUCT_VARIABLE: {return o_variable->representsPositive(allow_units);} case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isPositive();} case STRUCT_FUNCTION: { - if(o_function == CALCULATOR->f_stripunits && SIZE == 1) return CHILD(0).representsPositive(true); + if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsPositive(true); return (function_value && function_value->representsPositive(allow_units)) || o_function->representsPositive(*this, allow_units); } case STRUCT_UNIT: {return allow_units;} @@ -1212,7 +876,7 @@ case STRUCT_VARIABLE: {return o_variable->representsNegative(allow_units);} case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isNegative();} case STRUCT_FUNCTION: { - if(o_function == CALCULATOR->f_stripunits && SIZE == 1) return CHILD(0).representsNegative(true); + if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsNegative(true); return (function_value && function_value->representsNegative(allow_units)) || o_function->representsNegative(*this, allow_units); } case STRUCT_UNIT: {return false;} @@ -1245,7 +909,7 @@ case STRUCT_VARIABLE: {return o_variable->representsNonNegative(allow_units);} case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isNonNegative();} case STRUCT_FUNCTION: { - if(o_function == CALCULATOR->f_stripunits && SIZE == 1) return CHILD(0).representsNonNegative(true); + if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsNonNegative(true); return (function_value && function_value->representsNonNegative(allow_units)) || o_function->representsNonNegative(*this, allow_units); } case STRUCT_UNIT: {return allow_units;} @@ -1280,7 +944,7 @@ case STRUCT_VARIABLE: {return o_variable->representsNonPositive(allow_units);} case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isNonPositive();} case STRUCT_FUNCTION: { - if(o_function == CALCULATOR->f_stripunits && SIZE == 1) return CHILD(0).representsNonPositive(true); + if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsNonPositive(true); return (function_value && function_value->representsNonPositive(allow_units)) || o_function->representsNonPositive(*this, allow_units); } case STRUCT_UNIT: {return false;} @@ -1313,7 +977,7 @@ case STRUCT_VARIABLE: {return o_variable->representsRational(allow_units);} case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isRational();} case STRUCT_FUNCTION: { - if(o_function == CALCULATOR->f_stripunits && SIZE == 1) return CHILD(0).representsRational(true); + if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsRational(true); return (function_value && function_value->representsRational(allow_units)) || o_function->representsRational(*this, allow_units); } case STRUCT_UNIT: {return false;} @@ -1343,7 +1007,7 @@ case STRUCT_VARIABLE: {return o_variable->representsReal(allow_units);} case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isReal();} case STRUCT_FUNCTION: { - if(o_function == CALCULATOR->f_stripunits && SIZE == 1) return CHILD(0).representsReal(true); + if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsReal(true); return (function_value && function_value->representsReal(allow_units)) || o_function->representsReal(*this, allow_units); } case STRUCT_UNIT: {return allow_units;} @@ -1378,7 +1042,7 @@ } case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isReal();} case STRUCT_FUNCTION: { - if(o_function == CALCULATOR->f_stripunits && SIZE == 1) return CHILD(0).representsNonComplex(true); + if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsNonComplex(true); return (function_value && function_value->representsNonComplex(allow_units)) || o_function->representsNonComplex(*this, allow_units); } case STRUCT_UNIT: {return allow_units;} @@ -1468,7 +1132,7 @@ return true; } case STRUCT_POWER: { - return CHILD(0).representsNonZero(allow_units) || (!CHILD(0).isApproximatelyZero() && CHILD(1).representsNonPositive()); + return (CHILD(0).representsNonZero(allow_units) && ((CHILD(1).isNumber() && !CHILD(1).number().includesInfinity()) || (!CHILD(1).isNumber() && CHILD(1).representsNumber(true)))) || (!CHILD(0).isApproximatelyZero() && CHILD(1).representsNonPositive()); } default: {return false;} } @@ -1555,7 +1219,7 @@ case STRUCT_UNDEFINED: {return true;} case STRUCT_VARIABLE: {return o_variable->representsUndefined(include_childs, include_infinite, be_strict);} case STRUCT_FUNCTION: { - if(o_function == CALCULATOR->f_stripunits && SIZE == 1) return CHILD(0).representsUndefined(include_childs, include_infinite, be_strict); + if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsUndefined(include_childs, include_infinite, be_strict); return (function_value && function_value->representsUndefined(include_childs, include_infinite, be_strict)) || o_function->representsUndefined(*this); } case STRUCT_POWER: { @@ -1586,7 +1250,7 @@ case STRUCT_VARIABLE: {return o_variable->representsNonMatrix();} case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isNonMatrix();} case STRUCT_FUNCTION: { - if(o_function == CALCULATOR->f_stripunits && SIZE == 1) return CHILD(0).representsNonMatrix(); + if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsNonMatrix(); return (function_value && function_value->representsNonMatrix()) || o_function->representsNonMatrix(*this); } case STRUCT_INVERSE: {} @@ -1615,7 +1279,7 @@ case STRUCT_VARIABLE: {return o_variable->representsScalar();} case STRUCT_SYMBOLIC: {return CALCULATOR->defaultAssumptions()->isNonMatrix();} case STRUCT_FUNCTION: { - if(o_function == CALCULATOR->f_stripunits && SIZE == 1) return CHILD(0).representsScalar(); + if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) return CHILD(0).representsScalar(); return (function_value && function_value->representsScalar()) || o_function->representsScalar(*this); } case STRUCT_INVERSE: {} @@ -1750,6 +1414,11 @@ setFunction(o); b_parentheses = false; } +void MathStructure::transformById(int id) { + transform(STRUCT_FUNCTION); + setFunctionId(id); + b_parentheses = false; +} void MathStructure::transform(ComparisonType ctype, const MathStructure &o) { MathStructure *struct_o = new MathStructure(o); MathStructure *struct_this = new MathStructure(); @@ -2180,8 +1849,8 @@ case STRUCT_NUMBER: {return o_number.equals(o.number(), allow_interval, allow_infinite);} case STRUCT_VARIABLE: {return o_variable == o.variable();} case STRUCT_UNIT: { - Prefix *p1 = (o_prefix == NULL || o_prefix == CALCULATOR->decimal_null_prefix || o_prefix == CALCULATOR->binary_null_prefix) ? NULL : o_prefix; - Prefix *p2 = (o.prefix() == NULL || o.prefix() == CALCULATOR->decimal_null_prefix || o.prefix() == CALCULATOR->binary_null_prefix) ? NULL : o.prefix(); + Prefix *p1 = (o_prefix == NULL || o_prefix == CALCULATOR->getDecimalNullPrefix() || o_prefix == CALCULATOR->getBinaryNullPrefix()) ? NULL : o_prefix; + Prefix *p2 = (o.prefix() == NULL || o.prefix() == CALCULATOR->getDecimalNullPrefix() || o.prefix() == CALCULATOR->getBinaryNullPrefix()) ? NULL : o.prefix(); return o_unit == o.unit() && p1 == p2; } case STRUCT_COMPARISON: {if(ct_comp != o.comparisonType()) return false; break;} @@ -2251,7 +1920,7 @@ } return true; } -bool remove_rad_unit(MathStructure &m, const EvaluationOptions &eo, bool top = true) { +bool remove_rad_unit(MathStructure &m, const EvaluationOptions &eo, bool top) { if(top && !remove_rad_unit_cf(m)) return false; if(m.isUnit()) { if(m.unit() == CALCULATOR->getRadUnit()) { @@ -2313,7 +1982,7 @@ return incomp; } -bool replace_interval_unknowns(MathStructure &m, bool do_assumptions = false) { +bool replace_interval_unknowns(MathStructure &m, bool do_assumptions) { if(m.isVariable() && !m.variable()->isKnown()) { if(!((UnknownVariable*) m.variable())->interval().isUndefined()) { m = ((UnknownVariable*) m.variable())->interval(); @@ -2445,14 +2114,16 @@ int b_ass = (i == 0 ? 2 : contains_ass_intval(mtest)); if(b_ass == 0) break; CALCULATOR->beginTemporaryEnableIntervalArithmetic(); - CALCULATOR->beginTemporaryStopMessages(); - replace_interval_unknowns(mtest, i > 0); - if(b_ass == 2) mtest.calculateFunctions(eo); - mtest.calculatesub(eo, eo); - int incomp = 0; - remove_rad_unit(mtest, eo); - CALCULATOR->endTemporaryStopMessages(); + if(CALCULATOR->usesIntervalArithmetic()) { + CALCULATOR->beginTemporaryStopMessages(); + replace_interval_unknowns(mtest, i > 0); + if(b_ass == 2) mtest.calculateFunctions(eo); + mtest.calculatesub(eo, eo); + remove_rad_unit(mtest, eo); + CALCULATOR->endTemporaryStopMessages(); + } CALCULATOR->endTemporaryEnableIntervalArithmetic(); + int incomp = 0; if(mtest.isAddition()) { incomp = compare_check_incompability(&mtest); } @@ -2620,34206 +2291,774 @@ return COMPARISON_RESULT_UNKNOWN; } -int MathStructure::merge_addition(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool reversed) { - if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { - Number nr(o_number); - if(nr.add(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate())) { - if(o_number == nr) { - o_number = nr; - numberUpdated(); - return 2; - } - o_number = nr; - numberUpdated(); - return 1; - } - return -1; - } - if(isZero()) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; +bool MathStructure::containsOpaqueContents() const { + if(isFunction()) return true; + if(isUnit() && o_unit->subtype() != SUBTYPE_BASE_UNIT) return true; + if(isVariable() && o_variable->isKnown()) return true; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).containsOpaqueContents()) return true; } - if(mstruct.isZero()) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - if(m_type == STRUCT_NUMBER && o_number.isInfinite()) { - if(mstruct.representsReal(false)) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - } else if(mstruct.isNumber() && mstruct.number().isInfinite()) { - if(representsReal(false)) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - clear(true); - o_number = mstruct.number(); - MERGE_APPROX_AND_PREC(mstruct) - } - return 3; - } + return false; +} +bool MathStructure::containsAdditionPower() const { + if(m_type == STRUCT_POWER && CHILD(0).isAddition()) return true; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).containsAdditionPower()) return true; } - if(representsUndefined() || mstruct.representsUndefined()) return -1; - switch(m_type) { - case STRUCT_VECTOR: { - switch(mstruct.type()) { - case STRUCT_ADDITION: {return 0;} - case STRUCT_VECTOR: { - if(SIZE == mstruct.size()) { - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).calculateAdd(mstruct[i], eo, this, i); - } - MERGE_APPROX_AND_PREC(mstruct) - CHILDREN_UPDATED - return 1; - } - } - default: { - if(mstruct.representsScalar()) { - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).calculateAdd(mstruct, eo, this, i); - } - CHILDREN_UPDATED - return 1; - } - return -1; - } - } - return -1; - } - case STRUCT_ADDITION: { - switch(mstruct.type()) { - case STRUCT_ADDITION: { - for(size_t i = 0; i < mstruct.size(); i++) { - if(reversed) { - INSERT_REF(&mstruct[i], i) - calculateAddIndex(i, eo, false); - } else { - APPEND_REF(&mstruct[i]); - calculateAddLast(eo, false); - } - } - MERGE_APPROX_AND_PREC(mstruct) - if(SIZE == 1) { - setToChild(1, false, mparent, index_this + 1); - } else if(SIZE == 0) { - clear(true); - } else { - evalSort(); - } - return 1; - } - default: { - MERGE_APPROX_AND_PREC(mstruct) - if(reversed) { - PREPEND_REF(&mstruct); - calculateAddIndex(0, eo, true, mparent, index_this); - } else { - APPEND_REF(&mstruct); - calculateAddLast(eo, true, mparent, index_this); - } - return 1; - } - } - break; - } - case STRUCT_MULTIPLICATION: { - switch(mstruct.type()) { - case STRUCT_VECTOR: {return -1;} - case STRUCT_ADDITION: { - return 0; - } - case STRUCT_MULTIPLICATION: { - - size_t i1 = 0, i2 = 0; - bool b = true; - if(CHILD(0).isNumber()) i1 = 1; - if(mstruct[0].isNumber()) i2 = 1; - if(SIZE - i1 == mstruct.size() - i2) { - for(size_t i = i1; i < SIZE; i++) { - if(CHILD(i) != mstruct[i + i2 - i1]) { - b = false; - break; - } - } - if(b) { - if(i1 == 0) { - PREPEND(m_one); - } - if(i2 == 0) { - CHILD(0).number()++; - } else { - CHILD(0).number() += mstruct[0].number(); - } - MERGE_APPROX_AND_PREC(mstruct) - calculateMultiplyIndex(0, eo, true, mparent, index_this); - return 1; - } - } - - for(size_t i2 = 0; i2 < SIZE; i2++) { - if(eo.transform_trigonometric_functions && CHILD(i2).isPower() && CHILD(i2)[0].isFunction() && (CHILD(i2)[0].function() == CALCULATOR->f_cos || CHILD(i2)[0].function() == CALCULATOR->f_sin) && CHILD(i2)[0].size() == 1 && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isTwo() && mstruct.size() > 0) { - if(eo.protected_function != (CHILD(i2)[0].function() == CALCULATOR->f_sin ? CALCULATOR->f_cos : CALCULATOR->f_sin)) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isPower() && mstruct[i][0].isFunction() && mstruct[i][0].function() == (CHILD(i2)[0].function() == CALCULATOR->f_sin ? CALCULATOR->f_cos : CALCULATOR->f_sin) && mstruct[i][0].size() == 1 && mstruct[i][1].isNumber() && mstruct[i][1].number().isTwo() && CHILD(i2)[0][0] == mstruct[i][0][0]) { - MathStructure madd1(*this); - MathStructure madd2(mstruct); - MathStructure madd; - madd1.delChild(i2 + 1, true); - madd2.delChild(i + 1, true); - if(CHILD(i2)[0].function() == CALCULATOR->f_sin) {madd = madd2; madd2.calculateNegate(eo);} - else {madd = madd1; madd1.calculateNegate(eo);} - if(madd1.calculateAdd(madd2, eo)) { - SET_CHILD_MAP(i2); - CHILD(0).setFunction(CALCULATOR->f_sin); - calculateMultiply(madd1, eo); - EvaluationOptions eo2 = eo; - eo2.transform_trigonometric_functions = false; - calculateAdd(madd, eo2); - return 1; - } - } - } - } - if(eo.protected_function != CHILD(i2)[0].function()) { - bool b = false; - if(mstruct[0].isNumber()) { - if(CHILD(0).isNumber()) { - if(mstruct.size() == SIZE - 1 && CHILD(0).number() == -mstruct[0].number()) { - b = true; - for(size_t i = 1; i < mstruct.size(); i++) { - if(!mstruct[i].equals(CHILD(i2 > i ? i : i + 1))) {b = false; break;} - } - } - } else if(mstruct.size() == SIZE && mstruct[0].isMinusOne()) { - b = true; - for(size_t i = 1; i < mstruct.size(); i++) { - if(!mstruct[i].equals(CHILD(i2 >= i ? i - 1 : i))) {b = false; break;} - } - } - } else if(mstruct.size() == SIZE - 2 && CHILD(0).isMinusOne()) { - b = true; - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct[i].equals(CHILD(i2 - 1 >= i ? i + 1 : i + 2))) {b = false; break;} - } - } - if(b) { - CHILD(i2)[0].setFunction(CHILD(i2)[0].function() == CALCULATOR->f_cos ? CALCULATOR->f_sin : CALCULATOR->f_cos); - MERGE_APPROX_AND_PREC(mstruct) - calculateNegate(eo, mparent, index_this); - return 1; - } - } - } else if(eo.transform_trigonometric_functions && CHILD(i2).isPower() && CHILD(i2)[0].isFunction() && (CHILD(i2)[0].function() == CALCULATOR->f_cosh || CHILD(i2)[0].function() == CALCULATOR->f_sinh) && CHILD(i2)[0].size() == 1 && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isTwo() && mstruct.size() > 0) { - if(eo.protected_function != (CHILD(i2)[0].function() == CALCULATOR->f_sinh ? CALCULATOR->f_cosh : CALCULATOR->f_sinh)) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isPower() && mstruct[i][0].isFunction() && mstruct[i][0].function() == (CHILD(i2)[0].function() == CALCULATOR->f_sinh ? CALCULATOR->f_cosh : CALCULATOR->f_sinh) && mstruct[i][0].size() == 1 && mstruct[i][1].isNumber() && mstruct[i][1].number().isTwo() && CHILD(i2)[0][0] == mstruct[i][0][0]) { - MathStructure madd1(*this); - MathStructure madd2(mstruct); - MathStructure madd; - madd1.delChild(i2 + 1, true); - madd2.delChild(i + 1, true); - if(mstruct[i][0].function() == CALCULATOR->f_sinh) madd = madd1; - else madd = madd2; - if(madd1.calculateAdd(madd2, eo)) { - SET_CHILD_MAP(i2); - CHILD(0).setFunction(CALCULATOR->f_sinh); - calculateMultiply(madd1, eo); - EvaluationOptions eo2 = eo; - eo2.transform_trigonometric_functions = false; - calculateAdd(madd, eo2); - return 1; - } - } - } - } - if(eo.protected_function != CHILD(i2)[0].function()) { - if(CHILD(i2)[0].function() == CALCULATOR->f_sinh && mstruct.size() == SIZE - 1) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct[i].equals(CHILD(i2 > i ? i : i + 1))) break; - if(i == mstruct.size() - 1) { - CHILD(i2)[0].setFunction(CALCULATOR->f_cosh); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - } else if(CHILD(i2)[0].function() == CALCULATOR->f_cosh) { - bool b = false; - if(mstruct[0].isNumber()) { - if(CHILD(0).isNumber()) { - if(mstruct.size() == SIZE - 1 && CHILD(0).number() == -mstruct[0].number()) { - b = true; - for(size_t i = 1; i < mstruct.size(); i++) { - if(!mstruct[i].equals(CHILD(i2 > i ? i : i + 1))) {b = false; break;} - } - } - } else if(mstruct.size() == SIZE && mstruct[0].isMinusOne()) { - b = true; - for(size_t i = 1; i < mstruct.size(); i++) { - if(!mstruct[i].equals(CHILD(i2 >= i ? i - 1 : i))) {b = false; break;} - } - } - } else if(mstruct.size() == SIZE - 2 && CHILD(0).isMinusOne()) { - b = true; - for(size_t i = 1; i < mstruct.size(); i++) { - if(!mstruct[i].equals(CHILD(i2 - 1 >= i ? i + 1 : i + 2))) {b = false; break;} - } - } - if(b) { - CHILD(i2)[0].setFunction(CALCULATOR->f_sinh); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - } - } else if(CHILD(i2).isFunction()) { - if(CHILD(i2).function() == CALCULATOR->f_signum && eo.protected_function != CALCULATOR->f_signum && CHILD(i2).size() == 2 && CHILD(i2)[0].isAddition() && CHILD(i2)[0].size() == 2 && CHILD(i2)[0].representsReal(true)) { - for(size_t im = 0; im < mstruct.size(); im++) { - if(mstruct[im] == CHILD(i2)) { - MathStructure m1(*this), m2(mstruct); - m1.delChild(i2 + 1, true); - m2.delChild(im + 1, true); - if((m1 == CHILD(i2)[0][0] && m2 == CHILD(i2)[0][1]) || (m2 == CHILD(i2)[0][0] && m1 == CHILD(i2)[0][1])) { - SET_CHILD_MAP(i2) - setFunction(CALCULATOR->f_abs); - ERASE(1) - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - } - } else if(CHILD(i2).function() == CALCULATOR->f_asin || CHILD(i2).function() == CALCULATOR->f_acos) { - CHILD(i2).setFunction(CHILD(i2).function() == CALCULATOR->f_asin ? CALCULATOR->f_acos : CALCULATOR->f_asin); - if(equals(mstruct)) { - //asin(x)+acos(x)=pi/2 - delChild(i2 + 1, true); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {calculateMultiply(Number(90, 1, 0), eo); break;} - case ANGLE_UNIT_GRADIANS: {calculateMultiply(Number(100, 1, 0), eo); break;} - case ANGLE_UNIT_RADIANS: {calculateMultiply(CALCULATOR->v_pi, eo); calculateMultiply(nr_half, eo); break;} - default: {calculateMultiply(CALCULATOR->v_pi, eo); calculateMultiply(nr_half, eo); if(CALCULATOR->getRadUnit()) {calculateMultiply(CALCULATOR->getRadUnit(), eo);} break;} - } - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - CHILD(i2).setFunction(CHILD(i2).function() == CALCULATOR->f_asin ? CALCULATOR->f_acos : CALCULATOR->f_asin); - } else if(CHILD(i2).function() == CALCULATOR->f_sinh || CHILD(i2).function() == CALCULATOR->f_cosh) { - CHILD(i2).setFunction(CHILD(i2).function() == CALCULATOR->f_sinh ? CALCULATOR->f_cosh : CALCULATOR->f_sinh); - if(equals(mstruct)) { - //sinh(x)+cosh(x)=e^x - MathStructure *mexp = &CHILD(i2)[0]; - mexp->ref(); - delChild(i2 + 1, true); - MathStructure *mmul = new MathStructure(CALCULATOR->v_e); - mmul->raise_nocopy(mexp); - mmul->calculateRaiseExponent(eo); - MERGE_APPROX_AND_PREC(mstruct) - multiply_nocopy(mmul); - calculateMultiplyLast(eo, true, mparent, index_this); - return 1; - } - CHILD(i2).setFunction(CHILD(i2).function() == CALCULATOR->f_sinh ? CALCULATOR->f_cosh : CALCULATOR->f_sinh); - } - } - } - - if(eo.transform_trigonometric_functions) { - for(size_t i2 = 0; i2 < mstruct.size(); i2++) { - if(mstruct[i2].isPower() && mstruct[i2][0].isFunction() && (mstruct[i2][0].function() == CALCULATOR->f_cos || mstruct[i2][0].function() == CALCULATOR->f_sin) && mstruct[i2][0].size() == 1 && mstruct[i2][1].isNumber() && mstruct[i2][1].number().isTwo() && SIZE > 0) { - if(eo.protected_function != mstruct[i2][0].function()) { - bool b = false; - if(CHILD(0).isNumber()) { - if(mstruct[0].isNumber()) { - if(mstruct.size() - 1 == SIZE && CHILD(0).number() == -mstruct[0].number()) { - b = true; - for(size_t i = 1; i < SIZE; i++) { - if(!CHILD(i).equals(mstruct[i2 > i ? i : i + 1])) {b = false; break;} - } - } - } else if(mstruct.size() == SIZE && CHILD(0).isMinusOne()) { - b = true; - for(size_t i = 1; i < SIZE; i++) { - if(!CHILD(i).equals(mstruct[i2 >= i ? i - 1 : i])) {b = false; break;} - } - } - } else if(mstruct.size() - 2 == SIZE && mstruct[0].isMinusOne()) { - b = true; - for(size_t i = 0; i < SIZE; i++) { - if(!CHILD(i).equals(mstruct[i2 - 1 >= i ? i + 1 : i + 2])) {b = false; break;} - } - } - if(b) { - mstruct[i2][0].setFunction(mstruct[i2][0].function() == CALCULATOR->f_cos ? CALCULATOR->f_sin : CALCULATOR->f_cos); - mstruct.calculateNegate(eo); - if(mparent) mparent->swapChildren(index_this + 1, index_mstruct + 1); - else set_nocopy(mstruct, true); - return 1; - } - } - } else if(mstruct[i2].isPower() && mstruct[i2][0].isFunction() && (mstruct[i2][0].function() == CALCULATOR->f_cosh || mstruct[i2][0].function() == CALCULATOR->f_sinh) && mstruct[i2][0].size() == 1 && mstruct[i2][1].isNumber() && mstruct[i2][1].number().isTwo() && SIZE > 0) { - if(eo.protected_function != mstruct[i2][0].function()) { - if(mstruct[i2][0].function() == CALCULATOR->f_sinh && mstruct.size() - 1 == SIZE) { - for(size_t i = 0; i < SIZE; i++) { - if(!CHILD(i).equals(mstruct[i2 > i ? i : i + 1])) break; - if(i == SIZE - 1) { - mstruct[i2][0].setFunction(CALCULATOR->f_cosh); - if(mparent) mparent->swapChildren(index_this + 1, index_mstruct + 1); - else set_nocopy(mstruct, true); - return 1; - } - } - } else if(mstruct[i2][0].function() == CALCULATOR->f_cosh) { - bool b = false; - if(CHILD(0).isNumber()) { - if(mstruct[0].isNumber()) { - if(mstruct.size() - 1 == SIZE && CHILD(0).number() == -mstruct[0].number()) { - b = true; - for(size_t i = 1; i < SIZE; i++) { - if(!CHILD(i).equals(mstruct[i2 > i ? i : i + 1])) {b = false; break;} - } - } - } else if(mstruct.size() == SIZE && CHILD(0).isMinusOne()) { - b = true; - for(size_t i = 1; i < SIZE; i++) { - if(!CHILD(i).equals(mstruct[i2 >= i ? i - 1 : i])) {b = false; break;} - } - } - } else if(mstruct.size() - 2 == SIZE && mstruct[0].isMinusOne()) { - b = true; - for(size_t i = 1; i < SIZE; i++) { - if(!CHILD(i).equals(mstruct[i2 - 1 >= i ? i + 1 : i + 2])) {b = false; break;} - } - } - if(b) { - mstruct[i2][0].setFunction(CALCULATOR->f_sinh); - if(mparent) mparent->swapChildren(index_this + 1, index_mstruct + 1); - else set_nocopy(mstruct, true); - return 1; - } - } - } - } - } - } - - if(!eo.combine_divisions) break; - b = true; size_t divs = 0; - for(; b && i1 < SIZE; i1++) { - if(CHILD(i1).isPower() && CHILD(i1)[1].hasNegativeSign()) { - divs++; - b = false; - for(; i2 < mstruct.size(); i2++) { - if(mstruct[i2].isPower() && mstruct[i2][1].hasNegativeSign()) { - if(mstruct[i2] == CHILD(i1)) { - b = true; - } - i2++; - break; - } - } - } - } - if(b && divs > 0) { - for(; i2 < mstruct.size(); i2++) { - if(mstruct[i2].isPower() && mstruct[i2][1].hasNegativeSign()) { - b = false; - break; - } - } - } - if(b && divs > 0) { - if(SIZE - divs == 0) { - if(mstruct.size() - divs == 0) { - calculateMultiply(nr_two, eo); - } else if(mstruct.size() - divs == 1) { - PREPEND(m_one); - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct[i].isPower() || !mstruct[i][1].hasNegativeSign()) { - mstruct[i].ref(); - CHILD(0).add_nocopy(&mstruct[i], true); - CHILD(0).calculateAddLast(eo, true, this, 0); - break; - } - } - calculateMultiplyIndex(0, eo, true, mparent, index_this); - } else { - for(size_t i = 0; i < mstruct.size();) { - if(mstruct[i].isPower() && mstruct[i][1].hasNegativeSign()) { - mstruct.delChild(i + 1); - } else { - i++; - } - } - PREPEND(m_one); - mstruct.ref(); - CHILD(0).add_nocopy(&mstruct, true); - CHILD(0).calculateAddLast(eo, true, this, 0); - calculateMultiplyIndex(0, eo, true, mparent, index_this); - } - } else if(SIZE - divs == 1) { - size_t index = 0; - for(; index < SIZE; index++) { - if(!CHILD(index).isPower() || !CHILD(index)[1].hasNegativeSign()) { - break; - } - } - if(mstruct.size() - divs == 0) { - if(IS_REAL(CHILD(index))) { - CHILD(index).number()++; - } else { - CHILD(index).calculateAdd(m_one, eo, this, index); - } - calculateMultiplyIndex(index, eo, true, mparent, index_this); - } else if(mstruct.size() - divs == 1) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct[i].isPower() || !mstruct[i][1].hasNegativeSign()) { - mstruct[i].ref(); - CHILD(index).add_nocopy(&mstruct[i], true); - CHILD(index).calculateAddLast(eo, true, this, index); - break; - } - } - calculateMultiplyIndex(index, eo, true, mparent, index_this); - } else { - for(size_t i = 0; i < mstruct.size();) { - if(mstruct[i].isPower() && mstruct[i][1].hasNegativeSign()) { - mstruct.delChild(i + 1); - } else { - i++; - } - } - mstruct.ref(); - CHILD(index).add_nocopy(&mstruct, true); - CHILD(index).calculateAddLast(eo, true, this, index); - calculateMultiplyIndex(index, eo, true, mparent, index_this); - } - } else { - for(size_t i = 0; i < SIZE;) { - if(CHILD(i).isPower() && CHILD(i)[1].hasNegativeSign()) { - ERASE(i); - } else { - i++; - } - } - if(mstruct.size() - divs == 0) { - calculateAdd(m_one, eo); - } else if(mstruct.size() - divs == 1) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct[i].isPower() || !mstruct[i][1].hasNegativeSign()) { - mstruct[i].ref(); - add_nocopy(&mstruct[i], true); - calculateAddLast(eo); - break; - } - } - } else { - MathStructure *mstruct2 = new MathStructure(); - mstruct2->setType(STRUCT_MULTIPLICATION); - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct[i].isPower() || !mstruct[i][1].hasNegativeSign()) { - mstruct[i].ref(); - mstruct2->addChild_nocopy(&mstruct[i]); - } - } - add_nocopy(mstruct2, true); - calculateAddLast(eo, true, mparent, index_this); - } - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isPower() && mstruct[i][1].hasNegativeSign()) { - mstruct[i].ref(); - multiply_nocopy(&mstruct[i], true); - calculateMultiplyLast(eo); - } - } - } - return 1; - } + return false; +} - break; - } - case STRUCT_POWER: { - if(eo.combine_divisions && mstruct[1].hasNegativeSign()) { - bool b = false; - size_t index = 0; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isPower() && CHILD(i)[1].hasNegativeSign()) { - if(b) { - b = false; - break; - } - if(mstruct == CHILD(i)) { - index = i; - b = true; - } - if(!b) break; - } - } - if(b) { - if(SIZE == 2) { - if(index == 0) setToChild(2, true); - else setToChild(1, true); - } else { - ERASE(index); - } - calculateAdd(m_one, eo); - mstruct.ref(); - multiply_nocopy(&mstruct, false); - calculateMultiplyLast(eo, true, mparent, index_this); - return 1; - } - } - if(eo.transform_trigonometric_functions && SIZE == 2 && CHILD(0).isNumber() && mstruct[0].isFunction()) { - if((mstruct[0].function() == CALCULATOR->f_cos || mstruct[0].function() == CALCULATOR->f_sin) && eo.protected_function != (mstruct[0].function() == CALCULATOR->f_sin ? CALCULATOR->f_cos : CALCULATOR->f_sin) && mstruct[0].size() == 1 && mstruct[1].isNumber() && mstruct[1].number().isTwo()) { - if(CHILD(1).isPower() && CHILD(1)[0].isFunction() && CHILD(1)[0].function() == (mstruct[0].function() == CALCULATOR->f_sin ? CALCULATOR->f_cos : CALCULATOR->f_sin) && CHILD(1)[0].size() == 1 && CHILD(1)[1].isNumber() && CHILD(1)[1].number().isTwo() && mstruct[0][0] == CHILD(1)[0][0]) { - if(CHILD(0).calculateSubtract(m_one, eo)) { - add(m_one); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - } else if((mstruct[0].function() == CALCULATOR->f_cosh || mstruct[0].function() == CALCULATOR->f_sinh) && eo.protected_function != (mstruct[0].function() == CALCULATOR->f_sinh ? CALCULATOR->f_cosh : CALCULATOR->f_sinh) && mstruct[0].size() == 1 && mstruct[1].isNumber() && mstruct[1].number().isTwo()) { - if(CHILD(1).isPower() && CHILD(1)[0].isFunction() && CHILD(1)[0].function() == (mstruct[0].function() == CALCULATOR->f_sinh ? CALCULATOR->f_cosh : CALCULATOR->f_sinh) && CHILD(1)[0].size() == 1 && CHILD(1)[1].isNumber() && CHILD(1)[1].number().isTwo() && mstruct[0][0] == CHILD(1)[0][0]) { - if(CHILD(0).calculateAdd(m_one, eo)) { - add(CHILD(1)[0].function() == CALCULATOR->f_sinh ? m_one : m_minus_one); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - } - } - } - default: { - if(SIZE == 2 && CHILD(0).isNumber() && CHILD(1) == mstruct) { - CHILD(0).number()++; - MERGE_APPROX_AND_PREC(mstruct) - calculateMultiplyIndex(0, eo, true, mparent, index_this); - return 1; - } - if(eo.transform_trigonometric_functions && SIZE == 2 && CHILD(1).isPower() && CHILD(1)[0].isFunction() && CHILD(1)[0].function() != eo.protected_function && CHILD(1)[1] == nr_two && CHILD(1)[0].size() == 1) { - if(mstruct.isNumber() && CHILD(0).isNumber()) { - if(CHILD(1)[0].function() == CALCULATOR->f_sin && mstruct.number() == -CHILD(0).number()) { - CHILD(1)[0].setFunction(CALCULATOR->f_cos); - MERGE_APPROX_AND_PREC(mstruct) - calculateNegate(eo, mparent, index_this); - return 1; - } else if(CHILD(1)[0].function() == CALCULATOR->f_cos && mstruct.number() == -CHILD(0).number()) { - CHILD(1)[0].setFunction(CALCULATOR->f_sin); - MERGE_APPROX_AND_PREC(mstruct) - calculateNegate(eo, mparent, index_this); - return 1; - } else if(CHILD(1)[0].function() == CALCULATOR->f_cosh && mstruct.number() == -CHILD(0).number()) { - MERGE_APPROX_AND_PREC(mstruct) - CHILD(1)[0].setFunction(CALCULATOR->f_sinh); - return 1; - } else if(CHILD(1)[0].function() == CALCULATOR->f_sinh && mstruct == CHILD(0)) { - CHILD(1)[0].setFunction(CALCULATOR->f_cosh); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - } else if(eo.transform_trigonometric_functions && SIZE == 3 && CHILD(0).isMinusOne()) { - size_t i = 0; - if(CHILD(1).isPower() && CHILD(1)[0].isFunction() && (CHILD(1)[0].function() == CALCULATOR->f_sin || CHILD(1)[0].function() == CALCULATOR->f_cos || CHILD(1)[0].function() == CALCULATOR->f_cosh) && CHILD(1)[0].function() != eo.protected_function && CHILD(1)[1] == nr_two && CHILD(1)[0].size() == 1 && CHILD(2) == mstruct) i = 1; - if(CHILD(2).isPower() && CHILD(2)[0].isFunction() && (CHILD(2)[0].function() == CALCULATOR->f_sin || CHILD(2)[0].function() == CALCULATOR->f_cos || CHILD(2)[0].function() == CALCULATOR->f_cosh) && CHILD(2)[0].function() != eo.protected_function && CHILD(2)[1] == nr_two && CHILD(2)[0].size() == 1 && CHILD(1) == mstruct) i = 2; - if(i > 0) { - if(CHILD(i)[0].function() == CALCULATOR->f_sin) { - CHILD(i)[0].setFunction(CALCULATOR->f_cos); - MERGE_APPROX_AND_PREC(mstruct) - calculateNegate(eo, mparent, index_this); - return 1; - } else if(CHILD(i)[0].function() == CALCULATOR->f_cos) { - CHILD(i)[0].setFunction(CALCULATOR->f_sin); - MERGE_APPROX_AND_PREC(mstruct) - calculateNegate(eo, mparent, index_this); - return 1; - } else if(CHILD(i)[0].function() == CALCULATOR->f_cosh) { - MERGE_APPROX_AND_PREC(mstruct) - CHILD(i)[0].setFunction(CALCULATOR->f_sinh); - return 1; - } - } - } - if(mstruct.isDateTime() || (mstruct.isFunction() && mstruct.function() == CALCULATOR->f_signum && eo.protected_function != CALCULATOR->f_signum)) { - return 0; - } - } - } - break; - } - case STRUCT_POWER: { - if(CHILD(0).isFunction() && (CHILD(0).function() == CALCULATOR->f_cos || CHILD(0).function() == CALCULATOR->f_sin) && eo.protected_function != (CHILD(0).function() == CALCULATOR->f_sin ? CALCULATOR->f_cos : CALCULATOR->f_sin) && CHILD(0).size() == 1 && CHILD(1).isNumber() && CHILD(1).number().isTwo()) { - if(eo.transform_trigonometric_functions && mstruct.isMinusOne()) { - CHILD(0).setFunction(CHILD(0).function() == CALCULATOR->f_sin ? CALCULATOR->f_cos : CALCULATOR->f_sin); - negate(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct.isPower() && mstruct[0].isFunction() && mstruct[0].function() == (CHILD(0).function() == CALCULATOR->f_sin ? CALCULATOR->f_cos : CALCULATOR->f_sin) && mstruct[0].size() == 1 && mstruct[1].isNumber() && mstruct[1].number().isTwo() && CHILD(0)[0] == mstruct[0][0]) { - // cos(x)^2+sin(x)^2=1 - set(1, 1, 0, true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(eo.transform_trigonometric_functions && CHILD(0).isFunction() && (CHILD(0).function() == CALCULATOR->f_cosh || CHILD(0).function() == CALCULATOR->f_sinh) && eo.protected_function != (CHILD(0).function() == CALCULATOR->f_sinh ? CALCULATOR->f_cosh : CALCULATOR->f_sinh) && CHILD(0).size() == 1 && CHILD(1).isNumber() && CHILD(1).number().isTwo()) { - // cosh(x)^2=sinh(x)^2+1 - if(CHILD(0).function() == CALCULATOR->f_sinh && mstruct.isOne()) { - CHILD(0).setFunction(CALCULATOR->f_cosh); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(CHILD(0).function() == CALCULATOR->f_cosh && mstruct.isMinusOne()) { - CHILD(0).setFunction(CALCULATOR->f_sinh); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct.isPower() && mstruct[0].isFunction() && mstruct[0].function() == (CHILD(0).function() == CALCULATOR->f_sinh ? CALCULATOR->f_cosh : CALCULATOR->f_sinh) && mstruct[0].size() == 1 && mstruct[1].isNumber() && mstruct[1].number().isTwo() && CHILD(0)[0] == mstruct[0][0]) { - if(CHILD(0).function() == CALCULATOR->f_sinh) { - multiply(nr_two); - add(m_one); - } else { - CHILD(0).setFunction(CALCULATOR->f_sinh); - multiply(nr_two); - add(m_minus_one); - } - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - goto default_addition_merge; - } - case STRUCT_FUNCTION: { - if(o_function == CALCULATOR->f_signum && mstruct.isMultiplication() && eo.protected_function != CALCULATOR->f_signum) { - if(SIZE == 2 && CHILD(0).isAddition() && CHILD(0).size() == 2 && (CHILD(0)[0].isOne() || CHILD(0)[1].isOne()) && CHILD(0).representsReal(true)) { - for(size_t im = 0; im < mstruct.size(); im++) { - if(mstruct[im] == *this) { - MathStructure m2(mstruct); - m2.delChild(im + 1, true); - if((CHILD(0)[0].isOne() && m2 == CHILD(0)[1]) || (CHILD(0)[1].isOne() && m2 == CHILD(0)[0])) { - setFunction(CALCULATOR->f_abs); - ERASE(1) - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - } - } - } else if(mstruct.isFunction() && ((o_function == CALCULATOR->f_asin && mstruct.function() == CALCULATOR->f_acos) || (o_function == CALCULATOR->f_acos && mstruct.function() == CALCULATOR->f_asin)) && eo.protected_function != CALCULATOR->f_acos && eo.protected_function != CALCULATOR->f_asin && SIZE == 1 && mstruct.size() == 1 && CHILD(0) == mstruct[0]) { - //asin(x)+acos(x)=pi/2 - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {set(90, 1, 0, true); break;} - case ANGLE_UNIT_GRADIANS: {set(100, 1, 0, true); break;} - case ANGLE_UNIT_RADIANS: {set(CALCULATOR->v_pi, true); multiply(nr_half); calculatesub(eo, eo, true); break;} - default: {set(CALCULATOR->v_pi, true); multiply(nr_half); if(CALCULATOR->getRadUnit()) {multiply(CALCULATOR->getRadUnit(), true);} calculatesub(eo, eo, true); break;} - } - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct.isFunction() && ((o_function == CALCULATOR->f_sinh && mstruct.function() == CALCULATOR->f_cosh) || (o_function == CALCULATOR->f_cosh && mstruct.function() == CALCULATOR->f_sinh)) && eo.protected_function != CALCULATOR->f_cosh && eo.protected_function != CALCULATOR->f_sinh && SIZE == 1 && mstruct.size() == 1 && CHILD(0) == mstruct[0]) { - //sinh(x)+cosh(x)=e^x - MathStructure *mexp = &CHILD(0); - mexp->ref(); - set(CALCULATOR->v_e, true); - calculatesub(eo, eo, true); - raise_nocopy(mexp); - MERGE_APPROX_AND_PREC(mstruct) - calculateRaiseExponent(eo, mparent, index_this); - return 1; - } else if(mstruct.isFunction() && o_function == CALCULATOR->f_stripunits && mstruct.function() == CALCULATOR->f_stripunits && mstruct.size() == 1 && SIZE == 1) { - mstruct[0].ref(); - CHILD(0).add_nocopy(&mstruct[0]); - return 1; - } - goto default_addition_merge; - } - case STRUCT_DATETIME: { - if(mstruct.isDateTime()) { - if(o_datetime->add(*mstruct.datetime())) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isMinusOne() && mstruct[1].isDateTime() && (CALCULATOR->u_second || CALCULATOR->u_day)) { - if(CALCULATOR->u_day && !mstruct[1].datetime()->timeIsSet() && !o_datetime->timeIsSet()) { - Number ndays = mstruct[1].datetime()->daysTo(*o_datetime); - set(ndays, true); - multiply(CALCULATOR->u_day); - } else { - Number nsecs = mstruct[1].datetime()->secondsTo(*o_datetime, true); - set(nsecs, true); - multiply(CALCULATOR->u_second, true); - } - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(CALCULATOR->u_second && ((mstruct.isUnit() && mstruct.unit()->baseUnit() == CALCULATOR->u_second && mstruct.unit()->baseExponent() == 1 && !mstruct.unit()->hasNonlinearRelationTo(CALCULATOR->u_second)) || (mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber() && mstruct[0].number().isReal() && !mstruct[0].number().isInterval() && mstruct[1].isUnit() && mstruct[1].unit()->baseUnit() == CALCULATOR->u_second && mstruct[1].unit()->baseExponent() == 1 && !mstruct[1].unit()->hasNonlinearRelationTo(CALCULATOR->u_second)))) { - MathStructure mmul(1, 1, 0); - Unit *u; - if(mstruct.isMultiplication()) { - mmul = mstruct[0]; - u = mstruct[1].unit(); - } else { - u = mstruct.unit(); - } - if(CALCULATOR->u_month && u != CALCULATOR->u_year && (u == CALCULATOR->u_month || u->isChildOf(CALCULATOR->u_month))) { - if(u != CALCULATOR->u_month) { - CALCULATOR->u_month->convert(u, mmul); - mmul.eval(eo); - } - if(mmul.isNumber() && o_datetime->addMonths(mmul.number())) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(CALCULATOR->u_year && (u == CALCULATOR->u_year || u->isChildOf(CALCULATOR->u_year))) { - if(u != CALCULATOR->u_year) { - CALCULATOR->u_year->convert(u, mmul); - mmul.eval(eo); - } - if(mmul.isNumber() && o_datetime->addYears(mmul.number())) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(CALCULATOR->u_day && (u == CALCULATOR->u_day || u->isChildOf(CALCULATOR->u_day))) { - if(u != CALCULATOR->u_day) { - CALCULATOR->u_day->convert(u, mmul); - mmul.eval(eo); - } - if(mmul.isNumber() && o_datetime->addDays(mmul.number())) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(CALCULATOR->u_hour && (u == CALCULATOR->u_hour || u->isChildOf(CALCULATOR->u_hour))) { - if(u != CALCULATOR->u_hour) { - CALCULATOR->u_hour->convert(u, mmul); - mmul.eval(eo); - } - if(mmul.isNumber() && o_datetime->addHours(mmul.number())) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(CALCULATOR->u_minute && (u == CALCULATOR->u_minute || u->isChildOf(CALCULATOR->u_minute))) { - if(u != CALCULATOR->u_minute) { - CALCULATOR->u_minute->convert(u, mmul); - mmul.eval(eo); - } - if(mmul.isNumber() && o_datetime->addMinutes(mmul.number())) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else { - MathStructure mmulb(mmul); - if(u != CALCULATOR->u_second) { - u->convertToBaseUnit(mmul); - mmul.eval(eo); - } - if(mmul.isNumber() && o_datetime->addSeconds(mmul.number(), true)) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - } - } - default: { - default_addition_merge: - switch(mstruct.type()) { - case STRUCT_VECTOR: {return -1;} - case STRUCT_DATETIME: {} - case STRUCT_ADDITION: {} - case STRUCT_MULTIPLICATION: { - return 0; - } - default: { - if(equals(mstruct)) { - multiply_nocopy(new MathStructure(2, 1, 0), true); - MERGE_APPROX_AND_PREC(mstruct) - calculateMultiplyLast(eo, true, mparent, index_this); - return 1; - } - } - } - } +size_t MathStructure::countTotalChildren(bool count_function_as_one) const { + if((m_type == STRUCT_FUNCTION && count_function_as_one) || SIZE == 0) return 1; + size_t count = 0; + for(size_t i = 0; i < SIZE; i++) { + count += CHILD(i).countTotalChildren() + 1; } - return -1; + return count; } -bool reducable(const MathStructure &mnum, const MathStructure &mden, Number &nr) { - switch(mnum.type()) { - case STRUCT_NUMBER: {} - case STRUCT_ADDITION: { - break; - } - default: { - bool reduce = true; - for(size_t i = 0; i < mden.size() && reduce; i++) { - switch(mden[i].type()) { - case STRUCT_MULTIPLICATION: { - reduce = false; - for(size_t i2 = 0; i2 < mden[i].size(); i2++) { - if(mnum == mden[i][i2]) { - reduce = true; - if(!nr.isOne() && !nr.isFraction()) nr.set(1, 1, 0); - break; - } else if(mden[i][i2].isPower() && mden[i][i2][1].isNumber() && mden[i][i2][1].number().isReal() && mnum == mden[i][i2][0]) { - if(!mden[i][i2][1].number().isPositive()) { - break; - } - if(mden[i][i2][1].number().isLessThan(nr)) nr = mden[i][i2][1].number(); - reduce = true; - break; - } - } - break; - } - case STRUCT_POWER: { - if(mden[i][1].isNumber() && mden[i][1].number().isReal() && mnum == mden[i][0]) { - if(!mden[i][1].number().isPositive()) { - reduce = false; - break; - } - if(mden[i][1].number().isLessThan(nr)) nr = mden[i][1].number(); - break; - } - } - default: { - if(mnum != mden[i]) { - reduce = false; - break; - } - if(!nr.isOne() && !nr.isFraction()) nr.set(1, 1, 0); - } - } - } - return reduce; - } +void MathStructure::swapChildren(size_t index1, size_t index2) { + if(index1 > 0 && index2 > 0 && index1 <= SIZE && index2 <= SIZE) { + SWAP_CHILDREN(index1 - 1, index2 - 1) } - return false; } -void reduce(const MathStructure &mnum, MathStructure &mden, Number &nr, const EvaluationOptions &eo) { - switch(mnum.type()) { - case STRUCT_NUMBER: {} - case STRUCT_ADDITION: { - break; +void MathStructure::childToFront(size_t index) { + if(index > 0 && index <= SIZE) { + CHILD_TO_FRONT(index - 1) + } +} +void MathStructure::addChild(const MathStructure &o) { + APPEND(o); +} +void MathStructure::addChild_nocopy(MathStructure *o) { + APPEND_POINTER(o); +} +void MathStructure::delChild(size_t index, bool check_size) { + if(index > 0 && index <= SIZE) { + ERASE(index - 1); + if(check_size) { + if(SIZE == 1) setToChild(1, true); + else if(SIZE == 0) clear(true); } - default: { - for(size_t i = 0; i < mden.size(); i++) { - switch(mden[i].type()) { - case STRUCT_MULTIPLICATION: { - for(size_t i2 = 0; i2 < mden[i].size(); i2++) { - if(mden[i][i2] == mnum) { - if(!nr.isOne()) { - MathStructure *mexp = new MathStructure(1, 1, 0); - mexp->number() -= nr; - mden[i][i2].raise_nocopy(mexp); - mden[i][i2].calculateRaiseExponent(eo); - if(mden[i][i2].isOne() && mden[i].size() > 1) { - mden[i].delChild(i2 + 1); - if(mden[i].size() == 1) { - mden[i].setToChild(1, true, &mden, i + 1); - } - } - } else { - if(mden[i].size() == 1) { - mden[i].set(m_one); - } else { - mden[i].delChild(i2 + 1); - if(mden[i].size() == 1) { - mden[i].setToChild(1, true, &mden, i + 1); - } - } - } - break; - } else if(mden[i][i2].isPower() && mden[i][i2][1].isNumber() && mden[i][i2][1].number().isReal() && mnum.equals(mden[i][i2][0])) { - mden[i][i2][1].number() -= nr; - if(mden[i][i2][1].number().isOne()) { - mden[i][i2].setToChild(1, true, &mden[i], i2 + 1); - } else { - mden[i][i2].calculateRaiseExponent(eo); - if(mden[i][i2].isOne() && mden[i].size() > 1) { - mden[i].delChild(i2 + 1); - if(mden[i].size() == 1) { - mden[i].setToChild(1, true, &mden, i + 1); - } - } - } - break; - } - } - break; - } - case STRUCT_POWER: { - if(mden[i][1].isNumber() && mden[i][1].number().isReal() && mnum.equals(mden[i][0])) { - mden[i][1].number() -= nr; - if(mden[i][1].number().isOne()) { - mden[i].setToChild(1, true, &mden, i + 1); - } else { - mden[i].calculateRaiseExponent(eo, &mden, i); - } - break; - } - } - default: { - if(!nr.isOne()) { - MathStructure *mexp = new MathStructure(1, 1, 0); - mexp->number() -= nr; - mden[i].raise_nocopy(mexp); - mden[i].calculateRaiseExponent(eo, &mden, 1); - } else { - mden[i].set(m_one); - } - } - } - } - mden.calculatesub(eo, eo, false); + } +} +void MathStructure::insertChild(const MathStructure &o, size_t index) { + if(index > 0 && index <= v_subs.size()) { + v_order.insert(v_order.begin() + (index - 1), v_subs.size()); + v_subs.push_back(new MathStructure(o)); + CHILD_UPDATED(index - 1); + } else { + addChild(o); + } +} +void MathStructure::insertChild_nocopy(MathStructure *o, size_t index) { + if(index > 0 && index <= v_subs.size()) { + v_order.insert(v_order.begin() + (index - 1), v_subs.size()); + v_subs.push_back(o); + CHILD_UPDATED(index - 1); + } else { + addChild_nocopy(o); + } +} +void MathStructure::setChild(const MathStructure &o, size_t index, bool merge_precision) { + if(index > 0 && index <= SIZE) { + CHILD(index - 1).set(o, merge_precision); + CHILD_UPDATED(index - 1); + } +} +void MathStructure::setChild_nocopy(MathStructure *o, size_t index, bool merge_precision) { + if(index > 0 && index <= SIZE) { + MathStructure *o_prev = v_subs[v_order[index - 1]]; + if(merge_precision) { + if(!o->isApproximate() && o_prev->isApproximate()) o->setApproximate(true); + if(o_prev->precision() >= 0 && (o->precision() < 0 || o_prev->precision() < o->precision())) o->setPrecision(o_prev->precision()); } + o_prev->unref(); + v_subs[v_order[index - 1]] = o; + CHILD_UPDATED(index - 1); + } +} +const MathStructure *MathStructure::getChild(size_t index) const { + if(index > 0 && index <= v_order.size()) { + return &CHILD(index - 1); + } + return NULL; +} +MathStructure *MathStructure::getChild(size_t index) { + if(index > 0 && index <= v_order.size()) { + return &CHILD(index - 1); + } + return NULL; +} +size_t MathStructure::countChildren() const { + return SIZE; +} +size_t MathStructure::size() const { + return SIZE; +} +const MathStructure *MathStructure::base() const { + if(m_type == STRUCT_POWER && SIZE >= 1) { + return &CHILD(0); + } + return NULL; +} +const MathStructure *MathStructure::exponent() const { + if(m_type == STRUCT_POWER && SIZE >= 2) { + return &CHILD(1); + } + return NULL; +} +MathStructure *MathStructure::base() { + if(m_type == STRUCT_POWER && SIZE >= 1) { + return &CHILD(0); + } + return NULL; +} +MathStructure *MathStructure::exponent() { + if(m_type == STRUCT_POWER && SIZE >= 2) { + return &CHILD(1); } + return NULL; +} + +StructureType MathStructure::type() const { + return m_type; } -bool addablePower(const MathStructure &mstruct, const EvaluationOptions &eo) { - if(mstruct[0].representsNonNegative(true)) return true; - if(mstruct[1].representsInteger()) return true; - //return eo.allow_complex && mstruct[0].representsNegative(true) && mstruct[1].isNumber() && mstruct[1].number().isRational() && mstruct[1].number().denominatorIsEven(); - return eo.allow_complex && mstruct[1].isNumber() && mstruct[1].number().isRational() && mstruct[1].number().denominatorIsEven(); +bool contains_angle_unit(const MathStructure &m, const ParseOptions &po) { + if(m.isUnit() && m.unit()->baseUnit() == CALCULATOR->getRadUnit()->baseUnit()) return true; + if(m.isVariable() && m.variable()->isKnown()) return contains_angle_unit(((KnownVariable*) m.variable())->get(), po); + if(m.isFunction()) return po.angle_unit == ANGLE_UNIT_NONE && (m.function()->id() == FUNCTION_ID_ASIN || m.function()->id() == FUNCTION_ID_ACOS || m.function()->id() == FUNCTION_ID_ATAN); + for(size_t i = 0; i < m.size(); i++) { + if(contains_angle_unit(m[i], po)) return true; + } + return false; } -int MathStructure::merge_multiplication(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool reversed, bool do_append) { - if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { - Number nr(o_number); - if(nr.multiply(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) { - if(o_number == nr) { - o_number = nr; - numberUpdated(); - return 2; +int MathStructure::contains(const MathStructure &mstruct, bool structural_only, bool check_variables, bool check_functions, bool loose_equals) const { + if(mstruct.isUnit() && mstruct.prefix() == NULL && m_type == STRUCT_UNIT) return mstruct.unit() == o_unit; + if(equals(mstruct, loose_equals, loose_equals)) return 1; + if(structural_only) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).contains(mstruct, structural_only, check_variables, check_functions, loose_equals)) return 1; + } + if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { + return ((KnownVariable*) o_variable)->get().contains(mstruct, structural_only, check_variables, check_functions, loose_equals); + } else if(m_type == STRUCT_FUNCTION && check_functions) { + if(function_value) { + return function_value->contains(mstruct, structural_only, check_variables, check_functions, loose_equals); } - o_number = nr; - numberUpdated(); - return 1; } - return -1; - } - if(mstruct.isOne()) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } else if(isOne()) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); + } else { + int ret = 0; + if(m_type != STRUCT_FUNCTION) { + for(size_t i = 0; i < SIZE; i++) { + int retval = CHILD(i).contains(mstruct, structural_only, check_variables, check_functions, loose_equals); + if(retval == 1) return 1; + else if(retval < 0) ret = retval; + } } - return 3; - } - if(m_type == STRUCT_NUMBER && o_number.isInfinite()) { - if(o_number.isMinusInfinity(false)) { - if(mstruct.representsPositive(false)) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } else if(mstruct.representsNegative(false)) { - o_number.setPlusInfinity(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(o_number.isPlusInfinity(false)) { - if(mstruct.representsPositive(false)) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } else if(mstruct.representsNegative(false)) { - o_number.setMinusInfinity(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; + if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { + return ((KnownVariable*) o_variable)->get().contains(mstruct, structural_only, check_variables, check_functions, loose_equals); + } else if(m_type == STRUCT_FUNCTION && check_functions) { + if(function_value) { + return function_value->contains(mstruct, structural_only, check_variables, check_functions, loose_equals); } + return -1; + } else if(isAborted()) { + return -1; } - if(eo.approximation == APPROXIMATION_EXACT) { - CALCULATOR->beginTemporaryEnableIntervalArithmetic(); - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mtest(mstruct); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - if(eo2.interval_calculation == INTERVAL_CALCULATION_NONE) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; - mtest.calculateFunctions(eo2); - mtest.calculatesub(eo2, eo2); - CALCULATOR->endTemporaryStopMessages(); - CALCULATOR->endTemporaryEnableIntervalArithmetic(); - if(o_number.isMinusInfinity(false)) { - if(mtest.representsPositive(false)) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } else if(mtest.representsNegative(false)) { - o_number.setPlusInfinity(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(o_number.isPlusInfinity(false)) { - if(mtest.representsPositive(false)) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } else if(mtest.representsNegative(false)) { - o_number.setMinusInfinity(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } + return ret; + } + return 0; +} +size_t MathStructure::countOccurrences(const MathStructure &mstruct) const { + if(mstruct.isUnit() && mstruct.prefix() == NULL && m_type == STRUCT_UNIT && mstruct.unit() == o_unit) return 1; + if(equals(mstruct, true, true)) return 1; + size_t i_occ = 0; + for(size_t i = 0; i < SIZE; i++) { + i_occ += CHILD(i).countOccurrences(mstruct); + } + return i_occ; +} +int MathStructure::containsFunction(MathFunction *f, bool structural_only, bool check_variables, bool check_functions) const { + if(m_type == STRUCT_FUNCTION && o_function == f) return 1; + if(structural_only) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).containsFunction(f, structural_only, check_variables, check_functions)) return 1; + } + if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { + return ((KnownVariable*) o_variable)->get().containsFunction(f, structural_only, check_variables, check_functions); + } else if(m_type == STRUCT_FUNCTION && check_functions) { + if(function_value) { + return function_value->containsFunction(f, structural_only, check_variables, check_functions); } } - } else if(mstruct.isNumber() && mstruct.number().isInfinite()) { - if(mstruct.number().isMinusInfinity(false)) { - if(representsPositive(false)) { - clear(true); - o_number.setMinusInfinity(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(representsNegative(false)) { - clear(true); - o_number.setPlusInfinity(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(mstruct.number().isPlusInfinity(false)) { - if(representsPositive(false)) { - clear(true); - o_number.setPlusInfinity(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(representsNegative(false)) { - clear(true); - o_number.setMinusInfinity(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; + } else { + int ret = 0; + if(m_type != STRUCT_FUNCTION) { + for(size_t i = 0; i < SIZE; i++) { + int retval = CHILD(i).containsFunction(f, structural_only, check_variables, check_functions); + if(retval == 1) return 1; + else if(retval < 0) ret = retval; } } - if(eo.approximation == APPROXIMATION_EXACT) { - CALCULATOR->beginTemporaryEnableIntervalArithmetic(); - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mtest(*this); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - if(eo2.interval_calculation == INTERVAL_CALCULATION_NONE) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; - mtest.calculateFunctions(eo2); - mtest.calculatesub(eo2, eo2); - CALCULATOR->endTemporaryStopMessages(); - CALCULATOR->endTemporaryEnableIntervalArithmetic(); - if(mstruct.number().isMinusInfinity(false)) { - if(mtest.representsPositive(false)) { - clear(true); - o_number.setMinusInfinity(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mtest.representsNegative(false)) { - clear(true); - o_number.setPlusInfinity(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(mstruct.number().isPlusInfinity(false)) { - if(mtest.representsPositive(false)) { - clear(true); - o_number.setPlusInfinity(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mtest.representsNegative(false)) { - clear(true); - o_number.setMinusInfinity(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } + if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { + return ((KnownVariable*) o_variable)->get().containsFunction(f, structural_only, check_variables, check_functions); + } else if(m_type == STRUCT_FUNCTION && check_functions) { + if(function_value) { + return function_value->containsFunction(f, structural_only, check_variables, check_functions); } + return -1; + } else if(isAborted()) { + return -1; } + return ret; } - - if(representsUndefined() || mstruct.representsUndefined()) return -1; - - // x/(x^2+x)=1/(x+1) - const MathStructure *mnum = NULL, *mden = NULL; - bool b_nonzero = false; - if(eo.reduce_divisions) { - if(!isNumber() && mstruct.isPower() && mstruct[0].isAddition() && mstruct[0].size() > 1 && mstruct[1].isNumber() && mstruct[1].number().isMinusOne()) { - if((!isPower() || !CHILD(1).hasNegativeSign()) && representsNumber() && mstruct[0].representsNumber()) { - if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !mstruct[0].representsZero(true)) || mstruct[0].representsNonZero(true)) { - b_nonzero = true; - } - if(b_nonzero || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !mstruct[0].representsZero(true))) { - mnum = this; - mden = &mstruct[0]; - } + return 0; +} +int MathStructure::containsFunctionId(int id, bool structural_only, bool check_variables, bool check_functions) const { + if(m_type == STRUCT_FUNCTION && o_function->id() == id) return 1; + if(structural_only) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).containsFunctionId(id, structural_only, check_variables, check_functions)) return 1; + } + if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { + return ((KnownVariable*) o_variable)->get().containsFunctionId(id, structural_only, check_variables, check_functions); + } else if(m_type == STRUCT_FUNCTION && check_functions) { + if(function_value) { + return function_value->containsFunctionId(id, structural_only, check_variables, check_functions); } - } else if(!mstruct.isNumber() && isPower() && CHILD(0).isAddition() && CHILD(0).size() > 1 && CHILD(1).isNumber() && CHILD(1).number().isMinusOne()) { - if((!mstruct.isPower() || !mstruct[1].hasNegativeSign()) && mstruct.representsNumber() && CHILD(0).representsNumber()) { - if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true)) || CHILD(0).representsNonZero(true)) { - b_nonzero = true; - } - if(b_nonzero || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true))) { - mnum = &mstruct; - mden = &CHILD(0); - } + } + } else { + int ret = 0; + if(m_type != STRUCT_FUNCTION) { + for(size_t i = 0; i < SIZE; i++) { + int retval = CHILD(i).containsFunctionId(id, structural_only, check_variables, check_functions); + if(retval == 1) return 1; + else if(retval < 0) ret = retval; + } + } + if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { + return ((KnownVariable*) o_variable)->get().containsFunctionId(id, structural_only, check_variables, check_functions); + } else if(m_type == STRUCT_FUNCTION && check_functions) { + if(function_value) { + return function_value->containsFunctionId(id, structural_only, check_variables, check_functions); } + return -1; + } else if(isAborted()) { + return -1; } + return ret; } - - if(mnum && mden && eo.reduce_divisions) { - switch(mnum->type()) { - case STRUCT_ADDITION: { - break; + return 0; +} +int contains_interval_var(const MathStructure &m, bool structural_only, bool check_variables, bool check_functions, int ignore_high_precision_interval, bool include_interval_function) { + if(m.type() == STRUCT_NUMBER) { + if(m.number().isInterval(false)) { + if(ignore_high_precision_interval != 0) { + if(m.number().precision(true) > (ignore_high_precision_interval < 0 ? (ignore_high_precision_interval == -1 ? PRECISION + 29 : PRECISION - ignore_high_precision_interval) : PRECISION + (10 * ignore_high_precision_interval))) return 0; } - case STRUCT_MULTIPLICATION: { - Number nr; - vector nrs; - vector reducables; - for(size_t i = 0; i < mnum->size(); i++) { - switch((*mnum)[i].type()) { - case STRUCT_ADDITION: {break;} - case STRUCT_POWER: { - if((*mnum)[i][1].isNumber() && (*mnum)[i][1].number().isReal()) { - if((*mnum)[i][1].number().isPositive()) { - nr.set((*mnum)[i][1].number()); - if(reducable((*mnum)[i][0], *mden, nr)) { - nrs.push_back(nr); - reducables.push_back(i); - } - } - break; - } - } - default: { - nr.set(1, 1, 0); - if(reducable((*mnum)[i], *mden, nr)) { - nrs.push_back(nr); - reducables.push_back(i); - } - } - } - } - if(reducables.size() > 0) { - if(!b_nonzero && eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(*mden, eo)) break; - if(mnum == this) { - mstruct.ref(); - transform_nocopy(STRUCT_MULTIPLICATION, &mstruct); - } else { - transform(STRUCT_MULTIPLICATION); - PREPEND_REF(&mstruct); - } - size_t i_erased = 0; - for(size_t i = 0; i < reducables.size(); i++) { - switch(CHILD(0)[reducables[i] - i_erased].type()) { - case STRUCT_POWER: { - if(CHILD(0)[reducables[i] - i_erased][1].isNumber() && CHILD(0)[reducables[i] - i_erased][1].number().isReal()) { - reduce(CHILD(0)[reducables[i] - i_erased][0], CHILD(1)[0], nrs[i], eo); - if(nrs[i] == CHILD(0)[reducables[i] - i_erased][1].number()) { - CHILD(0).delChild(reducables[i] - i_erased + 1); - i_erased++; - } else { - CHILD(0)[reducables[i] - i_erased][1].number() -= nrs[i]; - if(CHILD(0)[reducables[i] - i_erased][1].number().isOne()) { - CHILD(0)[reducables[i] - i_erased].setToChild(1, true, &CHILD(0), reducables[i] - i_erased + 1); - } else { - CHILD(0)[reducables[i] - i_erased].calculateRaiseExponent(eo); - } - CHILD(0).calculateMultiplyIndex(reducables[i] - i_erased, eo, true); - } - break; - } - } - default: { - reduce(CHILD(0)[reducables[i] - i_erased], CHILD(1)[0], nrs[i], eo); - if(nrs[i].isOne()) { - CHILD(0).delChild(reducables[i] - i_erased + 1); - i_erased++; - } else { - MathStructure mexp(1, 1); - mexp.number() -= nrs[i]; - CHILD(0)[reducables[i] - i_erased].calculateRaise(mexp, eo); - CHILD(0).calculateMultiplyIndex(reducables[i] - i_erased, eo, true); - } - } - } - } - if(CHILD(0).size() == 0) { - setToChild(2, true, mparent, index_this + 1); - } else if(CHILD(0).size() == 1) { - CHILD(0).setToChild(1, true, this, 1); - calculateMultiplyIndex(0, eo, true, mparent, index_this); - } else { - calculateMultiplyIndex(0, eo, true, mparent, index_this); - } - return 1; - } - break; - } - case STRUCT_POWER: { - if((*mnum)[1].isNumber() && (*mnum)[1].number().isReal()) { - if((*mnum)[1].number().isPositive()) { - Number nr((*mnum)[1].number()); - if(reducable((*mnum)[0], *mden, nr)) { - if(!b_nonzero && eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(*mden, eo)) break; - if(nr != (*mnum)[1].number()) { - MathStructure mnum2((*mnum)[0]); - if(mnum == this) { - CHILD(1).number() -= nr; - if(CHILD(1).number().isOne()) { - set(mnum2); - } else { - calculateRaiseExponent(eo); - } - mstruct.ref(); - transform_nocopy(STRUCT_MULTIPLICATION, &mstruct); - reduce(mnum2, CHILD(1)[0], nr, eo); - calculateMultiplyLast(eo); - } else { - transform(STRUCT_MULTIPLICATION); - PREPEND(mstruct); - CHILD(0)[1].number() -= nr; - if(CHILD(0)[1].number().isOne()) { - CHILD(0) = mnum2; - } else { - CHILD(0).calculateRaiseExponent(eo); - } - reduce(mnum2, CHILD(1)[0], nr, eo); - calculateMultiplyIndex(0, eo); - } - } else { - if(mnum == this) { - MathStructure mnum2((*mnum)[0]); - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - reduce(mnum2, (*mparent)[index_this][0], nr, eo); - } else { - set_nocopy(mstruct, true); - reduce(mnum2, CHILD(0), nr, eo); - } - } else { - reduce((*mnum)[0], CHILD(0), nr, eo); - } - } - return 1; - } - } - break; - } - } - default: { - Number nr(1, 1); - if(reducable(*mnum, *mden, nr)) { - if(!b_nonzero && eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(*mden, eo)) break; - if(mnum == this) { - MathStructure mnum2(*mnum); - if(!nr.isOne()) { - reduce(*mnum, mstruct[0], nr, eo); - mstruct.calculateRaiseExponent(eo); - nr.negate(); - nr++; - calculateRaise(nr, eo); - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo, true, mparent, index_this); - } else if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - reduce(mnum2, (*mparent)[index_this][0], nr, eo); - (*mparent)[index_this].calculateRaiseExponent(eo, mparent, index_this); - } else { - set_nocopy(mstruct, true); - reduce(mnum2, CHILD(0), nr, eo); - calculateRaiseExponent(eo, mparent, index_this); - } - } else { - reduce(*mnum, CHILD(0), nr, eo); - if(!nr.isOne()) { - calculateRaiseExponent(eo); - nr.negate(); - nr++; - mstruct.calculateRaise(nr, eo); - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo, true, mparent, index_this); - } else { - calculateRaiseExponent(eo, mparent, index_this); - } - } - return 1; - } + return 1; + } else if(CALCULATOR->usesIntervalArithmetic() && m.number().precision() >= 0) { + if(ignore_high_precision_interval != 0) { + if(m.number().precision() > (ignore_high_precision_interval < 0 ? (ignore_high_precision_interval == -1 ? PRECISION + 29 : PRECISION - ignore_high_precision_interval) : PRECISION + (10 * ignore_high_precision_interval))) return 0; } - } - } - - if(mstruct.isFunction() && eo.protected_function != mstruct.function()) { - if(((mstruct.function() == CALCULATOR->f_abs && mstruct.size() == 1 && mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_signum && mstruct[0].size() == 2) || (mstruct.function() == CALCULATOR->f_signum && mstruct.size() == 2 && mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_abs && mstruct[0].size() == 1)) && (equals(mstruct[0][0]) || (isFunction() && o_function == CALCULATOR->f_abs && SIZE == 1 && CHILD(0) == mstruct[0][0]) || (isPower() && CHILD(0) == mstruct[0][0]) || (isPower() && CHILD(0).isFunction() && CHILD(0).function() == CALCULATOR->f_abs && CHILD(0).size() == 1 && CHILD(0)[0] == mstruct[0][0]))) { - // sgn(abs(x))*x^y=x^y - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } else if(mstruct.function() == CALCULATOR->f_signum && mstruct.size() == 2) { - if(equals(mstruct[0]) && representsReal(true)) { - // sgn(x)*x=abs(x) - transform(CALCULATOR->f_abs); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(isPower() && CHILD(1).representsOdd() && mstruct[0] == CHILD(0) && CHILD(0).representsReal(true)) { - //sgn(x)*x^3=abs(x)^3 - CHILD(0).transform(CALCULATOR->f_abs); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(mstruct.function() == CALCULATOR->f_root && VALID_ROOT(mstruct)) { - if(equals(mstruct[0]) && mstruct[0].representsReal(true) && mstruct[1].number().isOdd()) { - // root(x, 3)*x=abs(x)^(1/3)*x - mstruct[0].transform(STRUCT_FUNCTION); - mstruct[0].setFunction(CALCULATOR->f_abs); - mstruct[1].number().recip(); - mstruct.setType(STRUCT_POWER); - transform(STRUCT_FUNCTION); - setFunction(CALCULATOR->f_abs); - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } else if(isPower() && CHILD(1).representsOdd() && CHILD(0) == mstruct[0] && CHILD(0).representsReal(true) && mstruct[1].number().isOdd()) { - // root(x, 3)*x^3=abs(x)^(1/3)*x^3 - mstruct[0].transform(STRUCT_FUNCTION); - mstruct[0].setFunction(CALCULATOR->f_abs); - mstruct[1].number().recip(); - mstruct.setType(STRUCT_POWER); - CHILD(0).transform(STRUCT_FUNCTION); - CHILD(0).setFunction(CALCULATOR->f_abs); - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } else if(isPower() && CHILD(0).isFunction() && CHILD(0).function() == CALCULATOR->f_abs && CHILD(0).size() == 1 && CHILD(0)[0].equals(mstruct[0]) && CHILD(1).isNumber() && CHILD(1).number().isRational() && CHILD(1).number().isFraction() && CHILD(1).number().denominator() == mstruct[1].number() && CHILD(0).representsReal(true) && CHILD(1).number().numerator() == mstruct[1].number() - 1) { - // root(x, 3)*abs(x)^(2/3)=x - SET_CHILD_MAP(0) - SET_CHILD_MAP(0) - return 1; - } - } else if(eo.transform_trigonometric_functions && mstruct.function() == CALCULATOR->f_sinc && mstruct.size() == 1 && equals(mstruct[0])) { - // sinc(x)*x=sin(x) - calculateMultiply(CALCULATOR->getRadUnit(), eo); - transform(CALCULATOR->f_sin); - if(eo.calculate_functions) calculateFunctions(eo, false); - MERGE_APPROX_AND_PREC(mstruct) return 1; } } - if(isZero()) { - if(mstruct.isFunction()) { - if((mstruct.function() == CALCULATOR->f_ln || mstruct.function() == CALCULATOR->f_Ei) && mstruct.size() == 1) { - if(mstruct[0].representsNonZero() || warn_about_assumed_not_value(mstruct[0], m_zero, eo)) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - } else if(mstruct.function() == CALCULATOR->f_li && mstruct.size() == 1) { - if(mstruct.representsNumber(true) || warn_about_assumed_not_value(mstruct[0], m_one, eo)) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - } - } else if(mstruct.isPower() && mstruct[0].isFunction() && mstruct[1].representsNumber()) { - if((mstruct[0].function() == CALCULATOR->f_ln || mstruct[0].function() == CALCULATOR->f_Ei) && mstruct[0].size() == 1) { - if(mstruct[0][0].representsNonZero() || warn_about_assumed_not_value(mstruct[0][0], m_zero, eo)) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - } else if(mstruct[0].function() == CALCULATOR->f_li && mstruct[0].size() == 1) { - if(mstruct[0].representsNumber(true) || warn_about_assumed_not_value(mstruct[0][0], m_one, eo)) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - } + if(m.type() == STRUCT_FUNCTION && (m.function()->id() == FUNCTION_ID_INTERVAL || m.function()->id() == FUNCTION_ID_UNCERTAINTY)) return include_interval_function; + if(structural_only) { + for(size_t i = 0; i < m.size(); i++) { + if(contains_interval_var(m[i], structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function)) return 1; } - } - - switch(m_type) { - case STRUCT_VECTOR: { - switch(mstruct.type()) { - case STRUCT_ADDITION: { - return 0; - } - case STRUCT_VECTOR: { - if(isMatrix() && mstruct.isMatrix()) { - if(CHILD(0).size() != mstruct.size()) { - CALCULATOR->error(true, _("The second matrix must have as many rows (was %s) as the first has columns (was %s) for matrix multiplication."), i2s(mstruct.size()).c_str(), i2s(CHILD(0).size()).c_str(), NULL); - return -1; - } - MathStructure msave(*this); - size_t rows = SIZE; - clearMatrix(true); - resizeMatrix(rows, mstruct[0].size(), m_zero); - MathStructure mtmp; - for(size_t index_r = 0; index_r < SIZE; index_r++) { - for(size_t index_c = 0; index_c < CHILD(0).size(); index_c++) { - for(size_t index = 0; index < msave[0].size(); index++) { - mtmp = msave[index_r][index]; - mtmp.calculateMultiply(mstruct[index][index_c], eo); - CHILD(index_r)[index_c].calculateAdd(mtmp, eo, &CHILD(index_r), index_c); - } - } - } - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(isMatrix() && mstruct.isVector()) { - if(SIZE != mstruct.size() || CHILD(0).size() != 1) { - CALCULATOR->error(true, _("The second matrix must have as many rows (was %s) as the first has columns (was %s) for matrix multiplication."), i2s(1).c_str(), i2s(CHILD(0).size()).c_str(), NULL); - return -1; - } - MathStructure msave(*this); - size_t rows = SIZE; - clearMatrix(true); - resizeMatrix(rows, mstruct.size(), m_zero); - MathStructure mtmp; - for(size_t index_r = 0; index_r < SIZE; index_r++) { - for(size_t index_c = 0; index_c < CHILD(0).size(); index_c++) { - CHILD(index_r)[index_c].set(msave[index_r][0]); - CHILD(index_r)[index_c].calculateMultiply(mstruct[index_c], eo); - } - } - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else { - if(SIZE == mstruct.size()) { - for(size_t i = 0; i < SIZE; i++) { - mstruct[i].ref(); - CHILD(i).multiply_nocopy(&mstruct[i], true); - CHILD(i).calculateMultiplyLast(eo, true); - } - m_type = STRUCT_ADDITION; - MERGE_APPROX_AND_PREC(mstruct) - calculatesub(eo, eo, false, mparent, index_this); - return 1; - } - } - return -1; - } - default: { - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).calculateMultiply(mstruct, eo); - } - MERGE_APPROX_AND_PREC(mstruct) - calculatesub(eo, eo, false, mparent, index_this); - return 1; - } + if(m.type() == STRUCT_VARIABLE && check_variables && m.variable()->isKnown()) { + return contains_interval_var(((KnownVariable*) m.variable())->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); + } else if(m.type() == STRUCT_FUNCTION && check_functions) { + if(m.functionValue()) { + return contains_interval_var(*m.functionValue(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); } } - case STRUCT_ADDITION: { - if(eo.expand != 0 && containsType(STRUCT_DATETIME, false, true, false) > 0) return -1; - switch(mstruct.type()) { - case STRUCT_ADDITION: { - if(eo.expand != 0 && SIZE < 1000 && mstruct.size() < 1000 && (SIZE * mstruct.size() < (eo.expand == -1 ? 50 : 500))) { - - if(eo.expand > -2 || (!containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) && !mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0)) || (representsNonNegative(true) && mstruct.representsNonNegative(true))) { - MathStructure msave(*this); - CLEAR; - for(size_t i = 0; i < mstruct.size(); i++) { - if(CALCULATOR->aborted()) { - set(msave); - return -1; - } - APPEND(msave); - mstruct[i].ref(); - LAST.multiply_nocopy(&mstruct[i], true); - if(reversed) { - LAST.swapChildren(1, LAST.size()); - LAST.calculateMultiplyIndex(0, eo, true, this, SIZE - 1); - } else { - LAST.calculateMultiplyLast(eo, true, this, SIZE - 1); - } - } - MERGE_APPROX_AND_PREC(mstruct) - calculatesub(eo, eo, false, mparent, index_this); - return 1; - } else if(eo.expand <= -2 && (!mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) || representsNonNegative(true))) { - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).calculateMultiply(mstruct, eo, this, i); - } - calculatesub(eo, eo, false, mparent, index_this); - return 1; - } else if(eo.expand <= -2 && (!containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) || mstruct.representsNonNegative(true))) { - return 0; - } - } - if(equals(mstruct)) { - raise_nocopy(new MathStructure(2, 1, 0)); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - break; - } - case STRUCT_POWER: { - if(mstruct[1].isNumber() && *this == mstruct[0]) { - if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !representsZero(true)) - || (mstruct[1].isNumber() && mstruct[1].number().isReal() && !mstruct[1].number().isMinusOne()) - || representsNonZero(true) - || mstruct[1].representsPositive() - || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !representsZero(true) && warn_about_denominators_assumed_nonzero_or_positive(*this, mstruct[1], eo))) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - (*mparent)[index_this][1].number()++; - (*mparent)[index_this].calculateRaiseExponent(eo, mparent, index_this); - } else { - set_nocopy(mstruct, true); - CHILD(1).number()++; - calculateRaiseExponent(eo, mparent, index_this); - } - return 1; - } - } - if(eo.expand == 0 && mstruct[0].isAddition()) return -1; - if(eo.combine_divisions && mstruct[1].hasNegativeSign()) { - int ret; - vector merged; - merged.resize(SIZE, false); - size_t merges = 0; - MathStructure *mstruct2 = new MathStructure(mstruct); - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isOne()) ret = -1; - else ret = CHILD(i).merge_multiplication(*mstruct2, eo, NULL, 0, 0, false, false); - if(ret == 0) { - ret = mstruct2->merge_multiplication(CHILD(i), eo, NULL, 0, 0, true, false); - if(ret >= 1) { - mstruct2->ref(); - setChild_nocopy(mstruct2, i + 1); - } - } - if(ret >= 1) { - mstruct2->unref(); - if(i + 1 != SIZE) mstruct2 = new MathStructure(mstruct); - merged[i] = true; - merges++; - } else { - if(i + 1 == SIZE) mstruct2->unref(); - merged[i] = false; - } - } - if(merges == 0) { - return -1; - } else if(merges == SIZE) { - calculatesub(eo, eo, false, mparent, index_this); - return 1; - } else if(merges == SIZE - 1) { - for(size_t i = 0; i < SIZE; i++) { - if(!merged[i]) { - mstruct.ref(); - CHILD(i).multiply_nocopy(&mstruct, true); - break; - } - } - calculatesub(eo, eo, false, mparent, index_this); - } else { - MathStructure *mdiv = new MathStructure(); - merges = 0; - for(size_t i = 0; i - merges < SIZE; i++) { - if(!merged[i]) { - CHILD(i - merges).ref(); - if(merges > 0) { - (*mdiv)[0].add_nocopy(&CHILD(i - merges), merges > 1); - } else { - mdiv->multiply(mstruct); - mdiv->setChild_nocopy(&CHILD(i - merges), 1); - } - ERASE(i - merges); - merges++; - } - } - add_nocopy(mdiv, true); - calculatesub(eo, eo, false); - } - return 1; - } - if(eo.expand == 0 || (eo.expand < -1 && mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) && !representsNonNegative(true))) return -1; - } - case STRUCT_MULTIPLICATION: { - if(do_append && (eo.expand == 0 || (eo.expand < -1 && mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) && !representsNonNegative(true)))) { - transform(STRUCT_MULTIPLICATION); - for(size_t i = 0; i < mstruct.size(); i++) { - APPEND_REF(&mstruct[i]); - } - return 1; - } - } - default: { - if(eo.expand == 0 || (eo.expand < -1 && mstruct.containsInterval(true, false, false, eo.expand == -2 ? 1 : 0) && !representsNonNegative(true))) return -1; - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).multiply(mstruct, true); - if(reversed) { - CHILD(i).swapChildren(1, CHILD(i).size()); - CHILD(i).calculateMultiplyIndex(0, eo, true, this, i); - } else { - CHILD(i).calculateMultiplyLast(eo, true, this, i); - } - } - MERGE_APPROX_AND_PREC(mstruct) - calculatesub(eo, eo, false, mparent, index_this); - return 1; - } + } else { + int ret = 0; + if(m.type() != STRUCT_FUNCTION) { + for(size_t i = 0; i < m.size(); i++) { + int retval = contains_interval_var(m[i], structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); + if(retval == 1) return 1; + else if(retval < 0) ret = retval; } - return -1; } - case STRUCT_MULTIPLICATION: { - switch(mstruct.type()) { - case STRUCT_VECTOR: {} - case STRUCT_ADDITION: { - if(eo.expand == 0 || containsType(STRUCT_DATETIME, false, true, false) > 0) { - if(!do_append) return -1; - APPEND_REF(&mstruct); - return 1; - } - return 0; - } - case STRUCT_MULTIPLICATION: { - for(size_t i = 0; i < mstruct.size(); i++) { - if(reversed) { - PREPEND_REF(&mstruct[i]); - calculateMultiplyIndex(0, eo, false); - } else { - APPEND_REF(&mstruct[i]); - calculateMultiplyLast(eo, false); - } - } - MERGE_APPROX_AND_PREC(mstruct) - if(SIZE == 1) { - setToChild(1, false, mparent, index_this + 1); - } else if(SIZE == 0) { - clear(true); - } else { - evalSort(); - } - return 1; - } - case STRUCT_POWER: { - if(mstruct[1].isNumber()) { - if(*this == mstruct[0]) { - if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !representsZero(true)) - || (mstruct[1].isNumber() && mstruct[1].number().isReal() && !mstruct[1].number().isMinusOne()) - || representsNonZero(true) - || mstruct[1].representsPositive() - || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !representsZero(true) && warn_about_denominators_assumed_nonzero_or_positive(*this, mstruct[1], eo))) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - (*mparent)[index_this][1].number()++; - (*mparent)[index_this].calculateRaiseExponent(eo, mparent, index_this); - } else { - set_nocopy(mstruct, true); - CHILD(1).number()++; - calculateRaiseExponent(eo, mparent, index_this); - } - return 1; - } - } else { - for(size_t i = 0; i < SIZE; i++) { - int ret = CHILD(i).merge_multiplication(mstruct, eo, NULL, 0, 0, false, false); - if(ret == 0) { - ret = mstruct.merge_multiplication(CHILD(i), eo, NULL, 0, 0, true, false); - if(ret >= 1) { - if(ret == 2) ret = 3; - else if(ret == 3) ret = 2; - mstruct.ref(); - setChild_nocopy(&mstruct, i + 1); - } - } - if(ret >= 1) { - if(ret != 2) calculateMultiplyIndex(i, eo, true, mparent, index_this); - return 1; - } - } - } - } - } - default: { - if(do_append) { - MERGE_APPROX_AND_PREC(mstruct) - if(reversed) { - PREPEND_REF(&mstruct); - calculateMultiplyIndex(0, eo, true, mparent, index_this); - } else { - APPEND_REF(&mstruct); - calculateMultiplyLast(eo, true, mparent, index_this); - } - return 1; - } - } + if(m.type() == STRUCT_VARIABLE && check_variables && m.variable()->isKnown()) { + return contains_interval_var(((KnownVariable*) m.variable())->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); + } else if(m.type() == STRUCT_FUNCTION && check_functions) { + if(m.functionValue()) { + return contains_interval_var(*m.functionValue(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); } return -1; - } - case STRUCT_POWER: { - switch(mstruct.type()) { - case STRUCT_VECTOR: {} - case STRUCT_ADDITION: {} - case STRUCT_MULTIPLICATION: { - return 0; - } - case STRUCT_POWER: { - if(CHILD(0).isFunction() && CHILD(0).function() == CALCULATOR->f_abs && mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_root && mstruct[1].isMinusOne() && CHILD(0).size() == 1 && VALID_ROOT(mstruct[0]) && CHILD(0)[0].equals(mstruct[0][0]) && CHILD(1).isNumber() && CHILD(1).number().isRational() && CHILD(1).number().isFraction() && CHILD(1).number().denominator() == mstruct[0][1].number() && CHILD(0)[0].representsReal(true) && CHILD(1).number().numerator() == -(mstruct[0][1].number() - 1)) { - // root(x, 3)^-1*abs(x)^(-2/3)=1/x - SET_CHILD_MAP(0) - SET_CHILD_MAP(0) - raise(m_minus_one); - return 1; - } - if(mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_abs && CHILD(0).isFunction() && CHILD(0).function() == CALCULATOR->f_root && CHILD(1).isMinusOne() && mstruct[0].size() == 1 && VALID_ROOT(CHILD(0)) && CHILD(0)[0].equals(mstruct[0][0]) && mstruct[1].isNumber() && mstruct[1].number().isRational() && mstruct[1].number().isFraction() && mstruct[1].number().denominator() == CHILD(0)[1].number() && mstruct[0][0].representsReal(true) && mstruct[1].number().numerator() == -(CHILD(0)[1].number() - 1)) { - // root(x, 3)^-1*abs(x)^(-2/3)=1/x - SET_CHILD_MAP(0) - SET_CHILD_MAP(0) - raise(m_minus_one); - return 1; - } - if(mstruct[0] == CHILD(0) || (CHILD(0).isMultiplication() && CHILD(0).size() == 2 && CHILD(0)[0].isMinusOne() && CHILD(0)[1] == mstruct[0] && mstruct[1].representsEven())) { - if(mstruct[0].isUnit() && mstruct[0].prefix()) CHILD(0).setPrefix(mstruct[0].prefix()); - bool b = eo.allow_complex || CHILD(0).representsNonNegative(true), b2 = true, b_warn = false; - if(!b) { - b = CHILD(1).representsInteger() && mstruct[1].representsInteger(); - } - if(b) { - b = false; - bool b2test = false; - if(IS_REAL(mstruct[1]) && IS_REAL(CHILD(1))) { - if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) { - b2 = true; - b = true; - } else if(!mstruct[1].number().isMinusOne() && !CHILD(1).number().isMinusOne()) { - b2 = (mstruct[1].number() + CHILD(1).number()).isNegative(); - b = true; - if(!b2) b2test = true; - } - } - if(!b || b2test) { - b = (!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true)) - || CHILD(0).representsNonZero(true) - || (CHILD(1).representsPositive() && mstruct[1].representsPositive()) - || (CHILD(1).representsNegative() && mstruct[1].representsNegative()); - if(!b && eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true)) { - b = true; - b_warn = true; - } - if(b2test) { - b2 = b; - b = true; - } - } - } - if(b) { - if(IS_REAL(CHILD(1)) && IS_REAL(mstruct[1])) { - if(!b2 && !do_append) return -1; - if(b_warn && !warn_about_denominators_assumed_nonzero(CHILD(0), eo)) return -1; - if(b2) { - CHILD(1).number() += mstruct[1].number(); - calculateRaiseExponent(eo, mparent, index_this); - } else { - if(CHILD(1).number().isNegative()) { - CHILD(1).number()++; - mstruct[1].number() += CHILD(1).number(); - CHILD(1).number().set(-1, 1, 0); - } else { - mstruct[1].number()++; - CHILD(1).number() += mstruct[1].number(); - mstruct[1].number().set(-1, 1, 0); - } - MERGE_APPROX_AND_PREC(mstruct) - transform(STRUCT_MULTIPLICATION); - CHILD(0).calculateRaiseExponent(eo, this, 0); - if(reversed) { - PREPEND_REF(&mstruct); - CHILD(0).calculateRaiseExponent(eo, this, 0); - calculateMultiplyIndex(0, eo, true, mparent, index_this); - } else { - APPEND_REF(&mstruct); - CHILD(1).calculateRaiseExponent(eo, this, 1); - calculateMultiplyLast(eo, true, mparent, index_this); - } - } - return 1; - } else { - MathStructure mstruct2(CHILD(1)); - if(mstruct2.calculateAdd(mstruct[1], eo)) { - if(b_warn && !warn_about_denominators_assumed_nonzero_llgg(CHILD(0), CHILD(1), mstruct[1], eo)) return -1; - CHILD(1) = mstruct2; - calculateRaiseExponent(eo, mparent, index_this); - return 1; - } - } - } - } else if(mstruct[1] == CHILD(1)) { - if(!CHILD(0).isMultiplication() && !mstruct[0].isMultiplication() && (mstruct[1].representsInteger() || CHILD(0).representsPositive(true) || mstruct[0].representsPositive(true))) { - MathStructure mstruct2(CHILD(0)); - if(mstruct2.calculateMultiply(mstruct[0], eo)) { - CHILD(0) = mstruct2; - MERGE_APPROX_AND_PREC(mstruct) - calculateRaiseExponent(eo, mparent, index_this); - return 1; - } - } else if(eo.transform_trigonometric_functions && CHILD(1).representsInteger() && CHILD(0).isFunction() && mstruct[0].isFunction() && eo.protected_function != mstruct[0].function() && eo.protected_function != CHILD(0).function() && CHILD(0).size() == 1 && mstruct[0].size() == 1 && CHILD(0)[0] == mstruct[0][0]) { - if((CHILD(0).function() == CALCULATOR->f_cos && mstruct[0].function() == CALCULATOR->f_sin) || (CHILD(0).function() == CALCULATOR->f_sin && mstruct[0].function() == CALCULATOR->f_cos) || (CHILD(0).function() == CALCULATOR->f_cosh && mstruct[0].function() == CALCULATOR->f_sinh) || (CHILD(0).function() == CALCULATOR->f_sinh && mstruct[0].function() == CALCULATOR->f_cosh)) { - // cos(x)^n*sin(x)^n=sin(2x)^n/2^n - if(CHILD(0).function() == CALCULATOR->f_cosh) CHILD(0).setFunction(CALCULATOR->f_sinh); - else if(CHILD(0).function() == CALCULATOR->f_cos) CHILD(0).setFunction(CALCULATOR->f_sin); - CHILD(0)[0].calculateMultiply(nr_two, eo); - CHILD(0).childUpdated(1); - CHILD_UPDATED(0) - MathStructure *mdiv = new MathStructure(2, 1, 0); - mdiv->calculateRaise(CHILD(1), eo); - mdiv->calculateInverse(eo); - multiply_nocopy(mdiv); - calculateMultiplyLast(eo); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if((CHILD(0).function() == CALCULATOR->f_tan && mstruct[0].function() == CALCULATOR->f_cos) || (CHILD(0).function() == CALCULATOR->f_cos && mstruct[0].function() == CALCULATOR->f_tan)) { - // tan(x)^n*cos(x)^n=sin(x)^n - CHILD(0).setFunction(CALCULATOR->f_sin); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if((CHILD(0).function() == CALCULATOR->f_tanh && mstruct[0].function() == CALCULATOR->f_cosh) || (CHILD(0).function() == CALCULATOR->f_cosh && mstruct[0].function() == CALCULATOR->f_tanh)) { - // tanh(x)^n*cosh(x)^n=sinh(x)^n - CHILD(0).setFunction(CALCULATOR->f_sin); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - } else if(eo.transform_trigonometric_functions && CHILD(1).isInteger() && mstruct[1].isInteger() && CHILD(0).isFunction() && mstruct[0].isFunction() && eo.protected_function != mstruct[0].function() && eo.protected_function != CHILD(0).function() && mstruct[0].size() == 1 && CHILD(0).size() == 1 && CHILD(0)[0] == mstruct[0][0]) { - if(CHILD(1).number().isNonNegative() != mstruct[1].number().isNonNegative()) { - if(CHILD(0).function() == CALCULATOR->f_sin) { - if(mstruct[0].function() == CALCULATOR->f_cos) { - CHILD(0).setFunction(CALCULATOR->f_tan); - mstruct[1].number() += CHILD(1).number(); - if(mstruct[1].number().isZero()) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) { - mstruct[0].setFunction(CALCULATOR->f_sin); - CHILD(1).number() -= mstruct[1].number(); - } - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } else if(mstruct[0].function() == CALCULATOR->f_tan) { - CHILD(0).setFunction(CALCULATOR->f_cos); - mstruct[1].number() += CHILD(1).number(); - if(mstruct[1].number().isZero()) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) { - mstruct[0].setFunction(CALCULATOR->f_sin); - CHILD(1).number() -= mstruct[1].number(); - } - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } else if(CHILD(0).function() == CALCULATOR->f_cos) { - if(mstruct[0].function() == CALCULATOR->f_sin) { - mstruct[0].setFunction(CALCULATOR->f_tan); - CHILD(1).number() += mstruct[1].number(); - if(CHILD(1).number().isZero()) { - set(mstruct, true); - return 1; - } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) { - CHILD(0).setFunction(CALCULATOR->f_sin); - mstruct[1].number() -= CHILD(1).number(); - } - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } else if(CHILD(0).function() == CALCULATOR->f_tan) { - if(mstruct[0].function() == CALCULATOR->f_sin) { - mstruct[0].setFunction(CALCULATOR->f_cos); - CHILD(1).number() += mstruct[1].number(); - if(CHILD(1).number().isZero()) { - set(mstruct, true); - return 1; - } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) { - CHILD(0).setFunction(CALCULATOR->f_sin); - mstruct[1].number() -= CHILD(1).number(); - } - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } else if(CHILD(0).function() == CALCULATOR->f_sinh) { - if(mstruct[0].function() == CALCULATOR->f_cosh) { - CHILD(0).setFunction(CALCULATOR->f_tanh); - mstruct[1].number() += CHILD(1).number(); - if(mstruct[1].number().isZero()) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) { - mstruct[0].setFunction(CALCULATOR->f_sinh); - CHILD(1).number() -= mstruct[1].number(); - } - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } else if(mstruct[0].function() == CALCULATOR->f_tanh) { - CHILD(0).setFunction(CALCULATOR->f_cosh); - mstruct[1].number() += CHILD(1).number(); - if(mstruct[1].number().isZero()) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) { - mstruct[0].setFunction(CALCULATOR->f_sinh); - CHILD(1).number() -= mstruct[1].number(); - } - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } else if(CHILD(0).function() == CALCULATOR->f_cosh) { - if(mstruct[0].function() == CALCULATOR->f_sinh) { - mstruct[0].setFunction(CALCULATOR->f_tanh); - CHILD(1).number() += mstruct[1].number(); - if(CHILD(1).number().isZero()) { - set(mstruct, true); - return 1; - } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) { - CHILD(0).setFunction(CALCULATOR->f_sinh); - mstruct[1].number() -= CHILD(1).number(); - } - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } else if(CHILD(0).function() == CALCULATOR->f_tanh) { - if(mstruct[0].function() == CALCULATOR->f_sinh) { - mstruct[0].setFunction(CALCULATOR->f_cosh); - CHILD(1).number() += mstruct[1].number(); - if(CHILD(1).number().isZero()) { - set(mstruct, true); - return 1; - } else if(mstruct[1].number().isPositive() == CHILD(1).number().isPositive()) { - CHILD(0).setFunction(CALCULATOR->f_sinh); - mstruct[1].number() -= CHILD(1).number(); - } - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } - } else { - if((CHILD(0).function() == CALCULATOR->f_tan && mstruct[0].function() == CALCULATOR->f_cos)) { - // tan(x)^n*cos(x)^m=sin(x)^n*cos(x)^(m-n) - CHILD(0).setFunction(CALCULATOR->f_sin); - mstruct[1].number() -= CHILD(1).number(); - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } else if((CHILD(0).function() == CALCULATOR->f_cos && mstruct[0].function() == CALCULATOR->f_tan)) { - // tan(x)^n*cos(x)^m=sin(x)^n*cos(x)^(m-n) - mstruct[0].setFunction(CALCULATOR->f_sin); - CHILD(1).number() -= mstruct[1].number(); - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } else if((CHILD(0).function() == CALCULATOR->f_tanh && mstruct[0].function() == CALCULATOR->f_cosh)) { - // tanh(x)^n*cosh(x)^m=sinh(x)^n*cosh(x)^(m-n) - CHILD(0).setFunction(CALCULATOR->f_sinh); - mstruct[1].number() -= CHILD(1).number(); - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } else if((CHILD(0).function() == CALCULATOR->f_cosh && mstruct[0].function() == CALCULATOR->f_tanh)) { - // tanh(x)^n*cosh(x)^m=sinh(x)^n*cosh(x)^(m-n) - mstruct[0].setFunction(CALCULATOR->f_sinh); - CHILD(1).number() -= mstruct[1].number(); - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } - } else if(mstruct[0].isMultiplication() && mstruct[0].size() == 2 && mstruct[0][0].isMinusOne() && mstruct[0][1] == CHILD(0) && CHILD(1).representsEven()) { - return 0; - } - break; - } - case STRUCT_FUNCTION: { - if(eo.protected_function != CALCULATOR->f_signum && mstruct.function() == CALCULATOR->f_signum && mstruct.size() == 2 && CHILD(0).isFunction() && CHILD(0).function() == CALCULATOR->f_abs && CHILD(0).size() == 1 && mstruct[0] == CHILD(0)[0] && CHILD(1).isNumber() && CHILD(1).number().isRational() && CHILD(1).number().numeratorIsOne() && !CHILD(1).number().denominatorIsEven() && CHILD(0)[0].representsReal(true)) { - setType(STRUCT_FUNCTION); - setFunction(CALCULATOR->f_root); - CHILD(0).setToChild(1, true); - CHILD(1).number().recip(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - if(eo.transform_trigonometric_functions && CHILD(0).isFunction() && CHILD(0).size() == 1 && mstruct.size() == 1 && CHILD(1).isNumber() && CHILD(1).number().isNegative() && eo.protected_function != mstruct.function() && eo.protected_function != CHILD(0).function()) { - if(CHILD(0).function() == CALCULATOR->f_sin) { - if(mstruct.function() == CALCULATOR->f_cos && CHILD(0)[0] == mstruct[0]) { - if(CHILD(1).number().isMinusOne()) { - CHILD(0).setFunction(CALCULATOR->f_tan); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - mstruct.setFunction(CALCULATOR->f_tan); - mstruct.raise(nr_minus_one); - CHILD(1).number()++; - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } else if(mstruct.function() == CALCULATOR->f_tan && CHILD(0)[0] == mstruct[0]) { - if(CHILD(1).number().isMinusOne()) { - CHILD(0).setFunction(CALCULATOR->f_cos); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - mstruct.setFunction(CALCULATOR->f_cos); - mstruct.raise(nr_minus_one); - CHILD(1).number()++; - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } else if(CHILD(0).function() == CALCULATOR->f_cos) { - if(mstruct.function() == CALCULATOR->f_sin && CHILD(0)[0] == mstruct[0]) { - if(CHILD(1).number().isMinusOne()) { - CHILD(0).setFunction(CALCULATOR->f_tan); - SET_CHILD_MAP(0) - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - mstruct.setFunction(CALCULATOR->f_tan); - CHILD(1).number()++; - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } else if(CHILD(0).function() == CALCULATOR->f_tan) { - if(mstruct.function() == CALCULATOR->f_sin && CHILD(0)[0] == mstruct[0]) { - if(CHILD(1).number().isMinusOne()) { - CHILD(0).setFunction(CALCULATOR->f_cos); - SET_CHILD_MAP(0) - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - mstruct.setFunction(CALCULATOR->f_cos); - CHILD(1).number()++; - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } else if(CHILD(0).function() == CALCULATOR->f_sinh) { - if(mstruct.function() == CALCULATOR->f_cosh && CHILD(0)[0] == mstruct[0]) { - if(CHILD(1).number().isMinusOne()) { - CHILD(0).setFunction(CALCULATOR->f_tanh); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - mstruct.setFunction(CALCULATOR->f_tanh); - mstruct.raise(nr_minus_one); - CHILD(1).number()++; - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } else if(mstruct.function() == CALCULATOR->f_tanh && CHILD(0)[0] == mstruct[0]) { - if(CHILD(1).number().isMinusOne()) { - CHILD(0).setFunction(CALCULATOR->f_cosh); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - mstruct.setFunction(CALCULATOR->f_cosh); - mstruct.raise(nr_minus_one); - CHILD(1).number()++; - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } else if(CHILD(0).function() == CALCULATOR->f_cosh) { - if(mstruct.function() == CALCULATOR->f_sinh && CHILD(0)[0] == mstruct[0]) { - if(CHILD(1).number().isMinusOne()) { - CHILD(0).setFunction(CALCULATOR->f_tanh); - SET_CHILD_MAP(0) - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - mstruct.setFunction(CALCULATOR->f_tanh); - CHILD(1).number()++; - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } else if(CHILD(0).function() == CALCULATOR->f_tanh) { - if(mstruct.function() == CALCULATOR->f_sinh && CHILD(0)[0] == mstruct[0]) { - if(CHILD(1).number().isMinusOne()) { - CHILD(0).setFunction(CALCULATOR->f_cosh); - SET_CHILD_MAP(0) - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - mstruct.setFunction(CALCULATOR->f_cosh); - CHILD(1).number()++; - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } - } - if(mstruct.function() == CALCULATOR->f_stripunits && mstruct.size() == 1) { - if(m_type == STRUCT_POWER && CHILD(0).isVariable() && CHILD(0).variable()->isKnown() && mstruct[0].contains(CHILD(0), false) > 0) { - if(separate_unit_vars(CHILD(0), eo, false)) { - calculateRaiseExponent(eo); - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } - } - } - default: { - if(!mstruct.isNumber() && CHILD(1).isNumber() && CHILD(0) == mstruct) { - if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true)) - || (CHILD(1).isNumber() && CHILD(1).number().isReal() && !CHILD(1).number().isMinusOne()) - || CHILD(0).representsNonZero(true) - || CHILD(1).representsPositive() - || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !CHILD(0).representsZero(true) && warn_about_denominators_assumed_nonzero_or_positive(CHILD(0), CHILD(1), eo))) { - CHILD(1).number()++; - MERGE_APPROX_AND_PREC(mstruct) - calculateRaiseExponent(eo, mparent, index_this); - return 1; - } - } - if(mstruct.isNumber() && CHILD(1).isNumber() && !CHILD(1).number().includesInfinity() && CHILD(0).isNumber() && CHILD(0).number().isRational() && !CHILD(0).number().isZero() && mstruct.number().isRational()) { - if(CHILD(0).isInteger() && mstruct.number().denominator() == CHILD(0).number().numerator()) { - CHILD(1).number()--; - MERGE_APPROX_AND_PREC(mstruct) - calculateRaiseExponent(eo); - if(!mstruct.number().numeratorIsOne()) calculateMultiply(mstruct.number().numerator(), eo, mparent, index_this); - return 1; - } else if(mstruct.number().denominator() == CHILD(0).number().numerator() && mstruct.number().numerator() == CHILD(0).number().denominator()) { - CHILD(1).number()--; - MERGE_APPROX_AND_PREC(mstruct) - calculateRaiseExponent(eo); - return 1; - } - } - if(mstruct.isZero() && (!eo.keep_zero_units || containsType(STRUCT_UNIT, false, true, true) <= 0 || (CHILD(0).isUnit() && CHILD(0).unit() == CALCULATOR->getRadUnit()) || (CHILD(0).isFunction() && CHILD(0).representsNumber(false))) && !representsUndefined(true, true, !eo.assume_denominators_nonzero) && representsNonMatrix()) { - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - if(CHILD(0).isFunction() && mstruct.isZero() && CHILD(1).representsNumber()) { - if((CHILD(0).function() == CALCULATOR->f_ln || CHILD(0).function() == CALCULATOR->f_Ei) && SIZE == 1) { - if(CHILD(0)[0].representsNonZero() || warn_about_assumed_not_value(CHILD(0)[0], m_zero, eo)) { - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 3; - } - } else if(CHILD(0).function() == CALCULATOR->f_li && SIZE == 1) { - if(CHILD(0).representsNumber(true) || warn_about_assumed_not_value(CHILD(0)[0], m_one, eo)) { - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 3; - } - } - } - break; - } - } + } else if(m.isAborted()) { return -1; } - case STRUCT_FUNCTION: { - if(eo.protected_function != o_function) { - if(((o_function == CALCULATOR->f_abs && SIZE == 1 && CHILD(0).isFunction() && CHILD(0).function() == CALCULATOR->f_signum && CHILD(0).size() == 2) || (o_function == CALCULATOR->f_signum && SIZE == 2 && CHILD(0).isFunction() && CHILD(0).function() == CALCULATOR->f_abs && CHILD(0).size() == 1)) && (CHILD(0)[0] == mstruct || (mstruct.isFunction() && mstruct.function() == CALCULATOR->f_abs && mstruct.size() == 1 && CHILD(0)[0] == mstruct[0]) || (mstruct.isPower() && mstruct[0] == CHILD(0)[0]) || (mstruct.isPower() && mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_abs && mstruct[0].size() == 1 && CHILD(0)[0] == mstruct[0][0]))) { - // sgn(abs(x))*x^y=x^y - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; - } else if(o_function == CALCULATOR->f_abs && SIZE == 1) { - if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_abs && mstruct.size() == 1 && mstruct[0] == CHILD(0) && CHILD(0).representsReal(true)) { - // abs(x)*abs(x)=x^2 - SET_CHILD_MAP(0) - MERGE_APPROX_AND_PREC(mstruct) - calculateRaise(nr_two, eo); - return 1; - } else if(mstruct.isFunction() && eo.protected_function != mstruct.function() && mstruct.function() == CALCULATOR->f_signum && mstruct.size() == 2 && mstruct[0] == CHILD(0) && CHILD(0).representsScalar()) { - // sgn(x)*abs(x)=x - SET_CHILD_MAP(0) - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(o_function == CALCULATOR->f_signum && SIZE == 2) { - if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_signum && mstruct.size() == 2 && mstruct[0] == CHILD(0) && CHILD(0).representsReal(true)) { - if(mstruct[1].isOne() && CHILD(1).isOne()) { - set(1, 1, 0, true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct[1] == CHILD(1)) { - // sgn(x)*sgn(x)=sgn(abs(x)) - CHILD(0).transform(CALCULATOR->f_abs); - CHILD_UPDATED(0) - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(mstruct.isFunction() && eo.protected_function != mstruct.function() && mstruct.function() == CALCULATOR->f_abs && mstruct.size() == 1 && mstruct[0] == CHILD(0) && CHILD(0).representsScalar()) { - // sgn(x)*abs(x)=x - SET_CHILD_MAP(0) - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct == CHILD(0) && CHILD(0).representsReal(true)) { - // sgn(x)*x=abs(x) - setFunction(CALCULATOR->f_abs); - ERASE(1) - return 1; - } else if(mstruct.isPower() && mstruct[1].representsOdd() && mstruct[0] == CHILD(0) && CHILD(0).representsReal(true)) { - //sgn(x)*x^3=abs(x)^3 - mstruct[0].transform(STRUCT_FUNCTION); - mstruct[0].setFunction(CALCULATOR->f_abs); - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 1; - } - } else if(o_function == CALCULATOR->f_root && THIS_VALID_ROOT) { - if(CHILD(0) == mstruct && CHILD(0).representsReal(true) && CHILD(1).number().isOdd()) { - // root(x, 3)*x=abs(x)^(1/3)*x - CHILD(0).transform(STRUCT_FUNCTION); - CHILD(0).setFunction(CALCULATOR->f_abs); - CHILD(1).number().recip(); - m_type = STRUCT_POWER; - mstruct.transform(STRUCT_FUNCTION); - mstruct.setFunction(CALCULATOR->f_abs); - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } else if(mstruct.isPower() && mstruct[1].representsOdd() && CHILD(0) == mstruct[0] && CHILD(0).representsReal(true) && CHILD(1).number().isOdd()) { - // root(x, 3)*x^3=abs(x)^(1/3)*x^3 - CHILD(0).transform(STRUCT_FUNCTION); - CHILD(0).setFunction(CALCULATOR->f_abs); - CHILD(1).number().recip(); - m_type = STRUCT_POWER; - mstruct[0].transform(STRUCT_FUNCTION); - mstruct[0].setFunction(CALCULATOR->f_abs); - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } else if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_root && VALID_ROOT(mstruct) && CHILD(0) == mstruct[0] && CHILD(0).representsReal(true) && CHILD(1).number().isOdd() && mstruct[1].number().isOdd()) { - // root(x, y)*root(x, z)=abs(x)^(1/y)*abs(x)^(1/z) - CHILD(0).transform(STRUCT_FUNCTION); - CHILD(0).setFunction(CALCULATOR->f_abs); - CHILD(1).number().recip(); - m_type = STRUCT_POWER; - mstruct[0].transform(STRUCT_FUNCTION); - mstruct[0].setFunction(CALCULATOR->f_abs); - mstruct[1].number().recip(); - mstruct.setType(STRUCT_POWER); - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } else if(mstruct.isPower() && mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_abs && mstruct[0].size() == 1 && mstruct[0][0].equals(CHILD(0)) && mstruct[1].isNumber() && mstruct[1].number().isRational() && mstruct[1].number().isFraction() && mstruct[0].number().denominator() == CHILD(1).number() && CHILD(0).representsReal(true) && mstruct[1].number().numerator() == CHILD(1).number() - 1) { - // root(x, 3)*abs(x)^(2/3)=x - SET_CHILD_MAP(0) - return 1; - } - } else if((o_function == CALCULATOR->f_ln || o_function == CALCULATOR->f_Ei) && SIZE == 1 && mstruct.isZero()) { - if(CHILD(0).representsNonZero() || warn_about_assumed_not_value(CHILD(0), m_zero, eo)) { - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 3; - } - } else if(o_function == CALCULATOR->f_li && SIZE == 1 && mstruct.isZero()) { - if(representsNumber(true) || warn_about_assumed_not_value(CHILD(0), m_one, eo)) { - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 3; - } - } else if(eo.transform_trigonometric_functions && o_function == CALCULATOR->f_sinc && SIZE == 1 && CHILD(0) == mstruct) { - // sinc(x)*x=sin(x) - CHILD(0).calculateMultiply(CALCULATOR->getRadUnit(), eo); - CHILD_UPDATED(0) - setFunction(CALCULATOR->f_sin); - if(eo.calculate_functions) calculateFunctions(eo, false); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(eo.transform_trigonometric_functions && mstruct.isFunction() && mstruct.size() == 1 && eo.protected_function != mstruct.function()) { - if(o_function == CALCULATOR->f_tan && SIZE == 1) { - if(mstruct.function() == CALCULATOR->f_cos && mstruct[0] == CHILD(0)) { - // tan(x)*cos(x)=sin(x) - setFunction(CALCULATOR->f_sin); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(o_function == CALCULATOR->f_cos && SIZE == 1) { - if(mstruct.function() == CALCULATOR->f_tan && mstruct[0] == CHILD(0)) { - // tan(x)*cos(x)=sin(x) - setFunction(CALCULATOR->f_sin); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct.function() == CALCULATOR->f_sin && mstruct[0] == CHILD(0)) { - // cos(x)*sin(x)=sin(2x)/2 - setFunction(CALCULATOR->f_sin); - CHILD(0).calculateMultiply(nr_two, eo); - CHILD_UPDATED(0) - calculateDivide(nr_two, eo); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(o_function == CALCULATOR->f_sin && SIZE == 1) { - if(mstruct.function() == CALCULATOR->f_cos && mstruct[0] == CHILD(0)) { - // cos(x)*sin(x)=sin(2x)/2 - setFunction(CALCULATOR->f_sin); - CHILD(0).calculateMultiply(nr_two, eo); - CHILD_UPDATED(0) - calculateDivide(nr_two, eo); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(o_function == CALCULATOR->f_tanh && SIZE == 1) { - if(mstruct.function() == CALCULATOR->f_cosh && mstruct[0] == CHILD(0)) { - // tanh(x)*cosh(x)=sinh(x) - setFunction(CALCULATOR->f_sinh); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(o_function == CALCULATOR->f_sinh && SIZE == 1) { - if(mstruct.function() == CALCULATOR->f_cosh && mstruct[0] == CHILD(0)) { - // cosh(x)*sinh(x)=sinh(2x)/2 - setFunction(CALCULATOR->f_sinh); - CHILD(0).calculateMultiply(nr_two, eo); - CHILD_UPDATED(0) - calculateDivide(nr_two, eo); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(o_function == CALCULATOR->f_cosh && SIZE == 1) { - if(mstruct.function() == CALCULATOR->f_tanh && mstruct[0] == CHILD(0)) { - // tanh(x)*cosh(x)=sinh(x) - setFunction(CALCULATOR->f_sinh); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct.function() == CALCULATOR->f_sinh && mstruct[0] == CHILD(0)) { - // cosh(x)*sinh(x)=sinh(2x)/2 - setFunction(CALCULATOR->f_sinh); - CHILD(0).calculateMultiply(nr_two, eo); - CHILD_UPDATED(0) - calculateDivide(nr_two, eo); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - } - } - if(o_function == CALCULATOR->f_stripunits && SIZE == 1) { - if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_stripunits && mstruct.size() == 1) { - mstruct[0].ref(); - CHILD(0).multiply_nocopy(&mstruct[0]); - return 1; - } else if(mstruct.isVariable() && mstruct.variable()->isKnown() && CHILD(0).contains(mstruct, false) > 0) { - if(separate_unit_vars(mstruct, eo, false)) { - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } else if(mstruct.isPower() && mstruct[0].isVariable() && mstruct[0].variable()->isKnown() && CHILD(0).contains(mstruct[0], false) > 0) { - if(separate_unit_vars(mstruct[0], eo, false)) { - mstruct.calculateRaiseExponent(eo); - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } - } - } - default: { - switch(mstruct.type()) { - case STRUCT_VECTOR: {} - case STRUCT_ADDITION: {} - case STRUCT_MULTIPLICATION: {} - case STRUCT_POWER: { - return 0; - } - case STRUCT_COMPARISON: { - if(isComparison()) { - mstruct.ref(); - transform_nocopy(STRUCT_LOGICAL_AND, &mstruct); - return 1; - } - } - default: { - if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_stripunits && mstruct.size() == 1) { - if(m_type == STRUCT_VARIABLE && o_variable->isKnown() && mstruct[0].contains(*this, false) > 0) { - if(separate_unit_vars(*this, eo, false)) { - mstruct.ref(); - multiply_nocopy(&mstruct); - calculateMultiplyLast(eo); - return 1; - } - } - } - if(mstruct.isZero() && (!eo.keep_zero_units || containsType(STRUCT_UNIT, false, true, true) <= 0 || (isUnit() && unit() == CALCULATOR->getRadUnit()) || (isFunction() && representsNumber(false))) && !representsUndefined(true, true, !eo.assume_denominators_nonzero) && representsNonMatrix()) { - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 3; - } - if(isZero() && !mstruct.representsUndefined(true, true, !eo.assume_denominators_nonzero) && (!eo.keep_zero_units || mstruct.containsType(STRUCT_UNIT, false, true, true) <= 0 || (mstruct.isUnit() && mstruct.unit() == CALCULATOR->getRadUnit())) && mstruct.representsNonMatrix()) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - if(equals(mstruct)) { - if(mstruct.isUnit() && mstruct.prefix()) o_prefix = mstruct.prefix(); - raise_nocopy(new MathStructure(2, 1, 0)); - MERGE_APPROX_AND_PREC(mstruct) - calculateRaiseExponent(eo, mparent, index_this); - return 1; - } - break; - } - } - break; - } - } - return -1; -} - -bool test_if_numerator_not_too_large(Number &vb, Number &ve) { - if(!vb.isRational()) return false; - if(!mpz_fits_slong_p(mpq_numref(ve.internalRational()))) return false; - long int exp = labs(mpz_get_si(mpq_numref(ve.internalRational()))); - if(vb.isRational()) { - if((long long int) exp * mpz_sizeinbase(mpq_numref(vb.internalRational()), 10) <= 1000000LL && (long long int) exp * mpz_sizeinbase(mpq_denref(vb.internalRational()), 10) <= 1000000LL) return true; + return ret; } - return false; + return 0; } - -bool is_negation(const MathStructure &m1, const MathStructure &m2) { - if(m1.isAddition() && m2.isAddition() && m1.size() == m2.size()) { - for(size_t i = 0; i < m1.size(); i++) { - if(!is_negation(m1[i], m2[i])) return false; +int MathStructure::containsInterval(bool structural_only, bool check_variables, bool check_functions, int ignore_high_precision_interval, bool include_interval_function) const { + if(m_type == STRUCT_NUMBER && o_number.isInterval(false)) { + if(ignore_high_precision_interval != 0) { + if(o_number.precision(true) > (ignore_high_precision_interval < 0 ? (ignore_high_precision_interval == -1 ? PRECISION + 29 : PRECISION - ignore_high_precision_interval) : PRECISION + (10 * ignore_high_precision_interval))) return 0; } - return true; - } - if(m1.isNumber() && m2.isNumber()) { - return m1.number() == -m2.number(); + return 1; } - if(m1.isMultiplication() && m1.size() > 1) { - if(m1[0].isNumber()) { - if(m1[0].number().isMinusOne()) { - if(m1.size() == 2) return m1[1] == m2; - if(m2.isMultiplication() && m2.size() == m1.size() - 1) { - for(size_t i = 1; i < m1.size(); i++) { - if(!m1[i].equals(m2[i - 1], true, true)) return false; - } - return true; - } - return false; - } else { - if(m2.isMultiplication() && m2.size() == m1.size() && m2[0].isNumber()) { - for(size_t i = 1; i < m1.size(); i++) { - if(!m1[i].equals(m2[i], true, true)) return false; - } - return m1[0].number().equals(-m2[0].number(), true, true); - } - return false; + if(m_type == STRUCT_FUNCTION && (o_function->id() == FUNCTION_ID_INTERVAL || o_function->id() == FUNCTION_ID_UNCERTAINTY)) return include_interval_function; + if(structural_only) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).containsInterval(structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function)) return 1; + } + if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { + if(ignore_high_precision_interval == -1 && o_variable->isBuiltin()) { + return 0; + } + return contains_interval_var(((KnownVariable*) o_variable)->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); + } else if(m_type == STRUCT_FUNCTION && check_functions) { + if(function_value) { + return function_value->containsInterval(structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); } } - } - if(m2.isMultiplication() && m2.size() > 1) { - if(m2[0].isNumber()) { - if(m2[0].number().isMinusOne()) { - if(m2.size() == 2) return m2[1] == m1; - if(m1.isMultiplication() && m1.size() == m2.size() - 1) { - for(size_t i = 1; i < m2.size(); i++) { - if(!m2[i].equals(m1[i - 1], true, true)) return false; - } - return true; - } - return false; + } else { + int ret = 0; + if(m_type != STRUCT_FUNCTION) { + for(size_t i = 0; i < SIZE; i++) { + int retval = CHILD(i).containsInterval(structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); + if(retval == 1) return 1; + else if(retval < 0) ret = retval; } } - } - return false; -} - -int MathStructure::merge_power(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool) { - - if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { - // number^number - Number nr(o_number); - if(nr.raise(mstruct.number(), eo.approximation < APPROXIMATION_APPROXIMATE) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) { - // Exponentiation succeeded without inappropriate change in approximation status - if(o_number == nr) { - o_number = nr; - numberUpdated(); - return 2; + if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { + if(ignore_high_precision_interval == -1 && o_variable->isBuiltin()) { + return 0; } - o_number = nr; - numberUpdated(); - return 1; + return contains_interval_var(((KnownVariable*) o_variable)->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); + } else if(m_type == STRUCT_FUNCTION && check_functions) { + if(function_value) { + return function_value->containsInterval(structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); + } + return -1; + } else if(isAborted()) { + return -1; } - if(!o_number.isMinusOne() && !o_number.isOne() && mstruct.number().isRational() && !mstruct.isInteger()) { - if(o_number.isNegative()) { - MathStructure mtest(*this); - if(mtest.number().negate() && mtest.calculateRaise(mstruct, eo)) { - set(mtest); - MathStructure *mmul = new MathStructure(-1, 1, 0); - mmul->calculateRaise(mstruct, eo); - multiply_nocopy(mmul); - calculateMultiplyLast(eo); - return 1; - } - } else { - Number exp_num(mstruct.number().numerator()); - if(!exp_num.isOne() && !exp_num.isMinusOne() && o_number.isPositive() && test_if_numerator_not_too_large(o_number, exp_num)) { - // Try raise by exponent numerator if not very large - nr = o_number; - if(nr.raise(exp_num, eo.approximation < APPROXIMATION_APPROXIMATE) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) { - o_number = nr; - numberUpdated(); - nr.set(mstruct.number().denominator()); - nr.recip(); - calculateRaise(nr, eo, mparent, index_this); - return 1; - } - } - if(o_number.isPositive()) { - Number nr_root(mstruct.number().denominator()); - if(eo.split_squares && o_number.isInteger() && nr_root.isLessThanOrEqualTo(LARGEST_RAISED_PRIME_EXPONENT)) { - int root = nr_root.intValue(); - nr.set(1, 1, 0); - bool b = true, overflow; - long int val; - while(b) { - if(CALCULATOR->aborted()) break; - b = false; - overflow = false; - val = o_number.lintValue(&overflow); - if(overflow) { - mpz_srcptr cval = mpq_numref(o_number.internalRational()); - for(size_t i = 0; root == 2 ? (i < NR_OF_SQUARE_PRIMES) : (RAISED_PRIMES[root - 3][i] != 0); i++) { - if(CALCULATOR->aborted()) break; - if(mpz_divisible_ui_p(cval, (unsigned long int) (root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]))) { - nr *= PRIMES[i]; - o_number /= (root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]); - b = true; - break; - } - } - } else { - for(size_t i = 0; root == 2 ? (i < NR_OF_SQUARE_PRIMES) : (RAISED_PRIMES[root - 3][i] != 0); i++) { - if(CALCULATOR->aborted()) break; - if((root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]) > val) { - break; - } else if(val % (root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]) == 0) { - nr *= PRIMES[i]; - o_number /= (root == 2 ? SQUARE_PRIMES[i] : RAISED_PRIMES[root - 3][i]); - b = true; - break; - } - } - } - } - if(!nr.isOne()) { - transform(STRUCT_MULTIPLICATION); - CHILD(0).calculateRaise(mstruct, eo, this, 0); - PREPEND(nr); - if(!mstruct.number().numeratorIsOne()) { - CHILD(0).calculateRaise(mstruct.number().numerator(), eo, this, 0); - } - calculateMultiplyIndex(0, eo, true, mparent, index_this); - return 1; - } - } - if(eo.split_squares && nr_root != 2) { - // partial roots, e.g. 9^(1/4)=3^(1/2) - if(nr_root.isEven()) { - Number nr(o_number); - if(nr.sqrt() && !nr.isApproximate()) { - o_number = nr; - mstruct.number().multiply(2); - mstruct.ref(); - raise_nocopy(&mstruct); - calculateRaiseExponent(eo, mparent, index_this); - return 1; - } - } - for(size_t i = 1; i < NR_OF_PRIMES; i++) { - if(nr_root.isLessThanOrEqualTo(PRIMES[i])) break; - if(nr_root.isIntegerDivisible(PRIMES[i])) { - Number nr(o_number); - if(nr.root(Number(PRIMES[i], 1)) && !nr.isApproximate()) { - o_number = nr; - mstruct.number().multiply(PRIMES[i]); - mstruct.ref(); - raise_nocopy(&mstruct); - calculateRaiseExponent(eo, mparent, index_this); - return 1; - } - } - } - } - } - } - } - if(o_number.isMinusOne() && mstruct.number().isRational()) { - if(mstruct.number().isInteger()) { - if(mstruct.number().isEven()) set(m_one, true); - else set(m_minus_one, true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else { - Number nr_floor(mstruct.number()); - nr_floor.floor(); - if(mstruct.number().denominatorIsTwo()) { - if(nr_floor.isEven()) set(nr_one_i, true); - else set(nr_minus_i, true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else { - mstruct.number() -= nr_floor; - mstruct.numberUpdated(); - if(mstruct.number().denominator() == 3) { - set(3, 1, 0, true); - calculateRaise(nr_half, eo); - if(nr_floor.isEven()) calculateMultiply(nr_one_i, eo); - else calculateMultiply(nr_minus_i, eo); - calculateMultiply(nr_half, eo); - if(nr_floor.isEven() == mstruct.number().numeratorIsOne()) calculateAdd(nr_half, eo); - else calculateAdd(nr_minus_half, eo); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct.number().denominator() == 4) { - if(nr_floor.isEven() == mstruct.number().numeratorIsOne()) set(1, 1, 0, true); - else set(-1, 1, 0, true); - if(nr_floor.isEven()) calculateAdd(nr_one_i, eo); - else calculateAdd(nr_minus_i, eo); - multiply(nr_two); - LAST.calculateRaise(nr_minus_half, eo); - calculateMultiplyLast(eo); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(!nr_floor.isZero()) { - mstruct.ref(); - raise_nocopy(&mstruct); - calculateRaiseExponent(eo); - if(nr_floor.isOdd()) calculateNegate(eo); - return 1; - } - } - } - } - if(o_number.isRational() && !o_number.isInteger() && !o_number.numeratorIsOne() && mstruct.number().isRational()) { - Number num(o_number.numerator()); - Number den(o_number.denominator()); - set(num, true); - calculateRaise(mstruct, eo); - multiply(den); - LAST.calculateRaise(mstruct, eo); - LAST.calculateInverse(eo); - calculateMultiplyLast(eo); - return 1; - } - // If base numerator is larger than denominator, invert base and negate exponent - if(o_number.isRational() && !o_number.isInteger() && !o_number.isZero() && ((o_number.isNegative() && o_number.isGreaterThan(nr_minus_one) && mstruct.number().isInteger()) || (o_number.isPositive() && o_number.isLessThan(nr_one)))) { - mstruct.number().negate(); - o_number.recip(); - return 0; - } - return -1; + return ret; } - if(mstruct.isOne()) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } else if(isOne() && mstruct.representsNumber()) { - MERGE_APPROX_AND_PREC(mstruct) + return 0; +} +int MathStructure::containsInfinity(bool structural_only, bool check_variables, bool check_functions) const { + if(m_type == STRUCT_NUMBER && o_number.includesInfinity(false)) { return 1; } - if(m_type == STRUCT_NUMBER && o_number.isInfinite(false)) { - if(mstruct.representsNegative(false)) { - o_number.clear(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct.representsNonZero(false) && mstruct.representsPositive(false)) { - if(o_number.isMinusInfinity()) { - if(mstruct.representsEven(false)) { - o_number.setPlusInfinity(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct.representsOdd(false)) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(o_number.isPlusInfinity()) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; + if(structural_only) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).containsInfinity(structural_only, check_variables, check_functions)) return 1; + } + if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { + return ((KnownVariable*) o_variable)->get().containsInfinity(structural_only, check_variables, check_functions); + } else if(m_type == STRUCT_FUNCTION && check_functions) { + if(function_value) { + return function_value->containsInfinity(structural_only, check_variables, check_functions); } } - CALCULATOR->beginTemporaryEnableIntervalArithmetic(); - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mtest(mstruct); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - if(eo2.interval_calculation == INTERVAL_CALCULATION_NONE) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; - mtest.calculateFunctions(eo2); - mtest.calculatesub(eo2, eo2); - CALCULATOR->endTemporaryStopMessages(); - CALCULATOR->endTemporaryEnableIntervalArithmetic(); - if(mtest.representsNegative(false)) { - o_number.clear(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mtest.representsNonZero(false) && mtest.representsPositive(false)) { - if(o_number.isMinusInfinity()) { - if(mstruct.representsEven(false)) { - o_number.setPlusInfinity(); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct.representsOdd(false)) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(o_number.isPlusInfinity()) { - MERGE_APPROX_AND_PREC(mstruct) - return 1; + } else { + int ret = 0; + if(m_type != STRUCT_FUNCTION) { + for(size_t i = 0; i < SIZE; i++) { + int retval = CHILD(i).containsInfinity(structural_only, check_variables, check_functions); + if(retval == 1) return 1; + else if(retval < 0) ret = retval; } } - } else if(mstruct.isNumber() && mstruct.number().isInfinite(false)) { - CALCULATOR->beginTemporaryEnableIntervalArithmetic(); - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mtest(*this); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - if(eo2.interval_calculation == INTERVAL_CALCULATION_NONE) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; - mtest.calculateFunctions(eo2); - mtest.calculatesub(eo2, eo2); - CALCULATOR->endTemporaryStopMessages(); - CALCULATOR->endTemporaryEnableIntervalArithmetic(); - if(mtest.isNumber()) { - if(mtest.merge_power(mstruct, eo) > 0 && mtest.isNumber()) { - if(mtest.number().isPlusInfinity()) { - set(nr_plus_inf, true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mtest.number().isMinusInfinity()) { - set(nr_minus_inf, true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mtest.number().isZero()) { - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } + if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { + return ((KnownVariable*) o_variable)->get().containsInfinity(structural_only, check_variables, check_functions); + } else if(m_type == STRUCT_FUNCTION && check_functions) { + if(function_value) { + return function_value->containsInfinity(structural_only, check_variables, check_functions); } + return -1; + } else if(isAborted()) { + return -1; } + return ret; } + return 0; +} - if(representsUndefined() || mstruct.representsUndefined()) return -1; - if(isZero() && mstruct.representsPositive()) { - return 1; - } - if(mstruct.isZero() && !representsUndefined(true, true)) { - set(m_one); - MERGE_APPROX_AND_PREC(mstruct) - return 1; +int MathStructure::containsRepresentativeOf(const MathStructure &mstruct, bool check_variables, bool check_functions) const { + if(equals(mstruct)) return 1; + int ret = 0; + if(m_type != STRUCT_FUNCTION) { + for(size_t i = 0; i < SIZE; i++) { + int retval = CHILD(i).containsRepresentativeOf(mstruct, check_variables, check_functions); + if(retval == 1) return 1; + else if(retval < 0) ret = retval; + } } - - switch(m_type) { - case STRUCT_VECTOR: { - if(mstruct.isNumber() && mstruct.number().isInteger()) { - if(isMatrix()) { - if(matrixIsSquare()) { - Number nr(mstruct.number()); - bool b_neg = false; - if(nr.isNegative()) { - nr.setNegative(false); - b_neg = true; - } - if(!nr.isOne()) { - MathStructure msave(*this); - nr--; - while(nr.isPositive()) { - if(CALCULATOR->aborted()) { - set(msave); - return -1; - } - calculateMultiply(msave, eo); - nr--; - } - } - if(b_neg) { - if(!invertMatrix(eo)) { - if(mstruct.number().isMinusOne()) return -1; - raise(nr_minus_one); - } - } - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - return -1; - } else { - if(mstruct.number().isMinusOne()) { - return -1; - } - Number nr(mstruct.number()); - if(nr.isNegative()) { - nr++; - } else { - nr--; - } - MathStructure msave(*this); - calculateMultiply(msave, eo); - calculateRaise(nr, eo); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - - } - goto default_power_merge; + if(m_type == STRUCT_VARIABLE && check_variables) { + if(o_variable->isKnown()) return ((KnownVariable*) o_variable)->get().containsRepresentativeOf(mstruct, check_variables, check_functions); + else return ((UnknownVariable*) o_variable)->interval().containsRepresentativeOf(mstruct, check_variables, check_functions); + } else if(m_type == STRUCT_FUNCTION && check_functions) { + if(function_value) { + return function_value->containsRepresentativeOf(mstruct, check_variables, check_functions); } - case STRUCT_ADDITION: { - if(mstruct.isNumber() && mstruct.number().isInteger() && containsType(STRUCT_DATETIME, false, true, false) <= 0) { - if(eo.reduce_divisions && mstruct.number().isMinusOne()) { - int bnum = -1, bden = -1; - int inegs = 0; - bool b_break = false; - for(size_t i = 0; i < SIZE && !b_break; i++) { - switch(CHILD(i).type()) { - case STRUCT_NUMBER: { - if(!CHILD(i).number().isRational() || CHILD(i).number().numeratorIsGreaterThan(1000000L) || CHILD(i).number().numeratorIsLessThan(-1000000L) || CHILD(i).number().denominatorIsGreaterThan(1000L)) { - bnum = 0; bden = 0; inegs = 0; b_break = true; - } - if(bden != 0 && !CHILD(i).number().isInteger()) bden = 1; - if(bnum != 0 && !CHILD(i).isZero()) { - if(CHILD(i).number().numeratorIsOne() || CHILD(i).number().numeratorIsMinusOne()) bnum = 0; - else bnum = 1; - } - if(CHILD(i).number().isNegative()) { - inegs++; - if(i == 0) inegs++; - } else if(!CHILD(i).number().isZero()) inegs--; - break; - } - case STRUCT_MULTIPLICATION: { - if(CHILD(i).size() > 0 && CHILD(i)[0].isNumber()) { - if(!CHILD(i)[0].number().isRational() || CHILD(i)[0].number().numeratorIsGreaterThan(1000000L) || CHILD(i)[0].number().numeratorIsLessThan(-1000000L) || CHILD(i)[0].number().denominatorIsGreaterThan(1000L)) { - bnum = 0; bden = 0; inegs = 0; b_break = true; - } - if(bden != 0 && !CHILD(i)[0].number().isInteger()) bden = 1; - if(bnum != 0 && !CHILD(i)[0].isZero()) { - if(CHILD(i)[0].number().numeratorIsOne() || CHILD(i)[0].number().numeratorIsMinusOne()) bnum = 0; - else bnum = 1; - } - if(CHILD(i)[0].number().isNegative()) { - inegs++; - if(i == 0) inegs++; - } else if(!CHILD(i)[0].number().isZero()) inegs--; - break; - } - } - default: { - bnum = 0; - inegs--; - break; - } - } - } - if(bden < 0) bden = 0; - if(bnum < 0) bnum = 0; - if(bnum || bden) { - Number nr_num, nr_den(1, 1, 0); - for(size_t i = 0; i < SIZE && !nr_den.isZero(); i++) { - switch(CHILD(i).type()) { - case STRUCT_NUMBER: { - if(CHILD(i).number().isInteger()) { - if(bnum && !nr_num.isOne() && !CHILD(i).number().isZero()) { - if(nr_num.isZero()) nr_num = CHILD(i).number(); - else nr_num.gcd(CHILD(i).number()); - } - } else { - if(bnum && !nr_num.isOne() && !CHILD(i).number().isZero()) { - if(nr_num.isZero()) nr_num = CHILD(i).number().numerator(); - else nr_num.gcd(CHILD(i).number().numerator()); - } - if(bden) { - nr_den.lcm(CHILD(i).number().denominator()); - if(nr_den.isGreaterThan(1000000L)) nr_den.clear(); - } - } - break; - } - case STRUCT_MULTIPLICATION: { - if(CHILD(i).size() > 0 && CHILD(i)[0].isNumber()) { - if(CHILD(i)[0].number().isInteger()) { - if(bnum && !nr_num.isOne() && !CHILD(i)[0].number().isZero()) { - if(nr_num.isZero()) nr_num = CHILD(i)[0].number(); - else nr_num.gcd(CHILD(i)[0].number()); - } - } else { - if(bnum && !nr_num.isOne() && !CHILD(i)[0].number().isZero()) { - if(nr_num.isZero()) nr_num = CHILD(i)[0].number().numerator(); - else nr_num.gcd(CHILD(i)[0].number().numerator()); - } - if(bden) { - nr_den.lcm(CHILD(i)[0].number().denominator()); - if(nr_den.isGreaterThan(1000000L)) nr_den.clear(); - } - } - break; - } - } - default: { - break; - } - } - } - if(!nr_den.isZero() && (!nr_den.isOne() || !nr_num.isOne())) { - Number nr(nr_den); - nr.divide(nr_num); - nr.setNegative(inegs > 0); - for(size_t i = 0; i < SIZE; i++) { - switch(CHILD(i).type()) { - case STRUCT_NUMBER: { - CHILD(i).number() *= nr; - break; - } - case STRUCT_MULTIPLICATION: { - if(CHILD(i).size() > 0 && CHILD(i)[0].isNumber()) { - CHILD(i)[0].number() *= nr; - CHILD(i).calculateMultiplyIndex(0, eo, true, this, i); - break; - } - } - default: { - CHILD(i).calculateMultiply(nr, eo); - } - } - } - calculatesub(eo, eo, false); - mstruct.ref(); - raise_nocopy(&mstruct); - calculateRaiseExponent(eo); - calculateMultiply(nr, eo, mparent, index_this); - return 1; - } - } - if(inegs > 0) { - for(size_t i = 0; i < SIZE; i++) { - switch(CHILD(i).type()) { - case STRUCT_NUMBER: {CHILD(i).number().negate(); break;} - case STRUCT_MULTIPLICATION: { - if(CHILD(i).size() > 0 && CHILD(i)[0].isNumber()) { - CHILD(i)[0].number().negate(); - CHILD(i).calculateMultiplyIndex(0, eo, true, this, i); - break; - } - } - default: { - CHILD(i).calculateNegate(eo); - } - } - } - mstruct.ref(); - raise_nocopy(&mstruct); - negate(); - return 1; - } - } else if(eo.expand != 0 && !mstruct.number().isZero() && (eo.expand > -2 || !containsInterval())) { - bool b = true; - bool neg = mstruct.number().isNegative(); - Number m(mstruct.number()); - m.setNegative(false); - if(SIZE > 1) { - if(eo.expand == -1) { - switch(SIZE) { - case 4: {if(m.isGreaterThan(3)) {b = false;} break;} - case 3: {if(m.isGreaterThan(4)) {b = false;} break;} - case 2: {if(m.isGreaterThan(10)) {b = false;} break;} - default: { - if(SIZE > 8 || m.isGreaterThan(2)) b = false; - } - } - } else { - b = false; - long int i_pow = m.lintValue(&b); - if(b || i_pow > 300) { - b = false; - } else { - Number num_terms; - if(num_terms.binomial(i_pow + (long int) SIZE - 1, (long int) SIZE - 1)) { - size_t tc = countTotalChildren() / SIZE; - if(tc <= 4) tc = 0; - else tc -= 4; - b = num_terms.isLessThanOrEqualTo(tc > 1 ? 300 / tc : 300); - } - } - } - } - if(b) { - if(!representsNonMatrix()) { - MathStructure mthis(*this); - while(!m.isOne()) { - if(CALCULATOR->aborted()) { - set(mthis); - goto default_power_merge; - } - calculateMultiply(mthis, eo); - m--; - } - } else { - MathStructure mstruct1(CHILD(0)); - MathStructure mstruct2(CHILD(1)); - for(size_t i = 2; i < SIZE; i++) { - if(CALCULATOR->aborted()) goto default_power_merge; - mstruct2.add(CHILD(i), true); - } - Number k(1); - Number p1(m); - Number p2(1); - p1--; - Number bn; - MathStructure msave(*this); - CLEAR - APPEND(mstruct1); - CHILD(0).calculateRaise(m, eo); - while(k.isLessThan(m)) { - if(CALCULATOR->aborted() || !bn.binomial(m, k)) { - set(msave); - goto default_power_merge; - } - APPEND_NEW(bn); - LAST.multiply(mstruct1); - if(!p1.isOne()) { - LAST[1].raise_nocopy(new MathStructure(p1)); - LAST[1].calculateRaiseExponent(eo); - } - LAST.multiply(mstruct2, true); - if(!p2.isOne()) { - LAST[2].raise_nocopy(new MathStructure(p2)); - LAST[2].calculateRaiseExponent(eo); - } - LAST.calculatesub(eo, eo, false); - k++; - p1--; - p2++; - } - APPEND(mstruct2); - LAST.calculateRaise(m, eo); - calculatesub(eo, eo, false); - } - if(neg) calculateInverse(eo); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } + if(!mstruct.isNumber() && (o_function->isBuiltin() || representsNumber())) { + for(size_t i = 0; i < SIZE; i++) { + int retval = CHILD(i).containsRepresentativeOf(mstruct, check_variables, check_functions); + if(retval != 0) return -1; } - goto default_power_merge; + return 0; } - case STRUCT_MULTIPLICATION: { - if(mstruct.representsInteger()) { - // (xy)^a=x^a*y^a - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).calculateRaise(mstruct, eo); - } - MERGE_APPROX_AND_PREC(mstruct) - calculatesub(eo, eo, false, mparent, index_this); - return 1; - } else if(!mstruct.isInfinite()) { - // (-5xy)^z=5^z*x^z*(-y)^z && x >= 0 && y<0 - MathStructure mnew; - mnew.setType(STRUCT_MULTIPLICATION); - for(size_t i = 0; i < SIZE;) { - if(CHILD(i).representsNonNegative(true)) { - CHILD(i).ref(); - mnew.addChild_nocopy(&CHILD(i)); - ERASE(i); - } else if(CHILD(i).isNumber() && CHILD(i).number().isNegative() && !CHILD(i).number().isMinusOne()) { - // (-5)^z=5^z*(-1)^z - CHILD(i).number().negate(); - mnew.addChild(CHILD(i)); - CHILD(i).number().set(-1, 1, 0); - i++; - } else { - i++; - } - } - if(mnew.size() > 0) { - if(SIZE > 0) { - if(SIZE == 1) SET_CHILD_MAP(0) - mnew.addChild(*this); - } - set_nocopy(mnew, true); - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).calculateRaise(mstruct, eo); - } - MERGE_APPROX_AND_PREC(mstruct) - calculatesub(eo, eo, false, mparent, index_this); - return 1; - } - } - goto default_power_merge; + return -1; + } else if(isAborted()) { + return -1; + } + return ret; +} + +int MathStructure::containsType(StructureType mtype, bool structural_only, bool check_variables, bool check_functions) const { + if(m_type == mtype) return 1; + if(structural_only) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).containsType(mtype, true, check_variables, check_functions)) return 1; } - case STRUCT_POWER: { - if((eo.allow_complex && CHILD(1).representsFraction()) || (mstruct.representsInteger() && (eo.allow_complex || CHILD(0).representsInteger())) || representsNonNegative(true)) { - if((((!eo.assume_denominators_nonzero || eo.warn_about_denominators_assumed_nonzero) && !CHILD(0).representsNonZero(true)) || CHILD(0).isZero()) && CHILD(1).representsNegative(true)) { - if(!eo.assume_denominators_nonzero || CHILD(0).isZero() || !warn_about_denominators_assumed_nonzero(CHILD(0), eo)) break; - } - if(!CHILD(1).representsNonInteger() && !mstruct.representsInteger()) { - if(CHILD(1).representsEven() && CHILD(0).representsReal(true)) { - if(CHILD(0).representsNegative(true)) { - CHILD(0).calculateNegate(eo); - } else if(!CHILD(0).representsNonNegative(true)) { - MathStructure mstruct_base(CHILD(0)); - CHILD(0).set(CALCULATOR->f_abs, &mstruct_base, NULL); - } - } else if(!CHILD(1).representsOdd() && !CHILD(0).representsNonNegative(true)) { - goto default_power_merge; - } - } - mstruct.ref(); - MERGE_APPROX_AND_PREC(mstruct) - CHILD(1).multiply_nocopy(&mstruct, true); - CHILD(1).calculateMultiplyLast(eo, true, this, 1); - calculateRaiseExponent(eo, mparent, index_this); - return 1; - } - if(mstruct.isNumber() && CHILD(0).isVariable() && CHILD(0).variable() == CALCULATOR->v_e && CHILD(1).isNumber() && CHILD(1).number().hasImaginaryPart() && !CHILD(1).number().hasRealPart() && mstruct.number().isReal()) { - CALCULATOR->beginTemporaryEnableIntervalArithmetic(); - CALCULATOR->beginTemporaryStopMessages(); - Number nr(*CHILD(1).number().internalImaginary()); - nr.add(CALCULATOR->v_pi->get().number()); - nr.divide(CALCULATOR->v_pi->get().number() * 2); - Number nr_u(nr.upperEndPoint()); - nr = nr.lowerEndPoint(); - CALCULATOR->endTemporaryEnableIntervalArithmetic(); - nr_u.floor(); - nr.floor(); - if(!CALCULATOR->endTemporaryStopMessages() && nr == nr_u) { - nr.setApproximate(false); - nr *= 2; - nr.negate(); - nr *= nr_one_i; - if(!nr.isZero()) { - CHILD(1) += nr; - CHILD(1).last() *= CALCULATOR->v_pi; - } - mstruct.ref(); - CHILD(1).multiply_nocopy(&mstruct, true); - CHILD(1).calculateMultiplyLast(eo, true, this, 1); - calculateRaiseExponent(eo, mparent, index_this); - return true; - } + if(check_variables && m_type == STRUCT_VARIABLE && o_variable->isKnown()) { + return ((KnownVariable*) o_variable)->get().containsType(mtype, false, check_variables, check_functions); + } else if(check_functions && m_type == STRUCT_FUNCTION) { + if(function_value) { + return function_value->containsType(mtype, false, check_variables, check_functions); } - goto default_power_merge; } - case STRUCT_VARIABLE: { - if(o_variable == CALCULATOR->v_e) { - if(mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].isNumber()) { - if(mstruct[1].isVariable() && mstruct[1].variable() == CALCULATOR->v_pi) { - if(mstruct[0].number().isI() || mstruct[0].number().isMinusI()) { - //e^(i*pi)=-1 - set(m_minus_one, true); - return 1; - } else if(mstruct[0].number().hasImaginaryPart() && !mstruct[0].number().hasRealPart() && mstruct[0].number().internalImaginary()->isRational()) { - // e^(a*i*pi)=(-1)^(a) - set(-1, 1, 0, true); - calculateRaise(*mstruct[0].number().internalImaginary(), eo); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } else if(mstruct[0].number().isI() && mstruct[1].isFunction() && mstruct[1].function() == CALCULATOR->f_atan && mstruct[1].size() == 1 && !mstruct[1][0].containsUnknowns() && ((eo.expand != 0 && eo.expand > -2) || !mstruct[1][0].containsInterval(true, false, false, eo.expand == -2 ? 1 : 0))) { - set(mstruct[1][0], true); - calculateRaise(nr_two, eo); - calculateAdd(m_one, eo); - calculateRaise(nr_half, eo); - calculateInverse(eo); - multiply(mstruct[1][0]); - LAST.calculateMultiply(nr_one_i, eo); - LAST.calculateAdd(m_one, eo); - calculateMultiplyLast(eo); - MERGE_APPROX_AND_PREC(mstruct) - return true; - } - } else if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_ln && mstruct.size() == 1) { - if(mstruct[0].representsNumber() && (eo.allow_infinite || mstruct[0].representsNonZero())) { - // e^ln(x)=x; x!=0 - set_nocopy(mstruct[0], true); - return 1; - } - } + return 0; + } else { + int ret = 0; + if(m_type != STRUCT_FUNCTION) { + for(size_t i = 0; i < SIZE; i++) { + int retval = CHILD(i).containsType(mtype, false, check_variables, check_functions); + if(retval == 1) return 1; + else if(retval < 0) ret = retval; } - goto default_power_merge; } - case STRUCT_FUNCTION: { - if(eo.protected_function != o_function) { - if(o_function == CALCULATOR->f_abs && SIZE == 1) { - if(mstruct.representsEven() && CHILD(0).representsReal(true)) { - // abs(x)^2=x^2 - SET_CHILD_MAP(0); - mstruct.ref(); - raise_nocopy(&mstruct); - calculateRaiseExponent(eo); - return 1; - } - } else if(o_function == CALCULATOR->f_signum && CHILD(0).representsReal(true) && SIZE == 2 && ((CHILD(1).isZero() && mstruct.representsPositive()) || CHILD(1).isOne())) { - if(mstruct.representsOdd()) { - // sgn(x)^3=sgn(x) - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct.representsEven()) { - if(CHILD(1).isOne() && CHILD(0).representsReal(true)) { - SET_CHILD_MAP(0) - return 1; - } else { - // sgn(x)^2=sgn(abs(x)) - CHILD(0).transform(CALCULATOR->f_abs); - CHILD_UPDATED(0) - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - } else if(o_function == CALCULATOR->f_root && THIS_VALID_ROOT) { - if(mstruct.representsEven() && CHILD(0).representsReal(true) && CHILD(1).number().isOdd()) { - // root(x, 3)^2=abs(x)^(3/2) - CHILD(0).transform(STRUCT_FUNCTION); - CHILD(0).setFunction(CALCULATOR->f_abs); - CHILD(1).number().recip(); - m_type = STRUCT_POWER; - mstruct.ref(); - raise_nocopy(&mstruct); - calculateRaiseExponent(eo); - return 1; - } else if(mstruct.isNumber() && mstruct.number().isInteger() && !mstruct.number().isMinusOne()) { - if(mstruct == CHILD(1)) { - // root(x, a)^a=x - SET_CHILD_MAP(0) - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(mstruct.number().isIntegerDivisible(CHILD(1).number())) { - // root(x, a)^(2a)=x^2 - mstruct.calculateDivide(CHILD(1).number(), eo); - mstruct.ref(); - SET_CHILD_MAP(0) - raise_nocopy(&mstruct); - return 1; - } else if(CHILD(1).number().isIntegerDivisible(mstruct.number())) { - // root(x, 3a)^(a)=root(x, 3) - Number nr(CHILD(1).number()); - if(nr.divide(mstruct.number())) { - CHILD(1) = nr; - CHILD_UPDATED(1) - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - } - } - } - if(o_function == CALCULATOR->f_stripunits && SIZE == 1 && mstruct.containsType(STRUCT_UNIT, false, true, true) == 0) { - mstruct.ref(); - CHILD(0).raise_nocopy(&mstruct); - return 1; + if(check_variables && m_type == STRUCT_VARIABLE) { + if(o_variable->isKnown()) return ((KnownVariable*) o_variable)->get().containsType(mtype, false, check_variables, check_functions); + else if(!((UnknownVariable*) o_variable)->interval().isUndefined()) return ((UnknownVariable*) o_variable)->interval().containsType(mtype, false, check_variables, check_functions); + else if(mtype == STRUCT_UNIT) return -1; + } else if(check_functions && m_type == STRUCT_FUNCTION) { + if(function_value) { + return function_value->containsType(mtype, false, check_variables, check_functions); } - goto default_power_merge; - } - default: { - default_power_merge: - - if(mstruct.isAddition()) { - bool b = representsNonNegative(true); - if(!b) { - b = true; - bool bneg = representsNegative(true); - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct[i].representsInteger() && (!bneg || !eo.allow_complex || !mstruct[i].isNumber() || !mstruct[i].number().isRational() || !mstruct[i].number().denominatorIsEven())) { - b = false; - break; - } - } - } - if(b) { - MathStructure msave(*this); - clear(true); - m_type = STRUCT_MULTIPLICATION; - MERGE_APPROX_AND_PREC(mstruct) - for(size_t i = 0; i < mstruct.size(); i++) { - APPEND(msave); - mstruct[i].ref(); - LAST.raise_nocopy(&mstruct[i]); - LAST.calculateRaiseExponent(eo); - calculateMultiplyLast(eo, false); - } - if(SIZE == 1) { - setToChild(1, false, mparent, index_this + 1); - } else if(SIZE == 0) { - clear(true); - } else { - evalSort(); - } - return 1; - } - } else if(mstruct.isMultiplication() && mstruct.size() > 1) { - bool b = representsNonNegative(true); - if(!b) { - b = true; - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct[i].representsInteger()) { - b = false; - break; - } - } - } - if(b) { - MathStructure mthis(*this); - for(size_t i = 0; i < mstruct.size(); i++) { - if(i == 0) mthis.raise(mstruct[i]); - if(!mstruct[i].representsReal(true) || (isZero() && !mstruct[i].representsPositive(true))) continue; - if(i > 0) mthis[1] = mstruct[i]; - EvaluationOptions eo2 = eo; - eo2.split_squares = false; - // avoid abs(x)^(2y) loop - if(mthis.calculateRaiseExponent(eo2) && (!mthis.isPower() || ((!isFunction() || o_function != CALCULATOR->f_abs || SIZE != 1 || !CHILD(0).equals(mthis[0], true, true)) && (!is_negation(mthis[0], *this))))) { - set(mthis); - if(mstruct.size() == 2) { - if(i == 0) { - mstruct[1].ref(); - raise_nocopy(&mstruct[1]); - } else { - mstruct[0].ref(); - raise_nocopy(&mstruct[0]); - } - } else { - mstruct.ref(); - raise_nocopy(&mstruct); - CHILD(1).delChild(i + 1); - } - calculateRaiseExponent(eo); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - } - } else if(mstruct.isNumber() && mstruct.number().isRational() && !mstruct.number().isInteger() && !mstruct.number().numeratorIsOne() && !mstruct.number().numeratorIsMinusOne()) { - if(representsNonNegative(true) && (m_type != STRUCT_FUNCTION || o_function != CALCULATOR->f_abs)) { - if(isMultiplication() && SIZE == 2 && CHILD(0).isMinusOne() && mstruct.number().numeratorIsEven()) { - bool b; - if(mstruct.number().isNegative()) { - MathStructure mtest(CHILD(1)); - b = mtest.calculateRaise(-mstruct.number().numerator(), eo); - if(b && mtest.isPower() && mtest[1] == -mstruct.number().numerator()) b = false; - if(!b) break; - set(mtest, true); - raise(m_minus_one); - CHILD(1).number() /= mstruct.number().denominator(); - } else { - MathStructure mtest(CHILD(1)); - b = mtest.calculateRaise(mstruct.number().numerator(), eo); - if(b && mtest.isPower() && mtest[1] == mstruct.number().numerator()) b = false; - if(!b) break; - set(mtest, true); - raise(m_one); - CHILD(1).number() /= mstruct.number().denominator(); - } - if(b) calculateRaiseExponent(eo); - return 1; - } - bool b; - if(mstruct.number().isNegative()) { - b = calculateRaise(-mstruct.number().numerator(), eo); - if(!b) { - setToChild(1); - break; - } - raise(m_minus_one); - CHILD(1).number() /= mstruct.number().denominator(); - } else { - b = calculateRaise(mstruct.number().numerator(), eo); - if(!b) { - setToChild(1); - break; - } - raise(m_one); - CHILD(1).number() /= mstruct.number().denominator(); - } - if(b) calculateRaiseExponent(eo); - return 1; + if(mtype == STRUCT_UNIT) { + if(o_function->id() == FUNCTION_ID_STRIP_UNITS) return 0; + if(o_function->subtype() == SUBTYPE_USER_FUNCTION || o_function->id() == FUNCTION_ID_REGISTER || o_function->id() == FUNCTION_ID_STACK || o_function->id() == FUNCTION_ID_LOAD) return -1; + // (eo.parse_options.angle_unit == ANGLE_UNIT_NONE && (o_function->id() == FUNCTION_ID_ASIN || o_function->id() == FUNCTION_ID_ACOS || o_function->id() == FUNCTION_ID_ATAN || o_function->id() == FUNCTION_ID_RADIANS_TO_DEFAULT_ANGLE_UNIT)) + if(o_function->id() == FUNCTION_ID_LOG || o_function->id() == FUNCTION_ID_LOGN || o_function->id() == FUNCTION_ID_ARG || o_function->id() == FUNCTION_ID_GAMMA || o_function->id() == FUNCTION_ID_BETA || o_function->id() == FUNCTION_ID_FACTORIAL || o_function->id() == FUNCTION_ID_BESSELJ || o_function->id() == FUNCTION_ID_BESSELY || o_function->id() == FUNCTION_ID_ERF || o_function->id() == FUNCTION_ID_ERFI || o_function->id() == FUNCTION_ID_ERFC || o_function->id() == FUNCTION_ID_LOGINT || o_function->id() == FUNCTION_ID_POLYLOG || o_function->id() == FUNCTION_ID_EXPINT || o_function->id() == FUNCTION_ID_SININT || o_function->id() == FUNCTION_ID_COSINT || o_function->id() == FUNCTION_ID_SINHINT || o_function->id() == FUNCTION_ID_COSHINT || o_function->id() == FUNCTION_ID_FRESNEL_C || o_function->id() == FUNCTION_ID_FRESNEL_S || o_function->id() == FUNCTION_ID_SIGNUM || o_function->id() == FUNCTION_ID_HEAVISIDE || o_function->id() == FUNCTION_ID_LAMBERT_W || o_function->id() == FUNCTION_ID_SINC || o_function->id() == FUNCTION_ID_SIN || o_function->id() == FUNCTION_ID_COS || o_function->id() == FUNCTION_ID_TAN || o_function->id() == FUNCTION_ID_SINH || o_function->id() == FUNCTION_ID_COSH || o_function->id() == FUNCTION_ID_TANH || o_function->id() == FUNCTION_ID_ASINH || o_function->id() == FUNCTION_ID_ACOSH || o_function->id() == FUNCTION_ID_ATANH || o_function->id() == FUNCTION_ID_ASIN || o_function->id() == FUNCTION_ID_ACOS || o_function->id() == FUNCTION_ID_ATAN) return 0; + int ret = 0; + for(size_t i = 0; i < SIZE; i++) { + int ret_i = CHILD(i).containsType(mtype, false, check_variables, check_functions); + if(ret_i > 0) return ret_i; + else if(ret_i < 0) ret = ret_i; } + return ret; } - break; + return -1; + } else if(isAborted()) { + return -1; } + return ret; } - - return -1; } - -int MathStructure::merge_logical_and(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool) { - if(equals(mstruct, true, true)) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - if(mstruct.representsNonZero()) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - if(mstruct.isZero()) { - if(isZero()) return 2; - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 3; +int MathStructure::containsRepresentativeOfType(StructureType mtype, bool check_variables, bool check_functions) const { + if(m_type == mtype) return 1; + int ret = 0; + if(m_type != STRUCT_FUNCTION) { + for(size_t i = 0; i < SIZE; i++) { + int retval = CHILD(i).containsRepresentativeOfType(mtype, check_variables, check_functions); + if(retval == 1) return 1; + else if(retval < 0) ret = retval; + } } - if(representsNonZero()) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); + if(check_variables && m_type == STRUCT_VARIABLE && o_variable->isKnown()) { + return ((KnownVariable*) o_variable)->get().containsRepresentativeOfType(mtype, check_variables, check_functions); + } else if(check_functions && m_type == STRUCT_FUNCTION) { + if(function_value) { + return function_value->containsRepresentativeOfType(mtype, check_variables, check_functions); } - return 3; } - if(isZero()) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - - if(CALCULATOR->aborted()) return -1; - - if(eo.test_comparisons && isLogicalOr()) { - if(SIZE > 50) return -1; - if(mstruct.isLogicalOr()) { - if(mstruct.size() * SIZE > 50) return -1; - for(size_t i = 0; i < SIZE; ) { - MathStructure msave(CHILD(i)); - for(size_t i2 = 0; i2 < mstruct.size(); i2++) { - if(i2 > 0) { - insertChild(msave, i + 1); - } - CHILD(i).calculateLogicalAnd(mstruct[i2], eo, this, i); - i++; - } - } - } else { - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).calculateLogicalAnd(mstruct, eo, this, i); - } - } - MERGE_APPROX_AND_PREC(mstruct) - calculatesub(eo, eo, false); - return 1; - } else if(eo.test_comparisons && mstruct.isLogicalOr()) { - return 0; - } else if(isComparison() && mstruct.isComparison()) { - if(CHILD(0) == mstruct[0]) { - ComparisonResult cr = mstruct[1].compare(CHILD(1)); - ComparisonType ct1 = ct_comp, ct2 = mstruct.comparisonType(); - switch(cr) { - case COMPARISON_RESULT_NOT_EQUAL: { - if(ct_comp == COMPARISON_EQUALS && ct2 == COMPARISON_EQUALS) { - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(ct_comp == COMPARISON_EQUALS && ct2 == COMPARISON_NOT_EQUALS) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } else if(ct_comp == COMPARISON_NOT_EQUALS && ct2 == COMPARISON_EQUALS) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; - } - return -1; - } - case COMPARISON_RESULT_EQUAL: { - MERGE_APPROX_AND_PREC(mstruct) - if(ct_comp == ct2) return 1; - if(ct_comp == COMPARISON_NOT_EQUALS) { - if(ct2 == COMPARISON_LESS || ct2 == COMPARISON_EQUALS_LESS) { - ct_comp = COMPARISON_LESS; - if(ct2 == COMPARISON_LESS) return 3; - return 1; - } else if(ct2 == COMPARISON_GREATER || ct2 == COMPARISON_EQUALS_GREATER) { - ct_comp = COMPARISON_GREATER; - if(ct2 == COMPARISON_GREATER) return 3; - return 1; - } - } else if(ct2 == COMPARISON_NOT_EQUALS) { - if(ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) { - if(ct_comp == COMPARISON_LESS) return 2; - ct_comp = COMPARISON_LESS; - return 1; - } else if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) { - if(ct_comp == COMPARISON_GREATER) return 2; - ct_comp = COMPARISON_GREATER; - return 1; - } - } else if((ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_EQUALS) && (ct2 == COMPARISON_EQUALS_LESS || ct2 == COMPARISON_EQUALS_GREATER || ct2 == COMPARISON_EQUALS)) { - if(ct_comp == COMPARISON_EQUALS) return 2; - ct_comp = COMPARISON_EQUALS; - if(ct2 == COMPARISON_EQUALS) return 3; - return 1; - } else if((ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) && (ct2 == COMPARISON_LESS || ct2 == COMPARISON_EQUALS_LESS)) { - if(ct_comp == COMPARISON_LESS) return 2; - ct_comp = COMPARISON_LESS; - if(ct2 == COMPARISON_LESS) return 3; - return 1; - } else if((ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) && (ct2 == COMPARISON_GREATER || ct2 == COMPARISON_EQUALS_GREATER)) { - if(ct_comp == COMPARISON_GREATER) return 2; - ct_comp = COMPARISON_GREATER; - if(ct2 == COMPARISON_GREATER) return 3; - return 1; - } - clear(true); - return 1; - } - case COMPARISON_RESULT_EQUAL_OR_GREATER: { - switch(ct1) { - case COMPARISON_GREATER: {ct1 = COMPARISON_LESS; break;} - case COMPARISON_EQUALS_GREATER: {ct1 = COMPARISON_EQUALS_LESS; break;} - case COMPARISON_LESS: {ct1 = COMPARISON_GREATER; break;} - case COMPARISON_EQUALS_LESS: {ct1 = COMPARISON_EQUALS_GREATER; break;} - default: {} - } - switch(ct2) { - case COMPARISON_GREATER: {ct2 = COMPARISON_LESS; break;} - case COMPARISON_EQUALS_GREATER: {ct2 = COMPARISON_EQUALS_LESS; break;} - case COMPARISON_LESS: {ct2 = COMPARISON_GREATER; break;} - case COMPARISON_EQUALS_LESS: {ct2 = COMPARISON_EQUALS_GREATER; break;} - default: {} - } - } - case COMPARISON_RESULT_EQUAL_OR_LESS: { - switch(ct1) { - case COMPARISON_LESS: { - if(ct2 == COMPARISON_GREATER || ct2 == COMPARISON_EQUALS) { - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(ct2 == COMPARISON_LESS || ct2 == COMPARISON_EQUALS_LESS || ct2 == COMPARISON_NOT_EQUALS) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - break; - } - case COMPARISON_GREATER: { - if(ct2 == COMPARISON_GREATER) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; - } - break; - } - case COMPARISON_EQUALS_LESS: { - if(ct2 == COMPARISON_EQUALS_LESS) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - break; - } - case COMPARISON_EQUALS_GREATER: { - if(ct2 == COMPARISON_EQUALS_GREATER || ct2 == COMPARISON_EQUALS) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; - } - break; - } - case COMPARISON_EQUALS: { - if(ct2 == COMPARISON_GREATER) { - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - break; - } - case COMPARISON_NOT_EQUALS: { - if(ct2 == COMPARISON_GREATER) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; - } - break; - } - } - break; - } - case COMPARISON_RESULT_GREATER: { - switch(ct1) { - case COMPARISON_GREATER: {ct1 = COMPARISON_LESS; break;} - case COMPARISON_EQUALS_GREATER: {ct1 = COMPARISON_EQUALS_LESS; break;} - case COMPARISON_LESS: {ct1 = COMPARISON_GREATER; break;} - case COMPARISON_EQUALS_LESS: {ct1 = COMPARISON_EQUALS_GREATER; break;} - default: {} - } - switch(ct2) { - case COMPARISON_GREATER: {ct2 = COMPARISON_LESS; break;} - case COMPARISON_EQUALS_GREATER: {ct2 = COMPARISON_EQUALS_LESS; break;} - case COMPARISON_LESS: {ct2 = COMPARISON_GREATER; break;} - case COMPARISON_EQUALS_LESS: {ct2 = COMPARISON_EQUALS_GREATER; break;} - default: {} - } - } - case COMPARISON_RESULT_LESS: { - switch(ct1) { - case COMPARISON_EQUALS: { - switch(ct2) { - case COMPARISON_EQUALS: {} - case COMPARISON_EQUALS_GREATER: {} - case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) clear(true); return 1;} - case COMPARISON_NOT_EQUALS: {} - case COMPARISON_EQUALS_LESS: {} - case COMPARISON_LESS: {MERGE_APPROX_AND_PREC(mstruct) return 2;} - default: {} - } - break; - } - case COMPARISON_NOT_EQUALS: { - switch(ct2) { - case COMPARISON_EQUALS: {} - case COMPARISON_EQUALS_GREATER: {} - case COMPARISON_GREATER: { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; - } - default: {} - } - break; - } - case COMPARISON_EQUALS_LESS: {} - case COMPARISON_LESS: { - switch(ct2) { - case COMPARISON_EQUALS: {} - case COMPARISON_EQUALS_GREATER: {} - case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) clear(true); return 1;} - case COMPARISON_NOT_EQUALS: {} - case COMPARISON_EQUALS_LESS: {} - case COMPARISON_LESS: {MERGE_APPROX_AND_PREC(mstruct) return 2;} - } - break; - } - case COMPARISON_EQUALS_GREATER: {} - case COMPARISON_GREATER: { - switch(ct2) { - case COMPARISON_EQUALS: {} - case COMPARISON_EQUALS_GREATER: {} - case COMPARISON_GREATER: { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; - } - default: {} - } - break; - } - } - break; - } - default: { - if(!eo.test_comparisons) return -1; - if(comparisonType() == COMPARISON_EQUALS && !CHILD(1).contains(mstruct[0])) { - mstruct.calculateReplace(CHILD(0), CHILD(1), eo); - if(eo.isolate_x) {mstruct.isolate_x(eo, eo); mstruct.calculatesub(eo, eo, true);} - mstruct.ref(); - add_nocopy(&mstruct, OPERATION_LOGICAL_AND); - calculateLogicalAndLast(eo); - return 1; - } else if(mstruct.comparisonType() == COMPARISON_EQUALS && !mstruct[1].contains(CHILD(0))) { - calculateReplace(mstruct[0], mstruct[1], eo); - if(eo.isolate_x) {isolate_x(eo, eo); calculatesub(eo, eo, true);} - mstruct.ref(); - add_nocopy(&mstruct, OPERATION_LOGICAL_AND); - calculateLogicalAndLast(eo); - return 1; - } - return -1; - } - } - } else if(eo.test_comparisons && comparisonType() == COMPARISON_EQUALS && !CHILD(0).isNumber() && !CHILD(0).containsInterval() && CHILD(1).isNumber() && mstruct.contains(CHILD(0))) { - mstruct.calculateReplace(CHILD(0), CHILD(1), eo); - if(eo.isolate_x) {mstruct.isolate_x(eo, eo); mstruct.calculatesub(eo, eo, true);} - mstruct.ref(); - add_nocopy(&mstruct, OPERATION_LOGICAL_AND); - calculateLogicalAndLast(eo); - return 1; - } else if(eo.test_comparisons && mstruct.comparisonType() == COMPARISON_EQUALS && !mstruct[0].isNumber() && !mstruct[0].containsInterval() && mstruct[1].isNumber() && contains(mstruct[0])) { - calculateReplace(mstruct[0], mstruct[1], eo); - if(eo.isolate_x) {isolate_x(eo, eo); calculatesub(eo, eo, true);} - mstruct.ref(); - add_nocopy(&mstruct, OPERATION_LOGICAL_AND); - calculateLogicalAndLast(eo); - return 1; - } - } else if(isLogicalAnd()) { - if(mstruct.isLogicalAnd()) { - for(size_t i = 0; i < mstruct.size(); i++) { - APPEND_REF(&mstruct[i]); - } - MERGE_APPROX_AND_PREC(mstruct) - calculatesub(eo, eo, false); + if(m_type == STRUCT_SYMBOLIC || m_type == STRUCT_VARIABLE || m_type == STRUCT_FUNCTION || m_type == STRUCT_ABORTED) { + if(representsNumber(false)) { + if(mtype == STRUCT_UNIT) return -1; + return mtype == STRUCT_NUMBER; } else { - APPEND_REF(&mstruct); - MERGE_APPROX_AND_PREC(mstruct) - calculatesub(eo, eo, false); - } - return 1; - } else if(mstruct.isLogicalAnd()) { - transform(STRUCT_LOGICAL_AND); - for(size_t i = 0; i < mstruct.size(); i++) { - APPEND_REF(&mstruct[i]); + return -1; } - MERGE_APPROX_AND_PREC(mstruct) - calculatesub(eo, eo, false); - return 1; } - return -1; - + return ret; } - -int MathStructure::merge_logical_or(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this, size_t index_mstruct, bool) { - - if(mstruct.representsNonZero()) { - if(isOne()) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - set(1, 1, 0, true); - MERGE_APPROX_AND_PREC(mstruct) - return 3; - } - if(mstruct.isZero()) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - if(representsNonZero()) { - if(!isOne()) set(1, 1, 0, true); - MERGE_APPROX_AND_PREC(mstruct) - return 2; +bool MathStructure::containsUnknowns() const { + if(isUnknown()) return true; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).containsUnknowns()) return true; } - if(isZero()) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; + return false; +} +bool MathStructure::containsDivision() const { + if(m_type == STRUCT_DIVISION || m_type == STRUCT_INVERSE || (m_type == STRUCT_POWER && CHILD(1).hasNegativeSign())) return true; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).containsDivision()) return true; } - if(equals(mstruct, true, true)) { - return 2; + return false; +} +size_t MathStructure::countFunctions(bool count_subfunctions) const { + size_t c = 0; + if(isFunction()) { + if(!count_subfunctions) return 1; + c = 1; } - if(isLogicalAnd()) { - if(mstruct.isLogicalAnd()) { - if(SIZE < mstruct.size()) { - bool b = true; - for(size_t i = 0; i < SIZE; i++) { - b = false; - for(size_t i2 = 0; i2 < mstruct.size(); i2++) { - if(CHILD(i) == mstruct[i2]) { - b = true; - break; - } - } - if(!b) break; - } - if(b) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - } else if(SIZE > mstruct.size()) { - bool b = true; - for(size_t i = 0; i < mstruct.size(); i++) { - b = false; - for(size_t i2 = 0; i2 < SIZE; i2++) { - if(mstruct[i] == CHILD(i2)) { - b = true; - break; - } - } - if(!b) break; - } - if(b) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; - } - } - } else { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i) == mstruct) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; - } - } - } - } else if(mstruct.isLogicalAnd()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(equals(mstruct[i])) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; + for(size_t i = 0; i < SIZE; i++) { + c += CHILD(i).countFunctions(); + } + return c; +} +void MathStructure::findAllUnknowns(MathStructure &unknowns_vector) { + if(!unknowns_vector.isVector()) unknowns_vector.clearVector(); + switch(m_type) { + case STRUCT_VARIABLE: { + if(o_variable->isKnown()) { + break; } } - } - - if(isComparison() && mstruct.isComparison()) { - if(CHILD(0) == mstruct[0]) { - ComparisonResult cr = mstruct[1].compare(CHILD(1)); - ComparisonType ct1 = ct_comp, ct2 = mstruct.comparisonType(); - switch(cr) { - case COMPARISON_RESULT_NOT_EQUAL: { - return -1; - } - case COMPARISON_RESULT_EQUAL: { - if(ct_comp == ct2) return 1; - switch(ct_comp) { - case COMPARISON_EQUALS: { - switch(ct2) { - case COMPARISON_NOT_EQUALS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} - case COMPARISON_EQUALS_LESS: {} - case COMPARISON_EQUALS_GREATER: {ct_comp = ct2; MERGE_APPROX_AND_PREC(mstruct) return 3;} - case COMPARISON_LESS: {ct_comp = COMPARISON_EQUALS_LESS; MERGE_APPROX_AND_PREC(mstruct) return 1;} - case COMPARISON_GREATER: {ct_comp = COMPARISON_EQUALS_GREATER; MERGE_APPROX_AND_PREC(mstruct) return 1;} - default: {} - } - break; - } - case COMPARISON_NOT_EQUALS: { - switch(ct2) { - case COMPARISON_EQUALS_LESS: {} - case COMPARISON_EQUALS_GREATER: {} - case COMPARISON_EQUALS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} - case COMPARISON_LESS: {} - case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) return 2;} - default: {} - } - break; - } - case COMPARISON_EQUALS_LESS: { - switch(ct2) { - case COMPARISON_NOT_EQUALS: {} - case COMPARISON_GREATER: {} - case COMPARISON_EQUALS_GREATER: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} - case COMPARISON_EQUALS: {} - case COMPARISON_LESS: {MERGE_APPROX_AND_PREC(mstruct) return 2;} - default: {} - } - break; - } - case COMPARISON_LESS: { - switch(ct2) { - case COMPARISON_NOT_EQUALS: {} - case COMPARISON_EQUALS_LESS: {ct_comp = ct2; MERGE_APPROX_AND_PREC(mstruct) return 3;} - case COMPARISON_EQUALS_GREATER: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} - case COMPARISON_EQUALS: {ct_comp = COMPARISON_EQUALS_LESS; MERGE_APPROX_AND_PREC(mstruct) return 1;} - case COMPARISON_GREATER: {ct_comp = COMPARISON_NOT_EQUALS; MERGE_APPROX_AND_PREC(mstruct) return 1;} - default: {} - } - break; - } - case COMPARISON_EQUALS_GREATER: { - switch(ct2) { - case COMPARISON_NOT_EQUALS: {} - case COMPARISON_LESS: {} - case COMPARISON_EQUALS_LESS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} - case COMPARISON_EQUALS: {} - case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) return 2;} - default: {} - } - break; - } - case COMPARISON_GREATER: { - switch(ct2) { - case COMPARISON_NOT_EQUALS: {} - case COMPARISON_EQUALS_GREATER: {ct_comp = ct2; MERGE_APPROX_AND_PREC(mstruct) return 3;} - case COMPARISON_EQUALS_LESS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} - case COMPARISON_EQUALS: {ct_comp = COMPARISON_EQUALS_GREATER; MERGE_APPROX_AND_PREC(mstruct) return 1;} - case COMPARISON_LESS: {ct_comp = COMPARISON_NOT_EQUALS; MERGE_APPROX_AND_PREC(mstruct) return 1;} - default: {} - } - break; - } - } - break; - } - case COMPARISON_RESULT_EQUAL_OR_GREATER: { - switch(ct1) { - case COMPARISON_GREATER: {ct1 = COMPARISON_LESS; break;} - case COMPARISON_EQUALS_GREATER: {ct1 = COMPARISON_EQUALS_LESS; break;} - case COMPARISON_LESS: {ct1 = COMPARISON_GREATER; break;} - case COMPARISON_EQUALS_LESS: {ct1 = COMPARISON_EQUALS_GREATER; break;} - default: {} - } - switch(ct2) { - case COMPARISON_GREATER: {ct2 = COMPARISON_LESS; break;} - case COMPARISON_EQUALS_GREATER: {ct2 = COMPARISON_EQUALS_LESS; break;} - case COMPARISON_LESS: {ct2 = COMPARISON_GREATER; break;} - case COMPARISON_EQUALS_LESS: {ct2 = COMPARISON_EQUALS_GREATER; break;} - default: {} - } - } - case COMPARISON_RESULT_EQUAL_OR_LESS: { - switch(ct1) { - case COMPARISON_LESS: { - if(ct2 == COMPARISON_LESS || ct2 == COMPARISON_EQUALS_LESS || ct2 == COMPARISON_NOT_EQUALS) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; - } - break; - } - case COMPARISON_GREATER: { - if(ct2 == COMPARISON_GREATER) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - break; - } - case COMPARISON_EQUALS_LESS: { - if(ct2 == COMPARISON_EQUALS_LESS) { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; - } - break; - } - case COMPARISON_EQUALS_GREATER: { - if(ct2 == COMPARISON_EQUALS_GREATER || ct2 == COMPARISON_EQUALS) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - break; - } - case COMPARISON_NOT_EQUALS: { - if(ct2 == COMPARISON_GREATER) { - MERGE_APPROX_AND_PREC(mstruct) - return 2; - } - break; - } - default: {} - } - break; - } - case COMPARISON_RESULT_GREATER: { - switch(ct1) { - case COMPARISON_GREATER: {ct1 = COMPARISON_LESS; break;} - case COMPARISON_EQUALS_GREATER: {ct1 = COMPARISON_EQUALS_LESS; break;} - case COMPARISON_LESS: {ct1 = COMPARISON_GREATER; break;} - case COMPARISON_EQUALS_LESS: {ct1 = COMPARISON_EQUALS_GREATER; break;} - default: {} - } - switch(ct2) { - case COMPARISON_GREATER: {ct2 = COMPARISON_LESS; break;} - case COMPARISON_EQUALS_GREATER: {ct2 = COMPARISON_EQUALS_LESS; break;} - case COMPARISON_LESS: {ct2 = COMPARISON_GREATER; break;} - case COMPARISON_EQUALS_LESS: {ct2 = COMPARISON_EQUALS_GREATER; break;} - default: {} - } - } - case COMPARISON_RESULT_LESS: { - switch(ct1) { - case COMPARISON_EQUALS: { - switch(ct2) { - case COMPARISON_NOT_EQUALS: {} - case COMPARISON_EQUALS_LESS: {} - case COMPARISON_LESS: { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; - } - default: {} - } - break; - } - case COMPARISON_NOT_EQUALS: { - switch(ct2) { - case COMPARISON_EQUALS: {} - case COMPARISON_EQUALS_GREATER: {} - case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) return 2;} - case COMPARISON_EQUALS_LESS: {} - case COMPARISON_LESS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} - default: {} - } - break; - } - case COMPARISON_EQUALS_LESS: {} - case COMPARISON_LESS: { - switch(ct2) { - case COMPARISON_NOT_EQUALS: {} - case COMPARISON_EQUALS_LESS: {} - case COMPARISON_LESS: { - if(mparent) { - mparent->swapChildren(index_this + 1, index_mstruct + 1); - } else { - set_nocopy(mstruct, true); - } - return 3; - } - default: {} - } - break; - } - case COMPARISON_EQUALS_GREATER: {} - case COMPARISON_GREATER: { - switch(ct2) { - case COMPARISON_NOT_EQUALS: {} - case COMPARISON_EQUALS_LESS: {} - case COMPARISON_LESS: {set(1, 1, 0, true); MERGE_APPROX_AND_PREC(mstruct) return 1;} - case COMPARISON_EQUALS: {} - case COMPARISON_EQUALS_GREATER: {} - case COMPARISON_GREATER: {MERGE_APPROX_AND_PREC(mstruct) return 2;} - } - break; - } - } + case STRUCT_SYMBOLIC: { + bool b = false; + for(size_t i = 0; i < unknowns_vector.size(); i++) { + if(equals(unknowns_vector[i])) { + b = true; break; } - default: { - return -1; - } } - } else if(eo.test_comparisons && comparisonType() == COMPARISON_NOT_EQUALS && !CHILD(0).isNumber() && !CHILD(0).containsInterval() && CHILD(1).isNumber() && mstruct.contains(CHILD(0))) { - mstruct.calculateReplace(CHILD(0), CHILD(1), eo); - if(eo.isolate_x) {mstruct.isolate_x(eo, eo); mstruct.calculatesub(eo, eo, true);} - mstruct.ref(); - add_nocopy(&mstruct, OPERATION_LOGICAL_OR); - calculateLogicalOrLast(eo); - return 1; - } else if(eo.test_comparisons && mstruct.comparisonType() == COMPARISON_NOT_EQUALS && !mstruct[0].isNumber() && !mstruct[0].containsInterval() && mstruct[1].isNumber() && contains(mstruct[0])) { - calculateReplace(mstruct[0], mstruct[1], eo); - if(eo.isolate_x) {isolate_x(eo, eo); calculatesub(eo, eo, true);} - mstruct.ref(); - add_nocopy(&mstruct, OPERATION_LOGICAL_OR); - calculateLogicalOrLast(eo); - return 1; + if(!b) unknowns_vector.addChild(*this); + break; } - } else if(isLogicalOr()) { - if(mstruct.isLogicalOr()) { - for(size_t i = 0; i < mstruct.size(); i++) { - APPEND_REF(&mstruct[i]); + default: { + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).findAllUnknowns(unknowns_vector); } - MERGE_APPROX_AND_PREC(mstruct) - calculatesub(eo, eo, false); - } else { - APPEND_REF(&mstruct); - MERGE_APPROX_AND_PREC(mstruct) - calculatesub(eo, eo, false); - } - return 1; - } else if(mstruct.isLogicalOr()) { - transform(STRUCT_LOGICAL_OR); - for(size_t i = 0; i < mstruct.size(); i++) { - APPEND_REF(&mstruct[i]); } - MERGE_APPROX_AND_PREC(mstruct) - calculatesub(eo, eo, false); - return 1; - } - return -1; - -} - -int MathStructure::merge_logical_xor(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure*, size_t, size_t, bool) { - - if(equals(mstruct)) { - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - bool bp1 = representsNonZero(); - bool bp2 = mstruct.representsNonZero(); - if(bp1 && bp2) { - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - bool bn1 = isZero(); - bool bn2 = mstruct.isZero(); - if(bn1 && bn2) { - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - if((bn1 && bp2) || (bp1 && bn2)) { - set(1, 1, 0, true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - return -1; - - /*int b0, b1; - if(isZero()) { - b0 = 0; - } else if(representsNonZero(true)) { - b0 = 1; - } else { - b0 = -1; - } - if(mstruct.isZero()) { - b1 = 0; - } else if(mstruct.representsNonZero(true)) { - b1 = 1; - } else { - b1 = -1; - } - - if((b0 == 1 && b1 == 0) || (b0 == 0 && b1 == 1)) { - set(1, 1, 0, true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(b0 >= 0 && b1 >= 0) { - clear(true); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(b0 == 0) { - set(mstruct, true); - add(m_zero, OPERATION_NOT_EQUALS); - calculatesub(eo, eo, false); - return 1; - } else if(b0 == 1) { - set(mstruct, true); - add(m_zero, OPERATION_EQUALS); - calculatesub(eo, eo, false); - return 1; - } else if(b1 == 0) { - add(m_zero, OPERATION_NOT_EQUALS); - calculatesub(eo, eo, false); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } else if(b1 == 1) { - add(m_zero, OPERATION_EQUALS); - calculatesub(eo, eo, false); - MERGE_APPROX_AND_PREC(mstruct) - return 1; } - MathStructure *mstruct2 = new MathStructure(*this); - add(mstruct, OPERATION_LOGICAL_AND); - LAST.calculateLogicalNot(eo); - LAST.calculatesub(eo, eo, false); - calculatesub(eo, eo, false); - mstruct2->setLogicalNot(); - mstruct2->calculatesub(eo, eo, false); - mstruct2->add(mstruct, OPERATION_LOGICAL_AND); - mstruct2->calculatesub(eo, eo, false); - add_nocopy(mstruct2, OPERATION_LOGICAL_OR); - calculatesub(eo, eo, false); - - return 1;*/ - } - - -int MathStructure::merge_bitwise_and(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure*, size_t, size_t, bool) { - if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { - Number nr(o_number); - if(nr.bitAnd(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) { - if(o_number == nr) { - o_number = nr; - numberUpdated(); - return 2; - } - o_number = nr; - numberUpdated(); - return 1; - } - return -1; - } - switch(m_type) { - case STRUCT_VECTOR: { - switch(mstruct.type()) { - case STRUCT_VECTOR: { - if(SIZE < mstruct.size()) return 0; - for(size_t i = 0; i < mstruct.size(); i++) { - mstruct[i].ref(); - CHILD(i).add_nocopy(&mstruct[i], OPERATION_LOGICAL_AND); - CHILD(i).calculatesub(eo, eo, false); - } - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - default: { - return -1; - } - } - return -1; - } - case STRUCT_BITWISE_AND: { - switch(mstruct.type()) { - case STRUCT_VECTOR: { - return -1; - } - case STRUCT_BITWISE_AND: { - for(size_t i = 0; i < mstruct.size(); i++) { - APPEND_REF(&mstruct[i]); - } - calculatesub(eo, eo, false); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - default: { - APPEND_REF(&mstruct); - calculatesub(eo, eo, false); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - break; - } - default: { - switch(mstruct.type()) { - case STRUCT_BITWISE_AND: { - return 0; - } - default: {} - } - } - } - return -1; -} -int MathStructure::merge_bitwise_or(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure*, size_t, size_t, bool) { - if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { - Number nr(o_number); - if(nr.bitOr(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) { - if(o_number == nr) { - o_number = nr; - numberUpdated(); - return 2; - } - o_number = nr; - numberUpdated(); - return 1; - } - return -1; - } - switch(m_type) { - case STRUCT_VECTOR: { - switch(mstruct.type()) { - case STRUCT_VECTOR: { - if(SIZE < mstruct.size()) return 0; - for(size_t i = 0; i < mstruct.size(); i++) { - mstruct[i].ref(); - CHILD(i).add_nocopy(&mstruct[i], OPERATION_LOGICAL_OR); - CHILD(i).calculatesub(eo, eo, false); - } - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - default: { - return -1; - } - } - return -1; - } - case STRUCT_BITWISE_OR: { - switch(mstruct.type()) { - case STRUCT_VECTOR: { - return -1; - } - case STRUCT_BITWISE_OR: { - for(size_t i = 0; i < mstruct.size(); i++) { - APPEND_REF(&mstruct[i]); - } - calculatesub(eo, eo, false); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - default: { - APPEND_REF(&mstruct); - calculatesub(eo, eo, false); - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - } - break; - } - default: { - switch(mstruct.type()) { - case STRUCT_BITWISE_OR: { - return 0; - } - default: {} - } - } - } - return -1; -} -int MathStructure::merge_bitwise_xor(MathStructure &mstruct, const EvaluationOptions &eo, MathStructure*, size_t, size_t, bool) { - if(mstruct.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { - Number nr(o_number); - if(nr.bitXor(mstruct.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mstruct.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mstruct.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mstruct.number().includesInfinity())) { - if(o_number == nr) { - o_number = nr; - numberUpdated(); - return 2; - } - o_number = nr; - numberUpdated(); - return 1; - } - return -1; - } - switch(m_type) { - case STRUCT_VECTOR: { - switch(mstruct.type()) { - case STRUCT_VECTOR: { - if(SIZE < mstruct.size()) return 0; - for(size_t i = 0; i < mstruct.size(); i++) { - mstruct[i].ref(); - CHILD(i).add_nocopy(&mstruct[i], OPERATION_LOGICAL_XOR); - CHILD(i).calculatesub(eo, eo, false); - } - MERGE_APPROX_AND_PREC(mstruct) - return 1; - } - default: { - return -1; - } - } - return -1; - } - default: {} - } - return -1; -} - -#define MERGE_RECURSE if(recursive) {\ - for(size_t i = 0; i < SIZE; i++) {\ - if(CALCULATOR->aborted()) break;\ - if(!CHILD(i).isNumber()) CHILD(i).calculatesub(eo, feo, true, this, i);\ - }\ - CHILDREN_UPDATED;\ - } - -#define MERGE_ALL(FUNC, TRY_LABEL) size_t i2, i3 = SIZE;\ - bool do_abort = false; \ - for(size_t i = 0; i < SIZE - 1; i++) {\ - i2 = i + 1;\ - TRY_LABEL:\ - for(; i2 < i; i2++) {\ - if(CALCULATOR->aborted()) break;\ - int r = CHILD(i2).FUNC(CHILD(i), eo, this, i2, i);\ - if(r == 0) {\ - SWAP_CHILDREN(i2, i);\ - r = CHILD(i2).FUNC(CHILD(i), eo, this, i2, i, true);\ - if(r < 1) {\ - SWAP_CHILDREN(i2, i);\ - }\ - }\ - if(r >= 1) {\ - ERASE(i);\ - b = true;\ - i3 = i;\ - i = i2;\ - i2 = 0;\ - goto TRY_LABEL;\ - }\ - }\ - for(i2 = i + 1; i2 < SIZE; i2++) {\ - if(CALCULATOR->aborted()) break;\ - int r = CHILD(i).FUNC(CHILD(i2), eo, this, i, i2);\ - if(r == 0) {\ - SWAP_CHILDREN(i, i2);\ - r = CHILD(i).FUNC(CHILD(i2), eo, this, i, i2, true);\ - if(r < 1) {\ - SWAP_CHILDREN(i, i2);\ - } else if(r == 2) {\ - r = 3;\ - } else if(r == 3) {\ - r = 2;\ - }\ - }\ - if(r >= 1) {\ - ERASE(i2);\ - b = true;\ - if(r != 2) {\ - i2 = 0;\ - goto TRY_LABEL;\ - }\ - i2--;\ - } else if(CHILD(i).isDateTime()) {\ - do_abort = true;\ - break;\ - }\ - }\ - if(do_abort) break;\ - if(i3 < SIZE) {\ - if(i3 == SIZE - 1) break;\ - i = i3;\ - i3 = SIZE;\ - i2 = i + 1;\ - goto TRY_LABEL;\ - }\ - } - -#define MERGE_ALL2 if(SIZE == 1) {\ - setToChild(1, false, mparent, index_this + 1);\ - } else if(SIZE == 0) {\ - clear(true);\ - } else {\ - evalSort();\ - } - -bool do_simplification(MathStructure &mstruct, const EvaluationOptions &eo, bool combine_divisions = true, bool only_gcd = false, bool combine_only = false, bool recursive = true, bool limit_size = false, int i_run = 1); - -Number dos_count_points(const MathStructure &m, bool b_unknown) { - if(m.isPower() && (!b_unknown || m[0].containsUnknowns())) { - Number nr = dos_count_points(m[0], b_unknown); - if(!nr.isZero()) { - if(m[0].isNumber() && m[0].number().isNonZero()) { - nr *= m[1].number(); - if(nr.isNegative()) nr.negate(); - } else { - nr *= 2; - } - return nr; - } - } else if(m.size() == 0 && ((b_unknown && m.isUnknown()) || (!b_unknown && !m.isNumber()))) { - return nr_one; - } - Number nr; - for(size_t i = 0; i < m.size(); i++) { - nr += dos_count_points(m[i], b_unknown); - } - return nr; -} - -bool do_simplification(MathStructure &mstruct, const EvaluationOptions &eo, bool combine_divisions, bool only_gcd, bool combine_only, bool recursive, bool limit_size, int i_run) { - - if(!eo.expand || !eo.assume_denominators_nonzero) return false; - - if(recursive) { - bool b = false; - for(size_t i = 0; i < mstruct.size(); i++) { - b = do_simplification(mstruct[i], eo, combine_divisions, only_gcd || (!mstruct.isComparison() && !mstruct.isLogicalAnd() && !mstruct.isLogicalOr()), combine_only, true, limit_size) || b; - if(CALCULATOR->aborted()) return b; - } - if(b) mstruct.calculatesub(eo, eo, false); - return do_simplification(mstruct, eo, combine_divisions, only_gcd, combine_only, false, limit_size) || b; - } - if(mstruct.isPower() && mstruct[1].isNumber() && mstruct[1].number().isRational() && !mstruct[1].number().isInteger() && mstruct[0].isAddition() && mstruct[0].isRationalPolynomial()) { - MathStructure msqrfree(mstruct[0]); - if(sqrfree(msqrfree, eo) && msqrfree.isPower() && msqrfree.calculateRaise(mstruct[1], eo)) { - mstruct = msqrfree; - return true; - } - } else if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_root && VALID_ROOT(mstruct) && mstruct[0].isAddition() && mstruct[0].isRationalPolynomial()) { - MathStructure msqrfree(mstruct[0]); - if(sqrfree(msqrfree, eo) && msqrfree.isPower() && msqrfree[1].isInteger() && msqrfree[1].number().isPositive()) { - if(msqrfree[1] == mstruct[1]) { - if(msqrfree[1].number().isEven()) { - if(!msqrfree[0].representsReal(true)) return false; - msqrfree.delChild(2); - msqrfree.setType(STRUCT_FUNCTION); - msqrfree.setFunction(CALCULATOR->f_abs); - mstruct = msqrfree; - } else { - mstruct = msqrfree[0]; - } - return true; - } else if(msqrfree[1].number().isIntegerDivisible(mstruct[1].number())) { - if(msqrfree[1].number().isEven()) { - if(!msqrfree[0].representsReal(true)) return false; - msqrfree[0].transform(STRUCT_FUNCTION); - msqrfree[0].setFunction(CALCULATOR->f_abs); - } - msqrfree[1].number().divide(mstruct[1].number()); - mstruct = msqrfree; - mstruct.calculatesub(eo, eo, false); - return true; - } else if(mstruct[1].number().isIntegerDivisible(msqrfree[1].number())) { - if(msqrfree[1].number().isEven()) { - if(!msqrfree[0].representsReal(true)) return false; - msqrfree[0].transform(STRUCT_FUNCTION); - msqrfree[0].setFunction(CALCULATOR->f_abs); - } - Number new_root(mstruct[1].number()); - new_root.divide(msqrfree[1].number()); - mstruct[0] = msqrfree[0]; - mstruct[1] = new_root; - return true; - } - } - } - if(!mstruct.isAddition() && !mstruct.isMultiplication()) return false; - - if(combine_divisions) { - - MathStructure divs, nums, numleft, mleft; - - EvaluationOptions eo2 = eo; - eo2.do_polynomial_division = false; - eo2.keep_zero_units = false; - - if(!mstruct.isAddition()) mstruct.transform(STRUCT_ADDITION); - - // find division by polynomial - for(size_t i = 0; i < mstruct.size(); i++) { - if(CALCULATOR->aborted()) return false; - bool b = false; - if(mstruct[i].isMultiplication()) { - MathStructure div, num(1, 1, 0); - bool b_num = false; - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - if(mstruct[i][i2].isPower() && mstruct[i][i2][1].isInteger() && mstruct[i][i2][1].number().isNegative()) { - bool b_rat = mstruct[i][i2][0].isRationalPolynomial(); - if(!b_rat && mstruct[i][i2][0].isAddition() && mstruct[i][i2][0].size() > 1) { - b_rat = true; - for(size_t i3 = 0; i3 < mstruct[i][i2][0].size(); i3++) { - if(!mstruct[i][i2][0][i3].representsZero(true) && !mstruct[i][i2][0][i3].isRationalPolynomial()) { - b_rat = false; - break; - } - } - } - if(!b_rat) { - div.clear(); - break; - } - bool b_minone = mstruct[i][i2][1].isMinusOne(); - if(b_minone) { - if(div.isZero()) div = mstruct[i][i2][0]; - else div.multiply(mstruct[i][i2][0], true); - } else { - mstruct[i][i2][1].number().negate(); - if(div.isZero()) div = mstruct[i][i2]; - else div.multiply(mstruct[i][i2], true); - mstruct[i][i2][1].number().negate(); - } - } else if(mstruct[i][i2].isRationalPolynomial() || mstruct[i][i2].representsZero(true)) { - if(!b_num) {b_num = true; num = mstruct[i][i2];} - else num.multiply(mstruct[i][i2], true); - } else { - div.clear(); - break; - } - } - if(!div.isZero()) { - bool b_found = false; - for(size_t i3 = 0; i3 < divs.size(); i3++) { - if(divs[i3] == div) { - if(!num.representsZero(true)) { - if(num.isAddition()) { - for(size_t i4 = 0; i4 < num.size(); i4++) { - nums[i3].add(num[i4], true); - } - } else { - nums[i3].add(num, true); - } - } - b_found = true; - b = true; - break; - } - } - if(!b_found && (eo.assume_denominators_nonzero || div.representsNonZero(true)) && !div.representsZero(true)) { - if(!num.representsZero(true)) { - divs.addChild(div); - nums.addChild(num); - } - b = true; - } - } - } else if(mstruct[i].isPower() && mstruct[i][1].isInteger() && mstruct[i][1].number().isNegative()) { - bool b_rat = mstruct[i][0].isRationalPolynomial(); - if(!b_rat && mstruct[i][0].isAddition() && mstruct[i][0].size() > 1) { - b_rat = true; - for(size_t i2 = 0; i2 < mstruct[i][0].size(); i2++) { - if(!mstruct[i][0][i2].representsZero(true) && !mstruct[i][0].isRationalPolynomial()) { - b_rat = false; - break; - } - } - } - if(b_rat) { - bool b_minone = mstruct[i][1].isMinusOne(); - if(!b_minone) mstruct[i][1].number().negate(); - bool b_found = false; - for(size_t i3 = 0; i3 < divs.size(); i3++) { - if((b_minone && divs[i3] == mstruct[i][0]) || (!b_minone && divs[i3] == mstruct[i])) { - nums[i3].add(m_one, true); - b_found = true; - b = true; - break; - } - } - if(!b_found && (eo.assume_denominators_nonzero || mstruct[i][0].representsNonZero(true)) && !mstruct[i][0].representsZero(true)) { - if(b_minone) divs.addChild(mstruct[i][0]); - else divs.addChild(mstruct[i]); - nums.addChild(m_one); - b = true; - } - if(!b_minone) mstruct[i][1].number().negate(); - } - } - if(!b) { - if(i_run <= 1 && mstruct[i].isRationalPolynomial()) numleft.addChild(mstruct[i]); - else mleft.addChild(mstruct[i]); - } - } - - for(size_t i = 0; i < divs.size(); i++) { - if(divs[i].isAddition()) { - for(size_t i2 = 0; i2 < divs[i].size();) { - if(divs[i][i2].representsZero(true)) { - divs[i].delChild(i2 + 1); - } else i2++; - } - if(divs[i].size() == 1) divs[i].setToChild(1); - else if(divs[i].size() == 0) divs[i].clear(); - } - } - - if(divs.size() == 0) { - if(mstruct.size() == 1) mstruct.setToChild(1); - return false; - } - bool b_ret = false; - if(divs.size() > 1 || numleft.size() > 0) b_ret = true; - - /*divs.setType(STRUCT_VECTOR); - nums.setType(STRUCT_VECTOR); - numleft.setType(STRUCT_VECTOR); - mleft.setType(STRUCT_VECTOR); - cout << nums << ":" << divs << ":" << numleft << ":" << mleft << endl;*/ - - if(i_run > 1) { - for(size_t i = 0; i < divs.size();) { - bool b = true; - if(!divs[i].isRationalPolynomial() || !nums[i].isRationalPolynomial()) { - if(mstruct.size() == 1) mstruct.setToChild(1); - return false; - } - if(!combine_only && divs[i].isAddition() && nums[i].isAddition()) { - MathStructure ca, cb, mgcd; - if(MathStructure::gcd(nums[i], divs[i], mgcd, eo2, &ca, &cb, false) && !mgcd.isOne() && (!cb.isAddition() || !ca.isAddition() || ca.size() + cb.size() <= nums[i].size() + divs[i].size())) { - if(mgcd.representsNonZero(true) || !eo.warn_about_denominators_assumed_nonzero || warn_about_denominators_assumed_nonzero(mgcd, eo)) { - if(cb.isOne()) { - numleft.addChild(ca); - nums.delChild(i + 1); - divs.delChild(i + 1); - b = false; - } else { - nums[i] = ca; - divs[i] = cb; - } - b_ret = true; - } - } - } - if(CALCULATOR->aborted()) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} - if(b) i++; - } - - } else { - while(divs.size() > 0) { - bool b = true; - if(!divs[0].isRationalPolynomial() || !nums[0].isRationalPolynomial()) { - if(mstruct.size() == 1) mstruct.setToChild(1); - return false; - } - if(!combine_only && divs[0].isAddition() && nums[0].isAddition()) { - MathStructure ca, cb, mgcd; - if(MathStructure::gcd(nums[0], divs[0], mgcd, eo2, &ca, &cb, false) && !mgcd.isOne() && (!cb.isAddition() || !ca.isAddition() || ca.size() + cb.size() <= nums[0].size() + divs[0].size())) { - if(mgcd.representsNonZero(true) || !eo.warn_about_denominators_assumed_nonzero || warn_about_denominators_assumed_nonzero(mgcd, eo)) { - if(cb.isOne()) { - numleft.addChild(ca); - nums.delChild(1); - divs.delChild(1); - b = false; - } else { - nums[0] = ca; - divs[0] = cb; - } - b_ret = true; - } - } - } - if(CALCULATOR->aborted()) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} - if(b && divs.size() > 1) { - if(!combine_only && divs[1].isAddition() && nums[1].isAddition()) { - MathStructure ca, cb, mgcd; - EvaluationOptions eo3 = eo2; - eo3.transform_trigonometric_functions = false; - if(MathStructure::gcd(nums[1], divs[1], mgcd, eo3, &ca, &cb, false) && !mgcd.isOne() && (!cb.isAddition() || !ca.isAddition() || ca.size() + cb.size() <= nums[1].size() + divs[1].size())) { - if(mgcd.representsNonZero(true) || !eo.warn_about_denominators_assumed_nonzero || warn_about_denominators_assumed_nonzero(mgcd, eo)) { - if(cb.isOne()) { - numleft.addChild(ca); - nums.delChild(2); - divs.delChild(2); - b = false; - } else { - nums[1] = ca; - divs[1] = cb; - } - } - } - } - if(CALCULATOR->aborted()) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} - if(b) { - MathStructure ca, cb, mgcd; - b = MathStructure::gcd(divs[0], divs[1], mgcd, eo2, &ca, &cb, false) && !mgcd.isOne(); - if(CALCULATOR->aborted()) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} - bool b_merge = true; - if(b) { - if(limit_size && ((cb.isAddition() && ((divs[0].isAddition() && divs[0].size() * cb.size() > 200) || (nums[0].isAddition() && nums[0].size() * cb.size() > 200))) || (ca.isAddition() && nums[1].isAddition() && nums[1].size() * ca.size() > 200))) { - b_merge = false; - } else { - if(!cb.isOne()) { - divs[0].calculateMultiply(cb, eo2); - nums[0].calculateMultiply(cb, eo2); - } - if(!ca.isOne()) { - nums[1].calculateMultiply(ca, eo2); - } - } - } else { - if(limit_size && ((divs[1].isAddition() && ((divs[0].isAddition() && divs[0].size() * divs[1].size() > 200) || (nums[0].isAddition() && nums[0].size() * divs[1].size() > 200))) || (divs[0].isAddition() && nums[1].isAddition() && nums[1].size() * divs[0].size() > 200))) { - b_merge = false; - } else { - nums[0].calculateMultiply(divs[1], eo2); - nums[1].calculateMultiply(divs[0], eo2); - divs[0].calculateMultiply(divs[1], eo2); - } - } - if(b_merge) { - nums[0].calculateAdd(nums[1], eo2); - nums.delChild(2); - divs.delChild(2); - } else { - size_t size_1 = 2, size_2 = 2; - if(nums[0].isAddition()) size_1 += nums[0].size() - 1; - if(divs[0].isAddition()) size_1 += divs[0].size() - 1; - if(nums[1].isAddition()) size_2 += nums[1].size() - 1; - if(divs[1].isAddition()) size_2 += divs[1].size() - 1; - if(size_1 > size_2) { - nums[0].calculateDivide(divs[0], eo); - mleft.addChild(nums[0]); - nums.delChild(1); - divs.delChild(1); - } else { - nums[1].calculateDivide(divs[1], eo); - mleft.addChild(nums[1]); - nums.delChild(2); - divs.delChild(2); - } - } - } - } else if(b && numleft.size() > 0) { - if(limit_size && divs[0].isAddition() && numleft.size() > 0 && divs[0].size() * numleft.size() > 200) break; - if(numleft.size() == 1) numleft.setToChild(1); - else if(numleft.size() > 1) numleft.setType(STRUCT_ADDITION); - numleft.calculateMultiply(divs[0], eo2); - nums[0].calculateAdd(numleft, eo2); - numleft.clear(); - } else if(b) break; - } - - if(CALCULATOR->aborted()) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} - while(!combine_only && !only_gcd && divs.size() > 0 && divs[0].isAddition() && !nums[0].isNumber()) { - bool b_unknown = divs[0].containsUnknowns(); - if(!b_unknown || nums[0].containsUnknowns()) { - MathStructure mcomps; - mcomps.resizeVector(nums[0].isAddition() ? nums[0].size() : 1, m_zero); - if(nums[0].isAddition()) { - for(size_t i = 0; i < nums[0].size(); i++) { - if((b_unknown && nums[0][i].containsUnknowns()) || (!b_unknown && !nums[0][i].isNumber())) { - mcomps[i].setType(STRUCT_MULTIPLICATION); - if(nums[0][i].isMultiplication()) { - for(size_t i2 = 0; i2 < nums[0][i].size(); i2++) { - if((b_unknown && nums[0][i][i2].containsUnknowns()) || (!b_unknown && !nums[0][i][i2].isNumber())) { - nums[0][i][i2].ref(); - mcomps[i].addChild_nocopy(&nums[0][i][i2]); - } - } - } else { - nums[0][i].ref(); - mcomps[i].addChild_nocopy(&nums[0][i]); - } - } - } - } else { - mcomps[0].setType(STRUCT_MULTIPLICATION); - if(nums[0].isMultiplication()) { - for(size_t i2 = 0; i2 < nums[0].size(); i2++) { - if((b_unknown && nums[0][i2].containsUnknowns()) || (!b_unknown && !nums[0][i2].isNumber())) { - nums[0][i2].ref(); - mcomps[0].addChild_nocopy(&nums[0][i2]); - } - } - } else { - nums[0].ref(); - mcomps[0].addChild_nocopy(&nums[0]); - } - } - bool b_found = false; - unordered_map matches; - for(size_t i = 0; i < divs[0].size(); i++) { - if((b_unknown && divs[0][i].containsUnknowns()) || (!b_unknown && !divs[0][i].isNumber())) { - MathStructure mcomp1; - mcomp1.setType(STRUCT_MULTIPLICATION); - if(divs[0][i].isMultiplication()) { - for(size_t i2 = 0; i2 < divs[0][i].size(); i2++) { - if((b_unknown && divs[0][i][i2].containsUnknowns()) || (!b_unknown && !divs[0][i][i2].isNumber())) { - divs[0][i][i2].ref(); - mcomp1.addChild_nocopy(&divs[0][i][i2]); - } - } - } else { - divs[0][i].ref(); - mcomp1.addChild_nocopy(&divs[0][i]); - } - b_found = false; - for(size_t i2 = 0; i2 < mcomps.size(); i2++) { - if(mcomps[i2] == mcomp1) { - matches[i] = i2; - b_found = true; - break; - } - } - if(!b_found) break; - } - } - if(b_found) { - b_found = false; - size_t i_selected = 0; - if(nums[0].isAddition()) { - Number i_points; - for(size_t i = 0; i < divs[0].size(); i++) { - if((b_unknown && divs[0][i].containsUnknowns()) || (!b_unknown && !divs[0][i].isNumber())) { - Number new_points = dos_count_points(divs[0][i], b_unknown); - if(new_points > i_points) {i_points = new_points; i_selected = i;} - } - } - } - MathStructure mquo, mrem; - if(polynomial_long_division(nums[0].isAddition() ? nums[0][matches[i_selected]] : nums[0], divs[0], m_zero, mquo, mrem, eo2, false) && !mquo.isZero() && mrem != (nums[0].isAddition() ? nums[0][matches[i_selected]] : nums[0])) { - if(CALCULATOR->aborted()) return false; - if((nums[0].isAddition() && nums[0].size() > 1) || !mrem.isZero() || divs[0].representsNonZero(true) || (eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(divs[0], eo))) { - mleft.addChild(mquo); - if(nums[0].isAddition()) { - nums[0].delChild(matches[i_selected] + 1, true); - if(!mrem.isZero()) { - nums[0].calculateAdd(mrem, eo2); - } - } else { - if(mrem.isZero()) { - divs.clear(); - } else { - nums[0] = mrem; - } - } - b_ret = true; - b_found = true; - } - } - } - if(!b_found) break; - } else { - break; - } - } - - if(CALCULATOR->aborted()) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} - if(!combine_only && !only_gcd && divs.size() > 0 && divs[0].isAddition()) { - bool b_unknown = divs[0].containsUnknowns() || nums[0].containsUnknowns(); - MathStructure mquo, mrem; - vector symsd, symsn; - collect_symbols(nums[0], symsn); - if(!symsn.empty()) { - collect_symbols(divs[0], symsd); - } - for(size_t i = 0; i < symsd.size();) { - bool b_found = false; - if(!b_unknown || symsd[i].containsUnknowns()) { - for(size_t i2 = 0; i2 < symsn.size(); i2++) { - if(symsn[i2] == symsd[i]) { - b_found = (nums[0].degree(symsd[i]) >= divs[0].degree(symsd[i])); - break; - } - } - } - if(b_found) i++; - else symsd.erase(symsd.begin() + i); - } - for(size_t i = 0; i < symsd.size(); i++) { - if(polynomial_long_division(nums[0], divs[0], symsd[i], mquo, mrem, eo2, false) && !mquo.isZero() && mrem != nums[0]) { - if(CALCULATOR->aborted()) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} - if(!mrem.isZero() || divs[0].representsNonZero(true) || (eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(divs[0], eo))) { - if(mrem.isZero()) { - mleft.addChild(mquo); - divs.clear(); - b_ret = true; - break; - } else { - if(mquo.isAddition()) { - for(size_t i = 0; i < mquo.size(); ) { - MathStructure mtest(mquo[i]); - mtest.calculateMultiply(divs[0], eo2); - mtest.calculateAdd(mrem, eo2); - Number point = dos_count_points(mtest, b_unknown); - point -= dos_count_points(mquo[i], b_unknown); - point -= dos_count_points(mrem, b_unknown); - if(point <= 0) { - mquo.delChild(i + 1); - mrem = mtest; - } else { - i++; - } - } - if(mquo.size() == 0) mquo.clear(); - else if(mquo.size() == 1) mquo.setToChild(1); - } - if(!mquo.isZero()) { - Number point = dos_count_points(nums[0], b_unknown); - point -= dos_count_points(mquo, b_unknown); - point -= dos_count_points(mrem, b_unknown); - if(point > 0) { - mleft.addChild(mquo); - MathStructure ca, cb, mgcd; - if(mrem.isAddition() && MathStructure::gcd(mrem, divs[0], mgcd, eo2, &ca, &cb, false) && !mgcd.isOne() && (!cb.isAddition() || !ca.isAddition() || ca.size() + cb.size() <= mrem.size() + divs[0].size())) { - mrem = ca; - divs[0] = cb; - } - mrem.calculateDivide(divs[0], eo2); - mleft.addChild(mrem); - divs.clear(); - b_ret = true; - break; - } - } - } - } - } - } - } - } - - if(!b_ret) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} - - mstruct.clear(true); - for(size_t i = 0; i < divs.size() && (i == 0 || i_run > 1); i++) { - if(i == 0) mstruct = nums[0]; - else mstruct.add(nums[i], i > 1); - if(only_gcd || combine_only) { - divs[i].inverse(); - if(i == 0) mstruct.multiply(divs[i], true); - else mstruct.last().multiply(divs[i], true); - } else { - if(i == 0) mstruct.calculateDivide(divs[i], eo); - else mstruct.last().calculateDivide(divs[i], eo); - if(i == 0 && i_run <= 1 && mstruct.isAddition()) { - do_simplification(mstruct, eo, true, false, false, false, limit_size, 2); - } - } - } - for(size_t i = 0; i < mleft.size(); i++) { - if(i == 0 && mstruct.isZero()) mstruct = mleft[i]; - else mstruct.calculateAdd(mleft[i], eo); - } - for(size_t i = 0; i < numleft.size(); i++) { - if(i == 0 && mstruct.isZero()) mstruct = numleft[i]; - else mstruct.calculateAdd(numleft[i], eo); - } - - return true; - } - - MathStructure divs; - // find division by polynomial - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - if(mstruct[i][i2].isPower() && (mstruct[i][i2][0].isAddition() || combine_divisions) && mstruct[i][i2][1].isMinusOne() && mstruct[i][i2][0].isRationalPolynomial()) { - bool b_found = false; - for(size_t i3 = 0; i3 < divs.size(); i3++) { - if(divs[i3] == mstruct[i][i2][0]) { - divs[i3].number()++; - b_found = true; - break; - } - } - if(!b_found) divs.addChild(mstruct[i][i2][0]); - break; - } - } - } else if(mstruct[i].isPower() && (mstruct[i][0].isAddition() || combine_divisions) && mstruct[i][1].isMinusOne() && mstruct[i][0].isRationalPolynomial()) { - bool b_found = false; - for(size_t i3 = 0; i3 < divs.size(); i3++) { - if(divs[i3] == mstruct[i][0]) { - divs[i3].number()++; - b_found = true; - break; - } - } - if(!b_found) divs.addChild(mstruct[i][0]); - } - } - - // check if denominators is zero - for(size_t i = 0; i < divs.size(); ) { - if((!combine_divisions && divs[i].number().isZero()) || (!eo.assume_denominators_nonzero && !divs[i].representsNonZero(true)) || divs[i].representsZero(true)) divs.delChild(i + 1); - else i++; - } - - if(divs.size() == 0) return false; - - // combine numerators with same denominator - MathStructure nums, numleft, mleft; - nums.resizeVector(divs.size(), m_zero); - for(size_t i = 0; i < mstruct.size(); i++) { - bool b = false; - if(mstruct[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - if(mstruct[i][i2].isPower() && (mstruct[i][i2][0].isAddition() || combine_divisions) && mstruct[i][i2][1].isMinusOne() && mstruct[i][i2][0].isRationalPolynomial()) { - for(size_t i3 = 0; i3 < divs.size(); i3++) { - if(divs[i3] == mstruct[i][i2][0]) { - if(mstruct[i].size() == 1) nums[i3].addChild(m_one); - else if(mstruct[i].size() == 2) nums[i3].addChild(mstruct[i][i2 == 0 ? 1 : 0]); - else {nums[i3].addChild(mstruct[i]); nums[i3][nums[i3].size() - 1].delChild(i2 + 1);} - b = true; - break; - } - } - break; - } - } - } else if(mstruct[i].isPower() && (mstruct[i][0].isAddition() || combine_divisions) && mstruct[i][1].isMinusOne() && mstruct[i][0].isRationalPolynomial()) { - for(size_t i3 = 0; i3 < divs.size(); i3++) { - if(divs[i3] == mstruct[i][0]) { - nums[i3].addChild(m_one); - b = true; - break; - } - } - } - if(!b && combine_divisions) { - if(mstruct[i].isRationalPolynomial()) numleft.addChild(mstruct[i]); - else mleft.addChild(mstruct[i]); - } - } - - EvaluationOptions eo2 = eo; - eo2.do_polynomial_division = false; - eo2.keep_zero_units = false; - - // do polynomial division; give points to incomplete division - vector points(nums.size(), -1); - bool b = false, b_ready_candidate = false; - for(size_t i = 0; i < divs.size(); i++) { - if(CALCULATOR->aborted()) return false; - if(nums[i].size() > 1 && divs[i].isAddition()) { - nums[i].setType(STRUCT_ADDITION); - MathStructure xvar; - get_first_symbol(nums[i], xvar); - if(nums[i].isRationalPolynomial() && nums[i].degree(xvar).isLessThan(100) && divs[i].degree(xvar).isLessThan(100)) { - MathStructure mquo, mrem, ca, cb; - if(MathStructure::gcd(nums[i], divs[i], mquo, eo2, &ca, &cb, false) && !mquo.isOne()) { - if(!mquo.representsNonZero(true) && eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(mquo, eo)) { - nums[i].clear(); - } else { - points[i] = 1; - b_ready_candidate = true; - b = true; - } - if(ca.isOne()) { - if(cb.isOne()) { - nums[i].set(1, 1, 0, true); - } else { - nums[i] = cb; - nums[i].inverse(); - } - } else if(cb.isOne()) { - nums[i] = ca; - } else { - nums[i] = ca; - nums[i].calculateDivide(cb, eo); - } - } else if(!only_gcd && polynomial_long_division(nums[i], divs[i], xvar, mquo, mrem, eo2, false) && !mquo.isZero() && mrem != nums[i]) { - if(mrem.isZero() && !divs[i].representsNonZero(true) && eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(divs[i], eo)) { - nums[i].clear(); - } else { - long int point = 1; - if(!mrem.isZero()) point = nums[i].size(); - nums[i].set(mquo); - if(!mrem.isZero()) { - if(mquo.isAddition()) point -= mquo.size(); - else point--; - if(mrem.isAddition()) point -= mrem.size(); - else point--; - mrem.calculateDivide(divs[i], eo2); - nums[i].calculateAdd(mrem, eo2); - } - b = true; - points[i] = point; - if(point >= 0) {b_ready_candidate = true;} - else if(b_ready_candidate) nums[i].clear(); - } - } else { - nums[i].clear(); - } - } - } else { - nums[i].clear(); - } - } - - if(!b) return false; - - if(b_ready_candidate) { - // remove polynomial divisions that inrease complexity - for(size_t i = 0; i < nums.size(); i++) { - if(!nums[i].isZero() && points[i] < 0) nums[i].clear(); - } - } else { - // no simplying polynomial division found; see if result can be combined with other terms - b = false; - for(size_t i = 0; i < nums.size(); i++) { - if(!nums[i].isZero()) { - if(b) { - nums[i].clear(); - } else { - long int point = points[i]; - for(size_t i2 = 0; i2 < nums[i].size(); i2++) { - bool b2 = false; - if(!nums[i][i2].contains(divs[i], false, false, false)) { - MathStructure mtest1(mstruct), mtest2(nums[i][i2]); - for(size_t i3 = 0; i3 < mtest1.size(); i3++) { - if(!mtest1[i3].contains(divs[i], false, false, false)) { - int ret = mtest1[i3].merge_addition(mtest2, eo); - if(ret > 0) { - b2 = true; - point++; - if(mtest1[i3].isZero()) point++; - break; - } - if(ret == 0) ret = mtest2.merge_addition(mtest1[i3], eo); - if(ret > 0) { - b2 = true; - point++; - if(mtest2.isZero()) point++; - break; - } - } - } - if(b2) break; - } - if(point >= 0) break; - } - if(point >= 0) b = true; - else nums[i].clear(); - } - } - } - } - - if(!b) return false; - // replace terms with polynomial division result - for(size_t i = 0; i < mstruct.size(); ) { - bool b_del = false; - if(mstruct[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - if(mstruct[i][i2].isPower() && mstruct[i][i2][0].isAddition() && mstruct[i][i2][1].isMinusOne() && mstruct[i][i2][0].isRationalPolynomial()) { - for(size_t i3 = 0; i3 < divs.size(); i3++) { - if(divs[i3] == mstruct[i][i2][0]) { - b_del = !nums[i3].isZero(); - break; - } - } - break; - } - } - } else if(mstruct[i].isPower() && mstruct[i][0].isAddition() && mstruct[i][1].isMinusOne() && mstruct[i][0].isRationalPolynomial()) { - for(size_t i3 = 0; i3 < divs.size(); i3++) { - if(divs[i3] == mstruct[i][0]) { - b_del = !nums[i3].isZero(); - break; - } - } - } - if(b_del) mstruct.delChild(i + 1); - else i++; - } - for(size_t i = 0; i < nums.size(); ) { - if(nums[i].isZero()) { - nums.delChild(i + 1); - } else { - nums[i].evalSort(); - i++; - } - } - if(mstruct.size() == 0 && nums.size() == 1) { - mstruct.set(nums[0]); - } else { - for(size_t i = 0; i < nums.size(); i++) { - mstruct.addChild(nums[i]); - } - mstruct.evalSort(); - } - return true; -} - -bool fix_intervals(MathStructure &mstruct, const EvaluationOptions &eo, bool *failed = NULL, long int min_precision = 2, bool function_middle = false) { - if(mstruct.type() == STRUCT_NUMBER) { - if(eo.interval_calculation != INTERVAL_CALCULATION_NONE) { - if(!mstruct.number().isInterval(false) && mstruct.number().precision() >= 0 && (CALCULATOR->usesIntervalArithmetic() || mstruct.number().precision() <= PRECISION + 10)) { - mstruct.number().precisionToInterval(); - mstruct.setPrecision(-1); - mstruct.numberUpdated(); - return true; - } - } else if(mstruct.number().isInterval(false)) { - if(!mstruct.number().intervalToPrecision(min_precision)) { - if(failed) *failed = true; - return false; - } - mstruct.numberUpdated(); - return true; - } - } else if(mstruct.type() == STRUCT_FUNCTION && (mstruct.function() == CALCULATOR->f_interval || mstruct.function() == CALCULATOR->f_uncertainty)) { - if(eo.interval_calculation == INTERVAL_CALCULATION_NONE) { - bool b = mstruct.calculateFunctions(eo, false); - if(b) { - fix_intervals(mstruct, eo, failed, function_middle); - return true; - } else if(function_middle && mstruct.type() == STRUCT_FUNCTION && mstruct.function() == CALCULATOR->f_interval && mstruct.size() == 2) { - mstruct.setType(STRUCT_ADDITION); - mstruct.divide(nr_two); - return true; - } else if(function_middle && mstruct.type() == STRUCT_FUNCTION && mstruct.function() == CALCULATOR->f_uncertainty && mstruct.size() >= 1) { - mstruct.setToChild(1, true); - return true; - } - } - } else { - bool b = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(fix_intervals(mstruct[i], eo, failed, function_middle)) { - mstruct.childUpdated(i + 1); - b = true; - } - } - return b; - } - return false; -} - -bool contains_zero_unit(const MathStructure &mstruct); -bool contains_zero_unit(const MathStructure &mstruct) { - if(mstruct.isMultiplication() && mstruct.size() > 1 && mstruct[0].isZero()) { - bool b = true; - for(size_t i = 1; i < mstruct.size(); i++) { - if(!mstruct[i].isUnit_exp()) { - b = false; - break; - } - } - if(b) return true; - } - for(size_t i = 0; i < mstruct.size(); i++) { - if(contains_zero_unit(mstruct[i])) return true; - } - return false; -} - -bool test_var_int(const MathStructure &mstruct, bool *v = NULL) { - if(mstruct.isVariable() && (mstruct.variable() == CALCULATOR->v_e || mstruct.variable() == CALCULATOR->v_pi)) { - if(!v) return true; - if(*v) return false; - else *v = true; - return true; - } - if(mstruct.isNumber() && mstruct.number().isReal()) { - if(!v) { - if(mstruct.number().isInterval()) { - Number nr_int(mstruct.number()); - nr_int.round(); - return mstruct.number() < nr_int || mstruct.number() > nr_int; - } - if(mstruct.isApproximate()) { - Number nr_f = mstruct.number(); - nr_f.floor(); - Number nr_c(nr_f); - nr_c++; - return COMPARISON_IS_NOT_EQUAL(mstruct.number().compareApproximately(nr_f)) && COMPARISON_IS_NOT_EQUAL(mstruct.number().compareApproximately(nr_c)); - } - return !mstruct.number().isInterval() && !mstruct.number().isInteger(); - } - if(mstruct.isApproximate()) return false; - return mstruct.number().isRational(); - } - if(mstruct.isMultiplication() || mstruct.isAddition() || (mstruct.isPower() && mstruct[1].isInteger())) { - bool v2 = false; - if(!v) v = &v2; - for(size_t i = 0; i < mstruct.size(); i++) { - if(!test_var_int(mstruct[i], v)) return false; - } - if(*v) return true; - } - return false; -} - -bool test_non_integer(const MathStructure &mstruct, const EvaluationOptions&) { - if(test_var_int(mstruct)) return true; - if(!mstruct.isApproximate()) { - if((mstruct.isMultiplication() || mstruct.isAddition()) && mstruct.size() >= 2 && mstruct[0].isNumber() && mstruct[0].number().isReal() && !mstruct[0].number().isInterval() && !mstruct[0].number().isInteger()) { - for(size_t i = 1; i < mstruct.size(); i++) { - if(!mstruct[i].representsInteger()) return false; - } - return true; - } - } - return false; -} - -bool MathStructure::calculatesub(const EvaluationOptions &eo, const EvaluationOptions &feo, bool recursive, MathStructure *mparent, size_t index_this) { - if(b_protected) return false; - bool b = false; - - switch(m_type) { - case STRUCT_VARIABLE: { - if(eo.calculate_variables && o_variable->isKnown()) { - if((eo.approximation == APPROXIMATION_APPROXIMATE || (!o_variable->isApproximate() && !((KnownVariable*) o_variable)->get().containsInterval(true, false, false, 0, true))) && !((KnownVariable*) o_variable)->get().isAborted()) { - set(((KnownVariable*) o_variable)->get()); - unformat(eo); - if(eo.calculate_functions) { - calculateFunctions(feo); - } - fix_intervals(*this, feo, NULL, PRECISION); - b = true; - calculatesub(eo, feo, true, mparent, index_this); - } - } - break; - } - case STRUCT_POWER: { - if(recursive) { - CHILD(0).calculatesub(eo, feo, true, this, 0); - CHILD(1).calculatesub(eo, feo, true, this, 1); - CHILDREN_UPDATED; - } - if(CHILD(0).merge_power(CHILD(1), eo) >= 1) { - b = true; - setToChild(1, false, mparent, index_this + 1); - } - break; - } - case STRUCT_ADDITION: { - MERGE_RECURSE - bool found_nonlinear_relations = false; - if(eo.sync_units && (syncUnits(false, &found_nonlinear_relations, true, feo) || (found_nonlinear_relations && eo.sync_nonlinear_unit_relations))) { - if(found_nonlinear_relations && eo.sync_nonlinear_unit_relations) { - EvaluationOptions eo2 = eo; - eo2.expand = -3; - eo2.combine_divisions = false; - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).calculatesub(eo2, feo, true, this, i); - CHILD(i).factorizeUnits(); - } - CHILDREN_UPDATED; - syncUnits(true, NULL, true, feo); - } - unformat(eo); - MERGE_RECURSE - } - MERGE_ALL(merge_addition, try_add) - MERGE_ALL2 - break; - } - case STRUCT_MULTIPLICATION: { - - MERGE_RECURSE - if(eo.sync_units && syncUnits(eo.sync_nonlinear_unit_relations, NULL, true, feo)) { - unformat(eo); - MERGE_RECURSE - } - - if(representsNonMatrix()) { - if(SIZE > 2) { - int nonintervals = 0, had_interval = false; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isNumber()) { - if(CHILD(i).number().isInterval(false)) { - had_interval = true; - if(nonintervals >= 2) break; - } else if(nonintervals < 2) { - nonintervals++; - if(nonintervals == 2 && had_interval) break; - } - } - } - if(had_interval && nonintervals >= 2) evalSort(false); - } - - MERGE_ALL(merge_multiplication, try_multiply) - - } else { - size_t i2, i3 = SIZE; - for(size_t i = 0; i < SIZE - 1; i++) { - i2 = i + 1; - try_multiply_matrix: - bool b_matrix = !CHILD(i).representsNonMatrix(); - if(i2 < i) { - for(; ; i2--) { - int r = CHILD(i2).merge_multiplication(CHILD(i), eo, this, i2, i); - if(r == 0) { - SWAP_CHILDREN(i2, i); - r = CHILD(i2).merge_multiplication(CHILD(i), eo, this, i2, i, true); - if(r < 1) { - SWAP_CHILDREN(i2, i); - } - } - if(r >= 1) { - ERASE(i); - b = true; - i3 = i; - i = i2; - i2 = 0; - goto try_multiply_matrix; - } - if(i2 == 0) break; - if(b_matrix && !CHILD(i2).representsNonMatrix()) break; - } - } - bool had_matrix = false; - for(i2 = i + 1; i2 < SIZE; i2++) { - if(had_matrix && !CHILD(i2).representsNonMatrix()) continue; - int r = CHILD(i).merge_multiplication(CHILD(i2), eo, this, i, i2); - if(r == 0) { - SWAP_CHILDREN(i, i2); - r = CHILD(i).merge_multiplication(CHILD(i2), eo, this, i, i2, true); - if(r < 1) { - SWAP_CHILDREN(i, i2); - } else if(r == 2) { - r = 3; - } else if(r == 3) { - r = 2; - } - } - if(r >= 1) { - ERASE(i2); - b = true; - if(r != 2) { - i2 = 0; - goto try_multiply_matrix; - } - i2--; - } - if(i == SIZE - 1) break; - if(b_matrix && !CHILD(i2).representsNonMatrix()) had_matrix = true; - } - if(i3 < SIZE) { - if(i3 == SIZE - 1) break; - i = i3; - i3 = SIZE; - i2 = i + 1; - goto try_multiply_matrix; - } - } - } - - MERGE_ALL2 - - break; - } - case STRUCT_BITWISE_AND: { - MERGE_RECURSE - MERGE_ALL(merge_bitwise_and, try_bitand) - MERGE_ALL2 - break; - } - case STRUCT_BITWISE_OR: { - MERGE_RECURSE - MERGE_ALL(merge_bitwise_or, try_bitor) - MERGE_ALL2 - break; - } - case STRUCT_BITWISE_XOR: { - MERGE_RECURSE - MERGE_ALL(merge_bitwise_xor, try_bitxor) - MERGE_ALL2 - break; - } - case STRUCT_BITWISE_NOT: { - if(recursive) { - CHILD(0).calculatesub(eo, feo, true, this, 0); - CHILDREN_UPDATED; - } - switch(CHILD(0).type()) { - case STRUCT_NUMBER: { - Number nr(CHILD(0).number()); - if(nr.bitNot() && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || CHILD(0).number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || CHILD(0).number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || CHILD(0).number().includesInfinity())) { - set(nr, true); - } - break; - } - case STRUCT_VECTOR: { - SET_CHILD_MAP(0); - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).setLogicalNot(); - } - break; - } - case STRUCT_BITWISE_NOT: { - setToChild(1); - setToChild(1); - break; - } - default: {} - } - break; - } - case STRUCT_LOGICAL_AND: { - if(recursive) { - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).calculatesub(eo, feo, true, this, i); - CHILD_UPDATED(i) - if(CHILD(i).isZero()) { - clear(true); - b = true; - break; - } - } - if(b) break; - } - MERGE_ALL(merge_logical_and, try_logand) - if(SIZE == 1) { - if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) { - setToChild(1, false, mparent, index_this + 1); - } else if(CHILD(0).representsNonZero()) { - set(1, 1, 0, true); - } else if(CHILD(0).isZero()) { - clear(true); - } else { - APPEND(m_zero); - m_type = STRUCT_COMPARISON; - ct_comp = COMPARISON_NOT_EQUALS; - } - } else if(SIZE == 0) { - clear(true); - } else { - evalSort(); - } - break; - } - case STRUCT_LOGICAL_OR: { - bool isResistance = false; - switch(CHILD(0).type()) { - case STRUCT_MULTIPLICATION: { - if(CHILD(0)[1] != 0 && CHILD(0)[1].unit() && CHILD(0)[1].unit()->name().find("ohm") != string::npos) { - isResistance = true; - } - break; - } - case STRUCT_UNIT: { - if (CHILD(0).unit() && CHILD(0).unit()->name().find("ohm") != string::npos) { - isResistance = true; - } - break; - } - default: {} - } - - if(isResistance) { - MathStructure mstruct; - for (size_t i = 0; i < SIZE; i++) { - MathStructure mtemp(CHILD(i)); - mtemp.inverse(); - mstruct += mtemp; - } - mstruct.inverse(); - clear(); - set(mstruct); - break; - } - if(recursive) { - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).calculatesub(eo, feo, true, this, i); - CHILD_UPDATED(i) - if(CHILD(i).representsNonZero()) { - set(1, 1, 0, true); - b = true; - break; - } - } - if(b) break; - } - MERGE_ALL(merge_logical_or, try_logor) - if(SIZE == 1) { - if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) { - setToChild(1, false, mparent, index_this + 1); - } else if(CHILD(0).representsNonZero()) { - set(1, 1, 0, true); - } else if(CHILD(0).isZero()) { - clear(true); - } else { - APPEND(m_zero); - m_type = STRUCT_COMPARISON; - ct_comp = COMPARISON_NOT_EQUALS; - } - } else if(SIZE == 0) { - clear(true); - } else { - evalSort(); - } - break; - } - case STRUCT_LOGICAL_XOR: { - if(recursive) { - CHILD(0).calculatesub(eo, feo, true, this, 0); - CHILD(1).calculatesub(eo, feo, true, this, 1); - CHILDREN_UPDATED; - } - if(CHILD(0).merge_logical_xor(CHILD(1), eo) >= 1) { - b = true; - setToChild(1, false, mparent, index_this + 1); - } - break; - } - case STRUCT_LOGICAL_NOT: { - if(recursive) { - CHILD(0).calculatesub(eo, feo, true, this, 0); - CHILDREN_UPDATED; - } - if(CHILD(0).representsNonZero()) { - clear(true); - b = true; - } else if(CHILD(0).isZero()) { - set(1, 1, 0, true); - b = true; - } else if(CHILD(0).isLogicalNot()) { - setToChild(1); - setToChild(1); - if(!representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) { - add(m_zero, OPERATION_NOT_EQUALS); - calculatesub(eo, feo, false); - } - b = true; - } - break; - } - case STRUCT_COMPARISON: { - EvaluationOptions eo2 = eo; - if(eo2.assume_denominators_nonzero == 1) eo2.assume_denominators_nonzero = false; - if(recursive) { - CHILD(0).calculatesub(eo2, feo, true, this, 0); - CHILD(1).calculatesub(eo2, feo, true, this, 1); - CHILDREN_UPDATED; - } - if(eo.sync_units && syncUnits(eo.sync_nonlinear_unit_relations, NULL, true, feo)) { - unformat(eo); - if(recursive) { - CHILD(0).calculatesub(eo2, feo, true, this, 0); - CHILD(1).calculatesub(eo2, feo, true, this, 1); - CHILDREN_UPDATED; - } - } - if(CHILD(0).isAddition() || CHILD(1).isAddition()) { - size_t i2 = 0; - for(size_t i = 0; !CHILD(0).isAddition() || i < CHILD(0).size(); i++) { - if(CHILD(1).isAddition()) { - for(; i2 < CHILD(1).size(); i2++) { - if(CHILD(0).isAddition() && CHILD(0)[i] == CHILD(1)[i2]) { - CHILD(0).delChild(i + 1); - CHILD(1).delChild(i2 + 1); - break; - } else if(!CHILD(0).isAddition() && CHILD(0) == CHILD(1)[i2]) { - CHILD(0).clear(true); - CHILD(1).delChild(i2 + 1); - break; - } - } - } else if(CHILD(0)[i] == CHILD(1)) { - CHILD(1).clear(true); - CHILD(0).delChild(i + 1); - break; - } - if(!CHILD(0).isAddition()) break; - } - if(CHILD(0).isAddition()) { - if(CHILD(0).size() == 1) CHILD(0).setToChild(1, true); - else if(CHILD(0).size() == 0) CHILD(0).clear(true); - } - if(CHILD(1).isAddition()) { - if(CHILD(1).size() == 1) CHILD(1).setToChild(1, true); - else if(CHILD(1).size() == 0) CHILD(1).clear(true); - } - } - if(CHILD(0).isMultiplication() && CHILD(1).isMultiplication()) { - size_t i1 = 0, i2 = 0; - if(CHILD(0)[0].isNumber()) i1++; - if(CHILD(1)[0].isNumber()) i2++; - while(i1 < CHILD(0).size() && i2 < CHILD(1).size()) { - if(CHILD(0)[i1] == CHILD(1)[i2] && CHILD(0)[i1].representsPositive(true)) { - CHILD(0).delChild(i1 + 1); - CHILD(1).delChild(i2 + 1); - } else { - break; - } - } - if(CHILD(0).size() == 1) CHILD(0).setToChild(1, true); - else if(CHILD(0).size() == 0) CHILD(0).set(1, 1, 0, true); - if(CHILD(1).size() == 1) CHILD(1).setToChild(1, true); - else if(CHILD(1).size() == 0) CHILD(1).set(1, 1, 0, true); - } - if(((CHILD(0).isNumber() || (CHILD(0).isVariable() && !CHILD(0).variable()->isKnown() && ((UnknownVariable*) CHILD(0).variable())->interval().isNumber())) && (CHILD(1).isNumber() || ((CHILD(1).isVariable() && !CHILD(1).variable()->isKnown() && ((UnknownVariable*) CHILD(1).variable())->interval().isNumber())))) || (CHILD(0).isDateTime() && CHILD(1).isDateTime())) { - ComparisonResult cr; - if(CHILD(0).isNumber()) { - if(CHILD(1).isNumber()) cr = CHILD(1).number().compareApproximately(CHILD(0).number()); - else cr = ((UnknownVariable*) CHILD(1).variable())->interval().number().compareApproximately(CHILD(0).number()); - } else if(CHILD(1).isNumber()) { - cr = CHILD(1).number().compareApproximately(((UnknownVariable*) CHILD(0).variable())->interval().number()); - } else if(CHILD(1).isVariable()) { - cr = ((UnknownVariable*) CHILD(1).variable())->interval().number().compareApproximately(((UnknownVariable*) CHILD(0).variable())->interval().number()); - } else { - cr = CHILD(1).compare(CHILD(0)); - } - if(cr >= COMPARISON_RESULT_UNKNOWN) { - break; - } - switch(ct_comp) { - case COMPARISON_EQUALS: { - if(cr == COMPARISON_RESULT_EQUAL) { - set(1, 1, 0, true); - b = true; - } else if(COMPARISON_IS_NOT_EQUAL(cr)) { - clear(true); - b = true; - } - break; - } - case COMPARISON_NOT_EQUALS: { - if(cr == COMPARISON_RESULT_EQUAL) { - clear(true); - b = true; - } else if(COMPARISON_IS_NOT_EQUAL(cr)) { - set(1, 1, 0, true); - b = true; - } - break; - } - case COMPARISON_LESS: { - if(cr == COMPARISON_RESULT_LESS) { - set(1, 1, 0, true); - b = true; - } else if(cr != COMPARISON_RESULT_EQUAL_OR_LESS && cr != COMPARISON_RESULT_NOT_EQUAL) { - clear(true); - b = true; - } - break; - } - case COMPARISON_EQUALS_LESS: { - if(COMPARISON_IS_EQUAL_OR_LESS(cr)) { - set(1, 1, 0, true); - b = true; - } else if(cr != COMPARISON_RESULT_EQUAL_OR_GREATER && cr != COMPARISON_RESULT_NOT_EQUAL) { - clear(true); - b = true; - } - break; - } - case COMPARISON_GREATER: { - if(cr == COMPARISON_RESULT_GREATER) { - set(1, 1, 0, true); - b = true; - } else if(cr != COMPARISON_RESULT_EQUAL_OR_GREATER && cr != COMPARISON_RESULT_NOT_EQUAL) { - clear(true); - b = true; - } - break; - } - case COMPARISON_EQUALS_GREATER: { - if(COMPARISON_IS_EQUAL_OR_GREATER(cr)) { - set(1, 1, 0, true); - b = true; - } else if(cr != COMPARISON_RESULT_EQUAL_OR_LESS && cr != COMPARISON_RESULT_NOT_EQUAL) { - clear(true); - b = true; - } - break; - } - } - break; - } - if(!eo.test_comparisons) { - break; - } - if(eo2.keep_zero_units && contains_zero_unit(*this)) { - eo2.keep_zero_units = false; - MathStructure mtest(*this); - CALCULATOR->beginTemporaryStopMessages(); - mtest.calculatesub(eo2, feo, true); - if(mtest.isNumber()) { - CALCULATOR->endTemporaryStopMessages(true); - set(mtest); - b = true; - break; - } - CALCULATOR->endTemporaryStopMessages(); - } - if((CHILD(0).representsUndefined() && !CHILD(1).representsUndefined(true, true, true)) || (CHILD(1).representsUndefined() && !CHILD(0).representsUndefined(true, true, true))) { - if(ct_comp == COMPARISON_EQUALS) { - clear(true); - b = true; - break; - } else if(ct_comp == COMPARISON_NOT_EQUALS) { - set(1, 1, 0, true); - b = true; - break; - } - } - if((ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_GREATER) && CHILD(1).isZero()) { - if(CHILD(0).isLogicalNot() || CHILD(0).isLogicalAnd() || CHILD(0).isLogicalOr() || CHILD(0).isLogicalXor() || CHILD(0).isComparison()) { - if(ct_comp == COMPARISON_EQUALS_LESS) { - ERASE(1); - m_type = STRUCT_LOGICAL_NOT; - calculatesub(eo, feo, false, mparent, index_this); - } else { - setToChild(1, false, mparent, index_this + 1); - } - b = true; - } - } else if((ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_LESS) && CHILD(0).isZero()) { - if(CHILD(1).isLogicalNot() || CHILD(1).isLogicalAnd() || CHILD(1).isLogicalOr() || CHILD(1).isLogicalXor() || CHILD(1).isComparison()) { - if(ct_comp == COMPARISON_EQUALS_GREATER) { - ERASE(0); - m_type = STRUCT_LOGICAL_NOT; - calculatesub(eo, feo, false, mparent, index_this); - } else { - setToChild(2, false, mparent, index_this + 1); - } - b = true; - } - } - if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { - if((CHILD(0).representsReal(true) && CHILD(1).representsComplex(true)) || (CHILD(1).representsReal(true) && CHILD(0).representsComplex(true))) { - if(ct_comp == COMPARISON_EQUALS) { - clear(true); - } else { - set(1, 1, 0, true); - } - b = true; - } else if((CHILD(0).representsZero(true) && CHILD(1).representsZero(true))) { - if(ct_comp != COMPARISON_EQUALS) { - clear(true); - } else { - set(1, 1, 0, true); - } - b = true; - } else if(CHILD(0).isVariable() && !CHILD(0).variable()->isKnown() && CHILD(0).representsInteger() && test_non_integer(CHILD(1), eo)) { - if(ct_comp == COMPARISON_EQUALS) clear(true); - else set(1, 1, 0, true); - b = true; - } - } - if(b) break; - if(CHILD(1).isNumber() && CHILD(0).isVariable() && !CHILD(0).variable()->isKnown()) { - Assumptions *ass = ((UnknownVariable*) CHILD(0).variable())->assumptions(); - if(ass && ass->min()) { - bool b_inc = ass->includeEqualsMin(); - switch(ct_comp) { - case COMPARISON_EQUALS: { - if((b_inc && CHILD(1).number() < *ass->min()) || (!b_inc && CHILD(1).number() <= *ass->min())) {clear(true); b = true;} - break; - } - case COMPARISON_NOT_EQUALS: { - if((b_inc && CHILD(1).number() < *ass->min()) || (!b_inc && CHILD(1).number() <= *ass->min())) {set(1, 1, 0, true); b = true;} - break; - } - case COMPARISON_LESS: { - if(CHILD(1).number() <= *ass->min()) {clear(true); b = true;} - - break; - } - case COMPARISON_GREATER: { - if((b_inc && CHILD(1).number() < *ass->min()) || (!b_inc && CHILD(1).number() <= *ass->min())) {set(1, 1, 0, true); b = true;} - break; - } - case COMPARISON_EQUALS_LESS: { - if(b_inc && CHILD(1).number() == *ass->min()) {ct_comp = COMPARISON_EQUALS; b = true;} - else if((b_inc && CHILD(1).number() < *ass->min()) || (!b_inc && CHILD(1).number() <= *ass->min())) {clear(true); b = true;} - break; - } - case COMPARISON_EQUALS_GREATER: { - if(CHILD(1).number() <= *ass->min()) {set(1, 1, 0, true); b = true;} - break; - } - } - } - if(ass && ass->max() && isComparison()) { - bool b_inc = ass->includeEqualsMax(); - switch(ct_comp) { - case COMPARISON_EQUALS: { - if((b_inc && CHILD(1).number() > *ass->max()) || (!b_inc && CHILD(1).number() >= *ass->max())) {clear(true); b = true;} - break; - } - case COMPARISON_NOT_EQUALS: { - if((b_inc && CHILD(1).number() > *ass->max()) || (!b_inc && CHILD(1).number() >= *ass->max())) {set(1, 1, 0, true); b = true;} - break; - } - case COMPARISON_LESS: { - if((b_inc && CHILD(1).number() > *ass->max()) || (!b_inc && CHILD(1).number() >= *ass->max())) {set(1, 1, 0, true); b = true;} - break; - } - case COMPARISON_GREATER: { - if(CHILD(1).number() >= *ass->max()) {clear(true); b = true;} - break; - } - case COMPARISON_EQUALS_LESS: { - if(CHILD(1).number() >= *ass->max()) {set(1, 1, 0, true); b = true;} - break; - } - case COMPARISON_EQUALS_GREATER: { - if(b_inc && CHILD(1).number() == *ass->max()) {ct_comp = COMPARISON_EQUALS; b = true;} - else if((b_inc && CHILD(1).number() > *ass->max()) || (!b_inc && CHILD(1).number() >= *ass->max())) {clear(true); b = true;} - break; - } - } - } - } - if(b) break; - if(eo.approximation == APPROXIMATION_EXACT && eo.test_comparisons > 0) { - bool b_intval = CALCULATOR->usesIntervalArithmetic(); - bool b_failed = false; - EvaluationOptions eo3 = feo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - eo3.approximation = APPROXIMATION_APPROXIMATE; - eo2.test_comparisons = false; - MathStructure mtest(*this); - for(int i = 0; i < 2; i++) { - CALCULATOR->beginTemporaryEnableIntervalArithmetic(); - int b_ass = (i == 0 ? 2 : contains_ass_intval(mtest)); - if(b_ass == 0) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); break;} - replace_interval_unknowns(mtest, i > 0); - if(i == 0 && !b_intval) fix_intervals(mtest, eo2, &b_failed); - if(!b_failed) { - if(i == 0 && mtest[0].isAddition() && mtest[0].size() > 1 && mtest[1].isZero()) { - mtest[1] = mtest[0][0]; - mtest[1].negate(); - mtest[0].delChild(1, true); - } - CALCULATOR->beginTemporaryStopMessages(); - if(b_ass == 2) mtest[0].calculateFunctions(eo3); - mtest[0].calculatesub(eo2, eo3, true); - if(b_ass == 2) mtest[1].calculateFunctions(eo3); - mtest[1].calculatesub(eo2, eo3, true); - CALCULATOR->endTemporaryEnableIntervalArithmetic(); - mtest.childrenUpdated(); - if(CALCULATOR->endTemporaryStopMessages(NULL, NULL, MESSAGE_ERROR) == 0) { - eo2.approximation = eo.approximation; - eo2.test_comparisons = -1; - mtest.calculatesub(eo2, feo, false); - if(mtest.isNumber()) { - if(mtest.isZero()) clear(true); - else set(1, 1, 0, true); - b = true; - return b; - } - } - } else { - CALCULATOR->endTemporaryEnableIntervalArithmetic(); - break; - } - } - } - eo2 = eo; - if(eo2.assume_denominators_nonzero == 1) eo2.assume_denominators_nonzero = false; - bool mtest_new = false; - MathStructure *mtest; - if(!CHILD(1).isZero()) { - if(!eo.isolate_x || find_x_var().isUndefined()) { - CHILD(0).calculateSubtract(CHILD(1), eo2); - CHILD(1).clear(); - mtest = &CHILD(0); - mtest->ref(); - } else { - mtest = new MathStructure(CHILD(0)); - mtest->calculateSubtract(CHILD(1), eo2); - remove_rad_unit(*mtest, eo2); - mtest_new = true; - } - } else { - mtest = &CHILD(0); - mtest->ref(); - } - int incomp = 0; - if(mtest->isAddition()) { - mtest->evalSort(true); - incomp = compare_check_incompability(mtest); - if(incomp == 1 && !mtest_new) { - mtest->unref(); - mtest = new MathStructure(CHILD(0)); - if(remove_rad_unit(*mtest, eo2)) { - mtest_new = true; - if(mtest->isAddition()) { - mtest->evalSort(true); - incomp = compare_check_incompability(mtest); - } - } - } - } - if(incomp <= 0) { - if(mtest_new && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { - bool a_pos = CHILD(0).representsPositive(true); - bool a_nneg = a_pos || CHILD(0).representsNonNegative(true); - bool a_neg = !a_nneg && CHILD(0).representsNegative(true); - bool a_npos = !a_pos && (a_neg || CHILD(0).representsNonPositive(true)); - bool b_pos = CHILD(1).representsPositive(true); - bool b_nneg = b_pos || CHILD(1).representsNonNegative(true); - bool b_neg = !b_nneg && CHILD(1).representsNegative(true); - bool b_npos = !b_pos && (b_neg || CHILD(1).representsNonPositive(true)); - if(isApproximate()) { - if((a_pos && b_neg) || (a_neg && b_pos)) { - incomp = 1; - } - } else { - if((a_pos && b_npos) || (a_npos && b_pos) || (a_nneg && b_neg) || (a_neg && b_nneg)) { - incomp = 1; - } - } - } else if(incomp < 0) { - mtest->unref(); - break; - } - } - - switch(ct_comp) { - case COMPARISON_EQUALS: { - if(incomp > 0) { - clear(true); - b = true; - } else if(mtest->representsZero(true)) { - set(1, 1, 0, true); - b = true; - } else if(mtest->representsNonZero(true)) { - clear(true); - b = true; - } - break; - } - case COMPARISON_NOT_EQUALS: { - if(incomp > 0) { - set(1, 1, 0, true); - b = true; - } else if(mtest->representsNonZero(true)) { - set(1, 1, 0, true); - b = true; - } else if(mtest->representsZero(true)) { - clear(true); - b = true; - } - break; - } - case COMPARISON_LESS: { - if(incomp > 0) { - } else if(mtest->representsNegative(true)) { - set(1, 1, 0, true); - b = true; - } else if(mtest->representsNonNegative(true)) { - clear(true); - b = true; - } - break; - } - case COMPARISON_GREATER: { - if(incomp > 0) { - } else if(mtest->representsPositive(true)) { - set(1, 1, 0, true); - b = true; - } else if(mtest->representsNonPositive(true)) { - clear(true); - b = true; - } - break; - } - case COMPARISON_EQUALS_LESS: { - if(incomp > 0) { - } else if(mtest->representsNonPositive(true)) { - set(1, 1, 0, true); - b = true; - } else if(mtest->representsPositive(true)) { - clear(true); - b = true; - } - break; - } - case COMPARISON_EQUALS_GREATER: { - if(incomp > 0) { - } else if(mtest->representsNonNegative(true)) { - set(1, 1, 0, true); - b = true; - } else if(mtest->representsNegative(true)) { - clear(true); - b = true; - } - break; - } - } - mtest->unref(); - break; - } - case STRUCT_FUNCTION: { - if(o_function == CALCULATOR->f_abs || o_function == CALCULATOR->f_root || o_function == CALCULATOR->f_interval || o_function == CALCULATOR->f_uncertainty || o_function == CALCULATOR->f_signum || o_function == CALCULATOR->f_dirac || o_function == CALCULATOR->f_heaviside) { - b = calculateFunctions(eo, false); - if(b) { - calculatesub(eo, feo, true, mparent, index_this); - break; - } - } else if(o_function == CALCULATOR->f_stripunits) { - b = calculateFunctions(eo, false); - if(b) calculatesub(eo, feo, true, mparent, index_this); - break; - } - } - default: { - if(recursive) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).calculatesub(eo, feo, true, this, i)) b = true; - } - CHILDREN_UPDATED; - } - if(eo.sync_units && syncUnits(eo.sync_nonlinear_unit_relations, NULL, true, feo)) { - unformat(eo); - if(recursive) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).calculatesub(eo, feo, true, this, i)) b = true; - } - CHILDREN_UPDATED; - } - } - } - } - return b; -} - -#define MERGE_INDEX(FUNC, TRY_LABEL) bool b = false;\ - TRY_LABEL:\ - for(size_t i = 0; i < index; i++) {\ - if(CALCULATOR->aborted()) break; \ - int r = CHILD(i).FUNC(CHILD(index), eo, this, i, index);\ - if(r == 0) {\ - SWAP_CHILDREN(i, index);\ - r = CHILD(i).FUNC(CHILD(index), eo, this, i, index, true);\ - if(r < 1) {\ - SWAP_CHILDREN(i, index);\ - } else if(r == 2) {\ - r = 3;\ - } else if(r == 3) {\ - r = 2;\ - }\ - }\ - if(r >= 1) {\ - ERASE(index);\ - if(!b && r == 2) {\ - b = true;\ - index = SIZE;\ - break;\ - } else {\ - b = true;\ - index = i;\ - goto TRY_LABEL;\ - }\ - }\ - }\ - for(size_t i = index + 1; i < SIZE; i++) {\ - if(CALCULATOR->aborted()) break; \ - int r = CHILD(index).FUNC(CHILD(i), eo, this, index, i);\ - if(r == 0) {\ - SWAP_CHILDREN(index, i);\ - r = CHILD(index).FUNC(CHILD(i), eo, this, index, i, true);\ - if(r < 1) {\ - SWAP_CHILDREN(index, i);\ - } else if(r == 2) {\ - r = 3;\ - } else if(r == 3) {\ - r = 2;\ - }\ - }\ - if(r >= 1) {\ - ERASE(i);\ - if(!b && r == 3) {\ - b = true;\ - break;\ - }\ - b = true;\ - if(r != 2) {\ - goto TRY_LABEL;\ - }\ - i--;\ - }\ - } - -#define MERGE_INDEX2 if(b && check_size) {\ - if(SIZE == 1) {\ - setToChild(1, false, mparent, index_this + 1);\ - } else if(SIZE == 0) {\ - clear(true);\ - } else {\ - evalSort();\ - }\ - return true;\ - } else {\ - evalSort();\ - return b;\ - } - - -bool MathStructure::calculateMergeIndex(size_t index, const EvaluationOptions &eo, const EvaluationOptions &feo, MathStructure *mparent, size_t index_this) { - switch(m_type) { - case STRUCT_MULTIPLICATION: { - return calculateMultiplyIndex(index, eo, true, mparent, index_this); - } - case STRUCT_ADDITION: { - return calculateAddIndex(index, eo, true, mparent, index_this); - } - case STRUCT_POWER: { - return calculateRaiseExponent(eo, mparent, index_this); - } - case STRUCT_LOGICAL_AND: { - return calculateLogicalAndIndex(index, eo, true, mparent, index_this); - } - case STRUCT_LOGICAL_OR: { - return calculateLogicalOrIndex(index, eo, true, mparent, index_this); - } - case STRUCT_LOGICAL_XOR: { - return calculateLogicalXorLast(eo, mparent, index_this); - } - case STRUCT_BITWISE_AND: { - return calculateBitwiseAndIndex(index, eo, true, mparent, index_this); - } - case STRUCT_BITWISE_OR: { - return calculateBitwiseOrIndex(index, eo, true, mparent, index_this); - } - case STRUCT_BITWISE_XOR: { - return calculateBitwiseXorIndex(index, eo, true, mparent, index_this); - } - default: {} - } - return calculatesub(eo, feo, false, mparent, index_this); -} -bool MathStructure::calculateLogicalOrLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { - return calculateLogicalOrIndex(SIZE - 1, eo, check_size, mparent, index_this); -} -bool MathStructure::calculateLogicalOrIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { - - if(index >= SIZE || !isLogicalOr()) { - CALCULATOR->error(true, "calculateLogicalOrIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); - return false; - } - - MERGE_INDEX(merge_logical_or, try_logical_or_index) - - if(b && check_size) { - if(SIZE == 1) { - if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) { - setToChild(1, false, mparent, index_this + 1); - } else if(CHILD(0).representsPositive()) { - clear(true); - o_number.setTrue(); - } else if(CHILD(0).representsNonPositive()) { - clear(true); - o_number.setFalse(); - } else { - APPEND(m_zero); - m_type = STRUCT_COMPARISON; - ct_comp = COMPARISON_GREATER; - } - } else if(SIZE == 0) { - clear(true); - } else { - evalSort(); - } - return true; - } else { - evalSort(); - return false; - } - -} -bool MathStructure::calculateLogicalOr(const MathStructure &mor, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - add(mor, OPERATION_LOGICAL_OR, true); - LAST.evalSort(); - return calculateLogicalOrIndex(SIZE - 1, eo, true, mparent, index_this); -} -bool MathStructure::calculateLogicalXorLast(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - - if(!isLogicalXor()) { - CALCULATOR->error(true, "calculateLogicalXorLast() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); - return false; - } - if(CHILD(0).merge_logical_xor(CHILD(1), eo, this, 0, 1) >= 1) { - if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) { - setToChild(1, false, mparent, index_this + 1); - } else if(CHILD(0).representsPositive()) { - clear(true); - o_number.setTrue(); - } else if(CHILD(0).representsNonPositive()) { - clear(true); - o_number.setFalse(); - } else { - APPEND(m_zero); - m_type = STRUCT_COMPARISON; - ct_comp = COMPARISON_GREATER; - } - return true; - } - return false; - -} -bool MathStructure::calculateLogicalXor(const MathStructure &mxor, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - add(mxor, OPERATION_LOGICAL_XOR); - LAST.evalSort(); - return calculateLogicalXorLast(eo, mparent, index_this); -} -bool MathStructure::calculateLogicalAndLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { - return calculateLogicalAndIndex(SIZE - 1, eo, check_size, mparent, index_this); -} -bool MathStructure::calculateLogicalAndIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { - - if(index >= SIZE || !isLogicalAnd()) { - CALCULATOR->error(true, "calculateLogicalAndIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); - return false; - } - - MERGE_INDEX(merge_logical_and, try_logical_and_index) - - if(b && check_size) { - if(SIZE == 1) { - if(CHILD(0).representsBoolean() || (mparent && !mparent->isMultiplication() && mparent->representsBoolean())) { - setToChild(1, false, mparent, index_this + 1); - } else if(CHILD(0).representsPositive()) { - clear(true); - o_number.setTrue(); - } else if(CHILD(0).representsNonPositive()) { - clear(true); - o_number.setFalse(); - } else { - APPEND(m_zero); - m_type = STRUCT_COMPARISON; - ct_comp = COMPARISON_GREATER; - } - } else if(SIZE == 0) { - clear(true); - } else { - evalSort(); - } - return true; - } else { - evalSort(); - return false; - } - -} -bool MathStructure::calculateLogicalAnd(const MathStructure &mand, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - add(mand, OPERATION_LOGICAL_AND, true); - LAST.evalSort(); - return calculateLogicalAndIndex(SIZE - 1, eo, true, mparent, index_this); -} -bool MathStructure::calculateInverse(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - return calculateRaise(m_minus_one, eo, mparent, index_this); -} -bool MathStructure::calculateNegate(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - if(m_type == STRUCT_NUMBER) { - Number nr(o_number); - if(nr.negate() && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate())) { - o_number = nr; - numberUpdated(); - return true; - } - if(!isMultiplication()) transform(STRUCT_MULTIPLICATION); - PREPEND(m_minus_one); - return false; - } - if(!isMultiplication()) transform(STRUCT_MULTIPLICATION); - PREPEND(m_minus_one); - return calculateMultiplyIndex(0, eo, true, mparent, index_this); -} -bool MathStructure::calculateBitwiseNot(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - transform(STRUCT_LOGICAL_NOT); - return calculatesub(eo, eo, false, mparent, index_this); -} -bool MathStructure::calculateLogicalNot(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - transform(STRUCT_BITWISE_NOT); - return calculatesub(eo, eo, false, mparent, index_this); -} -bool MathStructure::calculateRaiseExponent(const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - if(!isPower()) { - CALCULATOR->error(true, "calculateRaiseExponent() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); - return false; - } - if(CHILD(0).merge_power(CHILD(1), eo, this, 0, 1) >= 1) { - setToChild(1, false, mparent, index_this + 1); - return true; - } - return false; -} -bool MathStructure::calculateRaise(const MathStructure &mexp, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - if(mexp.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { - Number nr(o_number); - if(nr.raise(mexp.number(), eo.approximation < APPROXIMATION_APPROXIMATE) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mexp.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mexp.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mexp.number().includesInfinity())) { - o_number = nr; - numberUpdated(); - return true; - } - } - raise(mexp); - LAST.evalSort(); - return calculateRaiseExponent(eo, mparent, index_this); -} -bool MathStructure::calculateBitwiseAndLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { - return calculateBitwiseAndIndex(SIZE - 1, eo, check_size, mparent, index_this); -} -bool MathStructure::calculateBitwiseAndIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { - - if(index >= SIZE || !isBitwiseAnd()) { - CALCULATOR->error(true, "calculateBitwiseAndIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); - return false; - } - - MERGE_INDEX(merge_bitwise_and, try_bitwise_and_index) - MERGE_INDEX2 - -} -bool MathStructure::calculateBitwiseAnd(const MathStructure &mand, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - add(mand, OPERATION_BITWISE_AND, true); - LAST.evalSort(); - return calculateBitwiseAndIndex(SIZE - 1, eo, true, mparent, index_this); -} -bool MathStructure::calculateBitwiseOrLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { - return calculateBitwiseOrIndex(SIZE - 1, eo, check_size, mparent, index_this); -} -bool MathStructure::calculateBitwiseOrIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { - - if(index >= SIZE || !isBitwiseOr()) { - CALCULATOR->error(true, "calculateBitwiseOrIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); - return false; - } - - MERGE_INDEX(merge_bitwise_or, try_bitwise_or_index) - MERGE_INDEX2 - -} -bool MathStructure::calculateBitwiseOr(const MathStructure &mor, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - add(mor, OPERATION_BITWISE_OR, true); - LAST.evalSort(); - return calculateBitwiseOrIndex(SIZE - 1, eo, true, mparent, index_this); -} -bool MathStructure::calculateBitwiseXorLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { - return calculateBitwiseXorIndex(SIZE - 1, eo, check_size, mparent, index_this); -} -bool MathStructure::calculateBitwiseXorIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { - - if(index >= SIZE || !isBitwiseXor()) { - CALCULATOR->error(true, "calculateBitwiseXorIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); - return false; - } - - MERGE_INDEX(merge_bitwise_xor, try_bitwise_xor_index) - MERGE_INDEX2 - -} -bool MathStructure::calculateBitwiseXor(const MathStructure &mxor, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - add(mxor, OPERATION_BITWISE_XOR, true); - LAST.evalSort(); - return calculateBitwiseXorIndex(SIZE - 1, eo, true, mparent, index_this); -} -bool MathStructure::calculateMultiplyLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { - return calculateMultiplyIndex(SIZE - 1, eo, check_size, mparent, index_this); -} -bool MathStructure::calculateMultiplyIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { - - if(index >= SIZE || !isMultiplication()) { - CALCULATOR->error(true, "calculateMultiplyIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); - return false; - } - - bool b = false; - try_multiply_matrix_index: - bool b_matrix = !CHILD(index).representsNonMatrix(); - if(index > 0) { - for(size_t i = index - 1; ; i--) { - if(CALCULATOR->aborted()) break; - int r = CHILD(i).merge_multiplication(CHILD(index), eo, this, i, index); - if(r == 0) { - SWAP_CHILDREN(i, index); - r = CHILD(i).merge_multiplication(CHILD(index), eo, this, i, index, true); - if(r < 1) { - SWAP_CHILDREN(i, index); - } else if(r == 2) { - r = 3; - } else if(r == 3) { - r = 2; - } - } - if(r >= 1) { - ERASE(index); - if(!b && r == 2) { - b = true; - index = SIZE; - break; - } else { - b = true; - index = i; - goto try_multiply_matrix_index; - } - } - if(i == 0) break; - if(b_matrix && !CHILD(i).representsNonMatrix()) break; - } - } - - bool had_matrix = false; - for(size_t i = index + 1; i < SIZE; i++) { - if(had_matrix && !CHILD(i).representsNonMatrix()) continue; - if(CALCULATOR->aborted()) break; - int r = CHILD(index).merge_multiplication(CHILD(i), eo, this, index, i); - if(r == 0) { - SWAP_CHILDREN(index, i); - r = CHILD(index).merge_multiplication(CHILD(i), eo, this, index, i, true); - if(r < 1) { - SWAP_CHILDREN(index, i); - } else if(r == 2) { - r = 3; - } else if(r == 3) { - r = 2; - } - } - if(r >= 1) { - ERASE(i); - if(!b && r == 3) { - b = true; - break; - } - b = true; - if(r != 2) { - goto try_multiply_matrix_index; - } - i--; - } - if(i == SIZE - 1) break; - if(b_matrix && !CHILD(i).representsNonMatrix()) had_matrix = true; - } - - MERGE_INDEX2 - -} -bool MathStructure::calculateMultiply(const MathStructure &mmul, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - if(mmul.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { - Number nr(o_number); - if(nr.multiply(mmul.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mmul.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mmul.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mmul.number().includesInfinity())) { - o_number = nr; - numberUpdated(); - return true; - } - } - multiply(mmul, true); - LAST.evalSort(); - return calculateMultiplyIndex(SIZE - 1, eo, true, mparent, index_this); -} -bool MathStructure::calculateDivide(const MathStructure &mdiv, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - if(mdiv.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { - Number nr(o_number); - if(nr.divide(mdiv.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || mdiv.number().isApproximate()) && (eo.allow_complex || !nr.isComplex() || o_number.isComplex() || mdiv.number().isComplex()) && (eo.allow_infinite || !nr.includesInfinity() || o_number.includesInfinity() || mdiv.number().includesInfinity())) { - o_number = nr; - numberUpdated(); - return true; - } - } - MathStructure *mmul = new MathStructure(mdiv); - mmul->evalSort(); - multiply_nocopy(mmul, true); - LAST.calculateInverse(eo, this, SIZE - 1); - return calculateMultiplyIndex(SIZE - 1, eo, true, mparent, index_this); -} -bool MathStructure::calculateAddLast(const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { - return calculateAddIndex(SIZE - 1, eo, check_size, mparent, index_this); -} -bool MathStructure::calculateAddIndex(size_t index, const EvaluationOptions &eo, bool check_size, MathStructure *mparent, size_t index_this) { - - if(index >= SIZE || !isAddition()) { - CALCULATOR->error(true, "calculateAddIndex() error: %s. %s", format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); - return false; - } - - MERGE_INDEX(merge_addition, try_add_index) - MERGE_INDEX2 - -} -bool MathStructure::calculateAdd(const MathStructure &madd, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - if(madd.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { - Number nr(o_number); - if(nr.add(madd.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || madd.number().isApproximate())) { - o_number = nr; - numberUpdated(); - return true; - } - } - add(madd, true); - LAST.evalSort(); - return calculateAddIndex(SIZE - 1, eo, true, mparent, index_this); -} -bool MathStructure::calculateSubtract(const MathStructure &msub, const EvaluationOptions &eo, MathStructure *mparent, size_t index_this) { - if(msub.type() == STRUCT_NUMBER && m_type == STRUCT_NUMBER) { - Number nr(o_number); - if(nr.subtract(msub.number()) && (eo.approximation >= APPROXIMATION_APPROXIMATE || !nr.isApproximate() || o_number.isApproximate() || msub.number().isApproximate())) { - o_number = nr; - numberUpdated(); - return true; - } - } - MathStructure *madd = new MathStructure(msub); - madd->evalSort(); - add_nocopy(madd, true); - LAST.calculateNegate(eo, this, SIZE - 1); - return calculateAddIndex(SIZE - 1, eo, true, mparent, index_this); -} - -bool MathStructure::calculateFunctions(const EvaluationOptions &eo, bool recursive, bool do_unformat) { - - if(m_type == STRUCT_FUNCTION && o_function != eo.protected_function) { - - if(function_value) { - function_value->unref(); - function_value = NULL; - } - - if(!o_function->testArgumentCount(SIZE)) { - return false; - } - - if(o_function->maxargs() > -1 && (long int) SIZE > o_function->maxargs()) { - if(o_function->maxargs() == 1 && o_function->getArgumentDefinition(1) && o_function->getArgumentDefinition(1)->handlesVector()) { - bool b = false; - for(size_t i2 = 0; i2 < CHILD(0).size(); i2++) { - CHILD(0)[i2].transform(o_function); - if(CHILD(0)[i2].calculateFunctions(eo, recursive, do_unformat)) b = true; - CHILD(0).childUpdated(i2 + 1); - } - SET_CHILD_MAP(0) - return b; - } - REDUCE(o_function->maxargs()); - } - m_type = STRUCT_VECTOR; - Argument *arg = NULL, *last_arg = NULL; - int last_i = 0; - - for(size_t i = 0; i < SIZE; i++) { - arg = o_function->getArgumentDefinition(i + 1); - if(arg) { - last_arg = arg; - last_i = i; - if(i > 0 && arg->type() == ARGUMENT_TYPE_SYMBOLIC && (CHILD(i).isZero() || CHILD(i).isUndefined())) { - CHILD(i).set(CHILD(0).find_x_var(), true); - if(CHILD(i).isUndefined() && CHILD(0).isVariable() && CHILD(0).variable()->isKnown()) CHILD(i).set(((KnownVariable*) CHILD(0).variable())->get().find_x_var(), true); - if(CHILD(i).isUndefined()) { - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mtest(CHILD(0)); - mtest.eval(eo); - CHILD(i).set(mtest.find_x_var(), true); - CALCULATOR->endTemporaryStopMessages(); - } - if(CHILD(i).isUndefined()) { - CALCULATOR->error(false, _("No unknown variable/symbol was found."), NULL); - CHILD(i).set(CALCULATOR->v_x, true); - } - } - if(!arg->test(CHILD(i), i + 1, o_function, eo)) { - if(arg->handlesVector() && CHILD(i).isVector()) { - bool b = false; - for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { - CHILD(i)[i2].transform(o_function); - for(size_t i3 = 0; i3 < SIZE; i3++) { - if(i3 < i) CHILD(i)[i2].insertChild(CHILD(i3), i3 + 1); - else if(i3 > i) CHILD(i)[i2].addChild(CHILD(i3)); - } - if(CHILD(i)[i2].calculateFunctions(eo, recursive, do_unformat)) b = true; - CHILD(i).childUpdated(i2 + 1); - } - SET_CHILD_MAP(i); - return b; - } - m_type = STRUCT_FUNCTION; - CHILD_UPDATED(i); - return false; - } else { - CHILD_UPDATED(i); - } - if(arg->handlesVector()) { - if(arg->tests() && !CHILD(i).isVector() && !CHILD(i).representsScalar()) { - CHILD(i).eval(eo); - CHILD_UPDATED(i); - } - if(CHILD(i).isVector()) { - bool b = false; - for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { - CHILD(i)[i2].transform(o_function); - for(size_t i3 = 0; i3 < SIZE; i3++) { - if(i3 < i) CHILD(i)[i2].insertChild(CHILD(i3), i3 + 1); - else if(i3 > i) CHILD(i)[i2].addChild(CHILD(i3)); - } - if(CHILD(i)[i2].calculateFunctions(eo, recursive, do_unformat)) b = true; - CHILD(i).childUpdated(i2 + 1); - } - SET_CHILD_MAP(i); - return b; - } - } - } - } - - if(last_arg && o_function->maxargs() < 0 && last_i >= o_function->minargs()) { - for(size_t i = last_i + 1; i < SIZE; i++) { - if(!last_arg->test(CHILD(i), i + 1, o_function, eo)) { - m_type = STRUCT_FUNCTION; - CHILD_UPDATED(i); - return false; - } else { - CHILD_UPDATED(i); - } - } - } - - if(!o_function->testCondition(*this)) { - m_type = STRUCT_FUNCTION; - return false; - } - MathStructure *mstruct = new MathStructure(); - int ret = o_function->calculate(*mstruct, *this, eo); - if(ret > 0) { - set_nocopy(*mstruct, true); - if(recursive) calculateFunctions(eo); - mstruct->unref(); - if(do_unformat) unformat(eo); - return true; - } else { - if(ret < 0) { - ret = -ret; - if(o_function->maxargs() > 0 && ret > o_function->maxargs()) { - if(mstruct->isVector()) { - if(do_unformat) mstruct->unformat(eo); - for(size_t arg_i = 1; arg_i <= SIZE && arg_i <= mstruct->size(); arg_i++) { - mstruct->getChild(arg_i)->ref(); - setChild_nocopy(mstruct->getChild(arg_i), arg_i); - } - } - } else if(ret <= (long int) SIZE) { - if(do_unformat) mstruct->unformat(eo); - mstruct->ref(); - setChild_nocopy(mstruct, ret); - } - } - /*if(eo.approximation == APPROXIMATION_EXACT) { - mstruct->clear(); - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - CALCULATOR->beginTemporaryStopMessages(); - if(o_function->calculate(*mstruct, *this, eo2) > 0) { - function_value = mstruct; - function_value->ref(); - function_value->calculateFunctions(eo2); - } - if(CALCULATOR->endTemporaryStopMessages() > 0 && function_value) { - function_value->unref(); - function_value = NULL; - } - }*/ - m_type = STRUCT_FUNCTION; - mstruct->unref(); - for(size_t i = 0; i < SIZE; i++) { - arg = o_function->getArgumentDefinition(i + 1); - if(arg && arg->handlesVector()) { - if(!CHILD(i).isVector()) { - CHILD(i).calculatesub(eo, eo, false); - if(!CHILD(i).isVector()) return false; - } - bool b = false; - for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { - CHILD(i)[i2].transform(o_function); - for(size_t i3 = 0; i3 < SIZE; i3++) { - if(i3 < i) CHILD(i)[i2].insertChild(CHILD(i3), i3 + 1); - else if(i3 > i) CHILD(i)[i2].addChild(CHILD(i3)); - } - if(CHILD(i)[i2].calculateFunctions(eo, recursive, do_unformat)) b = true; - CHILD(i).childUpdated(i2 + 1); - } - SET_CHILD_MAP(i); - return b; - } - } - return false; - } - } - bool b = false; - if(recursive) { - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) break; - if(CHILD(i).calculateFunctions(eo, recursive, do_unformat)) { - CHILD_UPDATED(i); - b = true; - } - } - } - return b; - -} - -int evalSortCompare(const MathStructure &mstruct1, const MathStructure &mstruct2, const MathStructure &parent, bool b_abs = false); -int evalSortCompare(const MathStructure &mstruct1, const MathStructure &mstruct2, const MathStructure &parent, bool b_abs) { - if(parent.isMultiplication()) { - if((!mstruct1.representsNonMatrix() && !mstruct2.representsScalar()) || (!mstruct2.representsNonMatrix() && !mstruct1.representsScalar())) { - return 0; - } - } - if(b_abs || parent.isAddition()) { - if(mstruct1.isMultiplication() && mstruct1.size() > 0) { - size_t start = 0; - while(mstruct1[start].isNumber() && mstruct1.size() > start + 1) { - start++; - } - int i2; - if(mstruct2.isMultiplication()) { - if(mstruct2.size() < 1) return -1; - size_t start2 = 0; - while(mstruct2[start2].isNumber() && mstruct2.size() > start2 + 1) { - start2++; - } - for(size_t i = 0; ; i++) { - if(i + start2 >= mstruct2.size()) { - if(i + start >= mstruct1.size()) { - if(start2 == start) { - for(size_t i3 = 0; i3 < start; i3++) { - i2 = evalSortCompare(mstruct1[i3], mstruct2[i3], parent, b_abs); - if(i2 != 0) return i2; - } - return 0; - } - if(start2 > start) return -1; - } - return 1; - } - if(i + start >= mstruct1.size()) return -1; - i2 = evalSortCompare(mstruct1[i + start], mstruct2[i + start2], parent, b_abs); - if(i2 != 0) return i2; - } - if(mstruct1.size() - start == mstruct2.size() - start2) return 0; - return -1; - } else { - i2 = evalSortCompare(mstruct1[start], mstruct2, parent, b_abs); - if(i2 != 0) return i2; - if(b_abs && start == 1 && (mstruct1[0].isMinusOne() || mstruct1[0].isOne())) return 0; - return 1; - } - } else if(mstruct2.isMultiplication() && mstruct2.size() > 0) { - size_t start = 0; - while(mstruct2[start].isNumber() && mstruct2.size() > start + 1) { - start++; - } - int i2; - if(mstruct1.isMultiplication()) { - return 1; - } else { - i2 = evalSortCompare(mstruct1, mstruct2[start], parent, b_abs); - if(i2 != 0) return i2; - if(b_abs && start == 1 && (mstruct2[0].isMinusOne() || mstruct2[0].isOne())) return 0; - return -1; - } - } - } - if(mstruct1.type() != mstruct2.type()) { - if(!parent.isMultiplication()) { - if(mstruct2.isNumber()) return -1; - if(mstruct1.isNumber()) return 1; - } - if(!parent.isMultiplication() || (!mstruct1.isNumber() && !mstruct2.isNumber())) { - if(mstruct2.isPower()) { - int i = evalSortCompare(mstruct1, mstruct2[0], parent, b_abs); - if(i == 0) { - return evalSortCompare(m_one, mstruct2[1], parent, b_abs); - } - return i; - } - if(mstruct1.isPower()) { - int i = evalSortCompare(mstruct1[0], mstruct2, parent, b_abs); - if(i == 0) { - return evalSortCompare(mstruct1[1], m_one, parent, b_abs); - } - return i; - } - } - if(mstruct2.isAborted()) return -1; - if(mstruct1.isAborted()) return 1; - if(mstruct2.isInverse()) return -1; - if(mstruct1.isInverse()) return 1; - if(mstruct2.isDivision()) return -1; - if(mstruct1.isDivision()) return 1; - if(mstruct2.isNegate()) return -1; - if(mstruct1.isNegate()) return 1; - if(mstruct2.isLogicalAnd()) return -1; - if(mstruct1.isLogicalAnd()) return 1; - if(mstruct2.isLogicalOr()) return -1; - if(mstruct1.isLogicalOr()) return 1; - if(mstruct2.isLogicalXor()) return -1; - if(mstruct1.isLogicalXor()) return 1; - if(mstruct2.isLogicalNot()) return -1; - if(mstruct1.isLogicalNot()) return 1; - if(mstruct2.isComparison()) return -1; - if(mstruct1.isComparison()) return 1; - if(mstruct2.isBitwiseOr()) return -1; - if(mstruct1.isBitwiseOr()) return 1; - if(mstruct2.isBitwiseXor()) return -1; - if(mstruct1.isBitwiseXor()) return 1; - if(mstruct2.isBitwiseAnd()) return -1; - if(mstruct1.isBitwiseAnd()) return 1; - if(mstruct2.isBitwiseNot()) return -1; - if(mstruct1.isBitwiseNot()) return 1; - if(mstruct2.isUndefined()) return -1; - if(mstruct1.isUndefined()) return 1; - if(mstruct2.isFunction()) return -1; - if(mstruct1.isFunction()) return 1; - if(mstruct2.isAddition()) return -1; - if(mstruct1.isAddition()) return 1; - if(mstruct2.isMultiplication()) return -1; - if(mstruct1.isMultiplication()) return 1; - if(mstruct2.isPower()) return -1; - if(mstruct1.isPower()) return 1; - if(mstruct2.isUnit()) return -1; - if(mstruct1.isUnit()) return 1; - if(mstruct2.isSymbolic()) return -1; - if(mstruct1.isSymbolic()) return 1; - if(mstruct2.isVariable()) return -1; - if(mstruct1.isVariable()) return 1; - if(mstruct2.isDateTime()) return -1; - if(mstruct1.isDateTime()) return 1; - if(parent.isMultiplication()) { - if(mstruct2.isNumber()) return -1; - if(mstruct1.isNumber()) return 1; - } - return -1; - } - switch(mstruct1.type()) { - case STRUCT_NUMBER: { - if(CALCULATOR->aborted()) return 0; - if(b_abs) { - ComparisonResult cmp = mstruct1.number().compareAbsolute(mstruct2.number()); - if(cmp == COMPARISON_RESULT_LESS) return -1; - else if(cmp == COMPARISON_RESULT_GREATER) return 1; - return 0; - } - if(!mstruct1.number().hasImaginaryPart() && !mstruct2.number().hasImaginaryPart()) { - if(mstruct1.number().isFloatingPoint()) { - if(!mstruct2.number().isFloatingPoint()) return 1; - if(mstruct1.number().isInterval()) { - if(!mstruct2.number().isInterval()) return 1; - } else if(mstruct2.number().isInterval()) return -1; - } else if(mstruct2.number().isFloatingPoint()) return -1; - ComparisonResult cmp = mstruct1.number().compare(mstruct2.number()); - if(cmp == COMPARISON_RESULT_LESS) return -1; - else if(cmp == COMPARISON_RESULT_GREATER) return 1; - return 0; - } else { - if(!mstruct1.number().hasRealPart()) { - if(mstruct2.number().hasRealPart()) { - return 1; - } else { - ComparisonResult cmp = mstruct1.number().compareImaginaryParts(mstruct2.number()); - if(cmp == COMPARISON_RESULT_LESS) return -1; - else if(cmp == COMPARISON_RESULT_GREATER) return 1; - return 0; - } - } else if(mstruct2.number().hasRealPart()) { - ComparisonResult cmp = mstruct1.number().compareRealParts(mstruct2.number()); - if(cmp == COMPARISON_RESULT_EQUAL) { - cmp = mstruct1.number().compareImaginaryParts(mstruct2.number()); - } - if(cmp == COMPARISON_RESULT_LESS) return -1; - else if(cmp == COMPARISON_RESULT_GREATER) return 1; - return 0; - } else { - return -1; - } - } - return -1; - } - case STRUCT_UNIT: { - if(mstruct1.unit() < mstruct2.unit()) return -1; - if(mstruct1.unit() == mstruct2.unit()) return 0; - return 1; - } - case STRUCT_SYMBOLIC: { - if(mstruct1.symbol() < mstruct2.symbol()) return -1; - else if(mstruct1.symbol() == mstruct2.symbol()) return 0; - return 1; - } - case STRUCT_VARIABLE: { - if(mstruct1.variable() < mstruct2.variable()) return -1; - else if(mstruct1.variable() == mstruct2.variable()) return 0; - return 1; - } - case STRUCT_FUNCTION: { - if(mstruct1.function() < mstruct2.function()) return -1; - if(mstruct1.function() == mstruct2.function()) { - for(size_t i = 0; i < mstruct2.size(); i++) { - if(i >= mstruct1.size()) { - return -1; - } - int i2 = evalSortCompare(mstruct1[i], mstruct2[i], parent, b_abs); - if(i2 != 0) return i2; - } - return 0; - } - return 1; - } - case STRUCT_POWER: { - int i = evalSortCompare(mstruct1[0], mstruct2[0], parent, b_abs); - if(i == 0) { - return evalSortCompare(mstruct1[1], mstruct2[1], parent, b_abs); - } - return i; - } - default: { - if(mstruct2.size() < mstruct1.size()) return -1; - else if(mstruct2.size() > mstruct1.size()) return 1; - int ie; - for(size_t i = 0; i < mstruct1.size(); i++) { - ie = evalSortCompare(mstruct1[i], mstruct2[i], parent, b_abs); - if(ie != 0) { - return ie; - } - } - } - } - return 0; -} - -void MathStructure::evalSort(bool recursive, bool b_abs) { - if(recursive) { - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).evalSort(true, b_abs); - } - } - //if(m_type != STRUCT_ADDITION && m_type != STRUCT_MULTIPLICATION && m_type != STRUCT_LOGICAL_AND && m_type != STRUCT_LOGICAL_OR && m_type != STRUCT_LOGICAL_XOR && m_type != STRUCT_BITWISE_AND && m_type != STRUCT_BITWISE_OR && m_type != STRUCT_BITWISE_XOR) return; - if(m_type != STRUCT_ADDITION && m_type != STRUCT_MULTIPLICATION && m_type != STRUCT_BITWISE_AND && m_type != STRUCT_BITWISE_OR && m_type != STRUCT_BITWISE_XOR) return; - if(m_type == STRUCT_ADDITION && containsType(STRUCT_DATETIME, false, true, false) > 0) return; - vector sorted; - sorted.reserve(SIZE); - for(size_t i = 0; i < SIZE; i++) { - if(i == 0) { - sorted.push_back(v_order[i]); - } else { - if(evalSortCompare(CHILD(i), *v_subs[sorted.back()], *this, b_abs) >= 0) { - sorted.push_back(v_order[i]); - } else if(sorted.size() == 1) { - sorted.insert(sorted.begin(), v_order[i]); - } else { - for(size_t i2 = sorted.size() - 2; ; i2--) { - if(evalSortCompare(CHILD(i), *v_subs[sorted[i2]], *this, b_abs) >= 0) { - sorted.insert(sorted.begin() + i2 + 1, v_order[i]); - break; - } - if(i2 == 0) { - sorted.insert(sorted.begin(), v_order[i]); - break; - } - } - } - } - } - for(size_t i2 = 0; i2 < sorted.size(); i2++) { - v_order[i2] = sorted[i2]; - } -} - -int sortCompare(const MathStructure &mstruct1, const MathStructure &mstruct2, const MathStructure &parent, const PrintOptions &po); -int sortCompare(const MathStructure &mstruct1, const MathStructure &mstruct2, const MathStructure &parent, const PrintOptions &po) { - if(parent.isMultiplication()) { - if(!mstruct1.representsNonMatrix() && !mstruct2.representsNonMatrix()) { - return 0; - } - } - if(parent.isAddition() && po.sort_options.minus_last) { - bool m1 = mstruct1.hasNegativeSign(), m2 = mstruct2.hasNegativeSign(); - if(m1 && !m2) { - return 1; - } else if(m2 && !m1) { - return -1; - } - } - if(parent.isAddition() && (mstruct1.isUnit() || (mstruct1.isMultiplication() && mstruct1.size() == 2 && mstruct1[1].isUnit())) && (mstruct2.isUnit() || (mstruct2.isMultiplication() && mstruct2.size() == 2 && mstruct2[1].isUnit()))) { - Unit *u1, *u2; - if(mstruct1.isUnit()) u1 = mstruct1.unit(); - else u1 = mstruct1[1].unit(); - if(mstruct2.isUnit()) u2 = mstruct2.unit(); - else u2 = mstruct2[1].unit(); - if(u1->isParentOf(u2)) return 1; - if(u2->isParentOf(u1)) return -1; - } - bool isdiv1 = false, isdiv2 = false; - if(!po.negative_exponents) { - if(mstruct1.isMultiplication()) { - for(size_t i = 0; i < mstruct1.size(); i++) { - if(mstruct1[i].isPower() && mstruct1[i][1].hasNegativeSign()) { - isdiv1 = true; - break; - } - } - } else if(mstruct1.isPower() && mstruct1[1].hasNegativeSign()) { - isdiv1 = true; - } - if(mstruct2.isMultiplication()) { - for(size_t i = 0; i < mstruct2.size(); i++) { - if(mstruct2[i].isPower() && mstruct2[i][1].hasNegativeSign()) { - isdiv2 = true; - break; - } - } - } else if(mstruct2.isPower() && mstruct2[1].hasNegativeSign()) { - isdiv2 = true; - } - } - if(parent.isAddition() && isdiv1 == isdiv2) { - if(mstruct1.isMultiplication() && mstruct1.size() > 0) { - size_t start = 0; - while(mstruct1[start].isNumber() && mstruct1.size() > start + 1) { - start++; - } - int i2; - if(mstruct2.isMultiplication()) { - if(mstruct2.size() < 1) return -1; - size_t start2 = 0; - while(mstruct2[start2].isNumber() && mstruct2.size() > start2 + 1) { - start2++; - } - for(size_t i = 0; i + start < mstruct1.size(); i++) { - if(i + start2 >= mstruct2.size()) return 1; - i2 = sortCompare(mstruct1[i + start], mstruct2[i + start2], parent, po); - if(i2 != 0) return i2; - } - if(mstruct1.size() - start == mstruct2.size() - start2) return 0; - if(parent.isMultiplication()) return -1; - else return 1; - } else { - i2 = sortCompare(mstruct1[start], mstruct2, parent, po); - if(i2 != 0) return i2; - } - } else if(mstruct2.isMultiplication() && mstruct2.size() > 0) { - size_t start = 0; - while(mstruct2[start].isNumber() && mstruct2.size() > start + 1) { - start++; - } - int i2; - if(mstruct1.isMultiplication()) { - return 1; - } else { - i2 = sortCompare(mstruct1, mstruct2[start], parent, po); - if(i2 != 0) return i2; - } - } - } - if(mstruct1.isVariable() && mstruct1.variable() == CALCULATOR->v_C) return 1; - if(mstruct2.isVariable() && mstruct2.variable() == CALCULATOR->v_C) return -1; - if(mstruct1.type() != mstruct2.type()) { - if(mstruct1.isVariable() && mstruct2.isSymbolic()) { - if(parent.isMultiplication()) { - if(mstruct1.variable()->isKnown()) return -1; - } - if(mstruct1.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name < mstruct2.symbol()) return -1; - else return 1; - } - if(mstruct2.isVariable() && mstruct1.isSymbolic()) { - if(parent.isMultiplication()) { - if(mstruct2.variable()->isKnown()) return 1; - } - if(mstruct1.symbol() < mstruct2.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name) return -1; - else return 1; - } - if(!parent.isMultiplication() || (!mstruct1.isNumber() && !mstruct2.isNumber())) { - if(mstruct2.isPower()) { - int i = sortCompare(mstruct1, mstruct2[0], parent, po); - if(i == 0) { - return sortCompare(m_one, mstruct2[1], parent, po); - } - return i; - } - if(mstruct1.isPower()) { - int i = sortCompare(mstruct1[0], mstruct2, parent, po); - if(i == 0) { - return sortCompare(mstruct1[1], m_one, parent, po); - } - return i; - } - } - if(parent.isMultiplication()) { - if(mstruct2.isUnit()) return -1; - if(mstruct1.isUnit()) return 1; - if(mstruct1.isAddition() && !mstruct2.isAddition() && !mstruct1.containsUnknowns() && (mstruct2.isUnknown_exp() || (mstruct2.isMultiplication() && mstruct2.containsUnknowns()))) return -1; - if(mstruct2.isAddition() && !mstruct1.isAddition() && !mstruct2.containsUnknowns() && (mstruct1.isUnknown_exp() || (mstruct1.isMultiplication() && mstruct1.containsUnknowns()))) return 1; - } - if(mstruct2.isAborted()) return -1; - if(mstruct1.isAborted()) return 1; - if(mstruct2.isInverse()) return -1; - if(mstruct1.isInverse()) return 1; - if(mstruct2.isDivision()) return -1; - if(mstruct1.isDivision()) return 1; - if(mstruct2.isNegate()) return -1; - if(mstruct1.isNegate()) return 1; - if(mstruct2.isLogicalAnd()) return -1; - if(mstruct1.isLogicalAnd()) return 1; - if(mstruct2.isLogicalOr()) return -1; - if(mstruct1.isLogicalOr()) return 1; - if(mstruct2.isLogicalXor()) return -1; - if(mstruct1.isLogicalXor()) return 1; - if(mstruct2.isLogicalNot()) return -1; - if(mstruct1.isLogicalNot()) return 1; - if(mstruct2.isComparison()) return -1; - if(mstruct1.isComparison()) return 1; - if(mstruct2.isBitwiseOr()) return -1; - if(mstruct1.isBitwiseOr()) return 1; - if(mstruct2.isBitwiseXor()) return -1; - if(mstruct1.isBitwiseXor()) return 1; - if(mstruct2.isBitwiseAnd()) return -1; - if(mstruct1.isBitwiseAnd()) return 1; - if(mstruct2.isBitwiseNot()) return -1; - if(mstruct1.isBitwiseNot()) return 1; - if(mstruct2.isUndefined()) return -1; - if(mstruct1.isUndefined()) return 1; - if(mstruct2.isFunction()) return -1; - if(mstruct1.isFunction()) return 1; - if(mstruct2.isAddition()) return -1; - if(mstruct1.isAddition()) return 1; - if(!parent.isMultiplication()) { - if(isdiv2 && mstruct2.isMultiplication()) return -1; - if(isdiv1 && mstruct1.isMultiplication()) return 1; - if(mstruct2.isNumber()) return -1; - if(mstruct1.isNumber()) return 1; - } - if(mstruct2.isMultiplication()) return -1; - if(mstruct1.isMultiplication()) return 1; - if(mstruct2.isPower()) return -1; - if(mstruct1.isPower()) return 1; - if(mstruct2.isUnit()) return -1; - if(mstruct1.isUnit()) return 1; - if(mstruct2.isSymbolic()) return -1; - if(mstruct1.isSymbolic()) return 1; - if(mstruct2.isVariable()) return -1; - if(mstruct1.isVariable()) return 1; - if(mstruct2.isDateTime()) return -1; - if(mstruct1.isDateTime()) return 1; - if(parent.isMultiplication()) { - if(mstruct2.isNumber()) return -1; - if(mstruct1.isNumber()) return 1; - } - return -1; - } - switch(mstruct1.type()) { - case STRUCT_NUMBER: { - if(!mstruct1.number().hasImaginaryPart() && !mstruct2.number().hasImaginaryPart()) { - ComparisonResult cmp; - if(parent.isMultiplication() && mstruct2.number().isNegative() != mstruct1.number().isNegative()) cmp = mstruct2.number().compare(mstruct1.number()); - else cmp = mstruct1.number().compare(mstruct2.number()); - if(cmp == COMPARISON_RESULT_LESS) return -1; - else if(cmp == COMPARISON_RESULT_GREATER) return 1; - return 0; - } else { - if(!mstruct1.number().hasRealPart()) { - if(mstruct2.number().hasRealPart()) { - return 1; - } else { - ComparisonResult cmp = mstruct1.number().compareImaginaryParts(mstruct2.number()); - if(cmp == COMPARISON_RESULT_LESS) return -1; - else if(cmp == COMPARISON_RESULT_GREATER) return 1; - return 0; - } - } else if(mstruct2.number().hasRealPart()) { - ComparisonResult cmp = mstruct1.number().compareRealParts(mstruct2.number()); - if(cmp == COMPARISON_RESULT_EQUAL) { - cmp = mstruct1.number().compareImaginaryParts(mstruct2.number()); - } - if(cmp == COMPARISON_RESULT_LESS) return -1; - else if(cmp == COMPARISON_RESULT_GREATER) return 1; - return 0; - } else { - return -1; - } - } - return -1; - } - case STRUCT_UNIT: { - if(mstruct1.unit() == mstruct2.unit()) return 0; - if(mstruct1.unit()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, mstruct1.isPlural(), po.use_reference_names).name < mstruct2.unit()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, mstruct2.isPlural(), po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name) return -1; - return 1; - } - case STRUCT_SYMBOLIC: { - if(mstruct1.symbol() < mstruct2.symbol()) return -1; - else if(mstruct1.symbol() == mstruct2.symbol()) return 0; - return 1; - } - case STRUCT_VARIABLE: { - if(mstruct1.variable() == mstruct2.variable()) return 0; - if(parent.isMultiplication()) { - if(mstruct1.variable()->isKnown() && !mstruct2.variable()->isKnown()) return -1; - if(!mstruct1.variable()->isKnown() && mstruct2.variable()->isKnown()) return 1; - } - if(mstruct1.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names).name < mstruct2.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name) return -1; - return 1; - } - case STRUCT_FUNCTION: { - if(mstruct1.function() == mstruct2.function()) { - for(size_t i = 0; i < mstruct2.size(); i++) { - if(i >= mstruct1.size()) { - return -1; - } - int i2 = sortCompare(mstruct1[i], mstruct2[i], parent, po); - if(i2 != 0) return i2; - } - return 0; - } - if(mstruct1.function()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names).name < mstruct2.function()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name) return -1; - return 1; - } - case STRUCT_POWER: { - if(!po.negative_exponents) { - bool b1 = mstruct1[1].hasNegativeSign(); - bool b2 = mstruct2[1].hasNegativeSign(); - if(b1 && !b2) return -1; - if(b2 && !b1) return 1; - } - int i = sortCompare(mstruct1[0], mstruct2[0], parent, po); - if(i == 0) { - return sortCompare(mstruct1[1], mstruct2[1], parent, po); - } - return i; - } - case STRUCT_MULTIPLICATION: { - if(isdiv1 != isdiv2) { - if(isdiv1) return 1; - return -1; - } - } - case STRUCT_COMPARISON: { - if(mstruct1.comparisonType() != mstruct2.comparisonType()) { - if(mstruct2.comparisonType() == COMPARISON_EQUALS || ((mstruct1.comparisonType() == COMPARISON_LESS || mstruct1.comparisonType() == COMPARISON_EQUALS_LESS) && (mstruct2.comparisonType() == COMPARISON_GREATER || mstruct2.comparisonType() == COMPARISON_EQUALS_GREATER))) { - return 1; - } - if(mstruct1.comparisonType() == COMPARISON_EQUALS || ((mstruct1.comparisonType() == COMPARISON_GREATER || mstruct1.comparisonType() == COMPARISON_EQUALS_GREATER) && (mstruct2.comparisonType() == COMPARISON_LESS || mstruct2.comparisonType() == COMPARISON_EQUALS_LESS))) { - return -1; - } - } - } - default: { - int ie; - for(size_t i = 0; i < mstruct1.size(); i++) { - if(i >= mstruct2.size()) return 1; - ie = sortCompare(mstruct1[i], mstruct2[i], parent, po); - if(ie != 0) { - return ie; - } - } - } - } - return 0; -} - -void MathStructure::sort(const PrintOptions &po, bool recursive) { - if(recursive) { - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) break; - CHILD(i).sort(po); - } - } - if(m_type == STRUCT_COMPARISON) { - if((CHILD(0).isZero() && !CHILD(1).isZero()) || (CHILD(0).isNumber() && !CHILD(1).isNumber())) { - SWAP_CHILDREN(0, 1) - if(ct_comp == COMPARISON_LESS) ct_comp = COMPARISON_GREATER; - else if(ct_comp == COMPARISON_EQUALS_LESS) ct_comp = COMPARISON_EQUALS_GREATER; - else if(ct_comp == COMPARISON_GREATER) ct_comp = COMPARISON_LESS; - else if(ct_comp == COMPARISON_EQUALS_GREATER) ct_comp = COMPARISON_EQUALS_LESS; - } - return; - } - if(m_type != STRUCT_ADDITION && m_type != STRUCT_MULTIPLICATION && m_type != STRUCT_BITWISE_AND && m_type != STRUCT_BITWISE_OR && m_type != STRUCT_BITWISE_XOR && m_type != STRUCT_LOGICAL_AND && m_type != STRUCT_LOGICAL_OR) return; - if(m_type == STRUCT_ADDITION && containsType(STRUCT_DATETIME, false, true, false) > 0) return; - vector sorted; - bool b; - PrintOptions po2 = po; - po2.sort_options.minus_last = po.sort_options.minus_last && SIZE == 2; - //!containsUnknowns(); - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return; - b = false; - for(size_t i2 = 0; i2 < sorted.size(); i2++) { - if(sortCompare(CHILD(i), *v_subs[sorted[i2]], *this, po2) < 0) { - sorted.insert(sorted.begin() + i2, v_order[i]); - b = true; - break; - } - } - if(!b) sorted.push_back(v_order[i]); - } - if(CALCULATOR->aborted()) return; - if(m_type == STRUCT_ADDITION && SIZE > 2 && po.sort_options.minus_last && v_subs[sorted[0]]->hasNegativeSign()) { - for(size_t i2 = 1; i2 < sorted.size(); i2++) { - if(CALCULATOR->aborted()) return; - if(!v_subs[sorted[i2]]->hasNegativeSign()) { - sorted.insert(sorted.begin(), sorted[i2]); - sorted.erase(sorted.begin() + (i2 + 1)); - break; - } - } - } - if(CALCULATOR->aborted()) return; - for(size_t i2 = 0; i2 < sorted.size(); i2++) { - v_order[i2] = sorted[i2]; - } -} -bool MathStructure::containsOpaqueContents() const { - if(isFunction()) return true; - if(isUnit() && o_unit->subtype() != SUBTYPE_BASE_UNIT) return true; - if(isVariable() && o_variable->isKnown()) return true; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).containsOpaqueContents()) return true; - } - return false; -} -bool MathStructure::containsAdditionPower() const { - if(m_type == STRUCT_POWER && CHILD(0).isAddition()) return true; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).containsAdditionPower()) return true; - } - return false; -} - -size_t MathStructure::countTotalChildren(bool count_function_as_one) const { - if((m_type == STRUCT_FUNCTION && count_function_as_one) || SIZE == 0) return 1; - size_t count = 0; - for(size_t i = 0; i < SIZE; i++) { - count += CHILD(i).countTotalChildren() + 1; - } - return count; -} -int test_comparisons(const MathStructure &msave, MathStructure &mthis, const MathStructure &x_var, const EvaluationOptions &eo, bool sub = false, int alt = 0); -bool try_isolate_x(MathStructure &mstruct, EvaluationOptions &eo3, const EvaluationOptions &eo); -bool try_isolate_x(MathStructure &mstruct, EvaluationOptions &eo3, const EvaluationOptions &eo) { - if(mstruct.isProtected()) return false; - if(mstruct.isComparison()) { - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mtest(mstruct); - eo3.test_comparisons = false; - eo3.warn_about_denominators_assumed_nonzero = false; - mtest[0].calculatesub(eo3, eo); - mtest[1].calculatesub(eo3, eo); - eo3.test_comparisons = eo.test_comparisons; - const MathStructure *x_var2; - if(eo.isolate_var) x_var2 = eo.isolate_var; - else x_var2 = &mstruct.find_x_var(); - if(x_var2->isUndefined() || (mtest[0] == *x_var2 && !mtest[1].contains(*x_var2))) { - CALCULATOR->endTemporaryStopMessages(); - return false; - } - if(mtest.isolate_x(eo3, eo, *x_var2, false)) { - if(test_comparisons(mstruct, mtest, *x_var2, eo3) >= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mstruct = mtest; - return true; - } - } - CALCULATOR->endTemporaryStopMessages(); - } else { - bool b = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(try_isolate_x(mstruct[i], eo3, eo)) b = true; - } - return b; - } - return false; -} - -bool compare_delete(MathStructure &mnum, MathStructure &mden, bool &erase1, bool &erase2, const EvaluationOptions &eo) { - erase1 = false; - erase2 = false; - if(mnum == mden) { - if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !mnum.representsZero(true)) - || mnum.representsNonZero(true) - || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !mnum.representsZero(true) && warn_about_denominators_assumed_nonzero(mnum, eo))) { - erase1 = true; - erase2 = true; - } else { - if(mnum.isPower()) { - mnum.setToChild(1); - mden.setToChild(1); - return true; - } - return false; - } - return true; - } - if(!mnum.isPower() && !mden.isPower()) return false; - MathStructure *mbase1, *mbase2, *mexp1 = NULL, *mexp2 = NULL; - if(mnum.isPower()) { - if(!IS_REAL(mnum[1])) return false; - mexp1 = &mnum[1]; - mbase1 = &mnum[0]; - } else { - mbase1 = &mnum; - } - if(mden.isPower()) { - if(!IS_REAL(mden[1])) return false; - mexp2 = &mden[1]; - mbase2 = &mden[0]; - } else { - mbase2 = &mden; - } - if(mbase1->equals(*mbase2)) { - if(mexp1 && mexp2) { - if(mexp1->number().isLessThan(mexp2->number())) { - erase1 = true; - mexp2->number() -= mexp1->number(); - if(mexp2->isOne()) mden.setToChild(1, true); - } else { - if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !mbase2->representsZero(true)) - || mbase2->representsNonZero(true) - || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !mbase2->representsZero(true) && warn_about_denominators_assumed_nonzero(*mbase2, eo))) { - erase2 = true; - mexp1->number() -= mexp2->number(); - if(mexp1->isOne()) mnum.setToChild(1, true); - } else { - if(mexp2->number().isFraction()) return false; - mexp2->number()--; - mexp1->number() -= mexp2->number(); - if(mexp1->isOne()) mnum.setToChild(1, true); - if(mexp2->isOne()) mden.setToChild(1, true); - return true; - } - - } - return true; - } else if(mexp1) { - if(mexp1->number().isFraction()) { - erase1 = true; - mbase2->raise(m_one); - (*mbase2)[1].number() -= mexp1->number(); - return true; - } - if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !mbase2->representsZero(true)) - || mbase2->representsNonZero(true) - || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !mbase2->representsZero(true) && warn_about_denominators_assumed_nonzero(*mbase2, eo))) { - mexp1->number()--; - erase2 = true; - if(mexp1->isOne()) mnum.setToChild(1, true); - return true; - } - return false; - - } else if(mexp2) { - if(mexp2->number().isFraction()) { - if((!eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !mbase2->representsZero(true)) - || mbase2->representsNonZero(true) - || (eo.warn_about_denominators_assumed_nonzero && eo.assume_denominators_nonzero && !mbase2->representsZero(true) && warn_about_denominators_assumed_nonzero(*mbase2, eo))) { - erase2 = true; - mbase1->raise(m_one); - (*mbase1)[1].number() -= mexp2->number(); - return true; - } - return false; - } - mexp2->number()--; - erase1 = true; - if(mexp2->isOne()) mden.setToChild(1, true); - return true; - } - } - return false; -} - -bool factor1(const MathStructure &mstruct, MathStructure &mnum, MathStructure &mden, const EvaluationOptions &eo) { - mnum.setUndefined(); - mden.setUndefined(); - if(mstruct.isAddition()) { - bool b_num = false, b_den = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - if(mstruct[i][i2].isPower() && mstruct[i][i2][1].hasNegativeSign()) { - b_den = true; - if(b_num) break; - } else { - b_num = true; - if(b_den) break; - } - } - } else if(mstruct[i].isPower() && mstruct[i][1].hasNegativeSign()) { - b_den = true; - if(b_num) break; - } else { - b_num = true; - if(b_den) break; - } - } - if(b_num && b_den) { - MathStructure *mden_cur = NULL; - vector multi_index; - for(size_t i = 0; i < mstruct.size(); i++) { - if(mnum.isUndefined()) { - mnum.transform(STRUCT_ADDITION); - } else { - mnum.addChild(m_undefined); - } - if(mstruct[i].isMultiplication()) { - if(!mden_cur) { - mden_cur = new MathStructure(); - mden_cur->setUndefined(); - } - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - if(mstruct[i][i2].isPower() && mstruct[i][i2][1].hasNegativeSign()) { - if(mden_cur->isUndefined()) { - if(mstruct[i][i2][1].isMinusOne()) { - *mden_cur = mstruct[i][i2][0]; - } else if(mstruct[i][i2][1].isNumber()) { - *mden_cur = mstruct[i][i2]; - (*mden_cur)[1].number().negate(); - } else { - *mden_cur = mstruct[i][i2]; - (*mden_cur)[1][0].number().negate(); - } - } else { - if(mstruct[i][i2][1].isMinusOne()) { - mden_cur->multiply(mstruct[i][i2][0], true); - } else if(mstruct[i][i2][1].isNumber()) { - mden_cur->multiply(mstruct[i][i2], true); - (*mden_cur)[mden_cur->size() - 1][1].number().negate(); - } else { - mden_cur->multiply(mstruct[i][i2], true); - (*mden_cur)[mden_cur->size() - 1][1][0].number().negate(); - } - } - } else { - if(mnum[mnum.size() - 1].isUndefined()) { - mnum[mnum.size() - 1] = mstruct[i][i2]; - } else { - mnum[mnum.size() - 1].multiply(mstruct[i][i2], true); - } - } - } - if(mnum[mnum.size() - 1].isUndefined()) mnum[mnum.size() - 1].set(1, 1, 0); - if(mden_cur->isUndefined()) { - multi_index.push_back(-1); - } else { - multi_index.push_back(mden.size()); - if(mden.isUndefined()) { - mden.transform(STRUCT_MULTIPLICATION); - mden[mden.size() - 1].set_nocopy(*mden_cur); - mden_cur->unref(); - } else { - mden.addChild_nocopy(mden_cur); - } - mden_cur = NULL; - } - } else if(mstruct[i].isPower() && mstruct[i][1].hasNegativeSign()) { - multi_index.push_back(mden.size()); - if(mden.isUndefined()) { - mden.transform(STRUCT_MULTIPLICATION); - } else { - mden.addChild(m_undefined); - } - if(mstruct[i][1].isMinusOne()) { - mden[mden.size() - 1] = mstruct[i][0]; - } else { - mden[mden.size() - 1] = mstruct[i]; - unnegate_sign(mden[mden.size() - 1][1]); - } - mnum[mnum.size() - 1].set(1, 1, 0); - } else { - multi_index.push_back(-1); - mnum[mnum.size() - 1] = mstruct[i]; - } - } - for(size_t i = 0; i < mnum.size(); i++) { - if(multi_index[i] < 0 && mnum[i].isOne()) { - if(mden.size() == 1) { - mnum[i] = mden[0]; - } else { - mnum[i] = mden; - } - } else { - for(size_t i2 = 0; i2 < mden.size(); i2++) { - if((long int) i2 != multi_index[i]) { - mnum[i].multiply(mden[i2], true); - } - } - } - mnum[i].calculatesub(eo, eo, false); - } - if(mden.size() == 1) { - mden.setToChild(1); - } else { - mden.calculatesub(eo, eo, false); - } - mnum.calculatesub(eo, eo, false); - } - } else if(mstruct.isMultiplication()) { - bool b_num = false, b_den = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isPower() && mstruct[i][1].hasNegativeSign()) { - b_den = true; - if(b_num) break; - } else { - b_num = true; - if(b_den) break; - } - } - if(b_den && b_num) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isPower() && mstruct[i][1].hasNegativeSign()) { - if(mden.isUndefined()) { - if(mstruct[i][1].isMinusOne()) { - mden = mstruct[i][0]; - } else { - mden = mstruct[i]; - unnegate_sign(mden[1]); - } - } else { - if(mstruct[i][1].isMinusOne()) { - mden.multiply(mstruct[i][0], true); - } else { - mden.multiply(mstruct[i], true); - unnegate_sign(mden[mden.size() - 1][1]); - } - } - } else { - if(mnum.isUndefined()) { - mnum = mstruct[i]; - } else { - mnum.multiply(mstruct[i], true); - } - } - } - } - mden.calculatesub(eo, eo, false); - } - if(!mnum.isUndefined() && !mden.isUndefined()) { - while(true) { - mnum.factorize(eo, false, false, 0, true); - mnum.evalSort(true); - if(mnum.isMultiplication()) { - for(size_t i = 0; i < mnum.size(); ) { - if(mnum[i].isPower() && mnum[i][1].hasNegativeSign()) { - if(mnum[i][1].isMinusOne()) { - mnum[i][0].ref(); - mden.multiply_nocopy(&mnum[i][0], true); - } else { - mnum[i].ref(); - mden.multiply_nocopy(&mnum[i], true); - unnegate_sign(mden[mden.size() - 1][1]); - } - mden.calculateMultiplyLast(eo); - mnum.delChild(i + 1); - } else { - i++; - } - } - if(mnum.size() == 0) mnum.set(1, 1, 0); - else if(mnum.size() == 1) mnum.setToChild(1); - } - mden.factorize(eo, false, false, 0, true); - mden.evalSort(true); - bool b = false; - if(mden.isMultiplication()) { - for(size_t i = 0; i < mden.size(); ) { - if(mden[i].isPower() && mden[i][1].hasNegativeSign()) { - MathStructure *mden_inv = new MathStructure(mden[i]); - if(mden_inv->calculateInverse(eo)) { - mnum.multiply_nocopy(mden_inv, true); - mnum.calculateMultiplyLast(eo); - mden.delChild(i + 1); - b = true; - } else { - mden_inv->unref(); - i++; - } - } else { - i++; - } - } - if(mden.size() == 0) mden.set(1, 1, 0); - else if(mden.size() == 1) mden.setToChild(1); - } - if(!b) break; - } - bool erase1, erase2; - if(mnum.isMultiplication()) { - for(long int i = 0; i < (long int) mnum.size(); i++) { - if(mden.isMultiplication()) { - for(size_t i2 = 0; i2 < mden.size(); i2++) { - if(compare_delete(mnum[i], mden[i2], erase1, erase2, eo)) { - if(erase1) mnum.delChild(i + 1); - if(erase2) mden.delChild(i2 + 1); - i--; - break; - } - } - } else { - if(compare_delete(mnum[i], mden, erase1, erase2, eo)) { - if(erase1) mnum.delChild(i + 1); - if(erase2) mden.set(1, 1, 0); - break; - } - } - } - } else if(mden.isMultiplication()) { - for(size_t i = 0; i < mden.size(); i++) { - if(compare_delete(mnum, mden[i], erase1, erase2, eo)) { - if(erase1) mnum.set(1, 1, 0); - if(erase2) mden.delChild(i + 1); - break; - } - } - } else { - if(compare_delete(mnum, mden, erase1, erase2, eo)) { - if(erase1) mnum.set(1, 1, 0); - if(erase2) mden.set(1, 1, 0); - } - } - if(mnum.isMultiplication()) { - if(mnum.size() == 0) mnum.set(1, 1, 0); - else if(mnum.size() == 1) mnum.setToChild(1); - } - if(mden.isMultiplication()) { - if(mden.size() == 0) mden.set(1, 1, 0); - else if(mden.size() == 1) mden.setToChild(1); - } - return true; - } - return false; -} - -bool combination_factorize_is_complicated(MathStructure &m) { - if(m.isPower()) { - return combination_factorize_is_complicated(m[0]) || combination_factorize_is_complicated(m[1]); - } - return m.size() > 0; -} - -bool combination_factorize(MathStructure &mstruct) { - bool retval = false; - switch(mstruct.type()) { - case STRUCT_ADDITION: { - bool b = false; - // 5/y + x/y + z = (5 + x)/y + z - MathStructure mstruct_units(mstruct); - MathStructure mstruct_new(mstruct); - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(mstruct_units[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct_units[i].size();) { - if(!mstruct_units[i][i2].isPower() || !mstruct_units[i][i2][1].hasNegativeSign()) { - mstruct_units[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); - else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); - for(size_t i2 = 0; i2 < mstruct_new[i].size();) { - if(mstruct_new[i][i2].isPower() && mstruct_new[i][i2][1].hasNegativeSign()) { - mstruct_new[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); - else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); - } else if(mstruct_new[i].isPower() && mstruct_new[i][1].hasNegativeSign()) { - mstruct_new[i].set(1, 1, 0); - } else { - mstruct_units[i].setUndefined(); - } - } - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(!mstruct_units[i].isUndefined()) { - for(size_t i2 = i + 1; i2 < mstruct_units.size();) { - if(mstruct_units[i2] == mstruct_units[i]) { - mstruct_new[i].add(mstruct_new[i2], true); - mstruct_new.delChild(i2 + 1); - mstruct_units.delChild(i2 + 1); - b = true; - } else { - i2++; - } - } - if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); - else mstruct_new[i].multiply(mstruct_units[i], true); - } - } - if(b) { - if(mstruct_new.size() == 1) { - mstruct.set(mstruct_new[0], true); - } else { - mstruct = mstruct_new; - } - b = false; - retval = true; - } - if(mstruct.isAddition()) { - // y*f(x) + z*f(x) = (y+z)*f(x) - MathStructure mstruct_units(mstruct); - MathStructure mstruct_new(mstruct); - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(mstruct_units[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct_units[i].size();) { - if(!combination_factorize_is_complicated(mstruct_units[i][i2])) { - mstruct_units[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); - else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); - for(size_t i2 = 0; i2 < mstruct_new[i].size();) { - if(combination_factorize_is_complicated(mstruct_new[i][i2])) { - mstruct_new[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); - else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); - } else if(combination_factorize_is_complicated(mstruct_units[i])) { - mstruct_new[i].set(1, 1, 0); - } else { - mstruct_units[i].setUndefined(); - } - } - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(!mstruct_units[i].isUndefined()) { - for(size_t i2 = i + 1; i2 < mstruct_units.size();) { - if(mstruct_units[i2] == mstruct_units[i]) { - mstruct_new[i].add(mstruct_new[i2], true); - mstruct_new.delChild(i2 + 1); - mstruct_units.delChild(i2 + 1); - b = true; - } else { - i2++; - } - } - if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); - else mstruct_new[i].multiply(mstruct_units[i], true); - } - } - if(b) { - if(mstruct_new.size() == 1) mstruct.set(mstruct_new[0], true); - else mstruct = mstruct_new; - retval = true; - } - } - if(mstruct.isAddition()) { - // 5x + pi*x + 5y + xy = (5 + pi)x + 5y + xy - MathStructure mstruct_units(mstruct); - MathStructure mstruct_new(mstruct); - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(mstruct_units[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct_units[i].size();) { - if(!mstruct_units[i][i2].containsType(STRUCT_UNIT, true) && !mstruct_units[i][i2].containsUnknowns()) { - mstruct_units[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); - else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); - for(size_t i2 = 0; i2 < mstruct_new[i].size();) { - if(mstruct_new[i][i2].containsType(STRUCT_UNIT, true) || mstruct_new[i][i2].containsUnknowns()) { - mstruct_new[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); - else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); - } else if(mstruct_units[i].containsType(STRUCT_UNIT, true) || mstruct_units[i].containsUnknowns()) { - mstruct_new[i].set(1, 1, 0); - } else { - mstruct_units[i].setUndefined(); - } - } - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(!mstruct_units[i].isUndefined()) { - for(size_t i2 = i + 1; i2 < mstruct_units.size();) { - if(mstruct_units[i2] == mstruct_units[i]) { - mstruct_new[i].add(mstruct_new[i2], true); - mstruct_new.delChild(i2 + 1); - mstruct_units.delChild(i2 + 1); - b = true; - } else { - i2++; - } - } - if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); - else mstruct_new[i].multiply(mstruct_units[i], true); - } - } - if(b) { - if(mstruct_new.size() == 1) mstruct.set(mstruct_new[0], true); - else mstruct = mstruct_new; - retval = true; - } - } - //if(retval) return retval; - } - default: { - bool b = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(combination_factorize(mstruct[i])) { - mstruct.childUpdated(i); - b = true; - } - } - if(b) retval = true; - } - } - return retval; -} - -bool MathStructure::simplify(const EvaluationOptions &eo, bool unfactorize) { - - if(SIZE == 0) return false; - if(unfactorize) { - unformat(); - EvaluationOptions eo2 = eo; - eo2.expand = true; - eo2.combine_divisions = false; - eo2.sync_units = false; - calculatesub(eo2, eo2); - bool b = do_simplification(*this, eo2, true, false, false); - return combination_factorize(*this) || b; - } - return combination_factorize(*this); - -} - -bool MathStructure::expand(const EvaluationOptions &eo, bool unfactorize) { - if(SIZE == 0) return false; - EvaluationOptions eo2 = eo; - eo2.sync_units = false; - eo2.expand = true; - if(unfactorize) calculatesub(eo2, eo2); - do_simplification(*this, eo2, true, false, false); - return false; -} - -bool MathStructure::structure(StructuringMode structuring, const EvaluationOptions &eo, bool restore_first) { - switch(structuring) { - case STRUCTURING_NONE: { - if(restore_first) { - EvaluationOptions eo2 = eo; - eo2.sync_units = false; - calculatesub(eo2, eo2); - } - return false; - } - case STRUCTURING_FACTORIZE: { - return factorize(eo, restore_first, 3, 0, true, 2, NULL, m_undefined, true, false, -1); - } - default: { - return simplify(eo, restore_first); - } - } -} - -void clean_multiplications(MathStructure &mstruct); -void clean_multiplications(MathStructure &mstruct) { - if(mstruct.isMultiplication()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isMultiplication()) { - size_t i2 = 0; - for(; i2 < mstruct[i + i2].size(); i2++) { - mstruct[i + i2][i2].ref(); - mstruct.insertChild_nocopy(&mstruct[i + i2][i2], i + i2 + 1); - } - mstruct.delChild(i + i2 + 1); - } - } - } - for(size_t i = 0; i < mstruct.size(); i++) { - clean_multiplications(mstruct[i]); - } -} - -bool containsComplexUnits(const MathStructure &mstruct) { - if(mstruct.type() == STRUCT_UNIT && mstruct.unit()->hasNonlinearRelationTo(mstruct.unit()->baseUnit())) return true; - if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_stripunits) return false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(containsComplexUnits(mstruct[i])) { - return true; - } - } - return false; -} - -bool variablesContainsComplexUnits(const MathStructure &mstruct, const EvaluationOptions &eo) { - if(mstruct.type() == STRUCT_VARIABLE && mstruct.variable()->isKnown() && (eo.approximation != APPROXIMATION_EXACT || !mstruct.variable()->isApproximate()) && ((KnownVariable*) mstruct.variable())->get().containsType(STRUCT_UNIT, false, true, true)) { - return containsComplexUnits(((KnownVariable*) mstruct.variable())->get()); - } - if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_stripunits) return false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(variablesContainsComplexUnits(mstruct[i], eo)) { - return true; - } - } - return false; -} - - -bool expandVariablesWithUnits(MathStructure &mstruct, const EvaluationOptions &eo) { - if(mstruct.type() == STRUCT_VARIABLE && mstruct.variable()->isKnown() && (eo.approximation != APPROXIMATION_EXACT || !mstruct.variable()->isApproximate()) && ((KnownVariable*) mstruct.variable())->get().containsType(STRUCT_UNIT, false, true, true) != 0) { - mstruct.set(((KnownVariable*) mstruct.variable())->get()); - return true; - } - bool retval = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(expandVariablesWithUnits(mstruct[i], eo)) { - mstruct.childUpdated(i + 1); - retval = true; - } - } - return retval; -} - -int limit_inf_cmp(const MathStructure &mstruct, const MathStructure &mcmp, const MathStructure &x_var) { - if(mstruct.equals(mcmp)) return 0; - bool b_multi1 = false, b_multi2 = false; - const MathStructure *m1 = NULL, *m2 = NULL; - if(mstruct.isMultiplication()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].contains(x_var)) { - if(!m1) { - m1 = &mstruct[i]; - } else { - int cmp = limit_inf_cmp(mstruct[i], *m1, x_var); - if(cmp > 0) { - m1 = &mstruct[i]; - } else if(cmp != -1) { - return -2; - } - b_multi1 = true; - } - } - } - } else if(mstruct.contains(x_var, true)) { - m1 = &mstruct; - } - if(mcmp.isMultiplication()) { - for(size_t i = 0; i < mcmp.size(); i++) { - if(mcmp[i].contains(x_var)) { - if(!m2) { - m2 = &mcmp[i]; - } else { - int cmp = limit_inf_cmp(mcmp[i], *m2, x_var); - if(cmp > 0) { - m2 = &mcmp[i]; - } else if(cmp != -1) { - return -2; - } - b_multi2 = true; - } - } - } - } else if(mcmp.contains(x_var, true)) { - m2 = &mcmp; - } - if(!m1 && !m2) return 0; - if(!m1) return -1; - if(!m2) return 1; - int itype1 = 0; - int itype2 = 0; - if(m1->isFunction() && m1->function() == CALCULATOR->f_gamma) itype1 = 4; - else if(m1->isPower() && m1->exponent()->contains(x_var, true)) itype1 = 3; - else if(m1->equals(x_var) || (m1->isPower() && m1->base()->equals(x_var) && m1->exponent()->representsPositive())) itype1 = 2; - else if(m1->isFunction() && m1->function() == CALCULATOR->f_ln) itype1 = 1; - else return -2; - if(m2->isFunction() && m2->function() == CALCULATOR->f_gamma) itype2 = 4; - else if(m2->isPower() && m2->exponent()->contains(x_var, true)) itype2 = 3; - else if(m2->equals(x_var) || (m2->isPower() && m2->base()->equals(x_var) && m2->exponent()->representsPositive())) itype2 = 2; - else if(m2->isFunction() && m2->function() == CALCULATOR->f_ln) itype2 = 1; - else return -2; - if(itype1 > itype2) return 1; - if(itype2 > itype1) return -1; - ComparisonResult cr = COMPARISON_RESULT_UNKNOWN; - CALCULATOR->beginTemporaryEnableIntervalArithmetic(); - if(itype1 == 4) { - cr = m1->getChild(1)->compare(*m2->getChild(1)); - } else if(itype1 == 1) { - int cmp = limit_inf_cmp(*m1->getChild(1), *m2->getChild(1), x_var); - if(cmp > 0) cr = COMPARISON_RESULT_LESS; - else if(cmp == -1) cr = COMPARISON_RESULT_GREATER; - } else if(itype1 == 3) { - if(m1->exponent()->equals(*m2->exponent())) { - if(m1->base()->contains(x_var, true) || m2->base()->contains(x_var, true)) { - int cmp = limit_inf_cmp(*m1->base(), *m2->base(), x_var); - if(cmp > 0) cr = COMPARISON_RESULT_LESS; - else if(cmp == -1) cr = COMPARISON_RESULT_GREATER; - } else { - cr = m1->base()->compareApproximately(*m2->base()); - } - } else if(m1->base()->equals(*m2->base())) { - int cmp = limit_inf_cmp(*m1->exponent(), *m2->exponent(), x_var); - if(cmp > 0) cr = COMPARISON_RESULT_LESS; - else if(cmp == -1) cr = COMPARISON_RESULT_GREATER; - else if(cmp == 0) cr = m1->exponent()->compareApproximately(*m2->exponent()); - } - } else if(itype1 == 2) { - if(m1->equals(x_var)) { - if(m2->equals(x_var)) cr = COMPARISON_RESULT_EQUAL; - else cr = m_one.compareApproximately(*m2->getChild(2)); - } else if(m2->equals(x_var)) { - cr = m1->getChild(2)->compareApproximately(m_one); - } else { - cr = m1->getChild(2)->compareApproximately(*m2->getChild(2)); - } - } - CALCULATOR->endTemporaryEnableIntervalArithmetic(); - if(cr == COMPARISON_RESULT_GREATER) return -1; - else if(cr == COMPARISON_RESULT_LESS) return 1; - else if(cr != COMPARISON_RESULT_EQUAL) return -2; - if(!b_multi1 && !b_multi2) return 0; - if(!b_multi1) return -1; - if(!b_multi2) return 1; - MathStructure mc1(mstruct), mc2(mcmp); - for(size_t i = 0; i < mc1.size(); i++) { - if(&mstruct[i] == m1) {mc1.delChild(i + 1, true); break;} - } - for(size_t i = 0; i < mc2.size(); i++) { - if(&mcmp[i] == m2) {mc2.delChild(i + 1, true); break;} - } - return limit_inf_cmp(mc1, mc2, x_var); -} - -bool is_limit_neg_power(const MathStructure &mstruct, const MathStructure &x_var, bool b_nil) { - return mstruct.isPower() && (((!b_nil || !mstruct[1].contains(x_var, true)) && mstruct[1].representsNegative()) || (b_nil && mstruct[1].isMultiplication() && mstruct[1].size() == 2 && mstruct[1][1] == x_var && mstruct[1][0].representsNegative())); -} - -bool limit_combine_divisions(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &nr_limit) { - if(mstruct.isAddition()) { - bool b = false; - bool b_nil = nr_limit.isInfinite(false) && nr_limit.number().isMinusInfinity(); - // 5/y + x/y + z = (5 + x)/y + z - for(size_t i = 0; i < mstruct.size() && !b; i++) { - if(mstruct[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct[i].size() && !b; i2++) { - if(is_limit_neg_power(mstruct[i][i2], x_var, b_nil)) { - b = true; - } - } - } else if(is_limit_neg_power(mstruct[i], x_var, b_nil)) { - b = true; - } - } - if(!b) return false; - b = false; - MathStructure mstruct_units(mstruct); - MathStructure mstruct_new(mstruct); - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(mstruct_units[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct_units[i].size();) { - if(!is_limit_neg_power(mstruct_units[i][i2], x_var, b_nil)) { - mstruct_units[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); - else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); - for(size_t i2 = 0; i2 < mstruct_new[i].size();) { - if(is_limit_neg_power(mstruct_new[i][i2], x_var, b_nil)) { - mstruct_new[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); - else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); - } else if(is_limit_neg_power(mstruct_new[i], x_var, b_nil)) { - mstruct_new[i].set(1, 1, 0); - } else { - mstruct_units[i].setUndefined(); - } - } - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(!mstruct_units[i].isUndefined()) { - for(size_t i2 = i + 1; i2 < mstruct_units.size();) { - if(mstruct_units[i2] == mstruct_units[i]) { - mstruct_new[i].add(mstruct_new[i2], true); - mstruct_new.delChild(i2 + 1); - mstruct_units.delChild(i2 + 1); - b = true; - } else { - i2++; - } - } - if(mstruct_new[i].isOne()) { - mstruct_new[i].set(mstruct_units[i]); - } else if(mstruct_units[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct_units[i].size(); i2++) { - mstruct_new[i].multiply(mstruct_units[i][i2], true); - } - } else { - mstruct_new[i].multiply(mstruct_units[i], true); - } - } - } - if(b) { - if(mstruct_new.size() == 1) { - mstruct.set(mstruct_new[0], true); - } else { - mstruct = mstruct_new; - } - return true; - } - } - return false; -} -bool limit_combine_divisions2(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &nr_limit, const EvaluationOptions &eo) { - if(mstruct.isAddition()) { - MathStructure mden(1, 1, 0); - bool b = false; - bool b_nil = nr_limit.isInfinite(false) && nr_limit.number().isMinusInfinity(); - size_t i_d = 0; - for(size_t i2 = 0; i2 < mstruct.size(); i2++) { - if(mstruct[i2].isMultiplication()) { - for(size_t i3 = 0; i3 < mstruct[i2].size(); i3++) { - if(is_limit_neg_power(mstruct[i2][i3], x_var, b_nil)) { - mden *= mstruct[i2][i3]; - mden.last()[1].negate(); - i_d++; - } else if(!mstruct[i2][i3].isOne() && !mstruct[i2][i3].isMinusOne()) { - b = true; - } - } - } else if(is_limit_neg_power(mstruct[i2], x_var, b_nil)) { - mden *= mstruct[i2]; - mden.last()[1].negate(); - i_d++; - } else { - b = true; - } - } - if(mden.isOne() || !b || i_d > 10) return false; - for(size_t i = 0; i < mstruct.size(); i++) { - for(size_t i2 = 0; i2 < mstruct.size(); i2++) { - if(i2 != i) { - if(mstruct[i2].isMultiplication()) { - for(size_t i3 = 0; i3 < mstruct[i2].size(); i3++) { - if(is_limit_neg_power(mstruct[i2][i3], x_var, b_nil)) { - mstruct[i].multiply(mstruct[i2][i3], true); - mstruct[i].last()[1].negate(); - } - } - } else if(is_limit_neg_power(mstruct[i2], x_var, b_nil)) { - mstruct[i].multiply(mstruct[i2], true); - mstruct[i].last()[1].negate(); - } - } - } - } - for(size_t i2 = 0; i2 < mstruct.size(); i2++) { - if(mstruct[i2].isMultiplication()) { - for(size_t i3 = 0; i3 < mstruct[i2].size();) { - if(is_limit_neg_power(mstruct[i2][i3], x_var, b_nil)) { - mstruct[i2].delChild(i3 + 1); - } else { - i3++; - } - } - if(mstruct[i2].size() == 0) mstruct[i2].set(1, 1, 0); - else if(mstruct[i2].size() == 1) mstruct[i2].setToChild(1); - } else if(is_limit_neg_power(mstruct[i2], x_var, b_nil)) { - mstruct[i2].set(1, 1, 0); - } - } - mden.calculatesub(eo, eo, true); - mstruct.calculatesub(eo, eo, true); - mstruct /= mden; - return true; - } - return false; -} - -bool contains_zero(const MathStructure &mstruct) { - if(mstruct.isNumber() && !mstruct.number().isNonZero()) return true; - for(size_t i = 0; i < mstruct.size(); i++) { - if(contains_zero(mstruct[i])) return true; - } - return false; -} -bool limit_contains_undefined(const MathStructure &mstruct) { - bool b_zero = false, b_infinity = false; - if(mstruct.isPower() && mstruct[0].isNumber() && ((!mstruct[0].number().isNonZero() && mstruct[1].representsNegative()) || mstruct[1].containsInfinity(true))) return true; - for(size_t i = 0; i < mstruct.size(); i++) { - if(limit_contains_undefined(mstruct[i])) return true; - if(contains_zero(mstruct[i])) { - if(b_infinity) return true; - b_zero = true; - } - if(mstruct[i].containsInfinity(true)) { - if(b_infinity || b_zero) return true; - b_infinity = true; - } - } - return false; -} -bool is_plus_minus_infinity(const MathStructure &mstruct) { - return mstruct.isInfinite(false) || (mstruct.isPower() && mstruct[0].isZero() && mstruct[1].representsNegative()) || (mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].representsReal() && mstruct[1].isPower() && mstruct[1][0].isZero() && mstruct[1][1].representsNegative()); -} - -bool calculate_limit_sub(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &nr_limit, const EvaluationOptions &eo, int approach_direction, Number *polydeg = NULL, int lhop_depth = 0, bool keep_inf_x = false, bool reduce_addition = true) { - - if(CALCULATOR->aborted()) return false; - if(mstruct == x_var) { - if(keep_inf_x && nr_limit.isInfinite(false)) return true; - mstruct.set(nr_limit, true); - return true; - } - if(!mstruct.contains(x_var, true)) return true; - - switch(mstruct.type()) { - case STRUCT_MULTIPLICATION: { - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isPower() && mstruct[i][0].isPower() && mstruct[i][0][0].contains(x_var, true) && !mstruct[i][0][0].representsNonPositive()) { - MathStructure mtest(mstruct[i][0][0]); - calculate_limit_sub(mtest, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); - if(mtest.representsPositive()) { - mstruct[i][0][1].calculateMultiply(mstruct[i][1], eo); - mstruct[i].setToChild(1); - } - } - } - MathStructure mzero(1, 1, 0); - MathStructure minfp(1, 1, 0); - MathStructure mleft; - vector irecalc; - MathStructure mbak(mstruct); - bool b_inf = false; - bool b_li = nr_limit.isInfinite(false); - bool b_fail = false; - bool b_test_inf = b_li; - bool b_possible_zero = false; - for(size_t i = 0; i < mstruct.size(); i++) { - bool b = false; - if(!b_fail && mstruct[i].isPower() && mstruct[i][0].contains(x_var, true) && mstruct[i][1].representsNegative()) { - if(mstruct[i][1].isMinusOne()) { - mstruct[i].setToChild(1); - } else { - mstruct[i][1].calculateNegate(eo); - } - calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); - if(mstruct[i].isZero()) { - b = true; - if(b_test_inf && !mbak[i][1].contains(x_var, true)) b_test_inf = false; - if(minfp.isOne()) { - minfp = mbak[i]; - if(!b_li) { - if(minfp[1].isMinusOne()) minfp.setToChild(1); - else minfp[1].calculateNegate(eo); - } - } else { - minfp.multiply(mbak[i], true); - if(!b_li) { - if(minfp.last()[1].isMinusOne()) minfp.last().setToChild(1); - else minfp.last()[1].calculateNegate(eo); - } - } - irecalc.push_back(i); - mstruct[i].inverse(); - } else if(mstruct[i].isInfinite()) { - b = true; - if(mzero.isOne()) { - mzero = mbak[i]; - if(b_li) { - if(mzero[1].isMinusOne()) mzero.setToChild(1); - else mzero[1].calculateNegate(eo); - } - } else { - mzero.multiply(mbak[i], true); - if(b_li) { - if(mzero.last()[1].isMinusOne()) mzero.last().setToChild(1); - else mzero.last()[1].calculateNegate(eo); - } - } - mstruct[i].clear(true); - } else { - mstruct[i].calculateInverse(eo); - } - } else { - calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); - } - if(!b_fail && !b) { - if(mstruct[i].isZero()) { - if(b_li && mbak[i].isPower()) { - if(b_test_inf && !mbak[i][1].contains(x_var, true)) b_test_inf = false; - if(mzero.isOne()) { - mzero = mbak[i]; - if(mzero[1].isMinusOne()) mzero.setToChild(1); - else mzero[1].calculateNegate(eo); - } else { - mzero.multiply(mbak[i], true); - if(mzero.last()[1].isMinusOne()) mzero.last().setToChild(1); - else mzero.last()[1].calculateNegate(eo); - } - } else { - b_test_inf = false; - if(mzero.isOne()) { - mzero = mbak[i]; - if(b_li) { - if(!mzero.isPower()) mzero.inverse(); - else if(mzero[1].isMinusOne()) mzero.setToChild(1); - else mzero[1].calculateNegate(eo); - } - } else { - mzero.multiply(mbak[i], true); - if(b_li) { - if(!mzero.last().isPower()) mzero.last().inverse(); - else if(mzero.last()[1].isMinusOne()) mzero.last().setToChild(1); - else mzero.last()[1].calculateNegate(eo); - } - } - } - } else if(is_plus_minus_infinity(mstruct[i])) { - if(mstruct[i].isInfinite()) { - b_inf = true; - if(minfp.isOne()) { - minfp = mbak[i]; - if(!b_li) { - if(!minfp.isPower()) minfp.inverse(); - else if(minfp[1].isMinusOne()) minfp.setToChild(1); - else minfp[1].calculateNegate(eo); - } - } else { - minfp.multiply(mbak[i], true); - if(!b_li) { - if(!minfp.last().isPower()) minfp.last().inverse(); - else if(minfp.last()[1].isMinusOne()) minfp.last().setToChild(1); - else minfp.last()[1].calculateNegate(eo); - } - } - } else { - b_test_inf = false; - if(minfp.isOne()) { - minfp = mbak[i]; - if(!b_li) { - if(!minfp.isPower()) minfp.inverse(); - else if(minfp[1].isMinusOne()) minfp[1].setToChild(1); - else minfp[1].calculateNegate(eo); - } - } else { - minfp.multiply(mbak[i], true); - if(!b_li) { - if(!minfp.last().isPower()) minfp.last().inverse(); - else if(minfp.last()[1].isMinusOne()) minfp.last().setToChild(1); - else minfp.last()[1].calculateNegate(eo); - } - } - } - } else if(!mstruct[i].representsNonZero(true) || !mstruct[i].representsNumber(true)) { - if(!mstruct[i].contains(x_var) && !mstruct.isZero() && mstruct[i].representsNumber(true)) { - mstruct[i].ref(); - mleft.addChild_nocopy(&mstruct[i]); - b_possible_zero = true; - } else { - b_fail = true; - } - } else { - mstruct[i].ref(); - mleft.addChild_nocopy(&mstruct[i]); - } - } - } - if(b_li) b_inf = !b_inf; - if(!b_fail && b_li && b_test_inf && !mzero.isOne() && !minfp.isOne()) { - MathStructure mnum(minfp); - MathStructure mden(mzero); - mnum.calculatesub(eo, eo, false); - mden.calculatesub(eo, eo, false); - MathStructure mnum_bak(mnum), mden_bak(mden); - calculate_limit_sub(mnum, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true); - calculate_limit_sub(mden, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true); - if(mnum.contains(x_var, true) && mden.contains(x_var, true)) { - int cmp = limit_inf_cmp(mnum, mden, x_var); - if(cmp == 0) { - mstruct.set(mnum); - EvaluationOptions eo2 = eo; - eo2.expand = false; - mstruct.calculateDivide(mden, eo2); - if(!mstruct.contains(x_var)) { - for(size_t i = 0; i < mleft.size(); i++) { - mstruct.calculateMultiply(mleft[i], eo); - } - break; - } - } - MathStructure mnum_b(mnum), mden_b(mden); - calculate_limit_sub(mnum, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); - calculate_limit_sub(mden, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); - if(mnum.isInfinite(false) && mden.isInfinite(false)) { - if(cmp > 0) { - if(keep_inf_x) { - mstruct.set(mnum_b, true); - mstruct.calculateDivide(mden_b, eo); - break; - } - mstruct.set(mnum, true); - if(mden.number().isNegative()) mstruct.calculateNegate(eo); - for(size_t i = 0; i < mleft.size(); i++) { - mstruct.calculateMultiply(mleft[i], eo); - } - break; - } else if(cmp == -1) { - mstruct.clear(true); - break; - } - if(mnum_b.isPower() && mden_b.isPower() && mnum_b[1].contains(x_var, true) && mden_b[1].contains(x_var, true)) { - bool b = true; - if(mden_b[1] != mnum_b[1]) { - b = false; - Number npow1(1, 1, 0), npow2; - MathStructure *x_p = &mnum_b[1]; - if(mnum_b[1].isMultiplication() && mnum_b[1].size() == 2 && mnum_b[1][0].isNumber()) { - npow1 = mnum_b[1][0].number(); - x_p = &mnum_b[1][1]; - } - if(mden_b[1] == *x_p) npow2.set(1, 1, 0); - else if(mden_b[1].isMultiplication() && mden_b[1].size() == 2 && mden_b[1][0].isNumber() && mden_b[1][1] == *x_p) npow2 = mden_b[1][0].number(); - if(!npow2.isZero() && npow1.isRational() && npow2.isRational()) { - if(npow1.isGreaterThan(npow2)) { - npow1 /= npow2; - npow2 = npow1.denominator(); - npow1 = npow1.numerator(); - } - if(mnum.number().isMinusInfinity() && !npow1.isOne()) { - if(npow2.isOne() && mden.number().isPlusInfinity()) { - mden_b[0].factorize(eo, false, false, 0, false, false, NULL, m_undefined, false, true); - if(mden_b[0].isPower() && mden_b[0][1].isInteger()) { - mden_b[0][1].number() /= npow1; - if(mden_b[0][1].number().isInteger()) { - mden_b[0].calculateRaiseExponent(eo); - b = true; - } - } - } - } else if(mden.number().isMinusInfinity() && !npow2.isOne()) { - if(npow1.isOne() && mnum.number().isPlusInfinity()) { - mnum_b[0].factorize(eo, false, false, 0, false, false, NULL, m_undefined, false, true); - if(mnum_b[0].isPower() && mnum_b[0][1].isInteger()) { - mnum_b[0][1].number() /= npow2; - if(mnum_b[0][1].number().isInteger()) { - mnum_b[0].calculateRaiseExponent(eo); - mnum_b[1] = mden_b[1]; - b = true; - } - } - } - } else { - if(!npow1.isOne()) mnum_b[0].calculateRaise(npow1, eo); - if(!npow2.isOne()) mden_b[0].calculateRaise(npow2, eo); - mnum_b.childUpdated(1); - mden_b.childUpdated(1); - if(!npow1.isOne()) { - if(&mnum_b[1] == x_p) { - npow1.recip(); - mnum_b[1] *= npow1; - mnum_b[1].swapChildren(1, 2); - } else { - mnum_b[1][0].number() /= npow1; - } - } - b = true; - } - } - } - if(b) { - mstruct.set(mnum_b[0], true); - mstruct /= mden_b[0]; - mstruct.transform(CALCULATOR->f_ln); - mstruct *= mnum_b[1]; - mstruct.raise(CALCULATOR->v_e); - mstruct.swapChildren(1, 2); - calculate_limit_sub(mstruct, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, keep_inf_x); - for(size_t i = 0; i < mleft.size(); i++) { - mstruct.calculateMultiply(mleft[i], eo); - } - break; - } - } - } - } - } - if(!b_possible_zero && !b_fail && lhop_depth < 5 && !mzero.isOne() && !minfp.isOne() && mzero.countTotalChildren(false) + minfp.countTotalChildren(false) < 50) { - //L'Hôpital's rule - MathStructure mden, mnum; - for(size_t i2 = 0; i2 < 2; i2++) { - if((i2 == 0) != b_inf) { - mnum = mzero; - mden = minfp; - if(b_li) { - mden.inverse(); - mnum.inverse(); - } - } else { - mnum = minfp; - mden = mzero; - if(!b_li) { - mden.inverse(); - mnum.inverse(); - } - } - if(mnum.differentiate(x_var, eo) && !contains_diff_for(mnum, x_var) && mden.differentiate(x_var, eo) && !contains_diff_for(mden, x_var)) { - mnum /= mden; - mnum.eval(eo); - calculate_limit_sub(mnum, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth + 1); - if(!limit_contains_undefined(mnum)) { - mstruct.set(mnum, true); - for(size_t i = 0; i < mleft.size(); i++) { - mstruct.calculateMultiply(mleft[i], eo); - } - return true; - } - } - } - } - for(size_t i = 0; i < irecalc.size(); i++) { - mstruct[irecalc[i]] = mbak[irecalc[i]]; - calculate_limit_sub(mstruct[irecalc[i]], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); - } - mstruct.childrenUpdated(); - mstruct.calculatesub(eo, eo, false); - if(keep_inf_x && mstruct.isInfinite(false)) { - mstruct = mbak; - if(reduce_addition) { - for(size_t i = 0; i < mstruct.size(); i++) { - calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true, reduce_addition); - if(mstruct[i].isZero()) mstruct[i] = mbak[i]; - } - mstruct.childrenUpdated(); - mstruct.calculatesub(eo, eo, false); - } - } - break; - } - case STRUCT_ADDITION: { - MathStructure mbak(mstruct); - bool b = limit_combine_divisions(mstruct, x_var, nr_limit); - if(mstruct.isAddition()) b = limit_combine_divisions2(mstruct, x_var, nr_limit, eo); - if(b) { - if(lhop_depth > 0) return calculate_limit_sub(mstruct, x_var, nr_limit, eo, approach_direction, polydeg, lhop_depth); - if(calculate_limit_sub(mstruct, x_var, nr_limit, eo, approach_direction, polydeg, lhop_depth) && !limit_contains_undefined(mstruct)) return true; - mstruct = mbak; - } - if(nr_limit.isInfinite(false)) { - size_t i_cmp = 0; - b = true; - for(size_t i = 0; i < mstruct.size(); i++) { - calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true); - } - if(mstruct.contains(x_var, true) && (!keep_inf_x || reduce_addition)) { - bool bfac = false; - MathStructure mstruct_units(mstruct); - MathStructure mstruct_new(mstruct); - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(mstruct_units[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct_units[i].size();) { - if(!mstruct_units[i][i2].contains(x_var, true)) { - mstruct_units[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); - else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); - for(size_t i2 = 0; i2 < mstruct_new[i].size();) { - if(mstruct_new[i][i2].contains(x_var, true)) { - mstruct_new[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); - else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); - } else if(mstruct_units[i].contains(x_var, true)) { - mstruct_new[i].set(1, 1, 0); - } else { - mstruct_units[i].setUndefined(); - } - } - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(!mstruct_units[i].isUndefined()) { - for(size_t i2 = i + 1; i2 < mstruct_units.size(); i2++) { - if(mstruct_units[i2] == mstruct_units[i]) { - mstruct_new[i].add(mstruct_new[i2], true); - bfac = true; - } - } - bool bfac2 = false; - MathStructure mzero(mstruct_new[i]); - mzero.calculatesub(eo, eo, false); - if(bfac && mzero.isZero() && lhop_depth < 5) { - MathStructure mfac(mbak[i]); - bool b_diff = false; - calculate_limit_sub(mfac, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true, false); - if(mfac != mstruct[i]) b_diff = true; - for(size_t i2 = i + 1; i2 < mstruct_units.size(); i2++) { - if(mstruct_units[i2] == mstruct_units[i]) { - mfac.add(mbak[i2], true); - calculate_limit_sub(mfac.last(), x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true, false); - if(!b_diff && mfac.last() != mstruct[i2]) b_diff = true; - bfac2 = true; - } - } - if(bfac2) { - mfac.calculatesub(eo, eo, false); - if(!mfac.isAddition()) { - calculate_limit_sub(mfac, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth + 1, true); - mstruct_new[i].set(mfac, true); - } else if(!b_diff) { - bfac2 = false; - } else if(mfac.size() == 2 && !mfac.containsType(STRUCT_FUNCTION)) { - MathStructure mfac2(mfac); - MathStructure mmul(mfac); - mmul.last().calculateNegate(eo); - mfac.calculateMultiply(mmul, eo); - mfac.divide(mmul); - calculate_limit_sub(mfac, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth + 1, true); - if(limit_contains_undefined(mfac)) { - mfac2.factorize(eo, false, false, 0, false, false, NULL, m_undefined, false, false); - if(!mfac2.isAddition()) { - calculate_limit_sub(mfac2, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth + 1, true); - mstruct_new[i].set(mfac2, true); - } else { - bfac2 = false; - } - } else { - mstruct_new[i].set(mfac, true); - } - } else { - mfac.factorize(eo, false, false, 0, false, false, NULL, m_undefined, false, false); - if(!mfac.isAddition()) { - calculate_limit_sub(mfac, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth + 1, true); - mstruct_new[i].set(mfac, true); - } else if(mstruct_units[i].isFunction() && mstruct_units[i].function() == CALCULATOR->f_ln) { - mstruct_new[i].clear(true); - } else { - bfac2 = false; - } - } - } - } - if(!bfac2) { - if(mstruct_new[i].isOne()) { - mstruct_new[i].set(mstruct_units[i]); - } else if(mstruct_units[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct_units[i].size(); i2++) { - mstruct_new[i].multiply(mstruct_units[i][i2], true); - } - } else { - mstruct_new[i].multiply(mstruct_units[i], true); - } - } - for(size_t i2 = i + 1; i2 < mstruct_units.size(); i2++) { - if(mstruct_units[i2] == mstruct_units[i]) { - mstruct_units[i2].setUndefined(); - mstruct_new[i2].clear(); - } - } - } - } - if(bfac) { - for(size_t i = 0; mstruct_new.size() > 1 && i < mstruct_new.size();) { - if(mstruct_new[i].isZero()) { - mstruct_new.delChild(i + 1); - } else { - i++; - } - } - mstruct = mstruct_new; - if(mstruct.size() == 1) { - mstruct.setToChild(1, true); - if(!keep_inf_x) calculate_limit_sub(mstruct, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); - break; - } else if(!mstruct.contains(x_var, true)) { - b = false; - } - } - for(size_t i = 0; i < mstruct.size(); i++) { - if(i > 0 && mstruct[i].contains(x_var, true)) { - int cmp = limit_inf_cmp(mstruct[i], mstruct[i_cmp], x_var); - if(cmp > 0) { - mstruct.delChild(i_cmp + 1, false); - i--; - i_cmp = i; - } else if(cmp == -1) { - mstruct.delChild(i + 1, false); - i--; - } else { - b = false; - } - } - } - if(b) { - MathStructure mbak(mstruct); - for(size_t i = 0; i < mstruct.size();) { - if(!mstruct[i].contains(x_var, true)) { - if(mstruct[i].representsNumber()) { - mstruct.delChild(i + 1, false); - } else { - mstruct = mbak; - break; - } - } else { - i++; - } - } - } - } - if(!b || !keep_inf_x) { - for(size_t i = 0; i < mstruct.size(); i++) { - calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); - } - } - mstruct.childrenUpdated(); - if(mstruct.size() == 1) mstruct.setToChild(1, true); - else if(!b || !keep_inf_x) mstruct.calculatesub(eo, eo, false); - break; - } else { - for(size_t i = 0; i < mstruct.size(); i++) { - calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth); - } - } - mstruct.childrenUpdated(); - mstruct.calculatesub(eo, eo, false); - break; - } - case STRUCT_POWER: { - MathStructure mbak(mstruct); - calculate_limit_sub(mstruct[0], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); - calculate_limit_sub(mstruct[1], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); - if(is_plus_minus_infinity(mstruct[1]) && (mstruct[0].isOne() || mstruct[0].isZero()) && mbak[1].contains(x_var, true) && mbak[0].contains(x_var, true)) { - mstruct.set(mbak[0], true); - mstruct.transform(CALCULATOR->f_ln); - mstruct *= mbak[1]; - mstruct.raise(CALCULATOR->v_e); - mstruct.swapChildren(1, 2); - calculate_limit_sub(mstruct, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, keep_inf_x); - break; - } - if(mstruct[0].isFunction() && (mstruct[0].function() == CALCULATOR->f_asin || mstruct[0].function() == CALCULATOR->f_acos) && mstruct[0].size() == 1 && mstruct[0][0].isInfinite(false) && mstruct[1].representsNegative()) { - mstruct.clear(true); - break; - } - if(keep_inf_x && nr_limit.isInfinite(false) && (mstruct[0].isInfinite(false) || mstruct[1].isInfinite(false))) { - MathStructure mbak2(mstruct); - mstruct.calculatesub(eo, eo, false); - if(mstruct.isInfinite(false)) { - mstruct = mbak2; - if(mstruct[0].isInfinite(false)) { - mstruct[0] = mbak[0]; - calculate_limit_sub(mstruct[0], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true, reduce_addition && !mstruct[1].isInfinite(false)); - } else if(mbak[0].contains(x_var, true)) { - mstruct[0] = mbak[0]; - } - if(mstruct[1].isInfinite(false)) { - mstruct[1] = mbak[1]; - calculate_limit_sub(mstruct[1], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true, false); - } else if(mbak[1].contains(x_var, true)) { - mstruct[1] = mbak[1]; - } - } - } else if(mstruct[0].isNumber() && !mstruct[0].number().isNonZero() && mstruct[1].representsNegative() && mbak[0].contains(x_var, true) > 0) { - bool b_test = true; - int i_sgn = 0; - if(mstruct[0].number().isInterval(false) && (mstruct[0].number().hasImaginaryPart() || !mstruct[1].isNumber())) { - b_test = false; - } - if(b_test && ((mbak[0].isFunction() && mbak[0].function() == CALCULATOR->f_abs) || mstruct[1].representsEven())) { - i_sgn = 1; - b_test = false; - } else if(b_test) { - if(mstruct[0].number().isInterval(false) && !mstruct[0].number().isNonNegative() && !mstruct[0].number().isNonPositive()) { - b_test = false; - } else { - MathStructure mpow(mbak[0]); - if(mstruct[1].isMinusOne()) { - MathStructure mfac(mpow); - mfac.factorize(eo, false, false, 0, false, false, NULL, m_undefined, false, true); - if(mfac.isPower() && mfac[1].representsEven()) { - i_sgn = 1; - b_test = false; - } - } else { - mpow ^= mstruct[1]; - mpow.last().calculateNegate(eo); - } - if(b_test) { - MathStructure mdiff(mpow); - if(mdiff.differentiate(x_var, eo) && !contains_diff_for(mdiff, x_var)) { - mdiff.replace(x_var, nr_limit); - CALCULATOR->beginTemporaryStopMessages(); - mdiff.eval(eo); - if(!CALCULATOR->endTemporaryStopMessages()) { - if(mdiff.representsPositive()) { - b_test = false; - if(approach_direction > 0) i_sgn = 1; - else if(approach_direction < 0) i_sgn = -1; - } else if(mdiff.representsNegative()) { - b_test = false; - if(approach_direction > 0) i_sgn = -1; - else if(approach_direction < 0) i_sgn = 1; - } - } - } - if(b_test) { - MathStructure mtestn(nr_limit); - if(eo.approximation != APPROXIMATION_EXACT) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - mtestn.eval(eo2); - } - if(mtestn.isNumber() && mtestn.number().isReal()) { - for(int i = 10; i < 20; i++) { - if(approach_direction == 0 || (i % 2 == (approach_direction < 0))) { - Number nr_test(i % 2 == 0 ? 1 : -1, 1, -(i / 2)); - if(!mtestn.number().isZero()) { - nr_test++; - if(!nr_test.multiply(mtestn.number())) {i_sgn = 0; break;} - } - MathStructure mtest(mpow); - mtest.replace(x_var, nr_test); - CALCULATOR->beginTemporaryStopMessages(); - mtest.eval(eo); - if(CALCULATOR->endTemporaryStopMessages()) {i_sgn = 0; break;} - int new_sgn = 0; - if(mtest.representsPositive()) new_sgn = 1; - else if(mtest.representsNegative()) new_sgn = -1; - if(new_sgn != 0 || mtest.isNumber()) { - if(new_sgn == 0 || (i_sgn != 0 && i_sgn != new_sgn)) {i_sgn = 0; break;} - i_sgn = new_sgn; - } - } - if(CALCULATOR->aborted()) {i_sgn = 0; break;} - } - } - } - } - } - } - if(i_sgn != 0) { - if(mstruct[0].number().isInterval()) { - Number nr_pow = mstruct[1].number(); - Number nr_high(mstruct[0].number()); - if(nr_pow.negate() && nr_high.raise(nr_pow) && !nr_high.hasImaginaryPart()) { - if(nr_high.isNonNegative() && i_sgn > 0) nr_high = nr_high.upperEndPoint(); - else if(nr_high.isNonPositive() && i_sgn < 0) nr_high = nr_high.lowerEndPoint(); - if(nr_high.isNonZero() && nr_high.recip()) { - Number nr; - if(i_sgn > 0) nr.setInterval(nr_high, nr_plus_inf); - else if(i_sgn < 0) nr.setInterval(nr_minus_inf, nr_high); - mstruct.set(nr, true); - if(b_test) CALCULATOR->error(false, _("Limit for %s determined graphically."), format_and_print(mbak).c_str(), NULL); - break; - } - } - } else { - if(b_test) CALCULATOR->error(false, _("Limit for %s determined graphically."), format_and_print(mbak).c_str(), NULL); - if(i_sgn > 0) mstruct.set(nr_plus_inf, true); - else if(i_sgn < 0) mstruct.set(nr_minus_inf, true); - break; - } - } - } - mstruct.childrenUpdated(); - mstruct.calculatesub(eo, eo, false); - break; - } - case STRUCT_FUNCTION: { - if(keep_inf_x && nr_limit.isInfinite(false) && mstruct.size() == 1 && (mstruct.function() == CALCULATOR->f_ln || mstruct.function() == CALCULATOR->f_gamma)) { - MathStructure mbak(mstruct); - calculate_limit_sub(mstruct[0], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); - if(mstruct[0].isInfinite(false) && (mstruct[0].number().isPlusInfinity() || mstruct.function() == CALCULATOR->f_ln)) { - mstruct[0] = mbak[0]; - calculate_limit_sub(mstruct[0], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true, mstruct.function() == CALCULATOR->f_ln && reduce_addition); - break; - } - } else { - for(size_t i = 0; i < mstruct.size(); i++) { - calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); - } - mstruct.childrenUpdated(); - } - if(approach_direction != 0 && mstruct.function() == CALCULATOR->f_gamma && mstruct.size() == 1 && mstruct[0].isInteger() && mstruct[0].number().isNonPositive()) { - if((mstruct[0].number().isEven() && approach_direction < 0) || (mstruct[0].number().isOdd() && approach_direction > 0)) { - mstruct.set(nr_minus_inf, true); - } else { - mstruct.set(nr_plus_inf, true); - } - break; - } - mstruct.calculateFunctions(eo, true); - mstruct.calculatesub(eo, eo, false); - break; - } - default: { - for(size_t i = 0; i < mstruct.size(); i++) { - calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false, reduce_addition); - } - mstruct.childrenUpdated(); - mstruct.calculatesub(eo, eo, false); - } - } - return true; -} - -bool replace_equal_limits(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &nr_limit, const EvaluationOptions &eo, int approach_direction, bool at_top = true) { - if(!nr_limit.isInfinite(false)) return false; - bool b_ret = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(replace_equal_limits(mstruct[i], x_var, nr_limit, eo, approach_direction, false)) { - mstruct.childUpdated(i + 1); - b_ret = true; - } - } - if(at_top) return b_ret; - if(mstruct.isFunction() && (mstruct.function() == CALCULATOR->f_sinh || mstruct.function() == CALCULATOR->f_cosh) && mstruct.size() == 1 && mstruct.contains(x_var, true)) { - MathStructure mterm1(CALCULATOR->v_e); - mterm1.raise(mstruct[0]); - MathStructure mterm2(mterm1); - mterm2[1].negate(); - mterm1 *= nr_half; - mterm2 *= nr_half; - mstruct = mterm1; - if(mstruct.function() == CALCULATOR->f_sinh) mstruct -= mterm2; - else mstruct += mterm2; - return true; - } - return b_ret; -} -bool replace_equal_limits2(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &nr_limit, const EvaluationOptions &eo, int approach_direction, bool at_top = true) { - if(!nr_limit.isInfinite(false)) return false; - bool b_ret = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(replace_equal_limits2(mstruct[i], x_var, nr_limit, eo, approach_direction, false)) { - mstruct.childUpdated(i + 1); - b_ret = true; - } - } - if(mstruct.isMultiplication()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isPower() && mstruct[i][1] == x_var && (nr_limit.number().isMinusInfinity() || mstruct[i][0].representsNonNegative())) { - for(size_t i2 = i + 1; i2 < mstruct.size();) { - if(mstruct[i2].isPower() && mstruct[i2][1] == x_var && (nr_limit.number().isMinusInfinity() || mstruct[i2][0].representsNonNegative())) { - mstruct[i][0].calculateMultiply(mstruct[i2][0], eo); - mstruct.delChild(i2 + 1, false); - } else { - i2++; - } - } - mstruct[i].childUpdated(1); - mstruct.childUpdated(i + 1); - if(mstruct.size() == 1) { - mstruct.setToChild(1, true); - break; - } - } - } - } - return b_ret; -} -bool replace_equal_limits3(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &nr_limit, const EvaluationOptions &eo, int approach_direction, bool at_top = true) { - if(!nr_limit.isInfinite(false)) return false; - bool b_ret = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(replace_equal_limits3(mstruct[i], x_var, nr_limit, eo, approach_direction, false)) { - mstruct.childUpdated(i + 1); - b_ret = true; - } - } - if(at_top) return b_ret; - if(mstruct.isFunction() && (mstruct.function() == CALCULATOR->f_asinh || mstruct.function() == CALCULATOR->f_acosh) && mstruct.size() == 1 && mstruct.contains(x_var, true)) { - MathStructure mtest(mstruct[0]); - calculate_limit_sub(mtest, x_var, nr_limit, eo, approach_direction); - if(mtest.isInfinite(false)) { - if(mtest.number().isPlusInfinity()) { - mstruct.setFunction(CALCULATOR->f_ln); - mstruct[0] *= nr_two; - return true; - } else if(mstruct.function() == CALCULATOR->f_asinh) { - mstruct.setFunction(CALCULATOR->f_ln); - mstruct[0] *= nr_two; - mstruct.negate(); - return true; - } - } - } - return b_ret; -} - -bool MathStructure::calculateLimit(const MathStructure &x_var, const MathStructure &limit, const EvaluationOptions &eo_pre, int approach_direction) { - EvaluationOptions eo = eo_pre; - eo.assume_denominators_nonzero = true; - eo.warn_about_denominators_assumed_nonzero = false; - eo.do_polynomial_division = false; - UnknownVariable *var = new UnknownVariable("", format_and_print(x_var)); - Assumptions *ass = new Assumptions(); - MathStructure nr_limit(limit); - if(eo.approximation != APPROXIMATION_EXACT && nr_limit.containsInterval(true, true, false, 0, true)) { - eo.approximation = APPROXIMATION_EXACT_VARIABLES; - } - nr_limit.eval(eo); - eo.approximation = eo_pre.approximation; - if(nr_limit.representsReal() || nr_limit.isInfinite()) ass->setType(ASSUMPTION_TYPE_REAL); - if(nr_limit.representsPositive()) ass->setSign(ASSUMPTION_SIGN_POSITIVE); - else if(nr_limit.representsNegative()) ass->setSign(ASSUMPTION_SIGN_NEGATIVE); - else if(nr_limit.isZero()) { - if(approach_direction < 0) ass->setSign(ASSUMPTION_SIGN_NEGATIVE); - else if(approach_direction > 0) ass->setSign(ASSUMPTION_SIGN_POSITIVE); - else ass->setSign(ASSUMPTION_SIGN_NONZERO); - } - var->setAssumptions(ass); - replace(x_var, var); - eval(eo); - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mbak(*this); - if(replace_equal_limits(*this, var, nr_limit, eo, approach_direction)) eval(eo); - replace_equal_limits2(*this, var, nr_limit, eo, approach_direction); - if(replace_equal_limits3(*this, var, nr_limit, eo, approach_direction)) { - eval(eo); - replace_equal_limits2(*this, var, nr_limit, eo, approach_direction); - } - do_simplification(*this, eo, true, false, false, true, true); - eo.do_polynomial_division = true; - calculate_limit_sub(*this, var, nr_limit, eo, approach_direction); - if(CALCULATOR->aborted() || (containsInfinity(true) && !isInfinite(true)) || limit_contains_undefined(*this)) { - set(mbak); - replace(var, x_var); - var->destroy(); - CALCULATOR->endTemporaryStopMessages(); - return false; - } - replace(var, nr_limit); - var->destroy(); - CALCULATOR->endTemporaryStopMessages(true); - return true; -} - - -#define IS_VAR_EXP(x, ofa) ((x.isVariable() && x.variable()->isKnown() && (!ofa || x.variable()->title() == "\b")) || (x.isPower() && x[0].isVariable() && x[0].variable()->isKnown() && (!ofa || x[0].variable()->title() == "\b"))) - -void factorize_variable(MathStructure &mstruct, const MathStructure &mvar, bool deg2) { - if(deg2) { - // ax^2+bx = (sqrt(b)*x+(a/sqrt(b))/2)^2-((a/sqrt(b))/2)^2 - MathStructure a_struct, b_struct, mul_struct(1, 1, 0); - for(size_t i2 = 0; i2 < mstruct.size();) { - bool b = false; - if(mstruct[i2] == mvar) { - a_struct.set(1, 1, 0); - b = true; - } else if(mstruct[i2].isPower() && mstruct[i2][0] == mvar && mstruct[i2][1].isNumber() && mstruct[i2][1].number().isTwo()) { - b_struct.set(1, 1, 0); - b = true; - } else if(mstruct[i2].isMultiplication()) { - for(size_t i3 = 0; i3 < mstruct[i2].size(); i3++) { - if(mstruct[i2][i3] == mvar) { - a_struct = mstruct[i2]; - a_struct.delChild(i3 + 1); - b = true; - break; - } else if(mstruct[i2][i3].isPower() && mstruct[i2][i3][0] == mvar && mstruct[i2][i3][1].isNumber() && mstruct[i2][i3][1].number().isTwo()) { - b_struct = mstruct[i2]; - b_struct.delChild(i3 + 1); - b = true; - break; - } - } - } - if(b) { - mstruct.delChild(i2 + 1); - } else { - i2++; - } - } - if(b_struct == a_struct) { - if(a_struct.isMultiplication() && a_struct.size() == 1) mul_struct = a_struct[0]; - else mul_struct = a_struct; - a_struct.set(1, 1, 0); - b_struct.set(1, 1, 0); - } else if(b_struct.isMultiplication() && a_struct.isMultiplication()) { - size_t i3 = 0; - for(size_t i = 0; i < a_struct.size();) { - bool b = false; - for(size_t i2 = i3; i2 < b_struct.size(); i2++) { - if(a_struct[i] == b_struct[i2]) { - i3 = i2; - if(mul_struct.isOne()) mul_struct = a_struct[i]; - else mul_struct.multiply(a_struct[i], true); - a_struct.delChild(i + 1); - b_struct.delChild(i2 + 1); - b = true; - break; - } - } - if(!b) i++; - } - } - if(a_struct.isMultiplication() && a_struct.size() == 0) a_struct.set(1, 1, 0); - else if(a_struct.isMultiplication() && a_struct.size() == 1) a_struct.setToChild(1); - if(b_struct.isMultiplication() && b_struct.size() == 0) b_struct.set(1, 1, 0); - else if(b_struct.isMultiplication() && b_struct.size() == 1) b_struct.setToChild(1); - if(!b_struct.isOne()) { - b_struct.raise(nr_half); - a_struct.divide(b_struct); - } - a_struct.multiply(nr_half); - if(b_struct.isOne()) b_struct = mvar; - else b_struct *= mvar; - b_struct += a_struct; - b_struct.raise(nr_two); - a_struct.raise(nr_two); - a_struct.negate(); - b_struct += a_struct; - if(!mul_struct.isOne()) b_struct *= mul_struct; - if(mstruct.size() == 0) mstruct = b_struct; - else mstruct.addChild(b_struct); - } else { - vector left_structs; - for(size_t i2 = 0; i2 < mstruct.size();) { - bool b = false; - if(mstruct[i2] == mvar) { - mstruct[i2].set(1, 1, 0, true); - b = true; - } else if(mstruct[i2].isMultiplication()) { - for(size_t i3 = 0; i3 < mstruct[i2].size(); i3++) { - if(mstruct[i2][i3] == mvar) { - mstruct[i2].delChild(i3 + 1, true); - b = true; - break; - } - } - } - if(b) { - i2++; - } else { - mstruct[i2].ref(); - left_structs.push_back(&mstruct[i2]); - mstruct.delChild(i2 + 1); - } - } - mstruct.multiply(mvar); - for(size_t i = 0; i < left_structs.size(); i++) { - mstruct.add_nocopy(left_structs[i], true); - mstruct.evalSort(false); - } - } -} - -bool var_contains_interval(const MathStructure &mstruct) { - if(mstruct.isNumber()) return mstruct.number().isInterval(); - if(mstruct.isFunction() && (mstruct.function() == CALCULATOR->f_interval || mstruct.function() == CALCULATOR->f_uncertainty)) return true; - if(mstruct.isVariable() && mstruct.variable()->isKnown()) return var_contains_interval(((KnownVariable*) mstruct.variable())->get()); - for(size_t i = 0; i < mstruct.size(); i++) { - if(var_contains_interval(mstruct[i])) return true; - } - return false; -} - -bool factorize_variables(MathStructure &mstruct, const EvaluationOptions &eo, bool ofa = false) { - bool b = false; - if(mstruct.type() == STRUCT_ADDITION) { - vector variables; - vector variable_count; - vector term_sgn; - vector term_deg2; - for(size_t i = 0; i < mstruct.size(); i++) { - if(CALCULATOR->aborted()) break; - if(mstruct[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - if(CALCULATOR->aborted()) break; - if(IS_VAR_EXP(mstruct[i][i2], ofa)) { - bool b_found = false; - for(size_t i3 = 0; i3 < variables.size(); i3++) { - if(variables[i3] == mstruct[i][i2]) { - variable_count[i3]++; - b_found = true; - if(term_sgn[i3] == 1 && !mstruct[i].representsNonNegative(true)) term_sgn[i3] = 0; - else if(term_sgn[i3] == -1 && !mstruct[i].representsNonPositive(true)) term_sgn[i3] = 0; - break; - } - } - if(!b_found) { - variables.push_back(mstruct[i][i2]); - variable_count.push_back(1); - term_deg2.push_back(false); - if(mstruct[i].representsNonNegative(true)) term_sgn.push_back(1); - else if(mstruct[i].representsNonPositive(true)) term_sgn.push_back(-1); - else term_sgn.push_back(0); - } - } - } - } else if(IS_VAR_EXP(mstruct[i], ofa)) { - bool b_found = false; - for(size_t i3 = 0; i3 < variables.size(); i3++) { - if(variables[i3] == mstruct[i]) { - variable_count[i3]++; - b_found = true; - if(term_sgn[i3] == 1 && !mstruct[i].representsNonNegative(true)) term_sgn[i3] = 0; - else if(term_sgn[i3] == -1 && !mstruct[i].representsNonPositive(true)) term_sgn[i3] = 0; - break; - } - } - if(!b_found) { - variables.push_back(mstruct[i]); - variable_count.push_back(1); - term_deg2.push_back(false); - if(mstruct[i].representsNonNegative(true)) term_sgn.push_back(1); - else if(mstruct[i].representsNonPositive(true)) term_sgn.push_back(-1); - else term_sgn.push_back(0); - } - } - } - for(size_t i = 0; i < variables.size();) { - bool b_erase = false; - if(!var_contains_interval(variables[i])) { - b_erase = true; - } else if(variable_count[i] == 1 || term_sgn[i] != 0) { - b_erase = true; - if(!variables[i].isPower() || (variables[i][1].isNumber() && variables[i][1].number().isTwo())) { - for(size_t i2 = i + 1; i2 < variables.size(); i2++) { - if((variables[i].isPower() && !variables[i2].isPower() && variables[i][0] == variables[i2])|| (!variables[i].isPower() && variables[i2].isPower() && variables[i2][0] == variables[i] && variables[i2][1].isNumber() && variables[i2][1].number().isTwo())) { - bool b_erase2 = false; - if(variable_count[i2] == 1) { - if(term_sgn[i] == 0 || term_sgn[i2] != term_sgn[i]) { - if(variable_count[i] == 1) { - term_deg2[i] = true; - variable_count[i] = 2; - term_sgn[i] = 0; - if(variables[i].isPower()) variables[i].setToChild(1); - } else { - term_sgn[i] = 0; - } - b_erase = false; - } - b_erase2 = true; - } else if(term_sgn[i2] != 0) { - if(term_sgn[i] == 0 || term_sgn[i2] != term_sgn[i]) { - if(variable_count[i] != 1) { - term_sgn[i] = 0; - b_erase = false; - } - term_sgn[i2] = 0; - } else { - b_erase2 = true; - } - } - if(b_erase2) { - variable_count.erase(variable_count.begin() + i2); - variables.erase(variables.begin() + i2); - term_deg2.erase(term_deg2.begin() + i2); - term_sgn.erase(term_sgn.begin() + i2); - } - break; - } - } - } - } - if(b_erase) { - variable_count.erase(variable_count.begin() + i); - variables.erase(variables.begin() + i); - term_deg2.erase(term_deg2.begin() + i); - term_sgn.erase(term_sgn.begin() + i); - } else if(variable_count[i] == mstruct.size()) { - factorize_variable(mstruct, variables[i], term_deg2[i]); - if(CALCULATOR->aborted()) return true; - factorize_variables(mstruct, eo, ofa); - return true; - } else { - i++; - } - } - if(variables.size() == 1) { - factorize_variable(mstruct, variables[0], term_deg2[0]); - if(CALCULATOR->aborted()) return true; - factorize_variables(mstruct, eo, ofa); - return true; - } - Number uncertainty; - size_t u_index = 0; - for(size_t i = 0; i < variables.size(); i++) { - const MathStructure *v_ms; - Number nr; - if(variables[i].isPower()) v_ms = &((KnownVariable*) variables[i][0].variable())->get(); - else v_ms = &((KnownVariable*) variables[i].variable())->get(); - if(v_ms->isNumber()) nr = v_ms->number(); - else if(v_ms->isMultiplication() && v_ms->size() > 0 && (*v_ms)[0].isNumber()) nr = (v_ms)[0].number(); - else { - MathStructure mtest(*v_ms); - mtest.unformat(eo); - mtest.calculatesub(eo, eo, true); - if(mtest.isNumber()) nr = mtest.number(); - else if(mtest.isMultiplication() && mtest.size() > 0 && mtest[0].isNumber()) nr = mtest[0].number(); - } - if(nr.isInterval()) { - Number u_candidate(nr.uncertainty()); - if(variables[i].isPower() && variables[i][1].isNumber() && variables[i][1].number().isReal()) u_candidate.raise(variables[i][1].number()); - u_candidate.multiply(variable_count[i]); - if(u_candidate.isGreaterThan(uncertainty)) { - uncertainty = u_candidate; - u_index = i; - } - } - } - if(!uncertainty.isZero()) { - factorize_variable(mstruct, variables[u_index], term_deg2[u_index]); - if(CALCULATOR->aborted()) return true; - factorize_variables(mstruct, eo, ofa); - return true; - } - - } - for(size_t i = 0; i < mstruct.size(); i++) { - if(factorize_variables(mstruct[i], eo, ofa)) { - mstruct.childUpdated(i + 1); - b = true; - } - if(CALCULATOR->aborted()) return b; - } - return b; -} - -void find_interval_variables(const MathStructure &mstruct, vector &vars, vector &v_count, vector &v_prec) { - if(mstruct.isVariable() && mstruct.variable()->isKnown()) { - KnownVariable *v = (KnownVariable*) mstruct.variable(); - int var_prec = PRECISION + 11; - const MathStructure &mv = v->get(); - for(size_t i = 0; i < vars.size(); i++) { - if(vars[i] == v) { - v_count[i]++; - return; - } - } - if(mv.isNumber()) { - if(mv.number().isInterval()) var_prec = mv.number().precision(1); - else if(CALCULATOR->usesIntervalArithmetic() && mv.number().precision() >= 0) var_prec = mv.number().precision(); - } else if(mv.isMultiplication()) { - for(size_t i = 0; i < mv.size(); i++) { - if(mv[i].isNumber()) { - if(mv[i].number().isInterval()) {var_prec = mv[i].number().precision(1); break;} - else if(mv[i].number().precision() >= 0) {var_prec = mv[i].number().precision(); break;} - } - } - } - if(var_prec <= PRECISION + 10) { - bool b = false; - for(size_t i = 0; i < v_prec.size(); i++) { - if(var_prec < v_prec[i]) { - v_prec.insert(v_prec.begin() + i, var_prec); - v_count.insert(v_count.begin() + i, 1); - vars.insert(vars.begin() + i, v); - b = true; - break; - } - } - if(!b) { - v_prec.push_back(var_prec); - v_count.push_back(1); - vars.push_back(v); - } - } - } - for(size_t i = 0; i < mstruct.size(); i++) { - find_interval_variables(mstruct[i], vars, v_count, v_prec); - } -} -bool contains_not_nonzero(MathStructure &m) { - if(m.isNumber() && !m.number().isNonZero()) { - return true; - } else if(m.isMultiplication()) { - for(size_t i = 0; i < m.size(); i++) { - if(contains_not_nonzero(m[i])) return true; - } - } - return false; -} -bool contains_undefined(MathStructure &m, const EvaluationOptions &eo = default_evaluation_options, bool calc = false, const MathStructure &x_var = m_zero, const MathStructure &m_intval = nr_zero) { - if(m.isPower() && (m[1].representsNegative() || (m[1].isNumber() && !m[1].number().isNonNegative()))) { - if(calc) { - m[0].replace(x_var, m_intval, true); - m[0].calculatesub(eo, eo, true); - } - if(contains_not_nonzero(m[0])) return true; - } - for(size_t i = 0; i < m.size(); i++) { - if(contains_undefined(m[i], eo, calc, x_var, m_intval)) return true; - } - return false; -} -bool find_interval_zeroes(const MathStructure &mstruct, MathStructure &malts, const MathStructure &mvar, const Number &nr_intval, const EvaluationOptions &eo, int depth, const Number &nr_prec, int orig_prec = 0, int is_real = -1, int undef_depth = 0) { - if(CALCULATOR->aborted()) return false; - if(depth == 0) orig_prec = nr_intval.precision(1); - MathStructure mtest(mstruct); - mtest.replace(mvar, nr_intval); - mtest.eval(eo); - if(is_real < 0) is_real = mtest.representsNonComplex(true); - ComparisonResult cmp; - if(is_real == 0) { - MathStructure m_re(CALCULATOR->f_re, &mtest, NULL); - m_re.calculateFunctions(eo); - cmp = m_re.compare(m_zero); - MathStructure m_im(CALCULATOR->f_im, &mtest, NULL); - m_im.calculateFunctions(eo); - ComparisonResult cmp2 = m_im.compare(m_zero); - if(COMPARISON_IS_NOT_EQUAL(cmp) || cmp2 == COMPARISON_RESULT_EQUAL || cmp == COMPARISON_RESULT_UNKNOWN) cmp = cmp2; - } else { - cmp = mtest.compare(m_zero); - } - if(COMPARISON_IS_NOT_EQUAL(cmp)) { - return true; - } else if(cmp != COMPARISON_RESULT_UNKNOWN || (undef_depth <= 5 && contains_undefined(mtest))) { - if(cmp == COMPARISON_RESULT_EQUAL || (nr_intval.precision(1) > (orig_prec > PRECISION ? orig_prec + 5 : PRECISION + 5) || (!nr_intval.isNonZero() && nr_intval.uncertainty().isLessThan(nr_prec)))) { - if(cmp == COMPARISON_RESULT_EQUAL && depth <= 3) return false; - if(malts.size() > 0 && (cmp = malts.last().compare(nr_intval)) != COMPARISON_RESULT_UNKNOWN && COMPARISON_MIGHT_BE_EQUAL(cmp)) { - malts.last().number().setInterval(malts.last().number(), nr_intval); - if(malts.last().number().precision(1) < (orig_prec > PRECISION ? orig_prec + 3 : PRECISION + 3)) { - return false; - } - } else { - malts.addChild(nr_intval); - } - return true; - } - vector splits; - nr_intval.splitInterval(2, splits); - for(size_t i = 0; i < splits.size(); i++) { - if(!find_interval_zeroes(mstruct, malts, mvar, splits[i], eo, depth + 1, nr_prec, orig_prec, is_real, cmp == COMPARISON_RESULT_UNKNOWN ? undef_depth + 1 : 0)) return false; - } - return true; - } - return false; -} -bool contains_interval_variable(const MathStructure &m, int i_type = 0) { - if(i_type == 0 && m.isVariable() && m.containsInterval(true, true, false, 1, false)) return true; - else if(i_type == 1 && m.containsInterval(true, false, false, 1, true)) return true; - else if(i_type == 2 && m.containsInterval(true, true, false, 1, true)) return true; - for(size_t i = 0; i < m.size(); i++) { - if(contains_interval_variable(m[i])) return true; - } - return false; -} -bool function_differentiable(MathFunction *o_function) { - return (o_function == CALCULATOR->f_sqrt || o_function == CALCULATOR->f_root || o_function == CALCULATOR->f_cbrt || o_function == CALCULATOR->f_ln || o_function == CALCULATOR->f_logn || o_function == CALCULATOR->f_arg || o_function == CALCULATOR->f_gamma || o_function == CALCULATOR->f_beta || o_function == CALCULATOR->f_abs || o_function == CALCULATOR->f_factorial || o_function == CALCULATOR->f_besselj || o_function == CALCULATOR->f_bessely || o_function == CALCULATOR->f_erf || o_function == CALCULATOR->f_erfc || o_function == CALCULATOR->f_li || o_function == CALCULATOR->f_Li || o_function == CALCULATOR->f_Ei || o_function == CALCULATOR->f_Si || o_function == CALCULATOR->f_Ci || o_function == CALCULATOR->f_Shi || o_function == CALCULATOR->f_Chi || o_function == CALCULATOR->f_abs || o_function == CALCULATOR->f_signum || o_function == CALCULATOR->f_heaviside || o_function == CALCULATOR->f_lambert_w || o_function == CALCULATOR->f_sinc || o_function == CALCULATOR->f_sin || o_function == CALCULATOR->f_cos || o_function == CALCULATOR->f_tan || o_function == CALCULATOR->f_asin || o_function == CALCULATOR->f_acos || o_function == CALCULATOR->f_atan || o_function == CALCULATOR->f_sinh || o_function == CALCULATOR->f_cosh || o_function == CALCULATOR->f_tanh || o_function == CALCULATOR->f_asinh || o_function == CALCULATOR->f_acosh || o_function == CALCULATOR->f_atanh || o_function == CALCULATOR->f_stripunits); -} - -bool calculate_differentiable_functions(MathStructure &m, const EvaluationOptions &eo, bool recursive = true, bool do_unformat = true) { - if(m.isFunction() && m.function() != eo.protected_function && function_differentiable(m.function())) { - return m.calculateFunctions(eo, recursive, do_unformat); - } - bool b = false; - if(recursive) { - for(size_t i = 0; i < m.size(); i++) { - if(CALCULATOR->aborted()) break; - if(calculate_differentiable_functions(m[i], eo, recursive, do_unformat)) { - m.childUpdated(i + 1); - b = true; - } - } - } - return b; -} -bool calculate_nondifferentiable_functions(MathStructure &m, const EvaluationOptions &eo, bool recursive = true, bool do_unformat = true, int i_type = 0) { - if(m.isFunction() && m.function() != eo.protected_function) { - if((i_type <= 0 && !function_differentiable(m.function())) || (i_type >= 0 && !contains_interval_variable(m, i_type))) { - if(m.calculateFunctions(eo, false, do_unformat)) { - if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type); - return true; - } - } else if(m.function() == CALCULATOR->f_abs && m.size() == 1) { - EvaluationOptions eo3 = eo; - eo3.split_squares = false; - eo3.assume_denominators_nonzero = false; - if(eo.approximation == APPROXIMATION_APPROXIMATE && !m.containsUnknowns()) eo3.approximation = APPROXIMATION_EXACT_VARIABLES; - else eo3.approximation = APPROXIMATION_EXACT; - m[0].calculatesub(eo3, eo); - m.childUpdated(1); - if(m[0].representsNegative(true)) { - m.setToChild(1); - m.negate(); - if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type); - return true; - } - if(m[0].representsNonNegative(true)) { - m.setToChild(1); - if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type); - return true; - } - if(m[0].isMultiplication()) { - m.setToChild(1); - for(size_t i = 0; i < m.size(); i++) { - m[i].transform(CALCULATOR->f_abs); - } - m.childrenUpdated(); - if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type); - return true; - } - if(eo.approximation != APPROXIMATION_EXACT) { - eo3.approximation = APPROXIMATION_APPROXIMATE; - MathStructure mtest(m[0]); - mtest.calculatesub(eo3, eo); - if(mtest.representsNegative(true)) { - m.setToChild(1); - m.negate(); - if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type); - return true; - } - if(mtest.representsNonNegative(true)) { - m.setToChild(1); - if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type); - return true; - } - } - } - } - bool b = false; - if(recursive) { - for(size_t i = 0; i < m.size(); i++) { - if(CALCULATOR->aborted()) break; - if(calculate_nondifferentiable_functions(m[i], eo, recursive, do_unformat, i_type)) { - m.childUpdated(i + 1); - b = true; - } - } - } - return b; -} - -void remove_nonzero_mul(MathStructure &msolve, const MathStructure &u_var, const EvaluationOptions &eo) { - if(!msolve.isMultiplication()) return; - for(size_t i = 0; i < msolve.size();) { - if(!msolve[i].contains(u_var, true)) { - msolve[i].eval(eo); - if(msolve[i].representsNonZero(true)) { - if(msolve.size() == 2) { - msolve.delChild(i + 1, true); - break; - } - msolve.delChild(i + 1, true); - } else { - remove_nonzero_mul(msolve[i], u_var, eo); - i++; - } - } else { - remove_nonzero_mul(msolve[i], u_var, eo); - i++; - } - } -} - -extern bool create_interval(MathStructure &mstruct, const MathStructure &m1, const MathStructure &m2); -void solve_intervals2(MathStructure &mstruct, vector vars, const EvaluationOptions &eo_pre) { - if(vars.size() > 0) { - EvaluationOptions eo = eo_pre; - eo.approximation = APPROXIMATION_EXACT_VARIABLES; - eo.expand = false; - if(eo.calculate_functions) calculate_differentiable_functions(mstruct, eo); - KnownVariable *v = vars[0]; - vars.erase(vars.begin()); - UnknownVariable *u_var = new UnknownVariable("", "u"); - Number nr_intval; - MathStructure mvar(u_var); - const MathStructure &mv = v->get(); - MathStructure mmul(1, 1, 0); - if(mv.isMultiplication()) { - for(size_t i = 0; i < mv.size(); i++) { - if(mv[i].isNumber() && mv[i].number().isInterval()) { - mmul = mv; - mmul.unformat(eo); - mmul.delChild(i + 1, true); - mvar.multiply(mmul); - nr_intval = mv[i].number(); - u_var->setInterval(nr_intval); - break; - } - } - } else { - nr_intval = mv.number(); - u_var->setInterval(mv); - } - MathStructure msolve(mstruct); - msolve.replace(v, mvar); - bool b = true; - CALCULATOR->beginTemporaryStopMessages(); - - if(!msolve.differentiate(u_var, eo) || msolve.countTotalChildren(false) > 10000 || contains_diff_for(msolve, u_var) || CALCULATOR->aborted()) { - b = false; - } - - MathStructure malts; - malts.clearVector(); - if(b) { - eo.keep_zero_units = false; - eo.approximation = APPROXIMATION_APPROXIMATE; - eo.expand = eo_pre.expand; - MathStructure mtest(msolve); - mtest.replace(u_var, nr_intval); - mtest.eval(eo); - if(mtest.countTotalChildren(false) < 100) { - if(mtest.representsNonComplex(true)) { - ComparisonResult cmp = mtest.compare(m_zero); - if(!COMPARISON_IS_EQUAL_OR_GREATER(cmp) && !COMPARISON_IS_EQUAL_OR_LESS(cmp)) b = false; - } else { - MathStructure m_re(CALCULATOR->f_re, &mtest, NULL); - m_re.calculateFunctions(eo); - ComparisonResult cmp = m_re.compare(m_zero); - if(!COMPARISON_IS_EQUAL_OR_GREATER(cmp) && !COMPARISON_IS_EQUAL_OR_LESS(cmp)) { - b = false; - } else { - MathStructure m_im(CALCULATOR->f_im, &mtest, NULL); - m_im.calculateFunctions(eo); - ComparisonResult cmp = m_im.compare(m_zero); - if(!COMPARISON_IS_EQUAL_OR_GREATER(cmp) && !COMPARISON_IS_EQUAL_OR_LESS(cmp)) b = false; - } - } - } else { - b = false; - } - eo.expand = false; - eo.approximation = APPROXIMATION_EXACT_VARIABLES; - if(!b) { - b = true; - msolve.calculatesub(eo, eo, true); - eo.approximation = APPROXIMATION_APPROXIMATE; - eo.expand = eo_pre.expand; - msolve.factorize(eo, false, false, 0, false, true, NULL, m_undefined, false, false, 1); - remove_nonzero_mul(msolve, u_var, eo); - if(msolve.isZero()) { - } else if(contains_undefined(msolve) || msolve.countTotalChildren(false) > 1000 || msolve.containsInterval(true, true, false, 1, true)) { - b = false; - } else { - MathStructure mtest(mstruct); - mtest.replace(v, u_var); - mtest.calculatesub(eo, eo, true); - if(contains_undefined(mtest, eo, true, u_var, mv)) { - b = false; - } else { - Number nr_prec(1, 1, -(PRECISION + 10)); - nr_prec *= nr_intval.uncertainty(); - b = find_interval_zeroes(msolve, malts, u_var, nr_intval, eo, 0, nr_prec); - } - } - eo.expand = false; - eo.approximation = APPROXIMATION_EXACT_VARIABLES; - } - eo.keep_zero_units = eo_pre.keep_zero_units; - } - CALCULATOR->endTemporaryStopMessages(); - CALCULATOR->beginTemporaryStopMessages(); - if(b) { - malts.addChild(nr_intval.lowerEndPoint()); - malts.addChild(nr_intval.upperEndPoint()); - MathStructure mnew; - for(size_t i = 0; i < malts.size(); i++) { - MathStructure mlim(mstruct); - if(!mmul.isOne()) malts[i] *= mmul; - mlim.replace(v, malts[i]); - mlim.calculatesub(eo, eo, true); - vector vars2 = vars; - solve_intervals2(mlim, vars2, eo_pre); - if(i == 0) { - mnew = mlim; - } else { - MathStructure mlim1(mnew); - if(!create_interval(mnew, mlim1, mlim)) { - eo.approximation = APPROXIMATION_APPROXIMATE; - eo.expand = eo_pre.expand; - mlim.eval(eo); - if(!create_interval(mnew, mlim1, mlim)) { - mlim1.eval(eo); - eo.expand = false; - eo.approximation = APPROXIMATION_EXACT_VARIABLES; - if(!create_interval(mnew, mlim1, mlim)) { - b = false; - break; - } - } - } - } - } - if(b) mstruct = mnew; - } - CALCULATOR->endTemporaryStopMessages(b); - if(!b) { - CALCULATOR->error(false, MESSAGE_CATEGORY_WIDE_INTERVAL, _("Interval potentially calculated wide."), NULL); - mstruct.replace(v, v->get()); - mstruct.unformat(eo_pre); - solve_intervals2(mstruct, vars, eo_pre); - } - u_var->destroy(); - } -} -KnownVariable *fix_find_interval_variable(MathStructure &mstruct) { - if(mstruct.isVariable() && mstruct.variable()->isKnown()) { - const MathStructure &m = ((KnownVariable*) mstruct.variable())->get(); - if(contains_interval_variable(m)) return (KnownVariable*) mstruct.variable(); - } - for(size_t i = 0; i < mstruct.size(); i++) { - KnownVariable *v = fix_find_interval_variable(mstruct[i]); - if(v) return v; - } - return NULL; -} -KnownVariable *fix_find_interval_variable2(MathStructure &mstruct) { - if(mstruct.isVariable() && mstruct.variable()->isKnown()) { - const MathStructure &m = ((KnownVariable*) mstruct.variable())->get(); - if(m.isNumber()) return NULL; - if(m.isMultiplication()) { - bool b_intfound = false;; - for(size_t i = 0; i < m.size(); i++) { - if(m[i].containsInterval(true, false, false, 1)) { - if(b_intfound || !m[i].isNumber()) return (KnownVariable*) mstruct.variable(); - b_intfound = true; - } - } - } else if(m.containsInterval(true, false, false, 1)) { - return (KnownVariable*) mstruct.variable(); - } - } - for(size_t i = 0; i < mstruct.size(); i++) { - KnownVariable *v = fix_find_interval_variable2(mstruct[i]); - if(v) return v; - } - return NULL; -} -bool replace_intervals(MathStructure &m) { - if(m.isNumber()) { - int var_prec = 0; - if(m.number().isInterval()) var_prec = m.number().precision(1); - else if(CALCULATOR->usesIntervalArithmetic() && m.number().precision() >= 0) var_prec = m.number().precision(); - if(var_prec <= PRECISION + 10) { - Variable *v = new KnownVariable("", format_and_print(m), m); - m.set(v, true); - v->destroy(); - } - } - bool b = false; - for(size_t i = 0; i < m.size(); i++) { - if(replace_intervals(m[i])) { - m.childUpdated(i + 1); - b = true; - } - } - return b; -} -void fix_interval_variable(KnownVariable *v, MathStructure &mvar) { - mvar = v->get(); - replace_intervals(mvar); -} - -void solve_intervals(MathStructure &mstruct, const EvaluationOptions &eo, const EvaluationOptions &feo) { - bool b = false; - while(true) { - KnownVariable *v = fix_find_interval_variable(mstruct); - if(!v) break; - b = true; - MathStructure mvar; - fix_interval_variable(v, mvar); - mstruct.replace(v, mvar); - } - while(true) { - KnownVariable *v = fix_find_interval_variable2(mstruct); - if(!v) break; - b = true; - MathStructure mvar; - fix_interval_variable(v, mvar); - mstruct.replace(v, mvar); - } - if(b) { - mstruct.unformat(eo); - EvaluationOptions eo2 = eo; - eo2.expand = false; - mstruct.calculatesub(eo2, feo, true); - } - vector vars; vector v_count; vector v_prec; - find_interval_variables(mstruct, vars, v_count, v_prec); - for(size_t i = 0; i < v_count.size();) { - if(v_count[i] < 2 || (feo.approximation == APPROXIMATION_EXACT && vars[i]->title() != "\b")) { - v_count.erase(v_count.begin() + i); - v_prec.erase(v_prec.begin() + i); - vars.erase(vars.begin() + i); - } else { - i++; - } - } - if(mstruct.isComparison()) { - if(feo.test_comparisons || feo.isolate_x) { - mstruct[0].subtract(mstruct[1]); - solve_intervals2(mstruct[0], vars, eo); - mstruct[1].clear(true); - } else { - solve_intervals2(mstruct[0], vars, eo); - solve_intervals2(mstruct[1], vars, eo); - } - return; - } - solve_intervals2(mstruct, vars, eo); -} - -bool simplify_ln(MathStructure &mstruct) { - bool b_ret = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(simplify_ln(mstruct[i])) b_ret = true; - } - if(mstruct.isAddition()) { - size_t i_ln = (size_t) -1, i_ln_m = (size_t) -1; - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isFunction() && mstruct[i].function() == CALCULATOR->f_ln && mstruct[i].size() == 1 && mstruct[i][0].isNumber() && mstruct[i][0].number().isReal()) { - if(i_ln == (size_t) -1) { - i_ln = i; - } else { - bool b = true; - if(mstruct[i_ln].isMultiplication()) { - if(mstruct[i_ln][1][0].number().raise(mstruct[i_ln][0].number(), true)) {mstruct[i_ln].setToChild(2, true); b_ret = true;} - else b = false; - } - if(b && mstruct[i_ln][0].number().multiply(mstruct[i][0].number())) { - mstruct.delChild(i + 1); - i--; - b_ret = true; - } - } - } else if(mstruct[i].isMultiplication() && mstruct[i].size() == 2 && mstruct[i][1].isFunction() && mstruct[i][1].function() == CALCULATOR->f_ln && mstruct[i][1].size() == 1 && mstruct[i][1][0].isNumber() && mstruct[i][1][0].number().isReal() && mstruct[i][0].isInteger() && mstruct[i][0].number().isLessThan(1000) && mstruct[i][0].number().isGreaterThan(-1000)) { - if(mstruct[i][0].number().isPositive()) { - if(i_ln == (size_t) -1) { - i_ln = i; - } else { - bool b = true; - if(mstruct[i_ln].isMultiplication()) { - if(mstruct[i_ln][1][0].number().raise(mstruct[i_ln][0].number())) {mstruct[i_ln].setToChild(2, true); b_ret = true;} - else b = false; - } - if(b && mstruct[i][1][0].number().raise(mstruct[i][0].number(), true)) { - if(mstruct[i_ln][0].number().multiply(mstruct[i][1][0].number())) { - mstruct.delChild(i + 1); - i--; - } else { - mstruct[i].setToChild(1, true); - } - b_ret = true; - } - } - } else if(mstruct[i][0].number().isNegative()) { - if(i_ln_m == (size_t) -1) { - i_ln_m = i; - } else { - bool b = mstruct[i_ln_m][0].number().isMinusOne(); - if(!b && mstruct[i_ln_m][1][0].number().raise(-mstruct[i_ln_m][0].number())) {mstruct[i_ln_m][0].set(m_minus_one, true); b_ret = true; b = true;} - bool b_m1 = b && mstruct[i][0].number().isMinusOne(); - if(b && (b_m1 || mstruct[i][1][0].number().raise(-mstruct[i][0].number(), true))) { - if(mstruct[i_ln_m][1][0].number().multiply(mstruct[i][1][0].number())) { - mstruct.delChild(i + 1); - b_ret = true; - i--; - } else if(!b_m1) b_ret = true; - } - } - } - } - } - if(mstruct.size() == 1) mstruct.setToChild(1, true); - } - return b_ret; -} - -void find_interval_create_var(const Number &nr, MathStructure &m, MathStructure &unc, MathStructure &unc2, KnownVariable **v, KnownVariable **v2) { - if(nr.hasImaginaryPart() && nr.internalImaginary()->isInterval()) { - if(nr.hasRealPart() && nr.isInterval(false)) { - unc = nr.internalImaginary()->uncertainty(); - unc2 = nr.realPart().uncertainty(); - Number nmid(*nr.internalImaginary()); - nmid.intervalToMidValue(); - Number nmid2(nr.realPart()); - nmid2.intervalToMidValue(); - *v = new KnownVariable("", string("(") + format_and_print(nmid) + ")", nmid); - (*v)->setApproximate(false); - *v2 = new KnownVariable("", string("(") + format_and_print(nmid2) + ")", nmid2); - (*v2)->setApproximate(false); - m.set(*v); - m.multiply(nr_one_i); - m.add(*v2); - (*v)->destroy(); - (*v2)->destroy(); - } else { - unc = nr.internalImaginary()->uncertainty(); - Number nmid(*nr.internalImaginary()); - nmid.intervalToMidValue(); - *v = new KnownVariable("", string("(") + format_and_print(nmid) + ")", nmid); - (*v)->setApproximate(false); - m.set(*v); - m.multiply(nr_one_i); - (*v)->destroy(); - } - } else { - unc = nr.uncertainty(); - Number nmid(nr); - nmid.intervalToMidValue(); - *v = new KnownVariable("", string("(") + format_and_print(nmid) + ")", nmid); - (*v)->setApproximate(false); - m.set(*v); - (*v)->destroy(); - } -} - -KnownVariable *find_interval_replace_var(MathStructure &m, MathStructure &unc, MathStructure &unc2, KnownVariable **v2, const EvaluationOptions &eo, MathStructure *mnew, Variable **prev_v, bool &b_failed) { - if(eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables && m.isVariable() && m.variable()->isKnown() && (eo.approximation != APPROXIMATION_EXACT || m.variable()->title() == "\b")) { - const MathStructure &mvar = ((KnownVariable*) m.variable())->get(); - if(!mvar.containsInterval(true, true, false, 1, true)) return NULL; - if(mvar.isNumber()) { - m.variable()->ref(); - *prev_v = m.variable(); - KnownVariable *v = NULL; - find_interval_create_var(mvar.number(), m, unc, unc2, &v, v2); - *mnew = m; - return v; - } else if(mvar.isMultiplication() && mvar[0].isNumber()) { - if(mvar[0].number().isInterval(false)) { - bool b = true; - for(size_t i = 1; i < mvar.size(); i++) { - if(mvar[i].containsInterval(true, true, false, 1, true)) { - b = false; - break; - } - } - if(b) { - m.variable()->ref(); - *prev_v = m.variable(); - KnownVariable *v = NULL; - find_interval_create_var(mvar[0].number(), m, unc, unc2, &v, v2); - for(size_t i = 1; i < mvar.size(); i++) { - m.multiply(mvar[i], true); - } - *mnew = m; - return v; - } - } - } else if(mvar.isFunction() && mvar.function() == CALCULATOR->f_interval && mvar.size() == 2 && !mvar[0].containsInterval(true, true, false, 1, true) && !mvar[1].containsInterval(true, true, false, 1, true)) { - if(mvar[0].isAddition() && mvar[0].size() == 2 && mvar[1].isAddition() && mvar[1].size() == 2) { - const MathStructure *mmid = NULL, *munc = NULL; - if(mvar[0][0].equals(mvar[1][0])) { - mmid = &mvar[0][0]; - if(mvar[0][1].isNegate() && mvar[0][1][0].equals(mvar[1][1])) munc = &mvar[1][1]; - if(mvar[1][1].isNegate() && mvar[1][1][0].equals(mvar[0][1])) munc = &mvar[0][1]; - } else if(mvar[0][1].equals(mvar[1][1])) { - mmid = &mvar[0][1]; - if(mvar[0][0].isNegate() && mvar[0][0][0].equals(mvar[1][0])) munc = &mvar[1][0]; - if(mvar[1][0].isNegate() && mvar[1][0][0].equals(mvar[0][0])) munc = &mvar[0][0]; - } else if(mvar[0][0].equals(mvar[1][1])) { - mmid = &mvar[0][0]; - if(mvar[0][1].isNegate() && mvar[0][1][0].equals(mvar[1][0])) munc = &mvar[1][0]; - if(mvar[1][0].isNegate() && mvar[1][0][0].equals(mvar[0][1])) munc = &mvar[0][1]; - } else if(mvar[0][1].equals(mvar[1][0])) { - mmid = &mvar[0][0]; - if(mvar[0][0].isNegate() && mvar[0][0][0].equals(mvar[1][1])) munc = &mvar[1][1]; - if(mvar[1][1].isNegate() && mvar[1][1][0].equals(mvar[0][0])) munc = &mvar[0][0]; - } - if(mmid && munc) { - unc = *munc; - MathStructure mmid2(*mmid); - KnownVariable *v = new KnownVariable("", string("(") + format_and_print(*mmid) + ")", mmid2); - m.set(v); - v->destroy(); - return v; - } - } - unc = mvar[1]; - unc -= mvar[0]; - unc *= nr_half; - MathStructure mmid(mvar[0]); - mmid += mvar[1]; - mmid *= nr_half; - KnownVariable *v = new KnownVariable("", string("(") + format_and_print(mmid) + ")", mmid); - m.variable()->ref(); - *prev_v = m.variable(); - m.set(v); - *mnew = m; - v->destroy(); - return v; - } else if(mvar.isFunction() && mvar.function() == CALCULATOR->f_uncertainty && mvar.size() == 3 && mvar[2].isNumber() && !mvar[0].containsInterval(true, true, false, 1, true) && !mvar[1].containsInterval(true, true, false, 1, true)) { - if(mvar[2].number().getBoolean()) { - unc = mvar[1]; - unc *= mvar[0]; - } else { - unc = mvar[1]; - } - KnownVariable *v = new KnownVariable("", string("(") + format_and_print(mvar[0]) + ")", mvar[0]); - m.variable()->ref(); - *prev_v = m.variable(); - m.set(v); - *mnew = m; - v->destroy(); - return v; - } - b_failed = true; - } else if(m.isNumber() && m.number().isInterval(false) && m.number().precision(true) <= PRECISION + 10) { - KnownVariable *v = NULL; - find_interval_create_var(m.number(), m, unc, unc2, &v, v2); - return v; - } else if(m.isFunction() && m.function() == CALCULATOR->f_interval && m.size() == 2 && !m[0].containsInterval(true, true, false, 1, true) && !m[1].containsInterval(true, true, false, 1, true)) { - if(m[0].isAddition() && m[0].size() == 2 && m[1].isAddition() && m[1].size() == 2) { - MathStructure *mmid = NULL, *munc = NULL; - if(m[0][0].equals(m[1][0])) { - mmid = &m[0][0]; - if(m[0][1].isNegate() && m[0][1][0].equals(m[1][1])) munc = &m[1][1]; - if(m[1][1].isNegate() && m[1][1][0].equals(m[0][1])) munc = &m[0][1]; - } else if(m[0][1].equals(m[1][1])) { - mmid = &m[0][1]; - if(m[0][0].isNegate() && m[0][0][0].equals(m[1][0])) munc = &m[1][0]; - if(m[1][0].isNegate() && m[1][0][0].equals(m[0][0])) munc = &m[0][0]; - } else if(m[0][0].equals(m[1][1])) { - mmid = &m[0][0]; - if(m[0][1].isNegate() && m[0][1][0].equals(m[1][0])) munc = &m[1][0]; - if(m[1][0].isNegate() && m[1][0][0].equals(m[0][1])) munc = &m[0][1]; - } else if(m[0][1].equals(m[1][0])) { - mmid = &m[0][0]; - if(m[0][0].isNegate() && m[0][0][0].equals(m[1][1])) munc = &m[1][1]; - if(m[1][1].isNegate() && m[1][1][0].equals(m[0][0])) munc = &m[0][0]; - } - if(mmid && munc) { - unc = *munc; - KnownVariable *v = new KnownVariable("", string("(") + format_and_print(*mmid) + ")", *mmid); - m.set(v); - v->destroy(); - return v; - } - } - unc = m[1]; - unc -= m[0]; - unc *= nr_half; - MathStructure mmid(m[0]); - mmid += m[1]; - mmid *= nr_half; - KnownVariable *v = new KnownVariable("", string("(") + format_and_print(mmid) + ")", mmid); - m.set(v); - v->destroy(); - return v; - } else if(m.isFunction() && m.function() == CALCULATOR->f_uncertainty && m.size() == 3 && m[2].isNumber() && !m[0].containsInterval(true, true, false, 1, true) && !m[1].containsInterval(true, true, false, 1, true)) { - if(m[2].number().getBoolean()) { - unc = m[1]; - unc *= m[0]; - } else { - unc = m[1]; - } - KnownVariable *v = new KnownVariable("", string("(") + format_and_print(m[0]) + ")", m[0]); - m.set(v); - v->destroy(); - return v; - } - for(size_t i = 0; i < m.size(); i++) { - KnownVariable *v = find_interval_replace_var(m[i], unc, unc2, v2, eo, mnew, prev_v, b_failed); - if(b_failed) return NULL; - if(v) return v; - } - return NULL; -} - -bool find_interval_replace_var_nr(MathStructure &m) { - if((m.isNumber() && m.number().isInterval(false) && m.number().precision(true) <= PRECISION + 10) || (m.isFunction() && m.function() == CALCULATOR->f_interval && m.size() == 2) || (m.isFunction() && m.function() == CALCULATOR->f_uncertainty && m.size() == 3)) { - KnownVariable *v = new KnownVariable("", string("(") + format_and_print(m) + ")", m); - m.set(v); - v->destroy(); - return true; - } - bool b = false; - for(size_t i = 0; i < m.size(); i++) { - if(find_interval_replace_var_nr(m[i])) b = true; - } - return b; -} - - -bool replace_variables_with_interval(MathStructure &m, const EvaluationOptions &eo, bool in_nounit = false, bool only_argument_vars = false) { - if(m.isVariable() && m.variable()->isKnown() && (!only_argument_vars || m.variable()->title() == "\b")) { - const MathStructure &mvar = ((KnownVariable*) m.variable())->get(); - if(!mvar.containsInterval(true, true, false, 1, true)) return false; - if(mvar.isNumber()) { - return false; - } else if(mvar.isMultiplication() && mvar[0].isNumber()) { - if(mvar[0].number().isInterval(false)) { - bool b = true; - for(size_t i = 1; i < mvar.size(); i++) { - if(mvar[i].containsInterval(true, true, false, 1, true)) { - b = false; - break; - } - } - if(b) return false; - } - } - m.set(mvar, true); - if(in_nounit) m.removeType(STRUCT_UNIT); - else m.unformat(eo); - return true; - } - bool b = false; - if(m.isFunction() && m.function() == CALCULATOR->f_stripunits && m.size() == 1) { - b = replace_variables_with_interval(m[0], eo, true, only_argument_vars); - if(b && m[0].containsType(STRUCT_UNIT, false, true, true) == 0) { - m.setToChild(1, true); - } - return b; - } - for(size_t i = 0; i < m.size(); i++) { - if(replace_variables_with_interval(m[i], eo, in_nounit, only_argument_vars)) b = true; - } - return b; -} - -bool contains_diff_for(const MathStructure &m, const MathStructure &x_var) { - if(m.isFunction() && m.function() && m.function() == CALCULATOR->f_diff && m.size() >= 2 && m[1] == x_var) return true; - for(size_t i = 0; i < m.size(); i++) { - if(contains_diff_for(m[i], x_var)) return true; - } - return false; -} - -bool sync_approximate_units(MathStructure &m, const EvaluationOptions &feo, vector *vars = NULL, vector *uncs = NULL, bool do_intervals = true); - -MathStructure calculate_uncertainty(MathStructure &m, const EvaluationOptions &eo, bool &b_failed) { - vector vars; - vector uncs; - MathStructure unc, unc2; - if(eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) replace_variables_with_interval(m, eo, false, eo.approximation == APPROXIMATION_EXACT); - while(true) { - Variable *prev_v = NULL; - MathStructure mnew; - KnownVariable *v2 = NULL; - KnownVariable *v = find_interval_replace_var(m, unc, unc2, &v2, eo, &mnew, &prev_v, b_failed); - if(!v) break; - if(!mnew.isZero()) { - m.replace(prev_v, mnew); - prev_v->unref(); - } - vars.push_back(v); - uncs.push_back(unc); - if(v2) { - vars.push_back(v2); - uncs.push_back(unc2); - } - } - m.unformat(eo); - if(eo.sync_units && eo.approximation != APPROXIMATION_EXACT) sync_approximate_units(m, eo, &vars, &uncs, true); - if(b_failed || vars.empty()) return m_zero; - MathStructure munc; - UnknownVariable *uv = new UnknownVariable("", "x"); - MathStructure muv(uv); - MathStructure *munc_i = NULL; - for(size_t i = 0; i < vars.size(); i++) { - if(!vars[i]->get().representsNonComplex(true)) { - b_failed = true; return m_zero; - } - MathStructure *mdiff = new MathStructure(m); - uv->setInterval(vars[i]->get()); - mdiff->replace(vars[i], muv); - if(!mdiff->differentiate(muv, eo) || contains_diff_for(*mdiff, muv) || CALCULATOR->aborted()) { - b_failed = true; - return m_zero; - } - mdiff->replace(muv, vars[i]); - if(!mdiff->representsNonComplex(true)) { - MathStructure *mdiff_i = new MathStructure(*mdiff); - mdiff->transform(CALCULATOR->f_re); - mdiff_i->transform(CALCULATOR->f_im); - mdiff_i->raise(nr_two); - mdiff_i->multiply(uncs[i]); - mdiff_i->last().raise(nr_two); - if(!munc_i) {munc_i = mdiff_i;} - else munc_i->add_nocopy(mdiff_i, true); - } - mdiff->raise(nr_two); - mdiff->multiply(uncs[i]); - mdiff->last().raise(nr_two); - if(munc.isZero()) {munc.set_nocopy(*mdiff); mdiff->unref();} - else munc.add_nocopy(mdiff, true); - } - uv->destroy(); - munc.raise(nr_half); - if(munc_i) { - munc_i->raise(nr_half); - munc_i->multiply(nr_one_i); - munc.add_nocopy(munc_i); - } - return munc; -} - -Variable *find_interval_replace_var_comp(MathStructure &m, const EvaluationOptions &eo, Variable **v) { - if(eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables && m.isVariable() && m.variable()->isKnown() && ((KnownVariable*) m.variable())->get().containsInterval(true, true, false, 1, true)) { - UnknownVariable *uv = new UnknownVariable("", format_and_print(m)); - uv->setInterval(m); - *v = m.variable(); - m.set(uv, true); - return uv; - } else if((m.isNumber() && m.number().isInterval(false) && m.number().precision(true) <= PRECISION + 10) || (m.isFunction() && m.function() == CALCULATOR->f_interval && m.size() == 2) || (m.isFunction() && m.function() == CALCULATOR->f_uncertainty && m.size() == 3)) { - Variable *uv = NULL; - if(eo.approximation == APPROXIMATION_EXACT || eo.approximation == APPROXIMATION_EXACT_VARIABLES) { - uv = new KnownVariable("", string("(") + format_and_print(m) + ")", m); - } else { - uv = new UnknownVariable("", string("(") + format_and_print(m) + ")"); - ((UnknownVariable*) uv)->setInterval(m); - } - *v = NULL; - m.set(uv, true); - return uv; - } - for(size_t i = 0; i < m.size(); i++) { - Variable *uv = find_interval_replace_var_comp(m[i], eo, v); - if(uv) return uv; - } - return NULL; -} - -bool eval_comparison_sides(MathStructure &m, const EvaluationOptions &eo) { - if(m.isComparison()) { - MathStructure mbak(m); - if(!m[0].isUnknown()) { - bool ret = true; - CALCULATOR->beginTemporaryStopMessages(); - m[0].eval(eo); - if(m[0].containsFunction(CALCULATOR->f_uncertainty) && !mbak[0].containsFunction(CALCULATOR->f_uncertainty)) { - CALCULATOR->endTemporaryStopMessages(); - m[0] = mbak[0]; - ret = false; - } else { - CALCULATOR->endTemporaryStopMessages(true); - } - CALCULATOR->beginTemporaryStopMessages(); - m[1].eval(eo); - if(m[1].containsFunction(CALCULATOR->f_uncertainty) && !mbak[1].containsFunction(CALCULATOR->f_uncertainty)) { - CALCULATOR->endTemporaryStopMessages(); - m[1] = mbak[1]; - ret = false; - } else { - CALCULATOR->endTemporaryStopMessages(true); - } - if(ret && !m.containsUnknowns()) { - m.calculatesub(eo, eo, false); - return true; - } - return false; - } else { - m[1].eval(eo); - m.calculatesub(eo, eo, false); - return true; - } - } else if(m.containsType(STRUCT_COMPARISON)) { - bool ret = true; - for(size_t i = 0; i < m.size(); i++) { - if(!eval_comparison_sides(m[i], eo)) ret = false; - } - m.childrenUpdated(); - m.calculatesub(eo, eo, false); - return ret; - } else { - m.eval(eo); - } - return true; -} - -bool separate_unit_vars(MathStructure &m, const EvaluationOptions &eo, bool only_approximate, bool dry_run) { - if(m.isVariable() && m.variable()->isKnown()) { - const MathStructure &mvar = ((KnownVariable*) m.variable())->get(); - if(mvar.isMultiplication()) { - bool b = false; - for(size_t i = 0; i < mvar.size(); i++) { - if(is_unit_multiexp(mvar[i])) { - if(!b) b = !only_approximate || contains_approximate_relation_to_base(mvar[i], true); - } else if(mvar[i].containsType(STRUCT_UNIT, false, true, true) != 0) { - b = false; - break; - } - } - if(!b) return false; - if(dry_run) return true; - m.transform(CALCULATOR->f_stripunits); - for(size_t i = 0; i < mvar.size(); i++) { - if(is_unit_multiexp(mvar[i])) { - m.multiply(mvar[i], i); - } - } - m.unformat(eo); - return true; - } - } - if(m.isFunction() && m.function() == CALCULATOR->f_stripunits) return false; - bool b = false; - for(size_t i = 0; i < m.size(); i++) { - if(separate_unit_vars(m[i], eo, only_approximate, dry_run)) { - b = true; - if(dry_run) return true; - } - } - return b; -} - -bool convert_to_default_angle_unit(MathStructure &m, const EvaluationOptions &eo) { - bool b = false; - for(size_t i = 0; i < m.size(); i++) { - if(convert_to_default_angle_unit(m[i], eo)) b = true; - if(m.isFunction() && m.function()->getArgumentDefinition(i + 1) && m.function()->getArgumentDefinition(i + 1)->type() == ARGUMENT_TYPE_ANGLE) { - Unit *u = NULL; - if(eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES) u = CALCULATOR->getDegUnit(); - else if(eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS) u = CALCULATOR->getGraUnit(); - if(u && m[i].contains(CALCULATOR->getRadUnit(), false, false, false)) { - m[i].divide(u); - m[i].multiply(u); - EvaluationOptions eo2 = eo; - if(eo.approximation == APPROXIMATION_TRY_EXACT) eo2.approximation = APPROXIMATION_APPROXIMATE; - eo2.calculate_functions = false; - eo2.sync_units = true; - m[i].calculatesub(eo2, eo2, true); - b = true; - } - } - } - return b; -} - -bool remove_add_zero_unit(MathStructure &m) { - if(m.isAddition() && m.size() > 1) { - bool b = false, b2 = false; - for(size_t i = 0; i < m.size(); i++) { - if(m[i].isMultiplication() && m[i].size() > 1 && m[i][0].isZero() && !m[i].isApproximate()) { - b = true; - } else { - b2 = true; - } - if(b && b2) break; - } - if(!b || !b2) return false; - b = false; - for(size_t i = 0; i < m.size();) { - b2 = false; - if(m[i].isMultiplication() && m[i].size() > 1 && m[i][0].isZero() && !m[i].isApproximate()) { - b2 = true; - for(size_t i2 = 1; i2 < m[i].size(); i2++) { - if(!m[i][i2].isUnit_exp() || (m[i][i2].isPower() && m[i][i2][0].unit()->hasNonlinearRelationToBase()) || (m[i][i2].isUnit() && m[i][i2].unit()->hasNonlinearRelationToBase())) { - b2 = false; - break; - } - } - if(b2) { - b = true; - m.delChild(i + 1); - if(m.size() == 1) { - m.setToChild(1, true); - break; - } - } - } - if(!b2) i++; - } - return b; - } - return false; -} - -bool contains_duplicate_interval_variables_eq(const MathStructure &mstruct, const MathStructure &xvar, vector &vars) { - if(mstruct.isVariable() && mstruct.variable()->isKnown() && ((KnownVariable*) mstruct.variable())->get().containsInterval(false, true, false, false)) { - KnownVariable *v = (KnownVariable*) mstruct.variable(); - for(size_t i = 0; i < vars.size(); i++) { - if(vars[i] == v) { - return true; - } - } - vars.push_back(v); - } - for(size_t i = 0; i < mstruct.size(); i++) { - if(contains_duplicate_interval_variables_eq(mstruct[i], xvar, vars)) return true; - } - return false; -} - -bool fix_eqs(MathStructure &m, const EvaluationOptions &eo) { - for(size_t i = 0; i < m.size(); i++) { - if(fix_eqs(m[i], eo)) m.childUpdated(i + 1); - } - if(m.isComparison()) { - if(CALCULATOR->aborted()) return false; - const MathStructure *x_var; - if(eo.isolate_var && m.contains(*eo.isolate_var)) x_var = eo.isolate_var; - else x_var = &m.find_x_var(); - if(!x_var->isUndefined()) { - vector vars; - if(contains_duplicate_interval_variables_eq(m, *x_var, vars)) { - if(!m[0].contains(*x_var)) { - m.swapChildren(1, 2); - } else if(m[0].isAddition()) { - for(size_t i = 0; i < m[0].size();) { - if(!m[0][i].contains(*x_var)) { - m[0][i].calculateNegate(eo); - m[0][i].ref(); - m[1].add_nocopy(&m[0][i], true); - m[1].calculateAddLast(eo); - m[0].delChild(i + 1); - } else { - i++; - } - } - if(m[0].size() == 1) m[0].setToChild(1, true); - else if(m[0].size() == 0) m[0].clear(true); - m.childrenUpdated(); - } - if(m[1].isAddition()) { - for(size_t i = 0; i < m[1].size();) { - if(m[1][i].contains(*x_var)) { - m[1][i].calculateNegate(eo); - m[1][i].ref(); - m[0].add_nocopy(&m[1][i], true); - m[0].calculateAddLast(eo); - m[1].delChild(i + 1); - } else { - i++; - } - } - if(m[1].size() == 1) m[1].setToChild(1, true); - else if(m[1].size() == 0) m[1].clear(true); - m.childrenUpdated(); - } else if(m[1].contains(*x_var)) { - m[0].calculateSubtract(m[1], eo); - m[1].clear(true); - } - vars.clear(); - if(m[0].containsType(STRUCT_ADDITION) && contains_duplicate_interval_variables_eq(m[0], *x_var, vars)) m[0].factorize(eo, false, false, 0, false, 1, NULL, m_undefined, false, false, 3); - return true; - } - } - } - return false; -} - -Unit *find_log_unit(const MathStructure &m, bool toplevel = true) { - if(!toplevel && m.isUnit() && m.unit()->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) m.unit())->hasNonlinearExpression() && (((AliasUnit*) m.unit())->expression().find("log") != string::npos || ((AliasUnit*) m.unit())->inverseExpression().find("log") != string::npos || ((AliasUnit*) m.unit())->expression().find("ln") != string::npos || ((AliasUnit*) m.unit())->inverseExpression().find("ln") != string::npos)) { - return ((AliasUnit*) m.unit())->firstBaseUnit(); - } - if(m.isMultiplication() && toplevel && m.last().isUnit()) { - Unit *u = find_log_unit(m.last(), false); - if(u) { - for(size_t i = 0; i < m.size(); i++) { - if(m[i].containsType(STRUCT_UNIT, true)) return u; - } - return NULL; - } - } - for(size_t i = 0; i < m.size(); i++) { - Unit *u = find_log_unit(m[i], false); - if(u) return u; - } - return NULL; -} -void convert_log_units(MathStructure &m, const EvaluationOptions &eo) { - while(true) { - Unit *u = find_log_unit(m); - if(!u) break; - CALCULATOR->error(false, "Log-based units were converted before calculation.", NULL); - m.convert(u, true, NULL, false, eo); - } -} -bool warn_ratio_units(MathStructure &m, bool top_level = true) { - if(!top_level && m.isUnit() && ((m.unit()->subtype() == SUBTYPE_BASE_UNIT && m.unit()->referenceName() == "Np") || (m.unit()->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) m.unit())->baseUnit()->referenceName() == "Np"))) { - CALCULATOR->error(true, "Logarithmic ratio units is treated as other units and the result might not be as expected.", NULL); - return true; - } - if(m.isMultiplication() && top_level && m.last().isUnit()) { - if(m.size() < 2) return false; - for(size_t i = 0; i < m.size() - 1; i++) { - if(warn_ratio_units(m[i], false)) return true; - } - } else { - for(size_t i = 0; i < m.size(); i++) { - if(warn_ratio_units(m[i], false)) return true; - } - } - return false; -} -int contains_interval_var(const MathStructure &m, bool structural_only, bool check_variables, bool check_functions, int ignore_high_precision_interval, bool include_interval_function); -int contains_function_interval(const MathStructure &m, bool structural_only = true, bool check_variables = false, bool check_functions = false, int ignore_high_precision_interval = 0, bool include_interval_function = false) { - for(size_t i = 0; i < m.size(); i++) { - if(contains_function_interval(m[i], structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function)) return true; - } - if(m.isVariable() && m.variable()->isKnown() && m.variable()->title() == "\b") { - if(ignore_high_precision_interval == 0) return true; - return contains_interval_var(((KnownVariable*) m.variable())->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); - } - return false; -} -bool replace_function_vars(MathStructure &m) { - for(size_t i = 0; i < m.size(); i++) { - if(replace_function_vars(m[i])) return true; - } - if(m.isVariable() && m.variable()->isKnown() && m.variable()->title() == "\b") { - m.set(((KnownVariable*) m.variable())->get(), true); - } - return false; -} -MathStructure &MathStructure::eval(const EvaluationOptions &eo) { - - if(m_type == STRUCT_NUMBER) { - if(eo.complex_number_form == COMPLEX_NUMBER_FORM_EXPONENTIAL) complexToExponentialForm(eo); - else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_POLAR) complexToPolarForm(eo); - else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_CIS) complexToCisForm(eo); - return *this; - } - - if(eo.structuring != STRUCTURING_NONE) warn_ratio_units(*this); - - unformat(eo); - - if(m_type == STRUCT_UNDEFINED || m_type == STRUCT_ABORTED || m_type == STRUCT_DATETIME || m_type == STRUCT_UNIT || m_type == STRUCT_SYMBOLIC || (m_type == STRUCT_VARIABLE && !o_variable->isKnown())) return *this; - - if(eo.structuring != STRUCTURING_NONE && eo.sync_units) convert_log_units(*this, eo); - - EvaluationOptions feo = eo; - feo.structuring = STRUCTURING_NONE; - feo.do_polynomial_division = false; - feo.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; - EvaluationOptions eo2 = eo; - eo2.structuring = STRUCTURING_NONE; - eo2.expand = false; - eo2.test_comparisons = false; - eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; - eo2.isolate_x = false; - - if(m_type == STRUCT_NUMBER) { - if(eo.complex_number_form == COMPLEX_NUMBER_FORM_EXPONENTIAL) complexToExponentialForm(eo); - else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_POLAR) complexToPolarForm(eo); - else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_CIS) complexToCisForm(eo); - return *this; - } - - if(eo.interval_calculation == INTERVAL_CALCULATION_INTERVAL_ARITHMETIC) { - if(eo.calculate_functions) calculate_nondifferentiable_functions(*this, feo, true, true, 0); - if(((eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) && containsInterval(true, true, false, 1, true)) || (eo.sync_units && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.approximation != APPROXIMATION_EXACT && sync_approximate_units(*this, eo)) || (eo.approximation == APPROXIMATION_EXACT && contains_function_interval(*this, true, true, false, 1, true))) { - EvaluationOptions eo3 = eo2; - eo3.split_squares = false; - eo3.assume_denominators_nonzero = false; - if(eo.approximation == APPROXIMATION_APPROXIMATE && !containsUnknowns()) eo3.approximation = APPROXIMATION_EXACT_VARIABLES; - else eo3.approximation = APPROXIMATION_EXACT; - vector vars; - vector uncs; - calculatesub(eo3, eo3); - while(eo.sync_units && (separate_unit_vars(*this, feo, true) || sync_approximate_units(*this, feo, &vars, &uncs, false))) { - calculatesub(eo3, eo3); - } - eo3.approximation = APPROXIMATION_APPROXIMATE; - if(eo.sync_units) { - sync_approximate_units(*this, feo, &vars, &uncs, true); - } - factorize_variables(*this, eo3); - if(eo.approximation == APPROXIMATION_APPROXIMATE && !containsUnknowns()) eo3.approximation = APPROXIMATION_EXACT_VARIABLES; - else eo3.approximation = APPROXIMATION_EXACT; - eo3.expand = eo.expand; - eo3.assume_denominators_nonzero = eo.assume_denominators_nonzero; - solve_intervals(*this, eo3, feo); - } - if(eo.calculate_functions) calculate_differentiable_functions(*this, feo); - } else if(eo.interval_calculation == INTERVAL_CALCULATION_VARIANCE_FORMULA) { - if(eo.calculate_functions) calculate_nondifferentiable_functions(*this, feo, true, true, -1); - if(!isNumber() && (((eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) && containsInterval(true, true, false, 1, true)) || containsInterval(true, false, false, 1, true) || (eo.sync_units && eo.approximation != APPROXIMATION_EXACT && sync_approximate_units(*this, eo)) || (eo.approximation == APPROXIMATION_EXACT && contains_function_interval(*this, true, true, false, 1, true)))) { - if(eo.calculate_functions) calculate_nondifferentiable_functions(*this, feo, true, true, (eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) ? 2 : 1); - MathStructure munc, mbak(*this); - if(eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) { - find_interval_replace_var_nr(*this); - EvaluationOptions eo3 = eo2; - eo3.split_squares = false; - if(eo.expand && eo.expand >= -1) eo3.expand = -1; - eo3.assume_denominators_nonzero = eo.assume_denominators_nonzero; - eo3.approximation = APPROXIMATION_EXACT; - vector vars; - vector uncs; - calculatesub(eo3, eo3); - while(eo.sync_units && (separate_unit_vars(*this, feo, true) || sync_approximate_units(*this, feo, &vars, &uncs, false))) { - calculatesub(eo3, eo3); - } - } - bool b_failed = false; - if(containsType(STRUCT_COMPARISON)) { - EvaluationOptions eo3 = eo; - eo3.approximation = APPROXIMATION_EXACT; - eo3.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; - eo3.structuring = STRUCTURING_NONE; - eo3.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; - vector vars; - while(true) { - Variable *v = NULL; - Variable *uv = find_interval_replace_var_comp(*this, eo3, &v); - if(!uv) break; - if(v) replace(v, uv); - vars.push_back(uv); - } - eval(eo3); - for(size_t i = 0; i < vars.size(); i++) { - if(vars[i]->isKnown()) replace(vars[i], ((KnownVariable*) vars[i])->get()); - else replace(vars[i], ((UnknownVariable*) vars[i])->interval()); - vars[i]->destroy(); - } - if(CALCULATOR->aborted()) return *this; - if(eval_comparison_sides(*this, feo)) { - if(eo.structuring != STRUCTURING_NONE) simplify_ln(*this); - structure(eo.structuring, eo2, false); - if(eo.structuring != STRUCTURING_NONE) simplify_ln(*this); - clean_multiplications(*this); - } else if(!CALCULATOR->aborted()) { - CALCULATOR->error(false, _("Calculation of uncertainty propagation partially failed (using interval arithmetic instead when necessary)."), NULL); - EvaluationOptions eo4 = eo; - eo4.interval_calculation = INTERVAL_CALCULATION_INTERVAL_ARITHMETIC; - eval(eo4); - } - return *this; - } else { - CALCULATOR->beginTemporaryStopMessages(); - munc = calculate_uncertainty(*this, eo, b_failed); - if(!b_failed && !munc.isZero()) { - EvaluationOptions eo3 = eo; - eo3.keep_zero_units = false; - eo3.structuring = STRUCTURING_NONE; - eo3.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; - eo3.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; - if(eo3.approximation == APPROXIMATION_TRY_EXACT) eo3.approximation = APPROXIMATION_APPROXIMATE; - - munc.eval(eo3); - eo3.keep_zero_units = eo.keep_zero_units; - eval(eo3); - - if(eo.keep_zero_units) remove_add_zero_unit(*this); - b_failed = true; - if(munc.isFunction() && munc.function() == CALCULATOR->f_abs && munc.size() == 1) { - munc.setToChild(1); - } - bool one_prepended = false; - test_munc: - if(munc.isNumber()) { - if(munc.isZero()) { - CALCULATOR->endTemporaryStopMessages(true); - return *this; - } else if(isNumber()) { - o_number.setUncertainty(munc.number()); - numberUpdated(); - CALCULATOR->endTemporaryStopMessages(true); - return *this; - } else if(isAddition()) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isNumber()) { - b_failed = false; - CHILD(i).number().setUncertainty(munc.number()); - CHILD(i).numberUpdated(); - CHILD_UPDATED(i); - break; - } - } - } - } else { - if(munc.isMultiplication()) { - if(!munc[0].isNumber()) { - munc.insertChild(m_one, 1); - one_prepended = true; - } - } else { - munc.transform(STRUCT_MULTIPLICATION); - munc.insertChild(m_one, 1); - one_prepended = true; - } - if(munc.isMultiplication()) { - if(munc.size() == 2) { - if(isMultiplication() && CHILD(0).isNumber() && (munc[1] == CHILD(1) || (munc[1].isFunction() && munc[1].function() == CALCULATOR->f_abs && munc[1].size() == 1 && CHILD(1) == munc[1][0]))) { - CHILD(0).number().setUncertainty(munc[0].number()); - CHILD(0).numberUpdated(); - CHILD_UPDATED(0) - b_failed = false; - } else if(equals(munc[1]) || (munc[1].isFunction() && munc[1].function() == CALCULATOR->f_abs && munc[1].size() == 1 && equals(munc[1][0]))) { - transform(STRUCT_MULTIPLICATION); - PREPEND(m_one); - CHILD(0).number().setUncertainty(munc[0].number()); - CHILD(0).numberUpdated(); - CHILD_UPDATED(0) - b_failed = false; - } - } else if(isMultiplication()) { - size_t i2 = 0; - if(CHILD(0).isNumber()) i2++; - if(SIZE + 1 - i2 == munc.size()) { - bool b = true; - for(size_t i = 1; i < munc.size(); i++, i2++) { - if(!munc[i].equals(CHILD(i2)) && !(munc[i].isFunction() && munc[i].function() == CALCULATOR->f_abs && munc[i].size() == 1 && CHILD(i2) == munc[i][0])) { - b = false; - break; - } - } - if(b) { - if(!CHILD(0).isNumber()) { - PREPEND(m_one); - } - CHILD(0).number().setUncertainty(munc[0].number()); - CHILD(0).numberUpdated(); - CHILD_UPDATED(0) - b_failed = false; - } - } - } - if(b_failed) { - bool b = false; - for(size_t i = 0; i < munc.size(); i++) { - if(munc[i].isFunction() && munc[i].function() == CALCULATOR->f_abs && munc[i].size() == 1) { - munc[i].setToChild(1); - b = true; - } - } - if(b) { - munc.eval(eo3); - goto test_munc; - } - } - } - } - if(b_failed && munc.countTotalChildren(false) < 50) { - if(one_prepended && munc.isMultiplication() && munc[0].isOne()) munc.delChild(1, true); - if(eo.structuring != STRUCTURING_NONE) {simplify_ln(*this); simplify_ln(munc);} - structure(eo.structuring, eo2, false); - munc.structure(eo.structuring, eo2, false); - if(eo.structuring != STRUCTURING_NONE) {simplify_ln(*this); simplify_ln(munc);} - clean_multiplications(*this); - clean_multiplications(munc); - transform(CALCULATOR->f_uncertainty); - addChild(munc); - addChild(m_zero); - CALCULATOR->endTemporaryStopMessages(true); - return *this; - } - if(!b_failed) { - CALCULATOR->endTemporaryStopMessages(true); - if(eo.structuring != STRUCTURING_NONE) simplify_ln(*this); - structure(eo.structuring, eo2, false); - if(eo.structuring != STRUCTURING_NONE) simplify_ln(*this); - clean_multiplications(*this); - return *this; - } - } - CALCULATOR->endTemporaryStopMessages(!b_failed); - if(b_failed) { - set(mbak); - if(CALCULATOR->aborted()) return *this; - CALCULATOR->error(false, _("Calculation of uncertainty propagation failed (using interval arithmetic instead)."), NULL); - EvaluationOptions eo3 = eo; - eo3.interval_calculation = INTERVAL_CALCULATION_INTERVAL_ARITHMETIC; - eval(eo3); - return *this; - } - } - } - if(eo.calculate_functions) calculate_differentiable_functions(*this, feo); - } else if(eo.calculate_functions) { - calculateFunctions(feo); - } - - if(m_type == STRUCT_NUMBER) { - if(eo.complex_number_form == COMPLEX_NUMBER_FORM_EXPONENTIAL) complexToExponentialForm(eo); - else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_POLAR) complexToPolarForm(eo); - else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_CIS) complexToCisForm(eo); - return *this; - } - - if(eo2.interval_calculation == INTERVAL_CALCULATION_INTERVAL_ARITHMETIC || eo2.interval_calculation == INTERVAL_CALCULATION_VARIANCE_FORMULA) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; - - if(eo2.approximation == APPROXIMATION_TRY_EXACT || (eo2.approximation == APPROXIMATION_APPROXIMATE && (containsUnknowns() || containsInterval(false, true, false, 0)))) { - EvaluationOptions eo3 = eo2; - if(eo.approximation == APPROXIMATION_APPROXIMATE && !containsUnknowns()) eo3.approximation = APPROXIMATION_EXACT_VARIABLES; - else eo3.approximation = APPROXIMATION_EXACT; - eo3.split_squares = false; - eo3.assume_denominators_nonzero = false; - calculatesub(eo3, feo); - if(m_type == STRUCT_NUMBER) { - if(eo.complex_number_form == COMPLEX_NUMBER_FORM_EXPONENTIAL) complexToExponentialForm(eo); - else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_POLAR) complexToPolarForm(eo); - else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_CIS) complexToCisForm(eo); - return *this; - } - if(eo.interval_calculation < INTERVAL_CALCULATION_INTERVAL_ARITHMETIC && eo.expand && eo.expand >= -1 && !containsType(STRUCT_COMPARISON, true, true, true)) { - unformat(eo); - eo3.expand = -1; - calculatesub(eo3, feo); - } - eo3.approximation = APPROXIMATION_APPROXIMATE; - if(eo2.interval_calculation >= INTERVAL_CALCULATION_INTERVAL_ARITHMETIC && containsInterval(false, true, false, -1)) factorize_variables(*this, eo3); - if(containsType(STRUCT_COMPARISON) && containsInterval(false, true, false, false)) { - eo3.approximation = APPROXIMATION_EXACT; - fix_eqs(*this, eo3); - } - eo2.approximation = APPROXIMATION_APPROXIMATE; - } else if(eo2.approximation == APPROXIMATION_EXACT && contains_function_interval(*this, false, true, false, -1)) { - EvaluationOptions eo3 = eo2; - eo3.split_squares = false; - eo3.assume_denominators_nonzero = false; - calculatesub(eo3, feo); - eo3.approximation = APPROXIMATION_APPROXIMATE; - if(eo2.interval_calculation >= INTERVAL_CALCULATION_INTERVAL_ARITHMETIC) factorize_variables(*this, eo3, true); - } - if(eo2.approximation == APPROXIMATION_EXACT) replace_function_vars(*this); - - calculatesub(eo2, feo); - - if(m_type == STRUCT_NUMBER) { - if(eo.complex_number_form == COMPLEX_NUMBER_FORM_EXPONENTIAL) complexToExponentialForm(eo); - else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_POLAR) complexToPolarForm(eo); - else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_CIS) complexToCisForm(eo); - return *this; - } - if(m_type == STRUCT_UNDEFINED || m_type == STRUCT_ABORTED || m_type == STRUCT_DATETIME || m_type == STRUCT_UNIT || m_type == STRUCT_SYMBOLIC || (m_type == STRUCT_VARIABLE && !o_variable->isKnown())) return *this; - if(CALCULATOR->aborted()) return *this; - - eo2.sync_units = false; - eo2.isolate_x = eo.isolate_x; - - if(eo2.isolate_x) { - eo2.assume_denominators_nonzero = false; - if(isolate_x(eo2, feo)) { - if(CALCULATOR->aborted()) return *this; - if(eo.assume_denominators_nonzero) eo2.assume_denominators_nonzero = 2; - calculatesub(eo2, feo); - } else { - if(eo.assume_denominators_nonzero) eo2.assume_denominators_nonzero = 2; - } - if(CALCULATOR->aborted()) return *this; - } - - if(eo.expand != 0 || (eo.test_comparisons && containsType(STRUCT_COMPARISON))) { - eo2.test_comparisons = eo.test_comparisons; - eo2.expand = eo.expand; - if(eo2.expand && (!eo.test_comparisons || !containsType(STRUCT_COMPARISON))) eo2.expand = -2; - bool b = eo2.test_comparisons; - if(!b && isAddition()) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).containsType(STRUCT_ADDITION, false) == 1) { - b = true; - break; - } - } - } else if(!b) { - b = containsType(STRUCT_ADDITION, false) == 1; - } - if(b) { - calculatesub(eo2, feo); - if(CALCULATOR->aborted()) return *this; - if(eo.do_polynomial_division) do_simplification(*this, eo2, true, eo.structuring == STRUCTURING_NONE || eo.structuring == STRUCTURING_FACTORIZE, false, true, true); - if(CALCULATOR->aborted()) return *this; - if(eo2.isolate_x) { - eo2.assume_denominators_nonzero = false; - if(isolate_x(eo2, feo)) { - if(CALCULATOR->aborted()) return *this; - if(eo.assume_denominators_nonzero) eo2.assume_denominators_nonzero = 2; - calculatesub(eo2, feo); - if(containsType(STRUCT_ADDITION, false) == 1 && eo.do_polynomial_division) do_simplification(*this, eo2, true, eo.structuring == STRUCTURING_NONE || eo.structuring == STRUCTURING_FACTORIZE, false, true, true); - } else { - if(eo.assume_denominators_nonzero) eo2.assume_denominators_nonzero = 2; - } - if(CALCULATOR->aborted()) return *this; - } - } - } - if(eo2.isolate_x && containsType(STRUCT_COMPARISON) && eo2.assume_denominators_nonzero) { - eo2.assume_denominators_nonzero = 2; - if(try_isolate_x(*this, eo2, feo)) { - if(CALCULATOR->aborted()) return *this; - calculatesub(eo2, feo); - if(containsType(STRUCT_ADDITION, false) == 1 && eo.do_polynomial_division) do_simplification(*this, eo2, true, eo.structuring == STRUCTURING_NONE || eo.structuring == STRUCTURING_FACTORIZE, false, true, true); - } - } - - simplify_functions(*this, eo2, feo); - - if(CALCULATOR->aborted()) return *this; - - if(eo.structuring != STRUCTURING_NONE) { - - if(eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS || eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES) convert_to_default_angle_unit(*this, eo); - simplify_ln(*this); - - if(eo.keep_zero_units) remove_add_zero_unit(*this); - - structure(eo.structuring, eo2, false); - - simplify_ln(*this); - - } - - clean_multiplications(*this); - - if(eo.complex_number_form == COMPLEX_NUMBER_FORM_EXPONENTIAL) complexToExponentialForm(eo); - else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_POLAR) complexToPolarForm(eo); - else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_CIS) complexToCisForm(eo); - - return *this; -} - -bool factorize_fix_root_power(MathStructure &m) { - if(!m[0].isFunction() || m[0].function() != CALCULATOR->f_root || !VALID_ROOT(m[0])) return false; - if(m[1].isNumber() && m[1].number().isInteger() && !m[1].number().isMinusOne()) { - if(m[1] == m[0][1]) { - // root(x, a)^a=x - m.setToChild(1, true); - m.setToChild(1, true); - return true; - } else if(m[1].number().isIntegerDivisible(m[0][1].number())) { - // root(x, a)^(2a)=x^2 - if(m[1].number().divide(m[0][1].number())) { - m[0].setToChild(1, true); - return true; - } - } else if(m[0][1].number().isIntegerDivisible(m[1].number())) { - // root(x, 3a)^(a)=root(x, 3) - if(m[0][1].number().divide(m[1].number())) { - m.setToChild(1, true); - m.childUpdated(2); - return true; - } - } - } - return false; -} - -bool factorize_find_multiplier(const MathStructure &mstruct, MathStructure &mnew, MathStructure &factor_mstruct, bool only_units) { - factor_mstruct.set(m_one); - switch(mstruct.type()) { - case STRUCT_ADDITION: { - if(!only_units) { - bool bfrac = false, bint = true; - idm1(mstruct, bfrac, bint); - if(bfrac || bint) { - Number gcd(1, 1); - idm2(mstruct, bfrac, bint, gcd); - if((bint || bfrac) && !gcd.isOne()) { - if(bfrac) gcd.recip(); - factor_mstruct.set(gcd); - } - } - } - if(mstruct.size() > 0) { - size_t i = 0; - const MathStructure *cur_mstruct; - while(true) { - if(mstruct[0].isMultiplication()) { - if(i >= mstruct[0].size()) { - break; - } - cur_mstruct = &mstruct[0][i]; - } else { - cur_mstruct = &mstruct[0]; - } - if(!cur_mstruct->containsInterval(true) && !cur_mstruct->isNumber() && (!only_units || cur_mstruct->isUnit_exp())) { - const MathStructure *exp = NULL; - const MathStructure *bas; - if(cur_mstruct->isPower() && IS_REAL((*cur_mstruct)[1]) && !(*cur_mstruct)[0].isNumber()) { - exp = cur_mstruct->exponent(); - bas = cur_mstruct->base(); - } else { - bas = cur_mstruct; - } - bool b = true; - for(size_t i2 = 1; i2 < mstruct.size(); i2++) { - b = false; - size_t i3 = 0; - const MathStructure *cmp_mstruct; - while(true) { - if(mstruct[i2].isMultiplication()) { - if(i3 >= mstruct[i2].size()) { - break; - } - cmp_mstruct = &mstruct[i2][i3]; - } else { - cmp_mstruct = &mstruct[i2]; - } - if(cmp_mstruct->equals(*bas)) { - if(exp) { - exp = NULL; - } - b = true; - break; - } else if(cmp_mstruct->isPower() && IS_REAL((*cmp_mstruct)[1]) && cmp_mstruct->base()->equals(*bas)) { - if(exp) { - if(cmp_mstruct->exponent()->number().isLessThan(exp->number())) { - exp = cmp_mstruct->exponent(); - } - b = true; - break; - } else { - b = true; - break; - } - } - if(!mstruct[i2].isMultiplication()) { - break; - } - i3++; - } - if(!b) break; - } - if(b) { - b = !factor_mstruct.isOne(); - if(exp) { - MathStructure *mstruct = new MathStructure(*bas); - mstruct->raise(*exp); - if(factor_mstruct.isOne()) { - factor_mstruct.set_nocopy(*mstruct); - mstruct->unref(); - } else { - factor_mstruct.multiply_nocopy(mstruct, true); - } - } else { - if(factor_mstruct.isOne()) factor_mstruct.set(*bas); - else factor_mstruct.multiply(*bas, true); - } - if(b) { - size_t i3 = 0; - const MathStructure *cmp_mstruct; - b = false; - while(true) { - if(i3 >= factor_mstruct.size() - 1) { - break; - } - cmp_mstruct = &factor_mstruct[i3]; - if(cmp_mstruct->equals(factor_mstruct.last())) { - if(exp) { - exp = NULL; - } - b = true; - break; - } else if(cmp_mstruct->isPower() && IS_REAL((*cmp_mstruct)[1]) && cmp_mstruct->base()->equals(factor_mstruct.last())) { - if(exp) { - if(cmp_mstruct->exponent()->number().isLessThan(exp->number())) { - exp = cmp_mstruct->exponent(); - } - b = true; - break; - } else { - b = true; - break; - } - } - i3++; - } - if(b) factor_mstruct.delChild(factor_mstruct.size(), true); - } - } - } - if(!mstruct[0].isMultiplication()) { - break; - } - i++; - } - } - if(!factor_mstruct.isOne()) { - if(&mstruct != &mnew) mnew.set(mstruct); - MathStructure *mfactor; - size_t i = 0; - while(true) { - if(factor_mstruct.isMultiplication()) { - if(i >= factor_mstruct.size()) break; - mfactor = &factor_mstruct[i]; - } else { - mfactor = &factor_mstruct; - } - for(size_t i2 = 0; i2 < mnew.size(); i2++) { - switch(mnew[i2].type()) { - case STRUCT_NUMBER: { - if(mfactor->isNumber()) { - mnew[i2].number() /= mfactor->number(); - } - break; - } - case STRUCT_POWER: { - if(!IS_REAL(mnew[i2][1])) { - if(mfactor->isNumber()) { - mnew[i2].transform(STRUCT_MULTIPLICATION); - mnew[i2].insertChild(MathStructure(1, 1, 0), 1); - mnew[i2][0].number() /= mfactor->number(); - } else { - mnew[i2].set(m_one); - } - } else if(mfactor->isNumber()) { - mnew[i2].transform(STRUCT_MULTIPLICATION); - mnew[i2].insertChild(MathStructure(1, 1, 0), 1); - mnew[i2][0].number() /= mfactor->number(); - } else if(mfactor->isPower() && IS_REAL((*mfactor)[1])) { - if(mfactor->equals(mnew[i2])) { - mnew[i2].set(m_one); - } else { - mnew[i2][1].number() -= mfactor->exponent()->number(); - if(mnew[i2][1].number().isOne()) { - mnew[i2].setToChild(1, true); - } else if(factorize_fix_root_power(mnew[i2])) { - mnew.childUpdated(i2 + 1); - } - } - } else { - mnew[i2][1].number() -= 1; - if(mnew[i2][1].number().isOne()) { - mnew[i2].setToChild(1); - } else if(mnew[i2][1].number().isZero()) { - mnew[i2].set(m_one); - } else if(factorize_fix_root_power(mnew[i2])) { - mnew.childUpdated(i2 + 1); - } - } - break; - } - case STRUCT_MULTIPLICATION: { - bool b = true; - if(mfactor->isNumber() && (mnew[i2].size() < 1 || !mnew[i2][0].isNumber())) { - mnew[i2].insertChild(MathStructure(1, 1, 0), 1); - } - for(size_t i3 = 0; i3 < mnew[i2].size() && b; i3++) { - switch(mnew[i2][i3].type()) { - case STRUCT_NUMBER: { - if(mfactor->isNumber()) { - if(mfactor->equals(mnew[i2][i3])) { - mnew[i2].delChild(i3 + 1); - } else { - mnew[i2][i3].number() /= mfactor->number(); - } - b = false; - } - break; - } - case STRUCT_POWER: { - if(!IS_REAL(mnew[i2][i3][1])) { - if(mfactor->equals(mnew[i2][i3])) { - mnew[i2].delChild(i3 + 1); - b = false; - } - } else if(mfactor->isPower() && IS_REAL((*mfactor)[1]) && mfactor->base()->equals(mnew[i2][i3][0])) { - if(mfactor->equals(mnew[i2][i3])) { - mnew[i2].delChild(i3 + 1); - } else { - mnew[i2][i3][1].number() -= mfactor->exponent()->number(); - if(mnew[i2][i3][1].number().isOne()) { - MathStructure mstruct2(mnew[i2][i3][0]); - mnew[i2][i3] = mstruct2; - } else if(mnew[i2][i3][1].number().isZero()) { - mnew[i2].delChild(i3 + 1); - } else if(factorize_fix_root_power(mnew[i2][i3])) { - mnew[i2].childUpdated(i3 + 1); - mnew.childUpdated(i2 + 1); - } - } - b = false; - } else if(mfactor->equals(mnew[i2][i3][0])) { - if(mnew[i2][i3][1].number() == 2) { - MathStructure mstruct2(mnew[i2][i3][0]); - mnew[i2][i3] = mstruct2; - } else if(mnew[i2][i3][1].number().isOne()) { - mnew[i2].delChild(i3 + 1); - } else { - mnew[i2][i3][1].number() -= 1; - if(factorize_fix_root_power(mnew[i2][i3])) { - mnew[i2].childUpdated(i3 + 1); - mnew.childUpdated(i2 + 1); - } - } - b = false; - } - break; - } - default: { - if(mfactor->equals(mnew[i2][i3])) { - mnew[i2].delChild(i3 + 1); - b = false; - } - } - } - } - if(mnew[i2].size() == 1) { - MathStructure mstruct2(mnew[i2][0]); - mnew[i2] = mstruct2; - } - break; - } - default: { - if(mfactor->isNumber()) { - mnew[i2].transform(STRUCT_MULTIPLICATION); - mnew[i2].insertChild(MathStructure(1, 1, 0), 1); - mnew[i2][0].number() /= mfactor->number(); - } else { - mnew[i2].set(m_one); - } - } - } - } - if(factor_mstruct.isMultiplication()) { - i++; - } else { - break; - } - } - return true; - } - } - default: {} - } - return false; -} - -bool get_first_symbol(const MathStructure &mpoly, MathStructure &xvar) { - if(IS_A_SYMBOL(mpoly) || mpoly.isUnit()) { - xvar = mpoly; - return true; - } else if(mpoly.isAddition() || mpoly.isMultiplication()) { - for(size_t i = 0; i < mpoly.size(); i++) { - if(get_first_symbol(mpoly[i], xvar)) return true; - } - } else if(mpoly.isPower()) { - return get_first_symbol(mpoly[0], xvar); - } - return false; -} - -bool MathStructure::polynomialDivide(const MathStructure &mnum, const MathStructure &mden, MathStructure &mquotient, const EvaluationOptions &eo, bool check_args) { - - mquotient.clear(); - - if(CALCULATOR->aborted()) return false; - - if(mden.isZero()) { - //division by zero - return false; - } - if(mnum.isZero()) { - mquotient.clear(); - return true; - } - if(mden.isNumber()) { - mquotient = mnum; - if(mnum.isNumber()) { - mquotient.number() /= mden.number(); - } else { - mquotient.calculateDivide(mden, eo); - } - return true; - } else if(mnum.isNumber()) { - return false; - } - - if(mnum == mden) { - mquotient.set(1, 1, 0); - return true; - } - - if(check_args && (!mnum.isRationalPolynomial() || !mden.isRationalPolynomial())) { - return false; - } - - - MathStructure xvar; - if(!get_first_symbol(mnum, xvar) && !get_first_symbol(mden, xvar)) return false; - - EvaluationOptions eo2 = eo; - eo2.keep_zero_units = false; - - Number numdeg = mnum.degree(xvar); - Number dendeg = mden.degree(xvar); - MathStructure dencoeff; - mden.coefficient(xvar, dendeg, dencoeff); - - MathStructure mrem(mnum); - - for(size_t i = 0; numdeg.isGreaterThanOrEqualTo(dendeg); i++) { - if(i > 1000 || CALCULATOR->aborted()) { - return false; - } - MathStructure numcoeff; - mrem.coefficient(xvar, numdeg, numcoeff); - numdeg -= dendeg; - if(numcoeff == dencoeff) { - if(numdeg.isZero()) { - numcoeff.set(1, 1, 0); - } else { - numcoeff = xvar; - if(!numdeg.isOne()) { - numcoeff.raise(numdeg); - } - } - } else { - if(dencoeff.isNumber()) { - if(numcoeff.isNumber()) { - numcoeff.number() /= dencoeff.number(); - } else { - numcoeff.calculateDivide(dencoeff, eo2); - } - } else { - MathStructure mcopy(numcoeff); - if((mcopy.equals(mnum, true, true) && dencoeff.equals(mden, true, true)) || !MathStructure::polynomialDivide(mcopy, dencoeff, numcoeff, eo2, false)) { - return false; - } - } - if(!numdeg.isZero() && !numcoeff.isZero()) { - if(numcoeff.isOne()) { - numcoeff = xvar; - if(!numdeg.isOne()) { - numcoeff.raise(numdeg); - } - } else { - numcoeff.multiply(xvar, true); - if(!numdeg.isOne()) { - numcoeff[numcoeff.size() - 1].raise(numdeg); - } - numcoeff.calculateMultiplyLast(eo2); - } - } - } - if(mquotient.isZero()) mquotient = numcoeff; - else mquotient.add(numcoeff, true); - if(numcoeff.isAddition() && mden.isAddition() && numcoeff.size() * mden.size() >= (eo.expand == -1 ? 50 : 500)) return false; - numcoeff.calculateMultiply(mden, eo2); - mrem.calculateSubtract(numcoeff, eo2); - if(mrem.isZero()) { - return true; - } - numdeg = mrem.degree(xvar); - } - return false; -} - -bool polynomial_divide_integers(const vector &vnum, const vector &vden, vector &vquotient) { - - vquotient.clear(); - - long int numdeg = vnum.size() - 1; - long int dendeg = vden.size() - 1; - Number dencoeff(vden[dendeg]); - - if(numdeg < dendeg) return false; - - vquotient.resize(numdeg - dendeg + 1, nr_zero); - - vector vrem = vnum; - - while(numdeg >= dendeg) { - Number numcoeff(vrem[numdeg]); - numdeg -= dendeg; - if(!numcoeff.isIntegerDivisible(dencoeff)) break; - numcoeff /= dencoeff; - vquotient[numdeg] += numcoeff; - for(size_t i = 0; i < vden.size(); i++) { - vrem[numdeg + i] -= (vden[i] * numcoeff); - } - while(true) { - if(vrem.back().isZero()) vrem.pop_back(); - else break; - if(vrem.size() == 0) return true; - } - numdeg = (long int) vrem.size() - 1; - } - return false; -} - -bool divide_in_z(const MathStructure &mnum, const MathStructure &mden, MathStructure &mquotient, const sym_desc_vec &sym_stats, size_t var_i, const EvaluationOptions &eo) { - - mquotient.clear(); - if(mden.isZero()) return false; - if(mnum.isZero()) return true; - if(mden.isOne()) { - mquotient = mnum; - return true; - } - if(mnum.isNumber()) { - if(!mden.isNumber()) { - return false; - } - mquotient = mnum; - return mquotient.number().divide(mden.number()) && mquotient.isInteger(); - } - if(mnum == mden) { - mquotient.set(1, 1, 0); - return true; - } - - if(mden.isPower()) { - MathStructure qbar(mnum); - for(Number ni(mden[1].number()); ni.isPositive(); ni--) { - if(!divide_in_z(qbar, mden[0], mquotient, sym_stats, var_i, eo)) return false; - qbar = mquotient; - } - return true; - } - - if(mden.isMultiplication()) { - MathStructure qbar(mnum); - for(size_t i = 0; i < mden.size(); i++) { - sym_desc_vec sym_stats2; - get_symbol_stats(mnum, mden[i], sym_stats2); - if(!divide_in_z(qbar, mden[i], mquotient, sym_stats2, 0, eo)) return false; - qbar = mquotient; - } - return true; - } - - if(var_i >= sym_stats.size()) return false; - const MathStructure &xvar = sym_stats[var_i].sym; - - Number numdeg = mnum.degree(xvar); - Number dendeg = mden.degree(xvar); - if(dendeg.isGreaterThan(numdeg)) return false; - MathStructure dencoeff; - MathStructure mrem(mnum); - mden.coefficient(xvar, dendeg, dencoeff); - - while(numdeg.isGreaterThanOrEqualTo(dendeg)) { - if(CALCULATOR->aborted()) return false; - MathStructure numcoeff; - mrem.coefficient(xvar, numdeg, numcoeff); - MathStructure term; - if(!divide_in_z(numcoeff, dencoeff, term, sym_stats, var_i + 1, eo)) break; - numdeg -= dendeg; - if(!numdeg.isZero() && !term.isZero()) { - if(term.isOne()) { - term = xvar; - if(!numdeg.isOne()) { - term.raise(numdeg); - } - } else { - term.multiply(xvar, true); - if(!numdeg.isOne()) { - term[term.size() - 1].raise(numdeg); - } - term.calculateMultiplyLast(eo); - } - } - if(mquotient.isZero()) { - mquotient = term; - } else { - mquotient.calculateAdd(term, eo); - } - if(term.isAddition() && mden.isAddition() && term.size() * mden.size() >= (eo.expand == -1 ? 50 : 500)) return false; - term.calculateMultiply(mden, eo); - mrem.calculateSubtract(term, eo); - if(mrem.isZero()) { - return true; - } - numdeg = mrem.degree(xvar); - - } - return false; -} - -bool prem(const MathStructure &mnum, const MathStructure &mden, const MathStructure &xvar, MathStructure &mrem, const EvaluationOptions &eo, bool check_args) { - - mrem.clear(); - if(mden.isZero()) { - //division by zero - return false; - } - if(mnum.isNumber()) { - if(!mden.isNumber()) { - mrem = mden; - } - return true; - } - if(check_args && (!mnum.isRationalPolynomial() || !mden.isRationalPolynomial())) { - return false; - } - - mrem = mnum; - MathStructure eb(mden); - Number rdeg = mrem.degree(xvar); - Number bdeg = eb.degree(xvar); - MathStructure blcoeff; - if(bdeg.isLessThanOrEqualTo(rdeg)) { - eb.coefficient(xvar, bdeg, blcoeff); - if(bdeg == 0) { - eb.clear(); - } else { - MathStructure mpow(xvar); - mpow.raise(bdeg); - mpow.calculateRaiseExponent(eo); - //POWER_CLEAN(mpow) - mpow.calculateMultiply(blcoeff, eo); - eb.calculateSubtract(mpow, eo); - } - } else { - blcoeff.set(1, 1, 0); - } - - Number delta(rdeg); - delta -= bdeg; - delta++; - int i = 0; - while(rdeg.isGreaterThanOrEqualTo(bdeg) && !mrem.isZero()) { - if(CALCULATOR->aborted() || delta < i / 10) {mrem.clear(); return false;} - MathStructure rlcoeff; - mrem.coefficient(xvar, rdeg, rlcoeff); - MathStructure term(xvar); - term.raise(rdeg); - term[1].number() -= bdeg; - term.calculateRaiseExponent(eo); - //POWER_CLEAN(term) - term.calculateMultiply(rlcoeff, eo); - term.calculateMultiply(eb, eo); - if(rdeg == 0) { - mrem = term; - mrem.calculateNegate(eo); - } else { - if(!rdeg.isZero()) { - rlcoeff.multiply(xvar, true); - if(!rdeg.isOne()) { - rlcoeff[rlcoeff.size() - 1].raise(rdeg); - rlcoeff[rlcoeff.size() - 1].calculateRaiseExponent(eo); - } - rlcoeff.calculateMultiplyLast(eo); - } - mrem.calculateSubtract(rlcoeff, eo); - if(mrem.isAddition() && blcoeff.isAddition() && mrem.size() * blcoeff.size() >= (eo.expand == -1 ? 50 : 500)) {mrem.clear(); return false;} - mrem.calculateMultiply(blcoeff, eo); - mrem.calculateSubtract(term, eo); - } - rdeg = mrem.degree(xvar); - i++; - } - delta -= i; - blcoeff.raise(delta); - blcoeff.calculateRaiseExponent(eo); - mrem.calculateMultiply(blcoeff, eo); - return true; -} - - -bool sr_gcd(const MathStructure &m1, const MathStructure &m2, MathStructure &mgcd, const sym_desc_vec &sym_stats, size_t var_i, const EvaluationOptions &eo) { - - if(var_i >= sym_stats.size()) return false; - const MathStructure &xvar = sym_stats[var_i].sym; - - MathStructure c, d; - Number adeg = m1.degree(xvar); - Number bdeg = m2.degree(xvar); - Number cdeg, ddeg; - if(adeg.isGreaterThanOrEqualTo(bdeg)) { - c = m1; - d = m2; - cdeg = adeg; - ddeg = bdeg; - } else { - c = m2; - d = m1; - cdeg = bdeg; - ddeg = adeg; - } - - MathStructure cont_c, cont_d; - c.polynomialContent(xvar, cont_c, eo); - d.polynomialContent(xvar, cont_d, eo); - - MathStructure gamma; - - if(!MathStructure::gcd(cont_c, cont_d, gamma, eo, NULL, NULL, false)) return false; - mgcd = gamma; - if(ddeg.isZero()) { - return true; - } - - MathStructure prim_c, prim_d; - c.polynomialPrimpart(xvar, cont_c, prim_c, eo); - d.polynomialPrimpart(xvar, cont_d, prim_d, eo); - c = prim_c; - d = prim_d; - - MathStructure r; - MathStructure ri(1, 1, 0); - MathStructure psi(1, 1, 0); - Number delta(cdeg); - delta -= ddeg; - - while(true) { - - if(CALCULATOR->aborted()) return false; - - if(!prem(c, d, xvar, r, eo, false)) return false; - - if(r.isZero()) { - mgcd = gamma; - MathStructure mprim; - d.polynomialPrimpart(xvar, mprim, eo); - if(CALCULATOR->aborted()) return false; - mgcd.calculateMultiply(mprim, eo); - return true; - } - - c = d; - cdeg = ddeg; - - MathStructure psi_pow(psi); - psi_pow.calculateRaise(delta, eo); - ri.calculateMultiply(psi_pow, eo); - - if(!divide_in_z(r, ri, d, sym_stats, var_i, eo)) { - return false; - } - - ddeg = d.degree(xvar); - if(ddeg.isZero()) { - if(r.isNumber()) { - mgcd = gamma; - } else { - r.polynomialPrimpart(xvar, mgcd, eo); - if(CALCULATOR->aborted()) return false; - mgcd.calculateMultiply(gamma, eo); - } - return true; - } - - c.lcoefficient(xvar, ri); - if(delta.isOne()) { - psi = ri; - } else if(!delta.isZero()) { - MathStructure ri_pow(ri); - ri_pow.calculateRaise(delta, eo); - MathStructure psi_pow(psi); - delta--; - psi_pow.calculateRaise(delta, eo); - divide_in_z(ri_pow, psi_pow, psi, sym_stats, var_i + 1, eo); - } - delta = cdeg; - delta -= ddeg; - - } - - return false; - -} - -Number MathStructure::maxCoefficient() { - if(isNumber()) { - Number nr(o_number); - nr.abs(); - return nr; - } else if(isAddition()) { - Number cur_max(overallCoefficient()); - cur_max.abs(); - for(size_t i = 0; i < SIZE; i++) { - Number a(CHILD(i).overallCoefficient()); - a.abs(); - if(a.isGreaterThan(cur_max)) cur_max = a; - } - return cur_max; - } else if(isMultiplication()) { - Number nr(overallCoefficient()); - nr.abs(); - return nr; - } else { - return nr_one; - } -} -void polynomial_smod(const MathStructure &mpoly, const Number &xi, MathStructure &msmod, const EvaluationOptions &eo, MathStructure *mparent, size_t index_smod) { - if(mpoly.isNumber()) { - msmod = mpoly; - msmod.number().smod(xi); - } else if(mpoly.isAddition()) { - msmod.clear(); - msmod.setType(STRUCT_ADDITION); - msmod.resizeVector(mpoly.size(), m_zero); - for(size_t i = 0; i < mpoly.size(); i++) { - polynomial_smod(mpoly[i], xi, msmod[i], eo, &msmod, i); - } - msmod.calculatesub(eo, eo, false, mparent, index_smod); - } else if(mpoly.isMultiplication()) { - msmod = mpoly; - if(msmod.size() > 0 && msmod[0].isNumber()) { - if(!msmod[0].number().smod(xi) || msmod[0].isZero()) { - msmod.clear(); - } - } - } else { - msmod = mpoly; - } -} - -bool interpolate(const MathStructure &gamma, const Number &xi, const MathStructure &xvar, MathStructure &minterp, const EvaluationOptions &eo) { - MathStructure e(gamma); - Number rxi(xi); - rxi.recip(); - minterp.clear(); - for(long int i = 0; !e.isZero(); i++) { - if(CALCULATOR->aborted()) return false; - MathStructure gi; - polynomial_smod(e, xi, gi, eo); - if(minterp.isZero() && !gi.isZero()) { - minterp = gi; - if(i != 0) { - if(minterp.isOne()) { - minterp = xvar; - if(i != 1) minterp.raise(i); - } else { - minterp.multiply(xvar, true); - if(i != 1) minterp[minterp.size() - 1].raise(i); - minterp.calculateMultiplyLast(eo); - } - } - } else if(!gi.isZero()) { - minterp.add(gi, true); - if(i != 0) { - if(minterp[minterp.size() - 1].isOne()) { - minterp[minterp.size() - 1] = xvar; - if(i != 1) minterp[minterp.size() - 1].raise(i); - } else { - minterp[minterp.size() - 1].multiply(xvar, true); - if(i != 1) minterp[minterp.size() - 1][minterp[minterp.size() - 1].size() - 1].raise(i); - minterp[minterp.size() - 1].calculateMultiplyLast(eo); - } - } - } - if(!gi.isZero()) e.calculateSubtract(gi, eo); - e.calculateMultiply(rxi, eo); - } - minterp.calculatesub(eo, eo, false); - return true; -} - -bool heur_gcd(const MathStructure &m1, const MathStructure &m2, MathStructure &mgcd, const EvaluationOptions &eo, MathStructure *ca, MathStructure *cb, sym_desc_vec &sym_stats, size_t var_i) { - - if(m1.isZero() || m2.isZero()) return false; - - if(m1.isNumber() && m2.isNumber()) { - mgcd = m1; - if(!mgcd.number().gcd(m2.number())) mgcd.set(1, 1, 0); - if(ca) { - *ca = m1; - ca->number() /= mgcd.number(); - } - if(cb) { - *cb = m2; - cb->number() /= mgcd.number(); - } - return true; - } - - if(var_i >= sym_stats.size()) return false; - const MathStructure &xvar = sym_stats[var_i].sym; - - Number nr_gc; - integer_content(m1, nr_gc); - Number nr_rgc; - integer_content(m2, nr_rgc); - nr_gc.gcd(nr_rgc); - nr_rgc = nr_gc; - nr_rgc.recip(); - MathStructure p(m1); - p.calculateMultiply(nr_rgc, eo); - MathStructure q(m2); - q.calculateMultiply(nr_rgc, eo); - Number maxdeg(p.degree(xvar)); - Number maxdeg2(q.degree(xvar)); - if(maxdeg2.isGreaterThan(maxdeg)) maxdeg = maxdeg2; - Number mp(p.maxCoefficient()); - Number mq(q.maxCoefficient()); - Number xi; - if(mp.isGreaterThan(mq)) { - xi = mq; - } else { - xi = mp; - } - xi *= 2; - xi += 2; - - for(int t = 0; t < 6; t++) { - - if(CALCULATOR->aborted()) return false; - - if(!xi.isInteger() || (maxdeg * xi.integerLength()).isGreaterThan(100000L)) { - return false; - } - - MathStructure cp, cq; - MathStructure gamma; - MathStructure psub(p); - psub.calculateReplace(xvar, xi, eo, true); - MathStructure qsub(q); - qsub.calculateReplace(xvar, xi, eo, true); - - if(heur_gcd(psub, qsub, gamma, eo, &cp, &cq, sym_stats, var_i + 1)) { - - if(!interpolate(gamma, xi, xvar, mgcd, eo)) return false; - - Number ig; - integer_content(mgcd, ig); - ig.recip(); - mgcd.calculateMultiply(ig, eo); - - MathStructure dummy; - - if(divide_in_z(p, mgcd, ca ? *ca : dummy, sym_stats, var_i, eo) && divide_in_z(q, mgcd, cb ? *cb : dummy, sym_stats, var_i, eo)) { - mgcd.calculateMultiply(nr_gc, eo); - return true; - } - } - - Number xi2(xi); - xi2.isqrt(); - xi2.isqrt(); - xi *= xi2; - xi *= 73794L; - xi.iquo(27011L); - - } - - return false; - -} - -int MathStructure::polynomialUnit(const MathStructure &xvar) const { - MathStructure coeff; - lcoefficient(xvar, coeff); - if(coeff.hasNegativeSign()) return -1; - return 1; -} - -void integer_content(const MathStructure &mpoly, Number &icontent) { - if(mpoly.isNumber()) { - icontent = mpoly.number(); - icontent.abs(); - } else if(mpoly.isAddition()) { - icontent.clear(); - Number l(1, 1); - for(size_t i = 0; i < mpoly.size(); i++) { - if(mpoly[i].isNumber()) { - if(!icontent.isOne()) { - Number c = icontent; - icontent = mpoly[i].number().numerator(); - icontent.gcd(c); - } - Number l2 = l; - l = mpoly[i].number().denominator(); - l.lcm(l2); - } else if(mpoly[i].isMultiplication()) { - if(!icontent.isOne()) { - Number c = icontent; - icontent = mpoly[i].overallCoefficient().numerator(); - icontent.gcd(c); - } - Number l2 = l; - l = mpoly[i].overallCoefficient().denominator(); - l.lcm(l2); - } else { - icontent.set(1, 1, 0); - } - } - icontent /= l; - } else if(mpoly.isMultiplication()) { - icontent = mpoly.overallCoefficient(); - icontent.abs(); - } else { - icontent.set(1, 1, 0); - } -} - -bool MathStructure::lcm(const MathStructure &m1, const MathStructure &m2, MathStructure &mlcm, const EvaluationOptions &eo, bool check_args) { - if(m1.isNumber() && m2.isNumber()) { - mlcm = m1; - return mlcm.number().lcm(m2.number()); - } - if(check_args && (!m1.isRationalPolynomial() || !m2.isRationalPolynomial())) { - return false; - } - MathStructure ca, cb; - if(!MathStructure::gcd(m1, m2, mlcm, eo, &ca, &cb, false)) return false; - mlcm.calculateMultiply(ca, eo); - mlcm.calculateMultiply(cb, eo); - return true; -} - -void MathStructure::polynomialContent(const MathStructure &xvar, MathStructure &mcontent, const EvaluationOptions &eo) const { - if(isZero()) { - mcontent.clear(); - return; - } - if(isNumber()) { - mcontent = *this; - mcontent.number().setNegative(false); - return; - } - - MathStructure c; - integer_content(*this, c.number()); - MathStructure r(*this); - if(!c.isOne()) r.calculateDivide(c, eo); - MathStructure lcoeff; - r.lcoefficient(xvar, lcoeff); - if(lcoeff.isInteger()) { - mcontent = c; - return; - } - Number deg(r.degree(xvar)); - Number ldeg(r.ldegree(xvar)); - if(deg == ldeg) { - mcontent = lcoeff; - if(lcoeff.polynomialUnit(xvar) == -1) { - c.number().negate(); - } - mcontent.calculateMultiply(c, eo); - return; - } - mcontent.clear(); - MathStructure mtmp, coeff; - for(Number i(ldeg); i.isLessThanOrEqualTo(deg); i++) { - coefficient(xvar, i, coeff); - mtmp = mcontent; - if(!MathStructure::gcd(coeff, mtmp, mcontent, eo, NULL, NULL, false)) mcontent.set(1, 1, 0); - if(mcontent.isOne()) break; - } - - if(!c.isOne()) mcontent.calculateMultiply(c, eo); - -} - -void MathStructure::polynomialPrimpart(const MathStructure &xvar, MathStructure &mprim, const EvaluationOptions &eo) const { - if(isZero()) { - mprim.clear(); - return; - } - if(isNumber()) { - mprim.set(1, 1, 0); - return; - } - - MathStructure c; - polynomialContent(xvar, c, eo); - if(c.isZero()) { - mprim.clear(); - return; - } - bool b = (polynomialUnit(xvar) == -1); - if(c.isNumber()) { - if(b) c.number().negate(); - mprim = *this; - mprim.calculateDivide(c, eo); - return; - } - if(b) c.calculateNegate(eo); - MathStructure::polynomialQuotient(*this, c, xvar, mprim, eo, false); -} -void MathStructure::polynomialUnitContentPrimpart(const MathStructure &xvar, int &munit, MathStructure &mcontent, MathStructure &mprim, const EvaluationOptions &eo) const { - - if(isZero()) { - munit = 1; - mcontent.clear(); - mprim.clear(); - return; - } - - if(isNumber()) { - if(o_number.isNegative()) { - munit = -1; - mcontent = *this; - mcontent.number().abs(); - } else { - munit = 1; - mcontent = *this; - } - mprim.set(1, 1, 0); - return; - } - - munit = polynomialUnit(xvar); - - polynomialContent(xvar, mcontent, eo); - - if(mcontent.isZero()) { - mprim.clear(); - return; - } - if(mcontent.isNumber()) { - mprim = *this; - if(munit == -1) { - Number c(mcontent.number()); - c.negate(); - mprim.calculateDivide(c, eo); - } else if(!mcontent.isOne()) { - mprim.calculateDivide(mcontent, eo); - } - } else { - if(munit == -1) { - MathStructure c(mcontent); - c.calculateNegate(eo); - MathStructure::polynomialQuotient(*this, c, xvar, mprim, eo, false); - } else { - MathStructure::polynomialQuotient(*this, mcontent, xvar, mprim, eo, false); - } - } -} - - -void MathStructure::polynomialPrimpart(const MathStructure &xvar, const MathStructure &c, MathStructure &mprim, const EvaluationOptions &eo) const { - if(isZero() || c.isZero()) { - mprim.clear(); - return; - } - if(isNumber()) { - mprim.set(1, 1, 0); - return; - } - bool b = (polynomialUnit(xvar) == -1); - if(c.isNumber()) { - MathStructure cn(c); - if(b) cn.number().negate(); - mprim = *this; - mprim.calculateDivide(cn, eo); - return; - } - if(b) { - MathStructure cn(c); - cn.calculateNegate(eo); - MathStructure::polynomialQuotient(*this, cn, xvar, mprim, eo, false); - } else { - MathStructure::polynomialQuotient(*this, c, xvar, mprim, eo, false); - } -} - -const Number& MathStructure::degree(const MathStructure &xvar) const { - const Number *c = NULL; - const MathStructure *mcur = NULL; - for(size_t i = 0; ; i++) { - if(isAddition()) { - if(i >= SIZE) break; - mcur = &CHILD(i); - } else { - mcur = this; - } - if((*mcur) == xvar) { - if(!c) { - c = &nr_one; - } - } else if(mcur->isPower() && (*mcur)[0] == xvar && (*mcur)[1].isNumber()) { - if(!c || c->isLessThan((*mcur)[1].number())) { - c = &(*mcur)[1].number(); - } - } else if(mcur->isMultiplication()) { - for(size_t i2 = 0; i2 < mcur->size(); i2++) { - if((*mcur)[i2] == xvar) { - if(!c) { - c = &nr_one; - } - } else if((*mcur)[i2].isPower() && (*mcur)[i2][0] == xvar && (*mcur)[i2][1].isNumber()) { - if(!c || c->isLessThan((*mcur)[i2][1].number())) { - c = &(*mcur)[i2][1].number(); - } - } - } - } - if(!isAddition()) break; - } - if(!c) return nr_zero; - return *c; -} -const Number& MathStructure::ldegree(const MathStructure &xvar) const { - const Number *c = NULL; - const MathStructure *mcur = NULL; - for(size_t i = 0; ; i++) { - if(isAddition()) { - if(i >= SIZE) break; - mcur = &CHILD(i); - } else { - mcur = this; - } - if((*mcur) == xvar) { - c = &nr_one; - } else if(mcur->isPower() && (*mcur)[0] == xvar && (*mcur)[1].isNumber()) { - if(!c || c->isGreaterThan((*mcur)[1].number())) { - c = &(*mcur)[1].number(); - } - } else if(mcur->isMultiplication()) { - bool b = false; - for(size_t i2 = 0; i2 < mcur->size(); i2++) { - if((*mcur)[i2] == xvar) { - c = &nr_one; - b = true; - } else if((*mcur)[i2].isPower() && (*mcur)[i2][0] == xvar && (*mcur)[i2][1].isNumber()) { - if(!c || c->isGreaterThan((*mcur)[i2][1].number())) { - c = &(*mcur)[i2][1].number(); - } - b = true; - } - } - if(!b) return nr_zero; - } else { - return nr_zero; - } - if(!isAddition()) break; - } - if(!c) return nr_zero; - return *c; -} -void MathStructure::lcoefficient(const MathStructure &xvar, MathStructure &mcoeff) const { - coefficient(xvar, degree(xvar), mcoeff); -} -void MathStructure::tcoefficient(const MathStructure &xvar, MathStructure &mcoeff) const { - coefficient(xvar, ldegree(xvar), mcoeff); -} -void MathStructure::coefficient(const MathStructure &xvar, const Number &pownr, MathStructure &mcoeff) const { - const MathStructure *mcur = NULL; - mcoeff.clear(); - for(size_t i = 0; ; i++) { - if(isAddition()) { - if(i >= SIZE) break; - mcur = &CHILD(i); - } else { - mcur = this; - } - if((*mcur) == xvar) { - if(pownr.isOne()) { - if(mcoeff.isZero()) mcoeff.set(1, 1, 0); - else mcoeff.add(m_one, true); - } - } else if(mcur->isPower() && (*mcur)[0] == xvar && (*mcur)[1].isNumber()) { - if((*mcur)[1].number() == pownr) { - if(mcoeff.isZero()) mcoeff.set(1, 1, 0); - else mcoeff.add(m_one, true); - } - } else if(mcur->isMultiplication()) { - bool b = false; - for(size_t i2 = 0; i2 < mcur->size(); i2++) { - bool b2 = false; - if((*mcur)[i2] == xvar) { - b = true; - if(pownr.isOne()) b2 = true; - } else if((*mcur)[i2].isPower() && (*mcur)[i2][0] == xvar && (*mcur)[i2][1].isNumber()) { - b = true; - if((*mcur)[i2][1].number() == pownr) b2 = true; - } - if(b2) { - if(mcoeff.isZero()) { - if(mcur->size() == 1) { - mcoeff.set(1, 1, 0); - } else { - for(size_t i3 = 0; i3 < mcur->size(); i3++) { - if(i3 != i2) { - if(mcoeff.isZero()) mcoeff = (*mcur)[i3]; - else mcoeff.multiply((*mcur)[i3], true); - } - } - } - } else if(mcur->size() == 1) { - mcoeff.add(m_one, true); - } else { - mcoeff.add(m_zero, true); - for(size_t i3 = 0; i3 < mcur->size(); i3++) { - if(i3 != i2) { - if(mcoeff[mcoeff.size() - 1].isZero()) mcoeff[mcoeff.size() - 1] = (*mcur)[i3]; - else mcoeff[mcoeff.size() - 1].multiply((*mcur)[i3], true); - } - } - } - break; - } - } - if(!b && pownr.isZero()) { - if(mcoeff.isZero()) mcoeff = *mcur; - else mcoeff.add(*mcur, true); - } - } else if(pownr.isZero()) { - if(mcoeff.isZero()) mcoeff = *mcur; - else mcoeff.add(*mcur, true); - } - if(!isAddition()) break; - } - mcoeff.evalSort(); -} - -bool get_multiplier(const MathStructure &mstruct, const MathStructure &xvar, MathStructure &mcoeff, size_t exclude_i = (size_t) -1) { - const MathStructure *mcur = NULL; - mcoeff.clear(); - for(size_t i = 0; ; i++) { - if(mstruct.isAddition()) { - if(i == exclude_i) i++; - if(i >= mstruct.size()) break; - mcur = &mstruct[i]; - } else { - mcur = &mstruct; - } - if((*mcur) == xvar) { - if(mcoeff.isZero()) mcoeff.set(1, 1, 0); - else mcoeff.add(m_one, true); - } else if(mcur->isMultiplication()) { - bool b = false; - for(size_t i2 = 0; i2 < mcur->size(); i2++) { - if((*mcur)[i2] == xvar) { - b = true; - if(mcoeff.isZero()) { - if(mcur->size() == 1) { - mcoeff.set(1, 1, 0); - } else { - for(size_t i3 = 0; i3 < mcur->size(); i3++) { - if(i3 != i2) { - if(mcoeff.isZero()) mcoeff = (*mcur)[i3]; - else mcoeff.multiply((*mcur)[i3], true); - } - } - } - } else if(mcur->size() == 1) { - mcoeff.add(m_one, true); - } else { - mcoeff.add(m_zero, true); - for(size_t i3 = 0; i3 < mcur->size(); i3++) { - if(i3 != i2) { - if(mcoeff[mcoeff.size() - 1].isZero()) mcoeff[mcoeff.size() - 1] = (*mcur)[i3]; - else mcoeff[mcoeff.size() - 1].multiply((*mcur)[i3], true); - } - } - } - break; - } else if(xvar.isMultiplication() && xvar.size() > 0 && (*mcur)[i2] == xvar[0]) { - if(mcur->size() - i2 < xvar.size()) break; - b = true; - for(size_t i3 = 1; i3 < xvar.size(); i3++) { - if((*mcur)[i2 + i3] != xvar[i3]) {b = false; break;} - } - if(!b) break; - if(mcoeff.isZero()) { - if(mcur->size() == xvar.size()) { - mcoeff.set(1, 1, 0); - } else { - for(size_t i3 = 0; i3 < mcur->size(); i3++) { - if(i3 < i2 || i3 >= i2 + xvar.size()) { - if(mcoeff.isZero()) mcoeff = (*mcur)[i3]; - else mcoeff.multiply((*mcur)[i3], true); - } - } - } - } else if(mcur->size() == xvar.size()) { - mcoeff.add(m_one, true); - } else { - mcoeff.add(m_zero, true); - for(size_t i3 = 0; i3 < mcur->size(); i3++) { - if(i3 < i2 || i3 >= i2 + xvar.size()) { - if(mcoeff[mcoeff.size() - 1].isZero()) mcoeff[mcoeff.size() - 1] = (*mcur)[i3]; - else mcoeff[mcoeff.size() - 1].multiply((*mcur)[i3], true); - } - } - } - break; - } - } - if(!b) { - mcoeff.clear(); - return false; - } - } else { - mcoeff.clear(); - return false; - } - if(!mstruct.isAddition()) break; - } - if(mcoeff.isZero()) return false; - mcoeff.evalSort(); - return true; -} - -bool get_power(const MathStructure &mstruct, const MathStructure &xvar, MathStructure &mpow) { - if(mstruct == xvar) { - mpow = m_one; - return true; - } - if(mstruct.isPower() && mstruct[0] == xvar) { - mpow = mstruct[1]; - return true; - } - for(size_t i = 0; i < mstruct.size(); i++) { - if(get_power(mstruct[i], xvar, mpow)) return true; - } - return false; -} -const MathStructure *get_power_term(const MathStructure &mstruct, const MathStructure &xvar) { - if(mstruct == xvar) { - return &mstruct; - } - if(mstruct.isPower() && mstruct[0] == xvar) { - return &mstruct; - } - for(size_t i = 0; i < mstruct.size(); i++) { - const MathStructure *mterm = get_power_term(mstruct[i], xvar); - if(mterm) return mterm; - } - return NULL; -} - -bool MathStructure::polynomialQuotient(const MathStructure &mnum, const MathStructure &mden, const MathStructure &xvar, MathStructure &mquotient, const EvaluationOptions &eo, bool check_args) { - mquotient.clear(); - if(CALCULATOR->aborted()) return false; - if(mden.isZero()) { - //division by zero - return false; - } - if(mnum.isZero()) { - mquotient.clear(); - return true; - } - if(mden.isNumber() && mnum.isNumber()) { - mquotient = mnum; - if(IS_REAL(mden) && IS_REAL(mnum)) { - mquotient.number() /= mden.number(); - } else { - mquotient.calculateDivide(mden, eo); - } - return true; - } - if(mnum == mden) { - mquotient.set(1, 1, 0); - return true; - } - if(check_args && (!mnum.isRationalPolynomial() || !mden.isRationalPolynomial())) { - return false; - } - - EvaluationOptions eo2 = eo; - eo2.keep_zero_units = false; - - Number numdeg = mnum.degree(xvar); - Number dendeg = mden.degree(xvar); - MathStructure dencoeff; - mden.coefficient(xvar, dendeg, dencoeff); - MathStructure mrem(mnum); - for(size_t i = 0; numdeg.isGreaterThanOrEqualTo(dendeg); i++) { - if(i > 1000 || CALCULATOR->aborted()) { - return false; - } - MathStructure numcoeff; - mrem.coefficient(xvar, numdeg, numcoeff); - numdeg -= dendeg; - if(numcoeff == dencoeff) { - if(numdeg.isZero()) { - numcoeff.set(1, 1, 0); - } else { - numcoeff = xvar; - if(!numdeg.isOne()) { - numcoeff.raise(numdeg); - } - } - } else { - if(dencoeff.isNumber()) { - if(numcoeff.isNumber()) { - numcoeff.number() /= dencoeff.number(); - } else { - numcoeff.calculateDivide(dencoeff, eo2); - } - } else { - MathStructure mcopy(numcoeff); - if(!MathStructure::polynomialDivide(mcopy, dencoeff, numcoeff, eo2, false)) { - return false; - } - } - if(!numdeg.isZero() && !numcoeff.isZero()) { - if(numcoeff.isOne()) { - numcoeff = xvar; - if(!numdeg.isOne()) { - numcoeff.raise(numdeg); - } - } else { - numcoeff.multiply(xvar, true); - if(!numdeg.isOne()) { - numcoeff[numcoeff.size() - 1].raise(numdeg); - } - numcoeff.calculateMultiplyLast(eo2); - } - } - } - if(mquotient.isZero()) mquotient = numcoeff; - else mquotient.calculateAdd(numcoeff, eo2); - numcoeff.calculateMultiply(mden, eo2); - mrem.calculateSubtract(numcoeff, eo2); - if(mrem.isZero()) break; - numdeg = mrem.degree(xvar); - } - return true; - -} - -bool remove_zerointerval_multiplier(MathStructure &mstruct, const EvaluationOptions &eo) { - if(mstruct.isAddition()) { - bool b; - for(size_t i = 0; i < mstruct.size(); i++) { - if(remove_zerointerval_multiplier(mstruct[i], eo)) b = true; - } - if(b) { - mstruct.calculatesub(eo, eo, false); - return true; - } - } else if(mstruct.isMultiplication()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isNumber() && !mstruct[i].number().isNonZero()) { - mstruct.clear(true); - return true; - } - } - } else if(mstruct.isNumber() && !mstruct.number().isNonZero()) { - mstruct.clear(true); - return true; - } - return false; -} -bool contains_zerointerval_multiplier(MathStructure &mstruct) { - if(mstruct.isAddition()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(contains_zerointerval_multiplier(mstruct[i])) return true; - } - } else if(mstruct.isMultiplication()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isNumber() && !mstruct[i].number().isNonZero()) return true; - } - } else if(mstruct.isNumber() && !mstruct.number().isNonZero()) { - return true; - } - return false; -} - -bool polynomial_long_division(const MathStructure &mnum, const MathStructure &mden, const MathStructure &xvar_pre, MathStructure &mquotient, MathStructure &mrem, const EvaluationOptions &eo, bool check_args, bool for_newtonraphson) { - mquotient.clear(); - mrem.clear(); - - if(CALCULATOR->aborted()) return false; - if(mden.isZero()) { - //division by zero - mrem.set(mnum); - return false; - } - if(mnum.isZero()) { - mquotient.clear(); - return true; - } - if(mden.isNumber() && mnum.isNumber()) { - mquotient = mnum; - if(IS_REAL(mden) && IS_REAL(mnum)) { - mquotient.number() /= mden.number(); - } else { - mquotient.calculateDivide(mden, eo); - } - return true; - } else if(mnum.isNumber()) { - mrem.set(mnum); - return false; - } - if(mnum == mden) { - mquotient.set(1, 1, 0); - return true; - } - - mrem.set(mnum); - - if(check_args && (!mnum.isRationalPolynomial(true, true) || !mden.isRationalPolynomial(true, true))) { - return false; - } - - MathStructure xvar(xvar_pre); - if(xvar.isZero()) { - vector symsd, symsn; - collect_symbols(mnum, symsn); - if(symsn.empty()) return false; - collect_symbols(mden, symsd); - if(symsd.empty()) return false; - for(size_t i = 0; i < symsd.size();) { - bool b_found = false; - for(size_t i2 = 0; i2 < symsn.size(); i2++) { - if(symsn[i2] == symsd[i]) { - b_found = (mnum.degree(symsd[i]) >= mden.degree(symsd[i])); - break; - } - } - if(b_found) i++; - else symsd.erase(symsd.begin() + i); - } - for(size_t i = 0; i < symsd.size(); i++) { - MathStructure mquotient2, mrem2; - if(polynomial_long_division(mrem, mden, symsd[i], mquotient2, mrem2, eo, false, for_newtonraphson) && !mquotient2.isZero()) { - mrem = mrem2; - if(mquotient.isZero()) mquotient = mquotient2; - else mquotient.calculateAdd(mquotient2, eo); - } - if(CALCULATOR->aborted()) { - mrem = mnum; - mquotient.clear(); - return false; - } - } - return true; - } - - EvaluationOptions eo2 = eo; - eo2.keep_zero_units = false; - eo2.do_polynomial_division = false; - - Number numdeg = mnum.degree(xvar); - Number dendeg = mden.degree(xvar); - MathStructure dencoeff; - mden.coefficient(xvar, dendeg, dencoeff); - - for(size_t i = 0; numdeg.isGreaterThanOrEqualTo(dendeg); i++) { - if(i > 10000 || CALCULATOR->aborted()) { - mrem = mnum; - mquotient.clear(); - return false; - } - MathStructure numcoeff; - mrem.coefficient(xvar, numdeg, numcoeff); - numdeg -= dendeg; - if(numcoeff == dencoeff) { - if(numdeg.isZero()) { - numcoeff.set(1, 1, 0); - } else { - numcoeff = xvar; - if(!numdeg.isOne()) { - numcoeff.raise(numdeg); - } - } - } else { - if(dencoeff.isNumber()) { - if(numcoeff.isNumber()) { - numcoeff.number() /= dencoeff.number(); - } else { - numcoeff.calculateDivide(dencoeff, eo2); - } - } else { - if(for_newtonraphson) {mrem = mnum; mquotient.clear(); return false;} - MathStructure mcopy(numcoeff); - if(!MathStructure::polynomialDivide(mcopy, dencoeff, numcoeff, eo2, check_args)) { - if(CALCULATOR->aborted()) {mrem = mnum; mquotient.clear(); return false;} - break; - } - } - if(!numdeg.isZero() && !numcoeff.isZero()) { - if(numcoeff.isOne()) { - numcoeff = xvar; - if(!numdeg.isOne()) { - numcoeff.raise(numdeg); - } - } else { - numcoeff.multiply(xvar, true); - if(!numdeg.isOne()) { - numcoeff[numcoeff.size() - 1].raise(numdeg); - } - numcoeff.calculateMultiplyLast(eo2); - } - } - } - if(mquotient.isZero()) mquotient = numcoeff; - else mquotient.calculateAdd(numcoeff, eo2); - if(numcoeff.isAddition() && mden.isAddition() && numcoeff.size() * mden.size() >= (eo.expand == -1 ? 50 : 500)) {mrem = mnum; mquotient.clear(); return false;} - numcoeff.calculateMultiply(mden, eo2); - mrem.calculateSubtract(numcoeff, eo2); - if(contains_zerointerval_multiplier(mquotient)) {mrem = mnum; mquotient.clear(); return false;} - if(mrem.isZero() || (for_newtonraphson && mrem.isNumber())) break; - if(contains_zerointerval_multiplier(mrem)) {mrem = mnum; mquotient.clear(); return false;} - numdeg = mrem.degree(xvar); - } - return true; - -} - -void add_symbol(const MathStructure &mpoly, sym_desc_vec &v) { - sym_desc_vec::const_iterator it = v.begin(), itend = v.end(); - while (it != itend) { - if(it->sym == mpoly) return; - ++it; - } - sym_desc d; - d.sym = mpoly; - v.push_back(d); -} - -void collect_symbols(const MathStructure &mpoly, sym_desc_vec &v) { - if(IS_A_SYMBOL(mpoly) || mpoly.isUnit()) { - add_symbol(mpoly, v); - } else if(mpoly.isAddition() || mpoly.isMultiplication()) { - for(size_t i = 0; i < mpoly.size(); i++) collect_symbols(mpoly[i], v); - } else if(mpoly.isPower()) { - collect_symbols(mpoly[0], v); - } -} - -void add_symbol(const MathStructure &mpoly, vector &v) { - vector::const_iterator it = v.begin(), itend = v.end(); - while (it != itend) { - if(*it == mpoly) return; - ++it; - } - v.push_back(mpoly); -} - -void collect_symbols(const MathStructure &mpoly, vector &v) { - if(IS_A_SYMBOL(mpoly)) { - add_symbol(mpoly, v); - } else if(mpoly.isAddition() || mpoly.isMultiplication()) { - for(size_t i = 0; i < mpoly.size(); i++) collect_symbols(mpoly[i], v); - } else if(mpoly.isPower()) { - collect_symbols(mpoly[0], v); - } -} - -void get_symbol_stats(const MathStructure &m1, const MathStructure &m2, sym_desc_vec &v) { - collect_symbols(m1, v); - collect_symbols(m2, v); - sym_desc_vec::iterator it = v.begin(), itend = v.end(); - while(it != itend) { - it->deg_a = m1.degree(it->sym); - it->deg_b = m2.degree(it->sym); - if(it->deg_a.isGreaterThan(it->deg_b)) { - it->max_deg = it->deg_a; - } else { - it->max_deg = it->deg_b; - } - it->ldeg_a = m1.ldegree(it->sym); - it->ldeg_b = m2.ldegree(it->sym); - MathStructure mcoeff; - m1.lcoefficient(it->sym, mcoeff); - it->max_lcnops = mcoeff.size(); - m2.lcoefficient(it->sym, mcoeff); - if(mcoeff.size() > it->max_lcnops) it->max_lcnops = mcoeff.size(); - ++it; - } - std::sort(v.begin(), v.end()); - -} - -bool has_noninteger_coefficient(const MathStructure &mstruct) { - if(mstruct.isNumber() && mstruct.number().isRational() && !mstruct.number().isInteger()) return true; - if(mstruct.isFunction() || mstruct.isPower()) return false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(has_noninteger_coefficient(mstruct[i])) return true; - } - return false; -} - -bool MathStructure::gcd(const MathStructure &m1, const MathStructure &m2, MathStructure &mresult, const EvaluationOptions &eo2, MathStructure *ca, MathStructure *cb, bool check_args) { - - EvaluationOptions eo = eo2; - eo.keep_zero_units = false; - - if(ca) *ca = m1; - if(cb) *cb = m2; - mresult.set(1, 1, 0); - - if(CALCULATOR->aborted()) return false; - - if(m1.isOne() || m2.isOne()) { - return true; - } - if(m1.isNumber() && m2.isNumber()) { - mresult = m1; - if(!mresult.number().gcd(m2.number())) mresult.set(1, 1, 0); - if(ca || cb) { - if(mresult.isZero()) { - if(ca) ca->clear(); - if(cb) cb->clear(); - } else { - if(ca) { - *ca = m1; - ca->number() /= mresult.number(); - } - if(cb) { - *cb = m2; - cb->number() /= mresult.number(); - } - } - } - return true; - } - - if(m1 == m2) { - if(ca) ca->set(1, 1, 0); - if(cb) cb->set(1, 1, 0); - mresult = m1; - return true; - } - if(m1.isZero()) { - if(ca) ca->clear(); - if(cb) cb->set(1, 1, 0); - mresult = m2; - return true; - } - if(m2.isZero()) { - if(ca) ca->set(1, 1, 0); - if(cb) cb->clear(); - mresult = m1; - return true; - } - - if(check_args && (!m1.isRationalPolynomial() || !m2.isRationalPolynomial())) { - return false; - } - - if(has_noninteger_coefficient(m1) || has_noninteger_coefficient(m2)) { - Number nlcm1; - lcm_of_coefficients_denominators(m1, nlcm1); - Number nlcm2; - lcm_of_coefficients_denominators(m2, nlcm2); - nlcm1.lcm(nlcm2); - if(!nlcm1.isOne()) { - MathStructure mtmp1, mtmp2; - multiply_lcm(m1, nlcm1, mtmp1, eo); - multiply_lcm(m2, nlcm1, mtmp2, eo); - if(mtmp1.equals(m1, true, true) || mtmp2.equals(m2, true, true)) return false; - return gcd(mtmp1, mtmp2, mresult, eo, ca, cb, false); - } - } - - if(m1.isMultiplication()) { - if(m2.isMultiplication() && m2.size() > m1.size()) - goto factored_2; -factored_1: - mresult.clear(); - mresult.setType(STRUCT_MULTIPLICATION); - MathStructure acc_ca; - acc_ca.setType(STRUCT_MULTIPLICATION); - MathStructure part_2(m2); - MathStructure part_ca, part_cb; - for(size_t i = 0; i < m1.size(); i++) { - mresult.addChild(m_zero); - MathStructure::gcd(m1[i], part_2, mresult[i], eo, &part_ca, &part_cb, false); - if(CALCULATOR->aborted()) return false; - acc_ca.addChild(part_ca); - part_2 = part_cb; - } - mresult.calculatesub(eo, eo, false); - if(ca) { - *ca = acc_ca; - ca->calculatesub(eo, eo, false); - } - if(cb) *cb = part_2; - return true; - } else if(m2.isMultiplication()) { - if(m1.isMultiplication() && m1.size() > m2.size()) - goto factored_1; -factored_2: - mresult.clear(); - mresult.setType(STRUCT_MULTIPLICATION); - MathStructure acc_cb; - acc_cb.setType(STRUCT_MULTIPLICATION); - MathStructure part_1(m1); - MathStructure part_ca, part_cb; - for(size_t i = 0; i < m2.size(); i++) { - mresult.addChild(m_zero); - MathStructure::gcd(part_1, m2[i], mresult[i], eo, &part_ca, &part_cb, false); - if(CALCULATOR->aborted()) return false; - acc_cb.addChild(part_cb); - part_1 = part_ca; - } - mresult.calculatesub(eo, eo, false); - if(ca) *ca = part_1; - if(cb) { - *cb = acc_cb; - cb->calculatesub(eo, eo, false); - } - return true; - } - - if(m1.isPower()) { - MathStructure p(m1[0]); - if(m2.isPower()) { - if(m1[0] == m2[0]) { - if(m1[1].number().isLessThan(m2[1].number())) { - if(ca) ca->set(1, 1, 0); - if(cb) { - *cb = m2; - (*cb)[1].number() -= m1[1].number(); - POWER_CLEAN((*cb)) - } - mresult = m1; - return true; - } else { - if(ca) { - *ca = m1; - (*ca)[1].number() -= m2[1].number(); - POWER_CLEAN((*ca)) - } - if(cb) cb->set(1, 1, 0); - mresult = m2; - return true; - } - } else { - MathStructure p_co, pb_co; - MathStructure p_gcd; - if(!MathStructure::gcd(m1[0], m2[0], p_gcd, eo, &p_co, &pb_co, false)) return false; - if(p_gcd.isOne()) { - return true; - } else { - if(m1[1].number().isLessThan(m2[1].number())) { - mresult = p_gcd; - mresult.calculateRaise(m1[1], eo); - mresult.multiply(m_zero, true); - p_co.calculateRaise(m1[1], eo); - pb_co.calculateRaise(m2[1], eo); - p_gcd.raise(m2[1]); - p_gcd[1].number() -= m1[1].number(); - p_gcd.calculateRaiseExponent(eo); - p_gcd.calculateMultiply(pb_co, eo); - bool b = MathStructure::gcd(p_co, p_gcd, mresult[mresult.size() - 1], eo, ca, cb, false); - mresult.calculateMultiplyLast(eo); - return b; - } else { - mresult = p_gcd; - mresult.calculateRaise(m2[1], eo); - mresult.multiply(m_zero, true); - p_co.calculateRaise(m1[1], eo); - pb_co.calculateRaise(m2[1], eo); - p_gcd.raise(m1[1]); - p_gcd[1].number() -= m2[1].number(); - p_gcd.calculateRaiseExponent(eo); - p_gcd.calculateMultiply(p_co, eo); - bool b = MathStructure::gcd(p_gcd, pb_co, mresult[mresult.size() - 1], eo, ca, cb, false); - mresult.calculateMultiplyLast(eo); - return b; - } - } - } - } else { - if(m1[0] == m2) { - if(ca) { - *ca = m1; - (*ca)[1].number()--; - POWER_CLEAN((*ca)) - } - if(cb) cb->set(1, 1, 0); - mresult = m2; - return true; - } - MathStructure p_co, bpart_co; - MathStructure p_gcd; - if(!MathStructure::gcd(m1[0], m2, p_gcd, eo, &p_co, &bpart_co, false)) return false; - if(p_gcd.isOne()) { - return true; - } else { - mresult = p_gcd; - mresult.multiply(m_zero, true); - p_co.calculateRaise(m1[1], eo); - p_gcd.raise(m1[1]); - p_gcd[1].number()--; - p_gcd.calculateRaiseExponent(eo); - p_gcd.calculateMultiply(p_co, eo); - bool b = MathStructure::gcd(p_gcd, bpart_co, mresult[mresult.size() - 1], eo, ca, cb, false); - mresult.calculateMultiplyLast(eo); - return b; - } - } - } else if(m2.isPower()) { - if(m2[0] == m1) { - if(ca) ca->set(1, 1, 0); - if(cb) { - *cb = m2; - (*cb)[1].number()--; - POWER_CLEAN((*cb)) - } - mresult = m1; - return true; - } - MathStructure p_co, apart_co; - MathStructure p_gcd; - if(!MathStructure::gcd(m1, m2[0], p_gcd, eo, &apart_co, &p_co, false)) return false; - if(p_gcd.isOne()) { - return true; - } else { - mresult = p_gcd; - mresult.multiply(m_zero, true); - p_co.calculateRaise(m2[1], eo); - p_gcd.raise(m2[1]); - p_gcd[1].number()--; - p_gcd.calculateRaiseExponent(eo); - p_gcd.calculateMultiply(p_co, eo); - bool b = MathStructure::gcd(apart_co, p_gcd, mresult[mresult.size() - 1], eo, ca, cb, false); - mresult.calculateMultiplyLast(eo); - return b; - } - } - if(IS_A_SYMBOL(m1) || m1.isUnit()) { - MathStructure bex(m2); - bex.calculateReplace(m1, m_zero, eo); - if(!bex.isZero()) { - return true; - } - } - if(IS_A_SYMBOL(m2) || m2.isUnit()) { - MathStructure aex(m1); - aex.calculateReplace(m2, m_zero, eo); - if(!aex.isZero()) { - return true; - } - } - - sym_desc_vec sym_stats; - get_symbol_stats(m1, m2, sym_stats); - - if(sym_stats.empty()) return false; - - size_t var_i = 0; - const MathStructure &xvar = sym_stats[var_i].sym; - - /*for(size_t i = 0; i< sym_stats.size(); i++) { - if(sym_stats[i].sym.size() > 0) { - MathStructure m1b(m1), m2b(m2); - vector vars; - for(; i < sym_stats.size(); i++) { - if(sym_stats[i].sym.size() > 0) { - UnknownVariable *var = new UnknownVariable("", format_and_print(sym_stats[i].sym)); - m1b.replace(sym_stats[i].sym, var); - m2b.replace(sym_stats[i].sym, var); - vars.push_back(var); - } - } - bool b = gcd(m1b, m2, mresult, eo2, ca, cb, false); - size_t i2 = 0; - for(i = 0; i < sym_stats.size(); i++) { - if(sym_stats[i].sym.size() > 0) { - mresult.replace(vars[i2], sym_stats[i].sym); - if(ca) ca->replace(vars[i2], sym_stats[i].sym); - if(cb) cb->replace(vars[i2], sym_stats[i].sym); - vars[i2]->destroy(); - i2++; - } - } - return b; - } - }*/ - - Number ldeg_a(sym_stats[var_i].ldeg_a); - Number ldeg_b(sym_stats[var_i].ldeg_b); - Number min_ldeg; - if(ldeg_a.isLessThan(ldeg_b)) { - min_ldeg = ldeg_a; - } else { - min_ldeg = ldeg_b; - } - - if(min_ldeg.isPositive()) { - MathStructure aex(m1), bex(m2); - MathStructure common(xvar); - if(!min_ldeg.isOne()) common.raise(min_ldeg); - aex.calculateDivide(common, eo); - bex.calculateDivide(common, eo); - MathStructure::gcd(aex, bex, mresult, eo, ca, cb, false); - mresult.calculateMultiply(common, eo); - return true; - } - - if(sym_stats[var_i].deg_a.isZero()) { - if(cb) { - MathStructure c, mprim; - int u; - m2.polynomialUnitContentPrimpart(xvar, u, c, mprim, eo); - if(!m2.equals(c, true, true)) MathStructure::gcd(m1, c, mresult, eo, ca, cb, false); - if(CALCULATOR->aborted()) { - if(ca) *ca = m1; - if(cb) *cb = m2; - mresult.set(1, 1, 0); - return false; - } - if(u == -1) { - cb->calculateNegate(eo); - } - cb->calculateMultiply(mprim, eo); - } else { - MathStructure c; - m2.polynomialContent(xvar, c, eo); - if(!m2.equals(c, true, true)) MathStructure::gcd(m1, c, mresult, eo, ca, cb, false); - } - return true; - } else if(sym_stats[var_i].deg_b.isZero()) { - if(ca) { - MathStructure c, mprim; - int u; - m1.polynomialUnitContentPrimpart(xvar, u, c, mprim, eo); - if(!m1.equals(c, true, true)) MathStructure::gcd(c, m2, mresult, eo, ca, cb, false); - if(CALCULATOR->aborted()) { - if(ca) *ca = m1; - if(cb) *cb = m2; - mresult.set(1, 1, 0); - return false; - } - if(u == -1) { - ca->calculateNegate(eo); - } - ca->calculateMultiply(mprim, eo); - } else { - MathStructure c; - m1.polynomialContent(xvar, c, eo); - if(!m1.equals(c, true, true)) MathStructure::gcd(c, m2, mresult, eo, ca, cb, false); - } - return true; - } - - if(!heur_gcd(m1, m2, mresult, eo, ca, cb, sym_stats, var_i)) { - if(!sr_gcd(m1, m2, mresult, sym_stats, var_i, eo)) { - if(ca) *ca = m1; - if(cb) *cb = m2; - mresult.set(1, 1, 0); - return false; - } - if(!mresult.isOne()) { - if(ca) { - if(!MathStructure::polynomialDivide(m1, mresult, *ca, eo, false)) { - if(ca) *ca = m1; - if(cb) *cb = m2; - mresult.set(1, 1, 0); - return false; - } - } - if(cb) { - if(!MathStructure::polynomialDivide(m2, mresult, *cb, eo, false)) { - if(ca) *ca = m1; - if(cb) *cb = m2; - mresult.set(1, 1, 0); - return false; - } - } - } - if(CALCULATOR->aborted()) { - if(ca) *ca = m1; - if(cb) *cb = m2; - mresult.set(1, 1, 0); - return false; - } - } - - return true; -} - -bool sqrfree_differentiate(const MathStructure &mpoly, const MathStructure &x_var, MathStructure &mdiff, const EvaluationOptions &eo) { - if(mpoly == x_var) { - mdiff.set(1, 1, 0); - return true; - } - switch(mpoly.type()) { - case STRUCT_ADDITION: { - mdiff.clear(); - mdiff.setType(STRUCT_ADDITION); - for(size_t i = 0; i < mpoly.size(); i++) { - mdiff.addChild(m_zero); - if(!sqrfree_differentiate(mpoly[i], x_var, mdiff[i], eo)) return false; - } - mdiff.calculatesub(eo, eo, false); - break; - } - case STRUCT_VARIABLE: {} - case STRUCT_FUNCTION: {} - case STRUCT_SYMBOLIC: {} - case STRUCT_UNIT: {} - case STRUCT_NUMBER: { - mdiff.clear(); - break; - } - case STRUCT_POWER: { - if(mpoly[0] == x_var) { - mdiff = mpoly[1]; - mdiff.multiply(x_var); - if(!mpoly[1].number().isTwo()) { - mdiff[1].raise(mpoly[1]); - mdiff[1][1].number()--; - } - mdiff.evalSort(true); - } else { - mdiff.clear(); - } - break; - } - case STRUCT_MULTIPLICATION: { - if(mpoly.size() < 1) { - mdiff.clear(); - break; - } else if(mpoly.size() < 2) { - return sqrfree_differentiate(mpoly[0], x_var, mdiff, eo); - } - mdiff.clear(); - for(size_t i = 0; i < mpoly.size(); i++) { - if(mpoly[i] == x_var) { - if(mpoly.size() == 2) { - if(i == 0) mdiff = mpoly[1]; - else mdiff = mpoly[0]; - } else { - mdiff.setType(STRUCT_MULTIPLICATION); - for(size_t i2 = 0; i2 < mpoly.size(); i2++) { - if(i2 != i) { - mdiff.addChild(mpoly[i2]); - } - } - } - break; - } else if(mpoly[i].isPower() && mpoly[i][0] == x_var) { - mdiff = mpoly; - if(mpoly[i][1].number().isTwo()) { - mdiff[i].setToChild(1); - } else { - mdiff[i][1].number()--; - } - if(mdiff[0].isNumber()) { - mdiff[0].number() *= mpoly[i][1].number(); - } else { - mdiff.insertChild(mpoly[i][1].number(), 1); - } - mdiff.evalSort(); - break; - } - } - break; - } - default: { - return false; - } - } - return true; -} -bool fix_root_pow(MathStructure &m, const MathStructure &xvar, const EvaluationOptions &eo) { - if(m.isPower() && m[0].contains(xvar) && m[1].isNumber()) { - return m.calculateRaiseExponent(eo); - } - bool b_ret = false; - for(size_t i = 0; i < m.size(); i++) { - if(fix_root_pow(m[i], xvar, eo)) {m.childUpdated(i + 1); b_ret = true;} - } - if(b_ret) m.calculatesub(eo, eo, false); - return b_ret; -} - -bool sqrfree_yun(const MathStructure &a, const MathStructure &xvar, MathStructure &factors, const EvaluationOptions &eo) { - MathStructure w(a); - MathStructure z; - if(!sqrfree_differentiate(a, xvar, z, eo)) { - return false; - } - MathStructure g; - if(!MathStructure::gcd(w, z, g, eo)) { - return false; - } - if(g.isOne()) { - factors.addChild(a); - return true; - } - MathStructure y; - MathStructure tmp; - do { - tmp = w; - if(!MathStructure::polynomialQuotient(tmp, g, xvar, w, eo)) { - return false; - } - if(!MathStructure::polynomialQuotient(z, g, xvar, y, eo)) { - return false; - } - if(!sqrfree_differentiate(w, xvar, tmp, eo)) { - return false; - } - z = y; - z.calculateSubtract(tmp, eo); - if(!MathStructure::gcd(w, z, g, eo)) { - return false; - } - factors.addChild(g); - } while (!z.isZero()); - return true; -} - -bool sqrfree_simple(const MathStructure &a, const MathStructure &xvar, MathStructure &factors, const EvaluationOptions &eo) { - MathStructure w(a); - size_t i = 0; - while(true) { - MathStructure z, zmod; - if(!sqrfree_differentiate(w, xvar, z, eo)) return false; - polynomial_smod(z, nr_three, zmod, eo); - if(z == w) { - factors.addChild(w); - break; - } - MathStructure mgcd; - if(!MathStructure::gcd(w, z, mgcd, eo)) return false; - if(mgcd.isOne() || mgcd == w) { - factors.addChild(w); - break; - } - MathStructure tmp(w); - if(!MathStructure::polynomialQuotient(tmp, mgcd, xvar, w, eo)) return false; - if(!sqrfree_simple(mgcd, xvar, factors, eo)) return false; - i++; - } - return true; -} - -void lcmcoeff(const MathStructure &e, const Number &l, Number &nlcm); -void lcmcoeff(const MathStructure &e, const Number &l, Number &nlcm) { - if(e.isNumber() && e.number().isRational()) { - nlcm = e.number().denominator(); - nlcm.lcm(l); - } else if(e.isAddition()) { - nlcm.set(1, 1, 0); - for(size_t i = 0; i < e.size(); i++) { - Number c(nlcm); - lcmcoeff(e[i], c, nlcm); - } - nlcm.lcm(l); - } else if(e.isMultiplication()) { - nlcm.set(1, 1, 0); - for(size_t i = 0; i < e.size(); i++) { - Number c(nlcm); - lcmcoeff(e[i], nr_one, c); - nlcm *= c; - } - nlcm.lcm(l); - } else if(e.isPower()) { - if(IS_A_SYMBOL(e[0]) || e[0].isUnit()) { - nlcm = l; - } else { - lcmcoeff(e[0], l, nlcm); - nlcm ^= e[1].number(); - } - } else { - nlcm = l; - } -} - -void lcm_of_coefficients_denominators(const MathStructure &e, Number &nlcm) { - return lcmcoeff(e, nr_one, nlcm); -} - -void multiply_lcm(const MathStructure &e, const Number &lcm, MathStructure &mmul, const EvaluationOptions &eo) { - if(e.isMultiplication()) { - Number lcm_accum(1, 1); - mmul.clear(); - for(size_t i = 0; i < e.size(); i++) { - Number op_lcm; - lcmcoeff(e[i], nr_one, op_lcm); - if(mmul.isZero()) { - multiply_lcm(e[i], op_lcm, mmul, eo); - if(mmul.isOne()) mmul.clear(); - } else { - mmul.multiply(m_one, true); - multiply_lcm(e[i], op_lcm, mmul[mmul.size() - 1], eo); - if(mmul[mmul.size() - 1].isOne()) { - mmul.delChild(i + 1); - if(mmul.size() == 1) mmul.setToChild(1); - } - } - lcm_accum *= op_lcm; - } - Number lcm2(lcm); - lcm2 /= lcm_accum; - if(mmul.isZero()) { - mmul = lcm2; - } else if(!lcm2.isOne()) { - if(mmul.size() > 0 && mmul[0].isNumber()) { - mmul[0].number() *= lcm2; - } else { - mmul.multiply(lcm2, true); - } - } - mmul.evalSort(); - } else if(e.isAddition()) { - mmul.clear(); - for (size_t i = 0; i < e.size(); i++) { - if(mmul.isZero()) { - multiply_lcm(e[i], lcm, mmul, eo); - } else { - mmul.add(m_zero, true); - multiply_lcm(e[i], lcm, mmul[mmul.size() - 1], eo); - } - } - mmul.evalSort(); - } else if(e.isPower()) { - if(IS_A_SYMBOL(e[0]) || e[0].isUnit()) { - mmul = e; - if(!lcm.isOne()) { - mmul *= lcm; - mmul.evalSort(); - } - } else { - mmul = e; - Number lcm_exp = e[1].number(); - lcm_exp.recip(); - multiply_lcm(e[0], lcm ^ lcm_exp, mmul[0], eo); - if(mmul[0] != e[0]) { - mmul.calculatesub(eo, eo, false); - } - } - } else if(e.isNumber()) { - mmul = e; - mmul.number() *= lcm; - } else if(IS_A_SYMBOL(e) || e.isUnit()) { - mmul = e; - if(!lcm.isOne()) { - mmul *= lcm; - mmul.evalSort(); - } - } else { - mmul = e; - if(!lcm.isOne()) { - mmul.calculateMultiply(lcm, eo); - mmul.evalSort(); - } - } -} - -//from GiNaC -bool sqrfree(MathStructure &mpoly, const EvaluationOptions &eo) { - vector symbols; - collect_symbols(mpoly, symbols); - return sqrfree(mpoly, symbols, eo); -} -bool sqrfree(MathStructure &mpoly, const vector &symbols, const EvaluationOptions &eo) { - - EvaluationOptions eo2 = eo; - eo2.assume_denominators_nonzero = true; - eo2.warn_about_denominators_assumed_nonzero = false; - eo2.reduce_divisions = true; - eo2.keep_zero_units = false; - eo2.do_polynomial_division = false; - eo2.sync_units = false; - eo2.expand = true; - eo2.calculate_functions = false; - eo2.protected_function = CALCULATOR->f_signum; - - if(mpoly.size() == 0) { - return true; - } - if(symbols.empty()) return true; - - size_t symbol_index = 0; - if(symbols.size() > 1) { - for(size_t i = 1; i < symbols.size(); i++) { - if(mpoly.degree(symbols[symbol_index]).isGreaterThan(mpoly.degree(symbols[i]))) symbol_index = i; - } - } - - MathStructure xvar(symbols[symbol_index]); - - UnknownVariable *var = NULL; - if(xvar.size() > 0) { - var = new UnknownVariable("", format_and_print(xvar)); - var->setAssumptions(xvar); - mpoly.replace(xvar, var); - xvar = var; - } - - Number nlcm; - lcm_of_coefficients_denominators(mpoly, nlcm); - - MathStructure tmp; - multiply_lcm(mpoly, nlcm, tmp, eo2); - - MathStructure factors; - factors.clearVector(); - - if(!sqrfree_yun(tmp, xvar, factors, eo2)) { - if(var) tmp.replace(var, symbols[symbol_index]); - factors.clearVector(); - factors.addChild(tmp); - } else { - if(var) tmp.replace(var, symbols[symbol_index]); - } - if(var) {mpoly.replace(var, symbols[symbol_index]); var->destroy();} - - vector newsymbols; - for(size_t i = 0; i < symbols.size(); i++) { - if(i != symbol_index) newsymbols.push_back(symbols[i]); - } - - if(newsymbols.size() > 0) { - for(size_t i = 0; i < factors.size(); i++) { - if(!sqrfree(factors[i], newsymbols, eo)) return false; - } - } - - mpoly.set(1, 1, 0); - for(size_t i = 0; i < factors.size(); i++) { - if(CALCULATOR->aborted()) return false; - if(!factors[i].isOne()) { - if(mpoly.isOne()) { - mpoly = factors[i]; - if(i != 0) mpoly.raise(MathStructure((long int) i + 1, 1L, 0L)); - } else { - mpoly.multiply(factors[i], true); - mpoly[mpoly.size() - 1].raise(MathStructure((long int) i + 1, 1L, 0L)); - } - } - } - - if(CALCULATOR->aborted()) return false; - if(mpoly.isZero()) { - CALCULATOR->error(true, "mpoly is zero: %s. %s", format_and_print(tmp).c_str(), _("This is a bug. Please report it."), NULL); - return false; - } - MathStructure mquo; - MathStructure mpoly_expand(mpoly); - EvaluationOptions eo3 = eo; - eo3.expand = true; - mpoly_expand.calculatesub(eo3, eo3); - - MathStructure::polynomialQuotient(tmp, mpoly_expand, xvar, mquo, eo2); - - if(CALCULATOR->aborted()) return false; - if(mquo.isZero()) { - //CALCULATOR->error(true, "quo is zero: %s. %s", format_and_print(tmp).c_str(), _("This is a bug. Please report it."), NULL); - return false; - } - if(newsymbols.size() > 0) { - if(!sqrfree(mquo, newsymbols, eo)) return false; - } - if(!mquo.isOne()) { - mpoly.multiply(mquo, true); - } - if(!nlcm.isOne()) { - nlcm.recip(); - mpoly.multiply(nlcm, true); - } - - eo3.expand = false; - mpoly.calculatesub(eo3, eo3, false); - - return true; - -} - -bool MathStructure::integerFactorize() { - if(!isNumber()) return false; - vector factors; - if(!o_number.factorize(factors)) return false; - if(factors.size() <= 1) return true; - clear(true); - bool b_pow = false; - Number *lastnr = NULL; - for(size_t i = 0; i < factors.size(); i++) { - if(lastnr && factors[i] == *lastnr) { - if(!b_pow) { - LAST.raise(m_one); - b_pow = true; - } - LAST[1].number()++; - } else { - APPEND(factors[i]); - b_pow = false; - } - lastnr = &factors[i]; - } - m_type = STRUCT_MULTIPLICATION; - return true; -} -size_t count_powers(const MathStructure &mstruct) { - if(mstruct.isPower()) { - if(mstruct[1].isInteger()) { - bool overflow = false; - int c = mstruct.number().intValue(&overflow) - 1; - if(overflow) return 0; - if(c < 0) return -c; - return c; - } - } - size_t c = 0; - for(size_t i = 0; i < mstruct.size(); i++) { - c += count_powers(mstruct[i]); - } - return c; -} - -bool gather_factors(const MathStructure &mstruct, const MathStructure &x_var, MathStructure &madd, MathStructure &mmul, MathStructure &mexp, bool mexp_as_x2 = false) { - madd.clear(); - if(mexp_as_x2) mexp = m_zero; - else mexp = m_one; - mmul = m_zero; - if(mstruct == x_var) { - mmul = m_one; - return true; - } else if(mexp_as_x2 && mstruct.isPower()) { - if(mstruct[1].isNumber() && mstruct[1].number().isTwo() && mstruct[0] == x_var) { - mexp = m_one; - return true; - } - } else if(!mexp_as_x2 && mstruct.isPower() && mstruct[1].isInteger() && mstruct[0] == x_var) { - if(mstruct[0] == x_var) { - mexp = mstruct[1]; - mmul = m_one; - return true; - } - } else if(mstruct.isMultiplication() && mstruct.size() >= 2) { - bool b_x = false; - bool b2 = false; - size_t i_x = 0; - for(size_t i = 0; i < mstruct.size(); i++) { - if(!b_x && mstruct[i] == x_var) { - b_x = true; - i_x = i; - } else if(!b_x && mexp_as_x2 && mstruct[i].isPower() && mstruct[i][1].isNumber() && mstruct[i][1].number().isTwo() && mstruct[i][0] == x_var) { - b_x = true; - b2 = true; - i_x = i; - } else if(!b_x && !mexp_as_x2 && mstruct[i].isPower() && mstruct[i][1].isInteger() && mstruct[i][0] == x_var) { - b_x = true; - i_x = i; - mexp = mstruct[i][1]; - } else if(mstruct[i].containsRepresentativeOf(x_var, true, true) != 0) { - return false; - } - } - if(!b_x) return false; - if(mstruct.size() == 1) { - if(b2) mexp = m_one; - else mmul = m_one; - } else if(mstruct.size() == 2) { - if(b2) { - if(i_x == 1) mexp = mstruct[0]; - else mexp = mstruct[1]; - } else { - if(i_x == 1) mmul = mstruct[0]; - else mmul = mstruct[1]; - } - } else { - if(b2) { - mexp = mstruct; - mexp.delChild(i_x + 1, true); - } else { - mmul = mstruct; - mmul.delChild(i_x + 1, true); - } - } - return true; - } else if(mstruct.isAddition()) { - mmul.setType(STRUCT_ADDITION); - if(mexp_as_x2) mexp.setType(STRUCT_ADDITION); - madd.setType(STRUCT_ADDITION); - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i] == x_var) { - if(mexp_as_x2 || mexp.isOne()) mmul.addChild(m_one); - else return false; - } else if(mexp_as_x2 && mstruct[i].isPower() && mstruct[i][1].isNumber() && mstruct[i][1].number().isTwo() && mstruct[i][0] == x_var) { - mexp.addChild(m_one); - } else if(!mexp_as_x2 && mstruct[i].isPower() && mstruct[i][1].isInteger() && mstruct[i][0] == x_var) { - if(mmul.size() == 0) { - mexp = mstruct[i][1]; - } else if(mexp != mstruct[i][1]) { - return false; - } - mmul.addChild(m_one); - } else if(mstruct[i].isMultiplication()) { - bool b_x = false; - bool b2 = false; - size_t i_x = 0; - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - if(!b_x && mstruct[i][i2] == x_var) { - if(!mexp_as_x2 && !mexp.isOne()) return false; - i_x = i2; - b_x = true; - } else if(!b_x && mexp_as_x2 && mstruct[i][i2].isPower() && mstruct[i][i2][1].isNumber() && mstruct[i][i2][1].number().isTwo() && mstruct[i][i2][0] == x_var) { - b2 = true; - i_x = i2; - b_x = true; - } else if(!b_x && !mexp_as_x2 && mstruct[i][i2].isPower() && mstruct[i][i2][1].isInteger() && mstruct[i][i2][0] == x_var) { - if(mmul.size() == 0) { - mexp = mstruct[i][i2][1]; - } else if(mexp != mstruct[i][i2][1]) { - return false; - } - i_x = i2; - b_x = true; - } else if(mstruct[i][i2].containsRepresentativeOf(x_var, true, true) != 0) { - return false; - } - } - if(b_x) { - if(mstruct[i].size() == 1) { - if(b2) mexp.addChild(m_one); - else mmul.addChild(m_one); - } else { - if(b2) { - mexp.addChild(mstruct[i]); - mexp[mexp.size() - 1].delChild(i_x + 1, true); - mexp.childUpdated(mexp.size()); - } else { - mmul.addChild(mstruct[i]); - mmul[mmul.size() - 1].delChild(i_x + 1, true); - mmul.childUpdated(mmul.size()); - } - } - } else { - madd.addChild(mstruct[i]); - } - } else if(mstruct[i].containsRepresentativeOf(x_var, true, true) != 0) { - return false; - } else { - madd.addChild(mstruct[i]); - } - } - if(mmul.size() == 0 && (!mexp_as_x2 || mexp.size() == 0)) { - mmul.clear(); - if(mexp_as_x2) mexp.clear(); - return false; - } - if(mmul.size() == 0) mmul.clear(); - else if(mmul.size() == 1) mmul.setToChild(1); - if(mexp_as_x2) { - if(mexp.size() == 0) mexp.clear(); - else if(mexp.size() == 1) mexp.setToChild(1); - } - if(madd.size() == 0) madd.clear(); - else if(madd.size() == 1) madd.setToChild(1); - return true; - } - return false; -} - -bool MathStructure::factorize(const EvaluationOptions &eo_pre, bool unfactorize, int term_combination_levels, int max_msecs, bool only_integers, int recursive, struct timeval *endtime_p, const MathStructure &force_factorization, bool complete_square, bool only_sqrfree, int max_factor_degree) { - - if(CALCULATOR->aborted()) return false; - struct timeval endtime; - if(max_msecs > 0 && !endtime_p) { -#ifndef CLOCK_MONOTONIC - gettimeofday(&endtime, NULL); -#else - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - endtime.tv_sec = ts.tv_sec; - endtime.tv_usec = ts.tv_nsec / 1000; -#endif - endtime.tv_sec += max_msecs / 1000; - long int usecs = endtime.tv_usec + (long int) (max_msecs % 1000) * 1000; - if(usecs >= 1000000) { - usecs -= 1000000; - endtime.tv_sec++; - } - endtime.tv_usec = usecs; - max_msecs = 0; - endtime_p = &endtime; - } - - EvaluationOptions eo = eo_pre; - eo.sync_units = false; - eo.structuring = STRUCTURING_NONE; - if(unfactorize) { - unformat(eo_pre); - EvaluationOptions eo2 = eo; - eo2.expand = true; - eo2.combine_divisions = false; - eo2.sync_units = false; - calculatesub(eo2, eo2); - do_simplification(*this, eo, true, false, true); - } else if(term_combination_levels && isAddition()) { - MathStructure *mdiv = new MathStructure; - mdiv->setType(STRUCT_ADDITION); - for(size_t i = 0; i < SIZE; ) { - bool b = false; - if(CHILD(i).isMultiplication()) { - for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { - if(CHILD(i)[i2].isPower() && CHILD(i)[i2][1].hasNegativeSign()) { - b = true; - break; - } - } - } else if(CHILD(i).isPower() && CHILD(i)[1].hasNegativeSign()) { - b = true; - } - if(b) { - CHILD(i).ref(); - mdiv->addChild_nocopy(&CHILD(i)); - ERASE(i) - } else { - i++; - } - } - if(mdiv->size() > 0) { - bool b_ret = false; - if(SIZE == 1 && recursive) { - b_ret = CHILD(0).factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - } else if(SIZE > 1) { - b_ret = factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - } - if(mdiv->size() > 1) { - // 5/y + x/y + z = (5 + x)/y + z - MathStructure mstruct_units(*mdiv); - MathStructure mstruct_new(*mdiv); - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(mstruct_units[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct_units[i].size();) { - if(!mstruct_units[i][i2].isPower() || !mstruct_units[i][i2][1].hasNegativeSign()) { - mstruct_units[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); - else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); - for(size_t i2 = 0; i2 < mstruct_new[i].size();) { - if(mstruct_new[i][i2].isPower() && mstruct_new[i][i2][1].hasNegativeSign()) { - mstruct_new[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); - else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); - } else if(mstruct_new[i].isPower() && mstruct_new[i][1].hasNegativeSign()) { - mstruct_new[i].set(1, 1, 0); - } else { - mstruct_units[i].setUndefined(); - } - } - bool b = false; - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(!mstruct_units[i].isUndefined()) { - for(size_t i2 = i + 1; i2 < mstruct_units.size();) { - if(mstruct_units[i2] == mstruct_units[i]) { - mstruct_new[i].add(mstruct_new[i2], true); - mstruct_new.delChild(i2 + 1); - mstruct_units.delChild(i2 + 1); - b = true; - } else { - i2++; - } - } - if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); - else mstruct_new[i].multiply(mstruct_units[i], true); - } - } - if(b) { - if(mstruct_new.size() == 1) { - mdiv->set_nocopy(mstruct_new[0], true); - } else { - mdiv->set_nocopy(mstruct_new); - } - b_ret = true; - } - } - size_t index = 1; - if(isAddition()) index = SIZE; - if(index == 0) { - set_nocopy(*mdiv); - } else if(mdiv->isAddition()) { - for(size_t i = 0; i < mdiv->size(); i++) { - (*mdiv)[i].ref(); - add_nocopy(&(*mdiv)[i], true); - } - mdiv->unref(); - } else { - add_nocopy(mdiv, true); - } - if(recursive) { - for(; index < SIZE; index++) { - b_ret = CHILD(index).factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree) || b_ret; - } - } - return b_ret; - } - mdiv->unref(); - } - - MathStructure mden, mnum; - evalSort(true); - - if(term_combination_levels >= -1 && isAddition() && isRationalPolynomial()) { - MathStructure msqrfree(*this); - eo.protected_function = CALCULATOR->f_signum; - if(sqrfree(msqrfree, eo)) { - if((!only_sqrfree || msqrfree.isPower()) && !equals(msqrfree) && (!msqrfree.isMultiplication() || msqrfree.size() != 2 || (!(msqrfree[0].isNumber() && msqrfree[1].isAddition()) && !(msqrfree[1].isNumber() && msqrfree[0].isAddition())))) { - MathStructure mcopy(msqrfree); - EvaluationOptions eo2 = eo; - eo2.expand = true; - eo2.calculate_functions = false; - CALCULATOR->beginTemporaryStopMessages(); - mcopy.calculatesub(eo2, eo2); - CALCULATOR->endTemporaryStopMessages(); - bool b_equal = equals(mcopy); - if(!b_equal && !CALCULATOR->aborted()) { - MathStructure mcopy2(*this); - CALCULATOR->beginTemporaryStopMessages(); - mcopy.calculatesub(eo2, eo2, true); - mcopy2.calculatesub(eo2, eo2, true); - CALCULATOR->endTemporaryStopMessages(); - b_equal = mcopy.equals(mcopy2); - } - if(!b_equal) { - eo.protected_function = eo_pre.protected_function; - if(CALCULATOR->aborted()) return false; - CALCULATOR->error(true, "factorized result is wrong: %s != %s. %s", format_and_print(msqrfree).c_str(), format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); - } else { - eo.protected_function = eo_pre.protected_function; - set(msqrfree); - if(!isAddition()) { - if(isMultiplication()) flattenMultiplication(*this); - if(isMultiplication() && SIZE >= 2 && CHILD(0).isNumber()) { - for(size_t i = 1; i < SIZE; i++) { - if(CHILD(i).isNumber()) { - CHILD(i).number() *= CHILD(0).number(); - CHILD(0).set(CHILD(i)); - delChild(i); - } else if(CHILD(i).isPower() && CHILD(i)[0].isMultiplication() && CHILD(i)[0].size() >= 2 && CHILD(i)[0][0].isNumber() && CHILD(i)[0][0].number().isRational() && !CHILD(i)[0][0].number().isInteger() && CHILD(i)[1].isInteger()) { - CHILD(i)[0][0].number().raise(CHILD(i)[1].number()); - CHILD(0).number().multiply(CHILD(i)[0][0].number()); - CHILD(i)[0].delChild(1); - if(CHILD(i)[0].size() == 1) CHILD(i)[0].setToChild(1, true); - } - } - if(SIZE > 1 && CHILD(0).isOne()) { - ERASE(0); - } - if(SIZE == 1) SET_CHILD_MAP(0); - } - if(isMultiplication() && SIZE >= 2 && CHILD(0).isNumber() && CHILD(0).number().isRational() && !CHILD(0).number().isInteger()) { - Number den = CHILD(0).number().denominator(); - for(size_t i = 1; i < SIZE; i++) { - if(CHILD(i).isAddition()) { - bool b = true; - for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { - if(CHILD(i)[i2].isNumber()) { - if(!CHILD(i)[i2].number().isIntegerDivisible(den)) {b = false; break;} - } else if(CHILD(i)[i2].isMultiplication() && CHILD(i)[i2][0].isNumber()) { - if(!CHILD(i)[i2][0].number().isIntegerDivisible(den)) {b = false; break;} - } else { - b = false; - break; - } - } - if(b) { - for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { - if(CHILD(i)[i2].isNumber()) { - CHILD(i)[i2].number().divide(den); - } else if(CHILD(i)[i2].isMultiplication()) { - CHILD(i)[i2][0].number().divide(den); - if(CHILD(i)[i2][0].isOne() && CHILD(i)[i2].size() > 1) { - CHILD(i)[i2].delChild(1); - if(CHILD(i)[i2].size() == 1) { - CHILD(i)[i2].setToChild(1, true); - } - } - } - } - CHILD(0).set(CHILD(0).number().numerator(), true); - if(SIZE > 1 && CHILD(0).isOne()) { - ERASE(0); - } - if(SIZE == 1) SET_CHILD_MAP(0); - break; - } - } - } - } - if(isMultiplication()) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isPower() && CHILD(i)[1].isInteger()) { - if(CHILD(i)[0].isAddition()) { - bool b = true; - for(size_t i2 = 0; i2 < CHILD(i)[0].size(); i2++) { - if((!CHILD(i)[0][i2].isNumber() || !CHILD(i)[0][i2].number().isNegative()) && (!CHILD(i)[0][i2].isMultiplication() || CHILD(i)[0][i2].size() < 2 || !CHILD(i)[0][i2][0].isNumber() || !CHILD(i)[0][i2][0].number().isNegative())) { - b = false; - break; - } - } - if(b) { - for(size_t i2 = 0; i2 < CHILD(i)[0].size(); i2++) { - if(CHILD(i)[0][i2].isNumber()) { - CHILD(i)[0][i2].number().negate(); - } else { - CHILD(i)[0][i2][0].number().negate(); - if(CHILD(i)[0][i2][0].isOne() && CHILD(i)[0][i2].size() > 1) { - CHILD(i)[0][i2].delChild(1); - if(CHILD(i)[0][i2].size() == 1) { - CHILD(i)[0][i2].setToChild(1, true); - } - } - } - } - if(CHILD(i)[1].number().isOdd()) { - if(CHILD(0).isNumber()) CHILD(0).number().negate(); - else { - PREPEND(MathStructure(-1, 1, 0)); - i++; - } - } - } - } else if(CHILD(i)[0].isMultiplication() && CHILD(i)[0].size() >= 2 && CHILD(i)[0][0].isNumber() && CHILD(i)[0][0].number().isNegative()) { - CHILD(i)[0][0].number().negate(); - if(CHILD(i)[0][0].isOne() && CHILD(i)[0].size() > 1) { - CHILD(i)[0].delChild(1); - if(CHILD(i)[0].size() == 1) { - CHILD(i)[0].setToChild(1, true); - } - } - if(CHILD(i)[1].number().isOdd()) { - if(CHILD(0).isNumber()) CHILD(0).number().negate(); - else { - PREPEND(MathStructure(-1, 1, 0)); - i++; - } - } - } - } else if(CHILD(i).isAddition()) { - bool b = true; - for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { - if((!CHILD(i)[i2].isNumber() || !CHILD(i)[i2].number().isNegative()) && (!CHILD(i)[i2].isMultiplication() || CHILD(i)[i2].size() < 2 || !CHILD(i)[i2][0].isNumber() || !CHILD(i)[i2][0].number().isNegative())) { - b = false; - break; - } - } - if(b) { - for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { - if(CHILD(i)[i2].isNumber()) { - CHILD(i)[i2].number().negate(); - } else { - CHILD(i)[i2][0].number().negate(); - if(CHILD(i)[i2][0].isOne() && CHILD(i)[i2].size() > 1) { - CHILD(i)[i2].delChild(1); - if(CHILD(i)[i2].size() == 1) { - CHILD(i)[i2].setToChild(1, true); - } - } - } - } - if(CHILD(0).isNumber()) CHILD(0).number().negate(); - else { - PREPEND(MathStructure(-1, 1, 0)); - i++; - } - } - } - } - if(SIZE > 1 && CHILD(0).isOne()) { - ERASE(0); - } - if(SIZE == 1) SET_CHILD_MAP(0); - } - if(isPower() && CHILD(1).isInteger()) { - if(CHILD(0).isAddition()) { - bool b = true; - for(size_t i2 = 0; i2 < CHILD(0).size(); i2++) { - if((!CHILD(0)[i2].isNumber() || !CHILD(0)[i2].number().isNegative()) && (!CHILD(0)[i2].isMultiplication() || CHILD(0)[i2].size() < 2 || !CHILD(0)[i2][0].isNumber() || !CHILD(0)[i2][0].number().isNegative())) { - b = false; - break; - } - } - if(b) { - for(size_t i2 = 0; i2 < CHILD(0).size(); i2++) { - if(CHILD(0)[i2].isNumber()) { - CHILD(0)[i2].number().negate(); - } else { - CHILD(0)[i2][0].number().negate(); - if(CHILD(0)[i2][0].isOne() && CHILD(0)[i2].size() > 1) { - CHILD(0)[i2].delChild(1); - if(CHILD(0)[i2].size() == 1) { - CHILD(0)[i2].setToChild(1, true); - } - } - } - } - if(CHILD(1).number().isOdd()) { - multiply(MathStructure(-1, 1, 0)); - CHILD_TO_FRONT(1) - } - } - } else if(CHILD(0).isMultiplication() && CHILD(0).size() >= 2 && CHILD(0)[0].isNumber() && CHILD(0)[0].number().isNegative()) { - CHILD(0)[0].number().negate(); - if(CHILD(0)[0].isOne() && CHILD(0).size() > 1) { - CHILD(0).delChild(1); - if(CHILD(0).size() == 1) { - CHILD(0).setToChild(1, true); - } - } - if(CHILD(1).number().isOdd()) { - multiply(MathStructure(-1, 1, 0)); - CHILD_TO_FRONT(1) - } - } - } - } - evalSort(true); - factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - return true; - } - } - } - eo.protected_function = eo_pre.protected_function; - } - - switch(type()) { - case STRUCT_ADDITION: { - - if(CALCULATOR->aborted()) return false; - if(term_combination_levels >= -1 && !only_sqrfree && max_factor_degree != 0) { - - if(SIZE <= 3 && SIZE > 1) { - MathStructure *xvar = NULL; - Number nr2(1, 1); - if(CHILD(0).isPower() && CHILD(0)[0].size() == 0 && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isTwo()) { - xvar = &CHILD(0)[0]; - } else if(CHILD(0).isMultiplication() && CHILD(0).size() == 2 && CHILD(0)[0].isNumber()) { - if(CHILD(0)[1].isPower()) { - if(CHILD(0)[1][0].size() == 0 && CHILD(0)[1][1].isNumber() && CHILD(0)[1][1].number().isTwo()) { - xvar = &CHILD(0)[1][0]; - nr2.set(CHILD(0)[0].number()); - } - } - } - if(xvar) { - bool factorable = false; - Number nr1, nr0; - if(SIZE == 2 && CHILD(1).isNumber()) { - factorable = true; - nr0 = CHILD(1).number(); - } else if(SIZE == 3 && CHILD(2).isNumber()) { - nr0 = CHILD(2).number(); - if(CHILD(1).isMultiplication()) { - if(CHILD(1).size() == 2 && CHILD(1)[0].isNumber() && xvar->equals(CHILD(1)[1])) { - nr1 = CHILD(1)[0].number(); - factorable = true; - } - } else if(xvar->equals(CHILD(1))) { - nr1.set(1, 1, 0); - factorable = true; - } - } - if(factorable) { - Number nr4ac(4, 1, 0); - nr4ac *= nr2; - nr4ac *= nr0; - Number nr2a(2, 1, 0); - nr2a *= nr2; - Number sqrtb24ac(nr1); - sqrtb24ac.raise(nr_two); - sqrtb24ac -= nr4ac; - if(sqrtb24ac.isNegative()) factorable = false; - MathStructure mstructb24(sqrtb24ac); - if(factorable) { - if(!only_integers) { - if(eo.approximation == APPROXIMATION_EXACT && !sqrtb24ac.isApproximate()) { - sqrtb24ac.raise(nr_half); - if(sqrtb24ac.isApproximate()) { - mstructb24.raise(nr_half); - } else { - mstructb24.set(sqrtb24ac); - } - } else { - mstructb24.number().raise(nr_half); - } - } else { - mstructb24.number().raise(nr_half); - if((!sqrtb24ac.isApproximate() && mstructb24.number().isApproximate()) || (sqrtb24ac.isInteger() && !mstructb24.number().isInteger())) { - factorable = false; - } - } - } - if(factorable) { - MathStructure m1(nr1), m2(nr1); - Number mul1(1, 1), mul2(1, 1); - if(mstructb24.isNumber()) { - m1.number() += mstructb24.number(); - m1.number() /= nr2a; - if(m1.number().isRational() && !m1.number().isInteger()) { - mul1 = m1.number().denominator(); - m1.number() *= mul1; - } - m2.number() -= mstructb24.number(); - m2.number() /= nr2a; - if(m2.number().isRational() && !m2.number().isInteger()) { - mul2 = m2.number().denominator(); - m2.number() *= mul2; - } - } else { - m1.calculateAdd(mstructb24, eo); - m1.calculateDivide(nr2a, eo); - if(m1.isNumber()) { - if(m1.number().isRational() && !m1.number().isInteger()) { - mul1 = m1.number().denominator(); - m1.number() *= mul1; - } - } else { - bool bint = false, bfrac = false; - idm1(m1, bfrac, bint); - if(bfrac) { - idm2(m1, bfrac, bint, mul1); - idm3(m1, mul1, true); - } - } - m2.calculateSubtract(mstructb24, eo); - m2.calculateDivide(nr2a, eo); - if(m2.isNumber()) { - if(m2.number().isRational() && !m2.number().isInteger()) { - mul2 = m2.number().denominator(); - m2.number() *= mul2; - } - } else { - bool bint = false, bfrac = false; - idm1(m2, bfrac, bint); - if(bfrac) { - idm2(m2, bfrac, bint, mul2); - idm3(m2, mul2, true); - } - } - } - nr2 /= mul1; - nr2 /= mul2; - if(m1 == m2 && mul1 == mul2) { - MathStructure xvar2(*xvar); - if(!mul1.isOne()) xvar2 *= mul1; - set(m1); - add(xvar2, true); - raise(MathStructure(2, 1, 0)); - if(!nr2.isOne()) { - multiply(nr2); - } - } else { - m1.add(*xvar, true); - if(!mul1.isOne()) m1[m1.size() - 1] *= mul1; - m2.add(*xvar, true); - if(!mul2.isOne()) m2[m2.size() - 1] *= mul2; - clear(true); - m_type = STRUCT_MULTIPLICATION; - if(!nr2.isOne()) { - APPEND_NEW(nr2); - } - APPEND(m1); - APPEND(m2); - } - EvaluationOptions eo2 = eo; - eo2.expand = false; - calculatesub(eo2, eo2, false); - evalSort(true); - return true; - } - } - } - } - - MathStructure *factor_mstruct = new MathStructure(1, 1, 0); - MathStructure mnew; - if(factorize_find_multiplier(*this, mnew, *factor_mstruct) && !factor_mstruct->isZero() && !mnew.isZero()) { - mnew.factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - factor_mstruct->factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - clear(true); - m_type = STRUCT_MULTIPLICATION; - APPEND_REF(factor_mstruct); - APPEND(mnew); - EvaluationOptions eo2 = eo; - eo2.expand = false; - calculatesub(eo2, eo2, false); - factor_mstruct->unref(); - evalSort(true); - return true; - } - factor_mstruct->unref(); - - if(SIZE > 1 && CHILD(SIZE - 1).isNumber() && CHILD(SIZE - 1).number().isInteger() && max_factor_degree != 0) { - MathStructure *xvar = NULL; - Number qnr(1, 1); - int degree = 1; - bool overflow = false; - int qcof = 1; - if(CHILD(0).isPower() && !CHILD(0)[0].isNumber() && CHILD(0)[0].size() == 0 && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isInteger() && CHILD(0)[1].number().isPositive()) { - xvar = &CHILD(0)[0]; - degree = CHILD(0)[1].number().intValue(&overflow); - } else if(CHILD(0).isMultiplication() && CHILD(0).size() == 2 && CHILD(0)[0].isNumber() && CHILD(0)[0].number().isInteger()) { - if(CHILD(0)[1].isPower()) { - if(CHILD(0)[1][0].size() == 0 && !CHILD(0)[1][0].isNumber() && CHILD(0)[1][1].isNumber() && CHILD(0)[1][1].number().isInteger() && CHILD(0)[1][1].number().isPositive()) { - xvar = &CHILD(0)[1][0]; - qcof = CHILD(0)[0].number().intValue(&overflow); - if(!overflow) { - if(qcof < 0) qcof = -qcof; - degree = CHILD(0)[1][1].number().intValue(&overflow); - } - } - } - } - - int pcof = 1; - if(!overflow) { - pcof = CHILD(SIZE - 1).number().intValue(&overflow); - if(pcof < 0) pcof = -pcof; - } - - if(xvar && !overflow && degree <= 1000 && degree > 2 && qcof != 0 && pcof != 0) { - bool b = true, b2 = true; - for(size_t i = 1; b && i < SIZE - 1; i++) { - switch(CHILD(i).type()) { - case STRUCT_NUMBER: { - b = false; - break; - } - case STRUCT_POWER: { - if(!CHILD(i)[1].isNumber() || !xvar->equals(CHILD(i)[0]) || !CHILD(i)[1].number().isInteger() || !CHILD(i)[1].number().isPositive()) { - b = false; - } - break; - } - case STRUCT_MULTIPLICATION: { - if(!(CHILD(i).size() == 2) || !CHILD(i)[0].isNumber()) { - b = false; - } else if(CHILD(i)[1].isPower()) { - if(!CHILD(i)[1][1].isNumber() || !xvar->equals(CHILD(i)[1][0]) || !CHILD(i)[1][1].number().isInteger() || !CHILD(i)[1][1].number().isPositive()) { - b = false; - } - } else if(!xvar->equals(CHILD(i)[1])) { - b = false; - } - if(b && b2 && !CHILD(i)[0].isInteger()) b2 = false; - break; - } - default: { - if(!xvar->equals(CHILD(i))) { - b = false; - } - } - } - } - - if(b) { - vector factors; - factors.resize(degree + 1, Number()); - factors[0] = CHILD(SIZE - 1).number(); - vector ps; - vector qs; - vector zeroes; - int curdeg = 1, prevdeg = 0; - for(size_t i = 0; b && i < SIZE - 1; i++) { - switch(CHILD(i).type()) { - case STRUCT_POWER: { - curdeg = CHILD(i)[1].number().intValue(&overflow); - if(curdeg == prevdeg || curdeg > degree || (prevdeg > 0 && curdeg > prevdeg) || overflow) { - b = false; - } else { - factors[curdeg].set(1, 1, 0); - } - break; - } - case STRUCT_MULTIPLICATION: { - if(CHILD(i)[1].isPower()) { - curdeg = CHILD(i)[1][1].number().intValue(&overflow); - } else { - curdeg = 1; - } - if(curdeg == prevdeg || curdeg > degree || (prevdeg > 0 && curdeg > prevdeg) || overflow) { - b = false; - } else { - factors[curdeg] = CHILD(i)[0].number(); - } - break; - } - default: { - curdeg = 1; - factors[curdeg].set(1, 1, 0); - } - } - prevdeg = curdeg; - } - - while(b && degree > 2) { - for(int i = 1; i <= 1000; i++) { - if(i > pcof) break; - if(pcof % i == 0) ps.push_back(i); - } - for(int i = 1; i <= 1000; i++) { - if(i > qcof) break; - if(qcof % i == 0) qs.push_back(i); - } - Number itest; - int i2; - size_t pi = 0, qi = 0; - if(ps.empty() || qs.empty()) break; - Number nrtest(ps[0], qs[0], 0); - while(true) { - itest.clear(); i2 = degree; - while(true) { - itest += factors[i2]; - if(i2 == 0) break; - itest *= nrtest; - i2--; - } - if(itest.isZero()) { - break; - } - if(nrtest.isPositive()) { - nrtest.negate(); - } else { - qi++; - if(qi == qs.size()) { - qi = 0; - pi++; - if(pi == ps.size()) { - break; - } - } - nrtest.set(ps[pi], qs[qi], 0); - } - } - if(itest.isZero()) { - itest.clear(); i2 = degree; - Number ntmp(factors[i2]); - for(; i2 > 0; i2--) { - itest += ntmp; - ntmp = factors[i2 - 1]; - factors[i2 - 1] = itest; - itest *= nrtest; - } - degree--; - nrtest.negate(); - zeroes.push_back(nrtest); - if(degree == 2) { - break; - } - qcof = factors[degree].intValue(&overflow); - if(!overflow) { - if(qcof < 0) qcof = -qcof; - pcof = factors[0].intValue(&overflow); - if(!overflow) { - if(pcof < 0) pcof = -pcof; - } - } - if(overflow || qcof == 0 || pcof == 0) { - break; - } - } else { - break; - } - ps.clear(); - qs.clear(); - } - - if(zeroes.size() > 0) { - MathStructure mleft; - MathStructure mtmp; - MathStructure *mcur; - for(int i = degree; i >= 0; i--) { - if(!factors[i].isZero()) { - if(mleft.isZero()) { - mcur = &mleft; - } else { - mleft.add(m_zero, true); - mcur = &mleft[mleft.size() - 1]; - } - if(i > 1) { - if(!factors[i].isOne()) { - mcur->multiply(*xvar); - (*mcur)[0].set(factors[i]); - mcur = &(*mcur)[1]; - } else { - mcur->set(*xvar); - } - mtmp.set(i, 1, 0); - mcur->raise(mtmp); - } else if(i == 1) { - if(!factors[i].isOne()) { - mcur->multiply(*xvar); - (*mcur)[0].set(factors[i]); - } else { - mcur->set(*xvar); - } - } else { - mcur->set(factors[i]); - } - } - } - mleft.factorize(eo, false, 0, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - vector powers; - vector powers_i; - int dupsfound = 0; - for(size_t i = 0; i < zeroes.size() - 1; i++) { - while(i + 1 < zeroes.size() && zeroes[i] == zeroes[i + 1]) { - dupsfound++; - zeroes.erase(zeroes.begin() + (i + 1)); - } - if(dupsfound > 0) { - powers_i.push_back(i); - powers.push_back(dupsfound + 1); - dupsfound = 0; - } - } - MathStructure xvar2(*xvar); - Number *nrmul; - if(mleft.isMultiplication()) { - set(mleft); - evalSort(); - if(CHILD(0).isNumber()) { - nrmul = &CHILD(0).number(); - } else if(CHILD(0).isMultiplication() && CHILD(0).size() > 0 && CHILD(0)[0].isNumber()) { - nrmul = &CHILD(0)[0].number(); - } else { - PREPEND(m_one); - nrmul = &CHILD(0).number(); - } - } else { - clear(true); - m_type = STRUCT_MULTIPLICATION; - APPEND(m_one); - APPEND(mleft); - nrmul = &CHILD(0).number(); - } - size_t pi = 0; - for(size_t i = 0; i < zeroes.size(); i++) { - if(zeroes[i].isInteger()) { - APPEND(xvar2); - } else { - APPEND(m_zero); - } - mcur = &CHILD(SIZE - 1); - if(pi < powers_i.size() && powers_i[pi] == i) { - mcur->raise(MathStructure(powers[pi], 1L, 0L)); - mcur = &(*mcur)[0]; - if(zeroes[i].isInteger()) { - mcur->add(zeroes[i]); - } else { - Number nr(zeroes[i].denominator()); - mcur->add(zeroes[i].numerator()); - (*mcur)[0] *= xvar2; - (*mcur)[0][0].number() = nr; - nr.raise(powers[pi]); - nrmul->divide(nr); - } - pi++; - } else { - if(zeroes[i].isInteger()) { - mcur->add(zeroes[i]); - } else { - nrmul->divide(zeroes[i].denominator()); - mcur->add(zeroes[i].numerator()); - (*mcur)[0] *= xvar2; - (*mcur)[0][0].number() = zeroes[i].denominator(); - } - } - } - if(CHILD(0).isNumber() && CHILD(0).number().isOne()) { - ERASE(0); - } else if(CHILD(0).isMultiplication() && CHILD(0).size() > 0 && CHILD(0)[0].isNumber() && CHILD(0)[0].number().isOne()) { - if(CHILD(0).size() == 1) { - ERASE(0); - } else if(CHILD(0).size() == 2) { - CHILD(0).setToChild(2, true); - } else { - CHILD(0).delChild(1); - } - } - evalSort(true); - Number dupspow; - for(size_t i = 0; i < SIZE - 1; i++) { - mcur = NULL; - if(CHILD(i).isPower()) { - if(CHILD(i)[0].isAddition() && CHILD(i)[1].isNumber()) { - mcur = &CHILD(i)[0]; - } - } else if(CHILD(i).isAddition()) { - mcur = &CHILD(i); - } - while(mcur && i + 1 < SIZE) { - if(CHILD(i + 1).isPower()) { - if(CHILD(i + 1)[0].isAddition() && CHILD(i + 1)[1].isNumber() && mcur->equals(CHILD(i + 1)[0])) { - dupspow += CHILD(i + 1)[1].number(); - } else { - mcur = NULL; - } - } else if(CHILD(i + 1).isAddition() && mcur->equals(CHILD(i + 1))) { - dupspow++; - } else { - mcur = NULL; - } - if(mcur) { - ERASE(i + 1); - } - } - if(!dupspow.isZero()) { - if(CHILD(i).isPower()) { - CHILD(i)[1].number() += dupspow; - } else { - dupspow++; - CHILD(i) ^= dupspow; - } - dupspow.clear(); - } - } - if(SIZE == 1) { - setToChild(1, true); - } else { - EvaluationOptions eo2 = eo; - eo2.expand = false; - calculatesub(eo2, eo2, false); - } - evalSort(true); - return true; - } - } - - if(b && b2 && (max_factor_degree < 0 || max_factor_degree >= 2) && degree > 3 && degree < 50) { - // Kronecker method - vector vnum; - vnum.resize(degree + 1, nr_zero); - bool overflow = false; - for(size_t i = 0; b && i < SIZE; i++) { - switch(CHILD(i).type()) { - case STRUCT_POWER: { - if(CHILD(i)[0] == *xvar && CHILD(i)[1].isInteger()) { - int curdeg = CHILD(i)[1].number().intValue(&overflow); - if(curdeg < 0 || overflow || curdeg > degree) b = false; - else vnum[curdeg] += 1; - } else { - b = false; - } - break; - } - case STRUCT_MULTIPLICATION: { - if(CHILD(i).size() == 2 && CHILD(i)[0].isInteger()) { - long int icoeff = CHILD(i)[0].number().intValue(&overflow); - if(!overflow && CHILD(i)[1].isPower() && CHILD(i)[1][0] == *xvar && CHILD(i)[1][1].isInteger()) { - int curdeg = CHILD(i)[1][1].number().intValue(&overflow); - if(curdeg < 0 || overflow || curdeg > degree) b = false; - else vnum[curdeg] += icoeff; - } else if(!overflow && CHILD(i)[1] == *xvar) { - vnum[1] += icoeff; - } else { - b = false; - } - } else { - b = false; - } - break; - } - default: { - if(CHILD(i).isInteger()) { - long int icoeff = CHILD(i).number().intValue(&overflow); - if(overflow) b = false; - else vnum[0] += icoeff; - } else if(CHILD(i) == *xvar) { - vnum[1] += 1; - } else { - b = false; - } - break; - } - } - } - - long int lcoeff = vnum[degree].lintValue(); - vector vs; - if(b && lcoeff != 0) { - degree /= 2; - if(max_factor_degree > 0 && degree > max_factor_degree) degree = max_factor_degree; - for(int i = 0; i <= degree; i++) { - if(CALCULATOR->aborted()) return false; - MathStructure mcalc(*this); - mcalc.calculateReplace(*xvar, Number((i / 2 + i % 2) * (i % 2 == 0 ? -1 : 1), 1), eo); - mcalc.calculatesub(eo, eo, false); - if(!mcalc.isInteger()) break; - bool overflow = false; - int v = ::abs(mcalc.number().intValue(&overflow)); - if(overflow) { - if(i > 2) degree = i; - else b = false; - break; - } - vs.push_back(v); - } - } - - if(b) { - vector factors0, factorsl; - factors0.push_back(1); - for(int i = 2; i < vs[0] / 3 && i < 1000; i++) { - if(vs[0] % i == 0) factors0.push_back(i); - } - if(vs[0] % 3 == 0) factors0.push_back(vs[0] / 3); - if(vs[0] % 2 == 0) factors0.push_back(vs[0] / 2); - factors0.push_back(vs[0]); - for(int i = 2; i < lcoeff / 3 && i < 1000; i++) { - if(lcoeff % i == 0) factorsl.push_back(i); - } - factorsl.push_back(1); - if(lcoeff % 3 == 0) factorsl.push_back(lcoeff / 3); - if(lcoeff % 2 == 0) factorsl.push_back(lcoeff / 2); - factorsl.push_back(lcoeff); - - long long int cmax = 500000LL / (factors0.size() * factorsl.size()); - if(term_combination_levels != 0) cmax *= 10; - if(degree >= 2 && cmax > 10) { - vector vden; - vector vquo; - vden.resize(3, nr_zero); - long int c0; - for(size_t i = 0; i < factors0.size() * 2; i++) { - c0 = factors0[i / 2]; - if(i % 2 == 1) c0 = -c0; - long int c2; - for(size_t i2 = 0; i2 < factorsl.size(); i2++) { - c2 = factorsl[i2]; - long int c1max = vs[1] - c0 - c2, c1min; - if(c1max < 0) {c1min = c1max; c1max = -vs[1] - c0 - c2;} - else {c1min = -vs[1] - c0 - c2;} - if(-(vs[2] - c0 - c2) < -(-vs[2] - c0 - c2)) { - if(c1max > -(-vs[2] - c0 - c2)) c1max = -(-vs[2] - c0 - c2); - if(c1min < -(vs[2] - c0 - c2)) c1min = -(vs[2] - c0 - c2); - } else { - if(c1max > -(vs[2] - c0 - c2)) c1max = -(vs[2] - c0 - c2); - if(c1min < -(-vs[2] - c0 - c2)) c1min = -(-vs[2] - c0 - c2); - } - if(c1min < -cmax / 2) c1min = -cmax / 2; - for(long int c1 = c1min; c1 <= c1max && c1 <= cmax / 2; c1++) { - long int v1 = ::labs(c2 + c1 + c0); - long int v2 = ::labs(c2 - c1 + c0); - if(v1 != 0 && v2 != 0 && v1 <= vs[1] && v2 <= vs[2] && (c1 != 0 || c2 != 0) && vs[1] % v1 == 0 && vs[2] % v2 == 0) { - vden[0] = c0; vden[1] = c1; vden[2] = c2; - if(CALCULATOR->aborted()) return false; - if(polynomial_divide_integers(vnum, vden, vquo)) { - MathStructure mtest; - mtest.setType(STRUCT_ADDITION); - if(c2 != 0) { - MathStructure *mpow = new MathStructure(); - mpow->setType(STRUCT_POWER); - mpow->addChild(*xvar); - mpow->addChild_nocopy(new MathStructure(2, 1, 0)); - if(c2 == 1) { - mtest.addChild_nocopy(mpow); - } else { - MathStructure *mterm = new MathStructure(); - mterm->setType(STRUCT_MULTIPLICATION); - mterm->addChild_nocopy(new MathStructure(c2, 1L, 0L)); - mterm->addChild_nocopy(mpow); - mtest.addChild_nocopy(mterm); - } - } - if(c1 == 1) { - mtest.addChild(*xvar); - } else if(c1 != 0) { - MathStructure *mterm = new MathStructure(); - mterm->setType(STRUCT_MULTIPLICATION); - mterm->addChild_nocopy(new MathStructure(c1, 1L, 0L)); - mterm->addChild(*xvar); - mtest.addChild_nocopy(mterm); - } - mtest.addChild_nocopy(new MathStructure(c0, 1L, 0L)); - MathStructure mthis(*this); - MathStructure mquo; - if(mtest.size() > 1 && polynomialDivide(mthis, mtest, mquo, eo, false)) { - mquo.factorize(eo, false, 0, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - set(mquo, true); - multiply(mtest, true); - return true; - } - } - } - } - } - } - } - for(int i_d = 3; i_d <= degree; i_d++) { - if(CALCULATOR->aborted()) return false; - long int t1max = ::pow(cmax / (i_d - 1), 1.0 / (i_d - 1)); - if(t1max < 1) break; - if(t1max > 1000) t1max = 1000; - long int c2totalmax = t1max; - long int c2cur; - for(int i = 0; i < i_d - 3; i++) { - c2totalmax *= t1max; - } - vector vden; - vector vquo; - long int *vc = (long int*) malloc(sizeof(long int) * (i_d + 1)); - vden.resize(i_d + 1, nr_zero); - int in = 0; - for(size_t i = 0; i < factors0.size() * 2; i++) { - vc[0] = factors0[i / 2] * (i % 2 == 1 ? -1 : 1); - for(size_t i2 = 0; i2 < factorsl.size(); i2++) { - vc[i_d] = factorsl[i2]; - for(long int c2p = 0; c2p <= c2totalmax; c2p++) { - c2cur = c2p; - for(int i = 2; i < i_d; i++) { - vc[i] = c2cur % t1max; - if(vc[i] % 2 == 1) vc[i] = -vc[i]; - vc[i] = vc[i] / 2 + vc[i] % 2; - c2cur /= t1max; - } - long int c1max = t1max / 2 + t1max % 2, c1min = -t1max / 2 - t1max % 2; - for(size_t i = 1; i < vs.size(); i++) { - long int vsmax = vs[i] - vc[0]; - long int vsmin = -vs[i] - vc[0]; - int ix = (i / 2 + i % 2) * (i % 2 == 0 ? -1 : 1); - int ixi = ix; - for(int i2 = 2; i2 <= i_d; i2++) { - ixi *= ix; - vsmax -= vc[i2] * ixi; - } - vsmax /= ix; - vsmin /= ix; - if(vsmax < vsmin) { - if(c1max > vsmin) c1max = vsmin; - if(c1min < vsmax) c1min = vsmax; - } else { - if(c1max > vsmax) c1max = vsmax; - if(c1min < vsmin) c1min = vsmin; - } - } - for(long int c1 = c1min; c1 <= c1max; c1++) { - vc[1] = c1; - bool b = true; - for(size_t i = 1; i < vs.size(); i++) { - long int v = vc[0]; - int ix = (i / 2 + i % 2) * (i % 2 == 0 ? -1 : 1); - int ixi = 1; - for(int i2 = 1; i2 <= i_d; i2++) { - ixi *= ix; - v += vc[i2] * ixi; - } - if(v < 0) v = -v; - if(v == 0 || v > vs[i] || vs[i] % v != 0) { - b = false; - break; - } - } - in++; - if(b) { - if(CALCULATOR->aborted()) return false; - for(size_t iden = 0; iden < vden.size(); iden++) { - vden[iden] = vc[iden]; - } - if(polynomial_divide_integers(vnum, vden, vquo)) { - MathStructure mtest; - mtest.setType(STRUCT_ADDITION); - for(int i2 = i_d; i2 >= 2; i2--) { - if(vc[i2] != 0) { - MathStructure *mpow = new MathStructure(); - mpow->setType(STRUCT_POWER); - mpow->addChild(*xvar); - mpow->addChild_nocopy(new MathStructure(i2, 1, 0)); - if(vc[i2] == 1) { - mtest.addChild_nocopy(mpow); - } else { - MathStructure *mterm = new MathStructure(); - mterm->setType(STRUCT_MULTIPLICATION); - mterm->addChild_nocopy(new MathStructure(vc[i2], 1L, 0L)); - mterm->addChild_nocopy(mpow); - mtest.addChild_nocopy(mterm); - } - } - } - if(vc[1] == 1) { - mtest.addChild(*xvar); - } else if(vc[1] != 0) { - MathStructure *mterm = new MathStructure(); - mterm->setType(STRUCT_MULTIPLICATION); - mterm->addChild_nocopy(new MathStructure(vc[1], 1L, 0L)); - mterm->addChild(*xvar); - mtest.addChild_nocopy(mterm); - } - mtest.addChild_nocopy(new MathStructure(vc[0], 1L, 0L)); - MathStructure mthis(*this); - MathStructure mquo; - if(mtest.size() > 1 && polynomialDivide(mthis, mtest, mquo, eo, false)) { - mquo.factorize(eo, false, 0, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - free(vc); - set(mquo, true); - multiply(mtest, true); - return true; - } - } - } - } - } - } - } - free(vc); - } - } - } - - } - } - - if(SIZE == 2 && max_factor_degree != 0) { - Number nr1(1, 1, 0), nr2(1, 1, 0); - bool b = true, b_nonnum = false; - bool b1_neg = false, b2_neg = false; - for(size_t i = 0; i < SIZE && b; i++) { - b = false; - if(CHILD(i).isInteger() && CHILD(i).number().integerLength() < 100) { - b = true; - if(i == 0) nr1 = CHILD(i).number(); - else nr2 = CHILD(i).number(); - } else if(CHILD(i).isMultiplication() && CHILD(i).size() > 1) { - b_nonnum = true; - b = true; - size_t i2 = 0; - if(CHILD(i)[0].isInteger() && CHILD(i).number().integerLength() < 100) { - if(i == 0) nr1 = CHILD(i)[0].number(); - else nr2 = CHILD(i)[0].number(); - i2++; - } - for(; i2 < CHILD(i).size(); i2++) { - if(!CHILD(i)[i2].isPower() || !CHILD(i)[i2][1].isInteger() || !CHILD(i)[i2][1].number().isPositive() || !CHILD(i)[i2][1].number().isEven() || CHILD(i)[1].number().integerLength() >= 100 || !CHILD(i)[i2][0].representsNonMatrix()) { - b = false; - break; - } - } - } else if(CHILD(i).isPower() && CHILD(i)[1].isNumber() && CHILD(i)[1].number().isInteger() && CHILD(i)[1].number().isPositive() && CHILD(i)[1].number().isEven() && CHILD(i)[1].number().integerLength() < 100 && CHILD(i)[0].representsNonMatrix()) { - b_nonnum = true; - b = true; - } - } - if(!b_nonnum) b = false; - if(b) { - b1_neg = nr1.isNegative(); - b2_neg = nr2.isNegative(); - if(b1_neg == b2_neg) b = false; - } - if(b) { - if(b1_neg) b = nr1.negate(); - if(b && !nr1.isOne()) { - b = nr1.isPerfectSquare() && nr1.isqrt(); - } - } - if(b) { - if(b2_neg) nr2.negate(); - if(!nr2.isOne()) { - b = nr2.isPerfectSquare() && nr2.isqrt(); - } - } - if(b) { - bool calc = false; - MathStructure *mmul = new MathStructure(*this); - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isNumber()) { - if(i == 0) { - CHILD(i).number() = nr1; - if(b1_neg) nr1.negate(); - (*mmul)[i].number() = nr1; - } else { - CHILD(i).number() = nr2; - if(b2_neg) nr2.negate(); - (*mmul)[i].number() = nr2; - } - } else if(CHILD(i).isMultiplication() && CHILD(i).size() > 1) { - b = true; - size_t i2 = 0; - if(CHILD(i)[0].isNumber()) { - if(i == 0) { - CHILD(i)[0].number() = nr1; - if(b1_neg) nr1.negate(); - (*mmul)[i][0].number() = nr1; - } else { - CHILD(i)[0].number() = nr2; - if(b2_neg) nr2.negate(); - (*mmul)[i][0].number() = nr2; - } - i2++; - } - for(; i2 < CHILD(i).size(); i2++) { - if(CHILD(i)[i2][1].number().isTwo()) { - CHILD(i)[i2].setToChild(1, true); - (*mmul)[i][i2].setToChild(1, true); - } else { - CHILD(i)[i2][1].number().divide(2); - (*mmul)[i][i2][1].number().divide(2); - } - CHILD(i).childUpdated(i2 + 1); - (*mmul)[i].childUpdated(i2 + 1); - } - if(CHILD(i)[0].isOne()) CHILD(i).delChild(1, true); - if((*mmul)[i][0].isOne()) (*mmul)[i].delChild(1, true); - } else if(CHILD(i).isPower()) { - if(CHILD(i)[1].number().isTwo()) { - CHILD(i).setToChild(1, true); - (*mmul)[i].setToChild(1, true); - } else { - CHILD(i)[1].number().divide(2); - (*mmul)[i][1].number().divide(2); - } - } - if(CHILD(i).isAddition()) calc = true; - CHILD_UPDATED(i) - mmul->childUpdated(i + 1); - } - if(calc) { - calculatesub(eo, eo, false); - mmul->calculatesub(eo, eo, false); - } - if(recursive) { - factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - mmul->factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - } - multiply_nocopy(mmul); - evalSort(true); - return true; - } - } - - //x^3-y^3=(x-y)(x^2+xy+y^2) - if(max_factor_degree != 0 && SIZE == 2 && CHILD(0).isPower() && CHILD(0)[1].isNumber() && CHILD(0)[1].number() == 3 && CHILD(1).isMultiplication() && CHILD(1).size() == 2 && CHILD(1)[0].isMinusOne() && CHILD(1)[1].isPower() && CHILD(1)[1][1].isNumber() && CHILD(1)[1][1].number() == 3) { - if(CHILD(0)[0].representsNonMatrix() && CHILD(1)[1][0].representsNonMatrix()) { - MathStructure *m2 = new MathStructure(*this); - (*m2)[0].setToChild(1, true); - (*m2)[1][1].setToChild(1, true); - EvaluationOptions eo2 = eo; - eo2.expand = false; - m2->calculatesub(eo2, eo2, false); - CHILD(0)[1].set(2, 1, 0, true); - CHILD(1).setToChild(2, true); - CHILD(1)[1].set(2, 1, 0, true); - MathStructure *m3 = new MathStructure(CHILD(0)[0]); - m3->calculateMultiply(CHILD(1)[0], eo2); - add_nocopy(m3, true); - calculatesub(eo2, eo2, false); - multiply_nocopy(m2, true); - evalSort(true); - return true; - } - } - //-x^3+y^3=(-x+y)(x^2+xy+y^2) - if(max_factor_degree != 0 && SIZE == 2 && CHILD(1).isPower() && CHILD(1)[1].isNumber() && CHILD(1)[1].number() == 3 && CHILD(0).isMultiplication() && CHILD(0).size() == 2 && CHILD(0)[0].isMinusOne() && CHILD(0)[1].isPower() && CHILD(0)[1][1].isNumber() && CHILD(0)[1][1].number() == 3) { - if(CHILD(1)[0].representsNonMatrix() && CHILD(0)[1][0].representsNonMatrix()) { - MathStructure *m2 = new MathStructure(*this); - (*m2)[1].setToChild(1, true); - (*m2)[0][1].setToChild(1, true); - EvaluationOptions eo2 = eo; - eo2.expand = false; - m2->calculatesub(eo2, eo2, false); - CHILD(1)[1].set(2, 1, 0, true); - CHILD(0).setToChild(2, true); - CHILD(0)[1].set(2, 1, 0, true); - MathStructure *m3 = new MathStructure(CHILD(0)[0]); - m3->calculateMultiply(CHILD(1)[0], eo2); - add_nocopy(m3, true); - calculatesub(eo2, eo2, false); - multiply_nocopy(m2, true); - evalSort(true); - return true; - } - } - - if(max_factor_degree != 0 && !only_integers && !force_factorization.isUndefined() && SIZE >= 2) { - MathStructure mexp, madd, mmul; - if(gather_factors(*this, force_factorization, madd, mmul, mexp) && !madd.isZero() && !mmul.isZero() && mexp.isInteger() && mexp.number().isGreaterThan(nr_two)) { - if(!mmul.isOne()) madd.calculateDivide(mmul, eo); - bool overflow = false; - int n = mexp.number().intValue(&overflow); - if(!overflow) { - if(n % 4 == 0) { - int i_u = 1; - if(n != 4) { - i_u = n / 4; - } - MathStructure m_sqrt2(2, 1, 0); - m_sqrt2.calculateRaise(nr_half, eo); - MathStructure m_sqrtb(madd); - m_sqrtb.calculateRaise(nr_half, eo); - MathStructure m_bfourth(madd); - m_bfourth.calculateRaise(Number(1, 4), eo); - m_sqrt2.calculateMultiply(m_bfourth, eo); - MathStructure m_x(force_factorization); - if(i_u != 1) m_x ^= i_u; - m_sqrt2.calculateMultiply(m_x, eo); - MathStructure *m2 = new MathStructure(force_factorization); - m2->raise(Number(i_u * 2, 1)); - m2->add(m_sqrtb); - m2->calculateAdd(m_sqrt2, eo); - set(force_factorization, true); - raise(Number(i_u * 2, 1)); - add(m_sqrtb); - calculateSubtract(m_sqrt2, eo); - multiply_nocopy(m2); - } else { - int i_u = 1; - if(n % 2 == 0) { - i_u = 2; - n /= 2; - } - MathStructure *m2 = new MathStructure(madd); - m2->calculateRaise(Number(n - 1, n), eo); - for(int i = 1; i < n - 1; i++) { - MathStructure *mterm = new MathStructure(madd); - mterm->calculateRaise(Number(n - i - 1, n), eo); - mterm->multiply(force_factorization); - if(i != 1 || i_u != 1) { - mterm->last().raise(Number(i * i_u, 1)); - mterm->childUpdated(mterm->size()); - } - if(i % 2 == 1) mterm->calculateMultiply(m_minus_one, eo); - m2->add_nocopy(mterm, true); - } - MathStructure *mterm = new MathStructure(force_factorization); - mterm->raise(Number((n - 1) * i_u, 1)); - m2->add_nocopy(mterm, true); - mterm = new MathStructure(force_factorization); - if(i_u != 1) mterm->raise(Number(i_u, 1)); - set(madd, true); - calculateRaise(Number(1, n), eo); - add_nocopy(mterm); - multiply_nocopy(m2); - } - if(!mmul.isOne()) multiply(mmul, true); - evalSort(true); - return true; - } - } - } - - //-x-y = -(x+y) - bool b = true; - for(size_t i2 = 0; i2 < SIZE; i2++) { - if((!CHILD(i2).isNumber() || !CHILD(i2).number().isNegative()) && (!CHILD(i2).isMultiplication() || CHILD(i2).size() < 2 || !CHILD(i2)[0].isNumber() || !CHILD(i2)[0].number().isNegative())) { - b = false; - break; - } - } - if(b) { - for(size_t i2 = 0; i2 < SIZE; i2++) { - if(CHILD(i2).isNumber()) { - CHILD(i2).number().negate(); - } else { - CHILD(i2)[0].number().negate(); - if(CHILD(i2)[0].isOne() && CHILD(i2).size() > 1) { - CHILD(i2).delChild(1); - if(CHILD(i2).size() == 1) { - CHILD(i2).setToChild(1, true); - } - } - } - } - multiply(MathStructure(-1, 1, 0)); - CHILD_TO_FRONT(1) - } - - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isMultiplication() && CHILD(i).size() > 1) { - for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { - if(CHILD(i)[i2].isAddition()) { - for(size_t i3 = i + 1; i3 < SIZE; i3++) { - if(CHILD(i3).isMultiplication() && CHILD(i3).size() > 1) { - for(size_t i4 = 0; i4 < CHILD(i3).size(); i4++) { - if(CHILD(i3)[i4].isAddition() && CHILD(i3)[i4] == CHILD(i)[i2]) { - MathStructure *mfac = &CHILD(i)[i2]; - mfac->ref(); - CHILD(i).delChild(i2 + 1, true); - CHILD(i3).delChild(i4 + 1, true); - CHILD(i3).ref(); - CHILD(i).add_nocopy(&CHILD(i3)); - CHILD(i).calculateAddLast(eo); - CHILD(i).multiply_nocopy(mfac); - CHILD_UPDATED(i) - delChild(i3 + 1, true); - evalSort(true); - factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - return true; - } - } - } - } - if(SIZE > 2) { - MathStructure mtest(*this); - mtest.delChild(i + 1); - if(mtest == CHILD(i)[i2]) { - CHILD(i).delChild(i2 + 1, true); - SET_CHILD_MAP(i); - add(m_one, true); - multiply(mtest); - evalSort(true); - factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - return true; - } - } - } - } - } - } - } - - //complete the square - if(max_factor_degree != 0 && (term_combination_levels != 0 || complete_square)) { - if(only_integers) { - if(SIZE <= 3 && SIZE > 1) { - MathStructure *xvar = NULL; - Number nr2(1, 1); - if(CHILD(0).isPower() && CHILD(0)[0].size() == 0 && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isTwo()) { - xvar = &CHILD(0)[0]; - } else if(CHILD(0).isMultiplication() && CHILD(0).size() == 2 && CHILD(0)[0].isNumber()) { - if(CHILD(0)[1].isPower()) { - if(CHILD(0)[1][0].size() == 0 && CHILD(0)[1][1].isNumber() && CHILD(0)[1][1].number().isTwo()) { - xvar = &CHILD(0)[1][0]; - nr2.set(CHILD(0)[0].number()); - } - } - } - if(xvar) { - bool factorable = false; - Number nr1, nr0; - if(SIZE == 2 && CHILD(1).isNumber()) { - factorable = true; - nr0 = CHILD(1).number(); - } else if(SIZE == 3 && CHILD(2).isNumber()) { - nr0 = CHILD(2).number(); - if(CHILD(1).isMultiplication()) { - if(CHILD(1).size() == 2 && CHILD(1)[0].isNumber() && xvar->equals(CHILD(1)[1])) { - nr1 = CHILD(1)[0].number(); - factorable = true; - } - } else if(xvar->equals(CHILD(1))) { - nr1.set(1, 1, 0); - factorable = true; - } - } - if(factorable && !nr2.isZero() && !nr1.isZero()) { - Number nrh(nr1); - nrh /= 2; - nrh /= nr2; - if(nrh.isInteger()) { - Number nrk(nrh); - if(nrk.square()) { - nrk *= nr2; - nrk.negate(); - nrk += nr0; - set(MathStructure(*xvar), true); - add(nrh); - raise(nr_two); - if(!nr2.isOne()) multiply(nr2); - if(!nrk.isZero()) add(nrk); - evalSort(true); - return true; - } - } - } - } - } - } else { - MathStructure m2, m1, m0; - const MathStructure *xvar = NULL; - if(!force_factorization.isUndefined()) { - xvar = &force_factorization; - } else { - if(CHILD(0).isPower() && CHILD(0)[0].size() == 0 && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isTwo()) { - xvar = &CHILD(0)[0]; - } else if(CHILD(0).isMultiplication()) { - for(size_t i2 = 0; i2 < CHILD(0).size(); i2++) { - if(CHILD(0).isPower() && CHILD(0)[i2][0].size() == 0 && CHILD(0)[i2][1].isNumber() && CHILD(0)[i2][1].number().isTwo()) { - xvar = &CHILD(0)[0]; - } - } - } - } - if(xvar && gather_factors(*this, *xvar, m0, m1, m2, true) && !m1.isZero() && !m2.isZero()) { - MathStructure *mx = new MathStructure(*xvar); - set(m1, true); - calculateMultiply(nr_half, eo); - if(!m2.isOne()) calculateDivide(m2, eo); - add_nocopy(mx); - calculateAddLast(eo); - raise(nr_two); - if(!m2.isOne()) multiply(m2); - if(!m1.isOne()) m1.calculateRaise(nr_two, eo); - m1.calculateMultiply(Number(-1, 4), eo); - if(!m2.isOne()) { - m2.calculateInverse(eo); - m1.calculateMultiply(m2, eo); - } - m0.calculateAdd(m1, eo); - if(!m0.isZero()) add(m0); - if(recursive) { - CHILD(0).factorize(eo, false, 0, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - CHILD(1).factorize(eo, false, 0, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - CHILDREN_UPDATED - } - evalSort(true); - return true; - } - } - } - - //Try factorize combinations of terms - if(SIZE > 2 && term_combination_levels > 0) { - bool b = false, b_ret = false; - // 5/y + x/y + z = (5 + x)/y + z - MathStructure mstruct_units(*this); - MathStructure mstruct_new(*this); - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(mstruct_units[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct_units[i].size();) { - if(!mstruct_units[i][i2].isPower() || !mstruct_units[i][i2][1].hasNegativeSign()) { - mstruct_units[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); - else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); - for(size_t i2 = 0; i2 < mstruct_new[i].size();) { - if(mstruct_new[i][i2].isPower() && mstruct_new[i][i2][1].hasNegativeSign()) { - mstruct_new[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); - else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); - } else if(mstruct_new[i].isPower() && mstruct_new[i][1].hasNegativeSign()) { - mstruct_new[i].set(1, 1, 0); - } else { - mstruct_units[i].setUndefined(); - } - } - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(!mstruct_units[i].isUndefined()) { - for(size_t i2 = i + 1; i2 < mstruct_units.size();) { - if(mstruct_units[i2] == mstruct_units[i]) { - mstruct_new[i].add(mstruct_new[i2], true); - mstruct_new.delChild(i2 + 1); - mstruct_units.delChild(i2 + 1); - b = true; - } else { - i2++; - } - } - if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); - else mstruct_new[i].multiply(mstruct_units[i], true); - } - } - if(b) { - if(mstruct_new.size() == 1) { - set(mstruct_new[0], true); - factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - return true; - } else { - set(mstruct_new); - } - b = false; - b_ret = true; - } - // a*y + a*z + x = a(y + z) + x - vector syms; - vector counts; - collect_symbols(*this, syms); - size_t max_count = 0, max_i = 0; - Number min_pow; - for(size_t i = 0; i < syms.size(); i++) { - if(syms[i].containsUnknowns()) { - size_t count = 0; - Number min_pow_i; - for(size_t i2 = 0; i2 < SIZE; i2++) { - if(CHILD(i2).isMultiplication()) { - for(size_t i3 = 0; i3 < CHILD(i2).size(); i3++) { - if(CHILD(i2)[i3].isPower() && CHILD(i2)[i3][1].isNumber() && CHILD(i2)[i3][1].number().isRational() && CHILD(i2)[i3][1].number().isNegative() && CHILD(i2)[i3][0] == syms[i]) { - if(min_pow_i.isZero() || CHILD(i2)[i3][1].number() > min_pow_i) min_pow_i = CHILD(i2)[i3][1].number(); - count++; - break; - } - } - } else if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isRational() && CHILD(i2)[1].number().isNegative() && CHILD(i2)[0] == syms[i]) { - if(min_pow_i.isZero() || CHILD(i2)[1].number() > min_pow_i) min_pow_i = CHILD(i2)[1].number(); - count++; - } - } - if(count > 1 && count > max_count) { - max_count = count; - min_pow = min_pow_i; - max_i = i; - } - } - } - if(!max_count) { - for(size_t i = 0; i < syms.size(); i++) { - if(syms[i].containsUnknowns()) { - size_t count = 0; - Number min_pow_i; - for(size_t i2 = 0; i2 < SIZE; i2++) { - if(CHILD(i2).isMultiplication()) { - for(size_t i3 = 0; i3 < CHILD(i2).size(); i3++) { - if(CHILD(i2)[i3].isPower() && CHILD(i2)[i3][1].isNumber() && CHILD(i2)[i3][1].number().isRational() && CHILD(i2)[i3][1].number().isPositive() && CHILD(i2)[i3][0] == syms[i]) { - if(min_pow_i.isZero() || CHILD(i2)[i3][1].number() < min_pow_i) min_pow_i = CHILD(i2)[i3][1].number(); - count++; - break; - } else if(CHILD(i2)[i3] == syms[i]) { - if(min_pow_i.isZero() || min_pow_i > 1) min_pow_i = 1; - count++; - break; - } - } - } else if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isRational() && CHILD(i2)[1].number().isPositive() && CHILD(i2)[0] == syms[i]) { - if(min_pow_i.isZero() || CHILD(i2)[1].number() < min_pow_i) min_pow_i = CHILD(i2)[1].number(); - count++; - } else if(CHILD(i2) == syms[i]) { - if(min_pow_i.isZero() || min_pow_i > 1) min_pow_i = 1; - count++; - } - } - if(count > 1 && count > max_count) { - max_count = count; - min_pow = min_pow_i; - max_i = i; - } - } - } - } - if(max_count > 0) { - size_t i = max_i; - vector mleft; - for(size_t i2 = 0; i2 < SIZE;) { - b = false; - if(CHILD(i2).isMultiplication()) { - for(size_t i3 = 0; i3 < CHILD(i2).size(); i3++) { - if(CHILD(i2)[i3].isPower() && CHILD(i2)[i3][1].isNumber() && CHILD(i2)[i3][1].number().isRational() && (min_pow.isPositive() ? CHILD(i2)[i3][1].number().isPositive() : CHILD(i2)[i3][1].number().isNegative()) && CHILD(i2)[i3][0] == syms[i]) { - if(CHILD(i2)[i3][1] == min_pow) CHILD(i2).delChild(i3 + 1, true); - else if(CHILD(i2)[i3][1] == min_pow + 1) CHILD(i2)[i3].setToChild(1, true); - else { - CHILD(i2)[i3][1].number() -= min_pow; - factorize_fix_root_power(CHILD(i2)[i3]); - } - b = true; - break; - } else if(min_pow.isPositive() && CHILD(i2)[i3] == syms[i]) { - if(min_pow.isOne()) CHILD(i2).delChild(i3 + 1, true); - else { - CHILD(i2)[i3].raise((-min_pow) + 1); - factorize_fix_root_power(CHILD(i2)[i3]); - } - b = true; - break; - } - } - } else if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isRational() && (min_pow.isPositive() ? CHILD(i2)[1].number().isPositive() : CHILD(i2)[1].number().isNegative()) && CHILD(i2)[0] == syms[i]) { - if(CHILD(i2)[1] == min_pow) CHILD(i2).set(1, 1, 0, true); - else if(CHILD(i2)[1] == min_pow + 1) CHILD(i2).setToChild(1, true); - else { - CHILD(i2)[1].number() -= min_pow; - factorize_fix_root_power(CHILD(i2)); - } - b = true; - } else if(min_pow.isPositive() && CHILD(i2) == syms[i]) { - if(min_pow.isOne()) CHILD(i2).set(1, 1, 0, true); - else { - CHILD(i2).raise((-min_pow) + 1); - factorize_fix_root_power(CHILD(i2)); - } - b = true; - } - if(b) { - i2++; - } else { - CHILD(i2).ref(); - mleft.push_back(&CHILD(i2)); - ERASE(i2) - } - } - multiply(syms[i]); - if(!min_pow.isOne()) LAST ^= min_pow; - for(size_t i2 = 0; i2 < mleft.size(); i2++) { - add_nocopy(mleft[i2], true); - } - factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - return true; - } - if(LAST.isNumber()) { - MathStructure *mdel = &LAST; - mdel->ref(); - delChild(SIZE, true); - b = factorize(eo, false, term_combination_levels - 1, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - add_nocopy(mdel, true); - if(term_combination_levels == 1) return b || b_ret; - if(b) b_ret = true; - } - for(size_t i = 0; !b && i < SIZE; i++) { - MathStructure *mdel = &CHILD(i); - mdel->ref(); - delChild(i + 1, true); - b = true; - if(mdel->isMultiplication()) { - for(size_t i2 = 0; i2 < mdel->size(); i2++) { - if((*mdel)[i2].isPower() && (*mdel)[i2][0].containsUnknowns()) { - if(contains((*mdel)[i2][0], false, false, false) > 0) {b = false; break;} - } else if((*mdel)[i2].containsUnknowns()) { - if(contains((*mdel)[i2], false, false, false) > 0) {b = false; break;} - } - } - - } else { - b = contains(*mdel, false, false, false) <= 0; - } - if(b) { - b = factorize(eo, false, term_combination_levels - 1, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - if(recursive) mdel->factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - add_nocopy(mdel, true); - if(term_combination_levels == 1) return b || b_ret; - if(b) b_ret = true; - break; - } else { - insertChild_nocopy(mdel, i + 1); - } - } - b = false; - // a*y + a*z + x = a(y + z) + x - syms.clear(); - counts.clear(); - collect_symbols(*this, syms); - max_count = 0; max_i = 0; - for(size_t i = 0; i < syms.size(); i++) { - size_t count = 0; - Number min_pow_i; - for(size_t i2 = 0; i2 < SIZE; i2++) { - if(CHILD(i2).isMultiplication()) { - for(size_t i3 = 0; i3 < CHILD(i2).size(); i3++) { - if(CHILD(i2)[i3].isPower() && CHILD(i2)[i3][1].isNumber() && CHILD(i2)[i3][1].number().isRational() && CHILD(i2)[i3][1].number().isNegative() && CHILD(i2)[i3][0] == syms[i]) { - if(min_pow_i.isZero() || CHILD(i2)[i3][1].number() > min_pow_i) min_pow_i = CHILD(i2)[i3][1].number(); - count++; - break; - } - } - } else if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isRational() && CHILD(i2)[1].number().isNegative() && CHILD(i2)[0] == syms[i]) { - if(min_pow_i.isZero() || CHILD(i2)[1].number() > min_pow_i) min_pow_i = CHILD(i2)[1].number(); - count++; - } - } - if(count > 1 && count > max_count) { - max_count = count; - min_pow = min_pow_i; - max_i = i; - } - } - if(!max_count) { - for(size_t i = 0; i < syms.size(); i++) { - size_t count = 0; - Number min_pow_i; - for(size_t i2 = 0; i2 < SIZE; i2++) { - if(CHILD(i2).isMultiplication()) { - for(size_t i3 = 0; i3 < CHILD(i2).size(); i3++) { - if(CHILD(i2)[i3].isPower() && CHILD(i2)[i3][1].isNumber() && CHILD(i2)[i3][1].number().isRational() && CHILD(i2)[i3][1].number().isPositive() && CHILD(i2)[i3][0] == syms[i]) { - if(min_pow_i.isZero() || CHILD(i2)[i3][1].number() < min_pow_i) min_pow_i = CHILD(i2)[i3][1].number(); - count++; - break; - } else if(CHILD(i2)[i3] == syms[i]) { - if(min_pow_i.isZero() || min_pow_i > 1) min_pow_i = 1; - count++; - break; - } - } - } else if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isRational() && CHILD(i2)[1].number().isPositive() && CHILD(i2)[0] == syms[i]) { - if(min_pow_i.isZero() || CHILD(i2)[1].number() < min_pow_i) min_pow_i = CHILD(i2)[1].number(); - count++; - } else if(CHILD(i2) == syms[i]) { - if(min_pow_i.isZero() || min_pow_i > 1) min_pow_i = 1; - count++; - } - } - if(count > 1 && count > max_count) { - max_count = count; - min_pow = min_pow_i; - max_i = i; - } - } - } - if(max_count > 0) { - size_t i = max_i; - vector mleft; - for(size_t i2 = 0; i2 < SIZE;) { - b = false; - if(CHILD(i2).isMultiplication()) { - for(size_t i3 = 0; i3 < CHILD(i2).size(); i3++) { - if(CHILD(i2)[i3].isPower() && CHILD(i2)[i3][1].isNumber() && CHILD(i2)[i3][1].number().isRational() && (min_pow.isPositive() ? CHILD(i2)[i3][1].number().isPositive() : CHILD(i2)[i3][1].number().isNegative()) && CHILD(i2)[i3][0] == syms[i]) { - if(CHILD(i2)[i3][1] == min_pow) CHILD(i2).delChild(i3 + 1, true); - else if(CHILD(i2)[i3][1] == min_pow + 1) CHILD(i2)[i3].setToChild(1, true); - else { - CHILD(i2)[i3][1].number() -= min_pow; - factorize_fix_root_power(CHILD(i2)[i3]); - } - b = true; - break; - } else if(min_pow.isPositive() && CHILD(i2)[i3] == syms[i]) { - if(min_pow.isOne()) CHILD(i2).delChild(i3 + 1, true); - else { - CHILD(i2)[i3].raise((-min_pow) + 1); - factorize_fix_root_power(CHILD(i2)[i3]); - } - b = true; - break; - } - } - } else if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isRational() && (min_pow.isPositive() ? CHILD(i2)[1].number().isPositive() : CHILD(i2)[1].number().isNegative()) && CHILD(i2)[0] == syms[i]) { - if(CHILD(i2)[1] == min_pow) CHILD(i2).set(1, 1, 0, true); - else if(CHILD(i2)[1] == min_pow + 1) CHILD(i2).setToChild(1, true); - else { - CHILD(i2)[1].number() -= min_pow; - factorize_fix_root_power(CHILD(i2)); - } - b = true; - } else if(min_pow.isPositive() && CHILD(i2) == syms[i]) { - if(min_pow.isOne()) CHILD(i2).set(1, 1, 0, true); - else { - CHILD(i2).raise((-min_pow) + 1); - factorize_fix_root_power(CHILD(i2)); - } - b = true; - } - if(b) { - i2++; - } else { - CHILD(i2).ref(); - mleft.push_back(&CHILD(i2)); - ERASE(i2) - } - } - multiply(syms[i]); - if(!min_pow.isOne()) LAST ^= min_pow; - for(size_t i2 = 0; i2 < mleft.size(); i2++) { - add_nocopy(mleft[i2], true); - } - factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - return true; - } - if(isAddition()) { - b = false; - // y*f(x) + z*f(x) = (y+z)*f(x) - mstruct_units.set(*this); - mstruct_new.set(*this); - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(mstruct_units[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct_units[i].size();) { - if(!combination_factorize_is_complicated(mstruct_units[i][i2])) { - mstruct_units[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); - else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); - for(size_t i2 = 0; i2 < mstruct_new[i].size();) { - if(combination_factorize_is_complicated(mstruct_new[i][i2])) { - mstruct_new[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); - else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); - } else if(combination_factorize_is_complicated(mstruct_units[i])) { - mstruct_new[i].set(1, 1, 0); - } else { - mstruct_units[i].setUndefined(); - } - } - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(!mstruct_units[i].isUndefined()) { - for(size_t i2 = i + 1; i2 < mstruct_units.size();) { - if(mstruct_units[i2] == mstruct_units[i]) { - mstruct_new[i].add(mstruct_new[i2], true); - mstruct_new.delChild(i2 + 1); - mstruct_units.delChild(i2 + 1); - b = true; - } else { - i2++; - } - } - if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); - else mstruct_new[i].multiply(mstruct_units[i], true); - } - } - if(b) { - if(mstruct_new.size() == 1) set(mstruct_new[0], true); - else set(mstruct_new); - factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - return true; - } - } - if(isAddition()) { - b = false; - mstruct_units.set(*this); - mstruct_new.set(*this); - // 5x + pi*x + 5y + xy = (5 + pi)x + 5y + xy - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(mstruct_units[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct_units[i].size();) { - if(!mstruct_units[i][i2].containsType(STRUCT_UNIT, true) && !mstruct_units[i][i2].containsUnknowns()) { - mstruct_units[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); - else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); - for(size_t i2 = 0; i2 < mstruct_new[i].size();) { - if(mstruct_new[i][i2].containsType(STRUCT_UNIT, true) || mstruct_new[i][i2].containsUnknowns()) { - mstruct_new[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); - else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); - } else if(mstruct_units[i].containsType(STRUCT_UNIT, true) || mstruct_units[i].containsUnknowns()) { - mstruct_new[i].set(1, 1, 0); - } else { - mstruct_units[i].setUndefined(); - } - } - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(!mstruct_units[i].isUndefined()) { - for(size_t i2 = i + 1; i2 < mstruct_units.size();) { - if(mstruct_units[i2] == mstruct_units[i]) { - mstruct_new[i].add(mstruct_new[i2], true); - mstruct_new.delChild(i2 + 1); - mstruct_units.delChild(i2 + 1); - b = true; - } else { - i2++; - } - } - if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); - else mstruct_new[i].multiply(mstruct_units[i], true); - } - } - if(b) { - if(mstruct_new.size() == 1) set(mstruct_new[0], true); - else set(mstruct_new); - factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - return true; - } - } - return b_ret; - } else if(term_combination_levels != 0 && SIZE > 2) { - int start_index = rand() % SIZE; - int index = start_index; - int best_index = -1; - int run_index = 0; - int max_run_index = SIZE - 3; - if(term_combination_levels < -1) { - run_index = -term_combination_levels - 2; - max_run_index = run_index; - } else if(term_combination_levels > 0 && term_combination_levels - 1 < max_run_index) { - max_run_index = term_combination_levels -1; - } - - MathStructure mbest; - do { - if(CALCULATOR->aborted()) break; - if(endtime_p && endtime_p->tv_sec > 0) { -#ifndef CLOCK_MONOTONIC - struct timeval curtime; - gettimeofday(&curtime, NULL); - if(curtime.tv_sec > endtime_p->tv_sec || (curtime.tv_sec == endtime_p->tv_sec && curtime.tv_usec > endtime_p->tv_usec)) { -#else - struct timespec curtime; - clock_gettime(CLOCK_MONOTONIC, &curtime); - if(curtime.tv_sec > endtime_p->tv_sec || (curtime.tv_sec == endtime_p->tv_sec && curtime.tv_nsec / 1000 > endtime_p->tv_usec)) { -#endif - CALCULATOR->error(false, _("Because of time constraints only a limited number of combinations of terms were tried during factorization. Repeat factorization to try other random combinations."), NULL); - break; - } - } - - MathStructure mtest(*this); - mtest.delChild(index + 1); - if(mtest.factorize(eo, false, run_index == 0 ? 0 : -1 - run_index, 0, only_integers, false, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree)) { - bool b = best_index < 0 || (mbest.isAddition() && !mtest.isAddition()); - if(!b && (mtest.isAddition() == mbest.isAddition())) { - b = mtest.isAddition() && (mtest.size() < mbest.size()); - if(!b && (!mtest.isAddition() || mtest.size() == mbest.size())) { - size_t c1 = mtest.countTotalChildren() + CHILD(index).countTotalChildren(); - size_t c2 = mbest.countTotalChildren() + CHILD(best_index).countTotalChildren(); - b = (c1 < c2); - if(c1 == c2) { - b = (count_powers(mtest) + count_powers(CHILD(index))) < (count_powers(mbest) + count_powers(CHILD(best_index))); - } - } - } - if(b) { - mbest = mtest; - best_index = index; - if(mbest.isPower()) { - break; - } - } - } - index++; - if(index == (int) SIZE) index = 0; - if(index == start_index) { - if(best_index >= 0) { - break; - } - run_index++; - if(run_index > max_run_index) break; - } - } while(true); - if(best_index >= 0) { - mbest.add(CHILD(best_index), true); - set(mbest); - if(term_combination_levels >= -1 && (run_index > 0 || recursive)) { - factorize(eo, false, term_combination_levels, 0, only_integers, true, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - } - return true; - } - } - } - default: { - if(term_combination_levels < -1) break; - bool b = false; - - if(isComparison()) { - EvaluationOptions eo2 = eo; - eo2.assume_denominators_nonzero = false; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).factorize(eo2, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree)) { - CHILD_UPDATED(i); - b = true; - } - } - } else if(recursive && (recursive > 1 || !isAddition())) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree)) { - CHILD_UPDATED(i); - b = true; - } - } - } - if(b) { - EvaluationOptions eo2 = eo; - eo2.expand = false; - calculatesub(eo2, eo2, false); - evalSort(true); - if(isAddition()) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isMultiplication() && CHILD(i).size() > 1) { - for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { - if(CHILD(i)[i2].isAddition()) { - for(size_t i3 = i + 1; i3 < SIZE; i3++) { - if(CHILD(i3).isMultiplication() && CHILD(i3).size() > 1) { - for(size_t i4 = 0; i4 < CHILD(i3).size(); i4++) { - if(CHILD(i3)[i4].isAddition() && CHILD(i3)[i4] == CHILD(i)[i2]) { - MathStructure *mfac = &CHILD(i)[i2]; - mfac->ref(); - CHILD(i).delChild(i2 + 1, true); - CHILD(i3).delChild(i4 + 1, true); - CHILD(i3).ref(); - CHILD(i).add_nocopy(&CHILD(i3)); - CHILD(i).calculateAddLast(eo); - CHILD(i).multiply_nocopy(mfac); - CHILD_UPDATED(i) - delChild(i3 + 1, true); - evalSort(true); - factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - return true; - } - } - } - } - if(SIZE > 2) { - MathStructure mtest(*this); - mtest.delChild(i + 1); - if(mtest == CHILD(i)[i2]) { - CHILD(i).delChild(i2 + 1, true); - SET_CHILD_MAP(i); - add(m_one, true); - multiply(mtest); - evalSort(true); - factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); - return true; - } - } - } - } - } - } - } - return true; - } - } - } - return false; -} - -void MathStructure::swapChildren(size_t index1, size_t index2) { - if(index1 > 0 && index2 > 0 && index1 <= SIZE && index2 <= SIZE) { - SWAP_CHILDREN(index1 - 1, index2 - 1) - } -} -void MathStructure::childToFront(size_t index) { - if(index > 0 && index <= SIZE) { - CHILD_TO_FRONT(index - 1) - } -} -void MathStructure::addChild(const MathStructure &o) { - APPEND(o); -} -void MathStructure::addChild_nocopy(MathStructure *o) { - APPEND_POINTER(o); -} -void MathStructure::delChild(size_t index, bool check_size) { - if(index > 0 && index <= SIZE) { - ERASE(index - 1); - if(check_size) { - if(SIZE == 1) setToChild(1, true); - else if(SIZE == 0) clear(true); - } - } -} -void MathStructure::insertChild(const MathStructure &o, size_t index) { - if(index > 0 && index <= v_subs.size()) { - v_order.insert(v_order.begin() + (index - 1), v_subs.size()); - v_subs.push_back(new MathStructure(o)); - CHILD_UPDATED(index - 1); - } else { - addChild(o); - } -} -void MathStructure::insertChild_nocopy(MathStructure *o, size_t index) { - if(index > 0 && index <= v_subs.size()) { - v_order.insert(v_order.begin() + (index - 1), v_subs.size()); - v_subs.push_back(o); - CHILD_UPDATED(index - 1); - } else { - addChild_nocopy(o); - } -} -void MathStructure::setChild(const MathStructure &o, size_t index, bool merge_precision) { - if(index > 0 && index <= SIZE) { - CHILD(index - 1).set(o, merge_precision); - CHILD_UPDATED(index - 1); - } -} -void MathStructure::setChild_nocopy(MathStructure *o, size_t index, bool merge_precision) { - if(index > 0 && index <= SIZE) { - MathStructure *o_prev = v_subs[v_order[index - 1]]; - if(merge_precision) { - if(!o->isApproximate() && o_prev->isApproximate()) o->setApproximate(true); - if(o_prev->precision() >= 0 && (o->precision() < 0 || o_prev->precision() < o->precision())) o->setPrecision(o_prev->precision()); - } - o_prev->unref(); - v_subs[v_order[index - 1]] = o; - CHILD_UPDATED(index - 1); - } -} -const MathStructure *MathStructure::getChild(size_t index) const { - if(index > 0 && index <= v_order.size()) { - return &CHILD(index - 1); - } - return NULL; -} -MathStructure *MathStructure::getChild(size_t index) { - if(index > 0 && index <= v_order.size()) { - return &CHILD(index - 1); - } - return NULL; -} -size_t MathStructure::countChildren() const { - return SIZE; -} -size_t MathStructure::size() const { - return SIZE; -} -const MathStructure *MathStructure::base() const { - if(m_type == STRUCT_POWER && SIZE >= 1) { - return &CHILD(0); - } - return NULL; -} -const MathStructure *MathStructure::exponent() const { - if(m_type == STRUCT_POWER && SIZE >= 2) { - return &CHILD(1); - } - return NULL; -} -MathStructure *MathStructure::base() { - if(m_type == STRUCT_POWER && SIZE >= 1) { - return &CHILD(0); - } - return NULL; -} -MathStructure *MathStructure::exponent() { - if(m_type == STRUCT_POWER && SIZE >= 2) { - return &CHILD(1); - } - return NULL; -} - -StructureType MathStructure::type() const { - return m_type; -} -void MathStructure::unformat(const EvaluationOptions &eo) { - if(m_type == STRUCT_FUNCTION && o_function == CALCULATOR->f_stripunits) { - EvaluationOptions eo2 = eo; - eo2.keep_prefixes = true; - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).unformat(eo2); - } - } else { - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).unformat(eo); - } - } - switch(m_type) { - case STRUCT_INVERSE: { - APPEND(m_minus_one); - m_type = STRUCT_POWER; - break; - } - case STRUCT_NEGATE: { - PREPEND(m_minus_one); - m_type = STRUCT_MULTIPLICATION; - break; - } - case STRUCT_DIVISION: { - CHILD(1).raise(m_minus_one); - m_type = STRUCT_MULTIPLICATION; - break; - } - case STRUCT_UNIT: { - if(o_prefix && !eo.keep_prefixes) { - if(o_prefix == CALCULATOR->decimal_null_prefix || o_prefix == CALCULATOR->binary_null_prefix) { - o_prefix = NULL; - } else { - Unit *u = o_unit; - Prefix *p = o_prefix; - set(p->value()); - multiply(u); - } - unformat(eo); - break; - } else if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) { - set(((CompositeUnit*) o_unit)->generateMathStructure(false, eo.keep_prefixes)); - unformat(eo); - break; - } - b_plural = false; - break; - } - default: {} - } -} - -void idm1(const MathStructure &mnum, bool &bfrac, bool &bint) { - switch(mnum.type()) { - case STRUCT_NUMBER: { - if((!bfrac || bint) && mnum.number().isRational()) { - if(!mnum.number().isInteger()) { - bint = false; - bfrac = true; - } - } else { - bint = false; - } - break; - } - case STRUCT_MULTIPLICATION: { - if((!bfrac || bint) && mnum.size() > 0 && mnum[0].isNumber() && mnum[0].number().isRational()) { - if(!mnum[0].number().isInteger()) { - bint = false; - bfrac = true; - } - - } else { - bint = false; - } - break; - } - case STRUCT_ADDITION: { - bool b_a = false; - for(size_t i = 0; i < mnum.size() && (!bfrac || bint); i++) { - if(mnum[i].isAddition()) b_a = true; - else idm1(mnum[i], bfrac, bint); - } - if(b_a) bint = false; - break; - } - default: { - bint = false; - } - } -} -void idm2(const MathStructure &mnum, bool &bfrac, bool &bint, Number &nr) { - switch(mnum.type()) { - case STRUCT_NUMBER: { - if(mnum.number().isRational()) { - if(mnum.number().isInteger()) { - if(bint) { - if(mnum.number().isOne()) { - bint = false; - } else if(nr.isOne()) { - nr = mnum.number(); - } else if(nr != mnum.number()) { - nr.gcd(mnum.number()); - if(nr.isOne()) bint = false; - } - } - } else { - if(nr.isOne()) { - nr = mnum.number().denominator(); - } else { - Number nden(mnum.number().denominator()); - if(nr != nden) { - Number ngcd(nden); - ngcd.gcd(nr); - nden /= ngcd; - nr *= nden; - } - } - } - } - break; - } - case STRUCT_MULTIPLICATION: { - if(mnum.size() > 0 && mnum[0].isNumber() && mnum[0].number().isRational()) { - if(mnum[0].number().isInteger()) { - if(bint) { - if(mnum[0].number().isOne()) { - bint = false; - } else if(nr.isOne()) { - nr = mnum[0].number(); - } else if(nr != mnum[0].number()) { - nr.gcd(mnum[0].number()); - if(nr.isOne()) bint = false; - } - } - } else { - if(nr.isOne()) { - nr = mnum[0].number().denominator(); - } else { - Number nden(mnum[0].number().denominator()); - if(nr != nden) { - Number ngcd(nden); - ngcd.gcd(nr); - nden /= ngcd; - nr *= nden; - } - } - } - } - break; - } - case STRUCT_ADDITION: { - for(size_t i = 0; i < mnum.size() && (bfrac || bint); i++) { - if(!mnum[i].isAddition()) idm2(mnum[i], bfrac, bint, nr); - } - break; - } - default: {} - } -} -int idm3(MathStructure &mnum, Number &nr, bool expand) { - switch(mnum.type()) { - case STRUCT_NUMBER: { - mnum.number() *= nr; - mnum.numberUpdated(); - break; - } - case STRUCT_MULTIPLICATION: { - if(mnum.size() > 0 && mnum[0].isNumber()) { - mnum[0].number() *= nr; - if(mnum[0].number().isOne() && mnum.size() != 1) { - mnum.delChild(1, true); - } - return -1; - } else if(expand) { - for(size_t i = 0; i < mnum.size(); i++) { - if(mnum[i].isAddition()) { - idm3(mnum[i], nr, true); - return -1; - } - } - } - mnum.insertChild(nr, 1); - return 1; - } - case STRUCT_ADDITION: { - if(expand) { - for(size_t i = 0; i < mnum.size(); i++) { - idm3(mnum[i], nr, true); - } - break; - } - } - default: { - mnum.transform(STRUCT_MULTIPLICATION); - mnum.insertChild(nr, 1); - return -1; - } - } - return 0; -} - -void idm1b(const MathStructure &mnum, bool &bint, bool &bint2) { - switch(mnum.type()) { - case STRUCT_NUMBER: { - if(mnum.number().isInteger() && !mnum.number().isOne()) { - bint = true; - if(mnum.number() > 9 || mnum.number() < -9) bint2 = true; - } else { - bint = false; - } - break; - } - case STRUCT_MULTIPLICATION: { - if(mnum.size() > 0 && mnum[0].isNumber()) { - idm1b(mnum[0], bint, bint2); - } else { - bint = false; - } - break; - } - case STRUCT_ADDITION: { - for(size_t i = 0; i < mnum.size(); i++) { - if(mnum[i].isAddition()) bint = false; - else idm1b(mnum[i], bint, bint2); - if(!bint) break; - } - break; - } - default: { - bint = false; - } - } -} -void idm2b(const MathStructure &mnum, Number &nr) { - switch(mnum.type()) { - case STRUCT_NUMBER: { - if(nr.isZero() || mnum.number() < nr) nr = mnum.number(); - break; - } - case STRUCT_MULTIPLICATION: { - idm2b(mnum[0], nr); - break; - } - case STRUCT_ADDITION: { - for(size_t i = 0; i < mnum.size(); i++) { - idm2b(mnum[i], nr); - } - break; - } - default: {} - } -} -void idm3b(MathStructure &mnum, Number &nr) { - switch(mnum.type()) { - case STRUCT_NUMBER: { - mnum.number() /= nr; - break; - } - case STRUCT_MULTIPLICATION: { - idm3b(mnum[0], nr); - break; - } - case STRUCT_ADDITION: { - for(size_t i = 0; i < mnum.size(); i++) { - idm3b(mnum[i], nr); - } - break; - } - default: {} - } -} - -bool displays_number_exact(Number nr, const PrintOptions &po, MathStructure *top_parent) { - if(po.base == BASE_ROMAN_NUMERALS || po.base == BASE_BIJECTIVE_26) return true; - InternalPrintStruct ips_n; - if(top_parent && top_parent->isApproximate()) ips_n.parent_approximate = true; - if(po.show_ending_zeroes && po.restrict_to_parent_precision && ips_n.parent_approximate && (nr > 9 || nr < -9)) return false; - if(top_parent && top_parent->precision() < 0) ips_n.parent_precision = top_parent->precision(); - bool approximately_displayed = false; - PrintOptions po2 = po; - po2.is_approximate = &approximately_displayed; - nr.print(po2, ips_n); - return !approximately_displayed; -} - -bool fix_approximate_multiplier(MathStructure &m, const PrintOptions &po, MathStructure *top_parent = NULL) { - if(!top_parent) top_parent = &m; - if(po.number_fraction_format == FRACTION_DECIMAL) { - PrintOptions po2 = po; - po2.number_fraction_format = FRACTION_FRACTIONAL; - po2.restrict_fraction_length = true; - return fix_approximate_multiplier(m, po2, top_parent); - } - bool b_ret = false; - if(m.isMultiplication() && m.size() >= 2 && m[0].isNumber() && m[0].number().isRational()) { - for(size_t i = 1; i < m.size(); i++) { - if(m[i].isAddition()) { - bool mul_exact = displays_number_exact(m[0].number(), po, top_parent); - bool b = false; - for(size_t i2 = 0; i2 < m[i].size() && !b; i2++) { - if(m[i][i2].isNumber() && (!mul_exact || !displays_number_exact(m[i][i2].number(), po, top_parent))) { - b = true; - } else if(m[i][i2].isMultiplication() && m[i][i2].size() >= 2 && m[i][i2][0].isNumber() && (!mul_exact || !displays_number_exact(m[i][i2][0].number(), po, top_parent))) { - b = true; - } - } - if(b) { - for(size_t i2 = 0; i2 < m[i].size() && !b; i2++) { - if(m[i][i2].isNumber()) { - if(!m[i][i2].number().multiply(m[0].number())) { - m[i][i2].multiply(m[0]); - } - } else if(m[i][i2].isMultiplication()) { - if(m[i][i2].size() < 2 || !m[i][i2][0].isNumber() || !m[i][i2][0].number().multiply(m[0].number())) { - m[i][i2].insertChild(m[0], 1); - } - } else { - m[i][i2].multiply(m[0]); - m[i][i2].swapChildren(1, 2); - } - } - m.delChild(1, true); - b_ret = true; - break; - } - } - } - } - for(size_t i = 0; i < m.size(); i++) { - if(fix_approximate_multiplier(m[i], po, top_parent)) { - m.childUpdated(i + 1); - b_ret = true; - } - } - return b_ret; -} - -int idm3_test(bool &b_fail, const MathStructure &mnum, const Number &nr, bool expand, const PrintOptions &po, MathStructure *top_parent) { - switch(mnum.type()) { - case STRUCT_NUMBER: { - Number nr2(mnum.number()); - nr2 *= nr; - b_fail = !displays_number_exact(nr2, po, top_parent); - break; - } - case STRUCT_MULTIPLICATION: { - if(mnum.size() > 0 && mnum[0].isNumber()) { - Number nr2(mnum[0].number()); - nr2 *= nr; - b_fail = !nr2.isOne() && !displays_number_exact(nr2, po, top_parent); - return -1; - } else if(expand) { - for(size_t i = 0; i < mnum.size(); i++) { - if(mnum[i].isAddition()) { - idm3_test(b_fail, mnum[i], nr, true, po, top_parent); - return -1; - } - } - } - b_fail = !displays_number_exact(nr, po, top_parent); - return 1; - } - case STRUCT_ADDITION: { - if(expand) { - for(size_t i = 0; i < mnum.size(); i++) { - idm3_test(b_fail, mnum[i], nr, true, po, top_parent); - if(b_fail) break; - } - break; - } - } - default: { - b_fail = !displays_number_exact(nr, po, top_parent); - return -1; - } - } - return 0; -} - -bool is_unit_multiexp(const MathStructure &mstruct) { - if(mstruct.isUnit_exp()) return true; - if(mstruct.isMultiplication()) { - for(size_t i3 = 0; i3 < mstruct.size(); i3++) { - if(!mstruct[i3].isUnit_exp()) { - return false; - break; - } - } - return true; - } - if(mstruct.isPower() && mstruct[0].isMultiplication()) { - for(size_t i3 = 0; i3 < mstruct[0].size(); i3++) { - if(!mstruct[0][i3].isUnit_exp()) { - return false; - break; - } - } - return true; - } - return false; -} - -bool MathStructure::improve_division_multipliers(const PrintOptions &po, MathStructure *top_parent) { - if(!top_parent) top_parent = this; - switch(m_type) { - case STRUCT_MULTIPLICATION: { - size_t inum = 0, iden = 0; - bool bfrac = false, bint = true, bdiv = false, bnonunitdiv = false; - size_t index1 = 0, index2 = 0; - bool dofrac = !po.negative_exponents; - for(size_t i2 = 0; i2 < SIZE; i2++) { - if(CHILD(i2).isPower() && CHILD(i2)[1].isMinusOne()) { - if(!po.place_units_separately || !is_unit_multiexp(CHILD(i2)[0])) { - if(iden == 0) index1 = i2; - iden++; - bdiv = true; - if(!CHILD(i2)[0].isUnit()) bnonunitdiv = true; - if(CHILD(i2)[0].containsType(STRUCT_ADDITION)) { - dofrac = true; - } - } - } else if(!bdiv && !po.negative_exponents && CHILD(i2).isPower() && CHILD(i2)[1].hasNegativeSign()) { - if(!po.place_units_separately || !is_unit_multiexp(CHILD(i2)[0])) { - if(!bdiv) index1 = i2; - bdiv = true; - if(!CHILD(i2)[0].isUnit()) bnonunitdiv = true; - } - } else { - if(!po.place_units_separately || !is_unit_multiexp(CHILD(i2))) { - if(inum == 0) index2 = i2; - inum++; - } - } - } - if(!bdiv || !bnonunitdiv) break; - if(iden > 1 && !po.negative_exponents) { - size_t i2 = index1 + 1; - while(i2 < SIZE) { - if(CHILD(i2).isPower() && CHILD(i2)[1].isMinusOne()) { - CHILD(index1)[0].multiply(CHILD(i2)[0], true); - ERASE(i2); - if(index2 > i2) index2--; - } else { - i2++; - } - } - iden = 1; - } - if(bint) bint = inum > 0 && iden == 1; - if(inum > 0) idm1(CHILD(index2), bfrac, bint); - if(iden > 0) idm1(CHILD(index1)[0], bfrac, bint); - bool b = false; - if(!dofrac) bfrac = false; - if(bint || bfrac) { - Number nr(1, 1); - if(inum > 0) idm2(CHILD(index2), bfrac, bint, nr); - if(iden > 0) idm2(CHILD(index1)[0], bfrac, bint, nr); - if((bint || bfrac) && !nr.isOne()) { - if(bint) nr.recip(); - - bool b_fail = false; - if(inum > 1 && !CHILD(index2).isNumber()) { - int i = idm3_test(b_fail, *this, nr, !po.allow_factorization, po, top_parent); - if(i >= 0 && !b_fail && iden > 0) idm3_test(b_fail, CHILD(index1)[0], nr, !po.allow_factorization, po, top_parent); - } else { - if(inum != 0) idm3_test(b_fail, CHILD(index2), nr, !po.allow_factorization, po, top_parent); - if(!b_fail && iden > 0) idm3_test(b_fail, CHILD(index1)[0], nr, !po.allow_factorization, po, top_parent); - } - if(!b_fail) { - if(inum == 0) { - PREPEND(MathStructure(nr)); - index1 += 1; - } else if(inum > 1 && !CHILD(index2).isNumber()) { - int i = idm3(*this, nr, !po.allow_factorization); - if(i == 1) index1++; - else if(i < 0) iden = 0; - } else { - idm3(CHILD(index2), nr, !po.allow_factorization); - } - if(iden > 0) { - idm3(CHILD(index1)[0], nr, !po.allow_factorization); - } else { - MathStructure mstruct(nr); - mstruct.raise(m_minus_one); - insertChild(mstruct, index1); - } - b = true; - } - } - } - if(!b && po.show_ending_zeroes && po.restrict_to_parent_precision && top_parent->isApproximate() && po.base != BASE_ROMAN_NUMERALS && po.base != BASE_BIJECTIVE_26 && inum > 0 && iden > 0) { - bint = false; - bool bint2 = false; - idm1b(CHILD(index2), bint, bint2); - if(bint) idm1b(CHILD(index1)[0], bint, bint2); - if(bint && bint2) { - Number nr; - idm2b(CHILD(index2), nr); - idm2b(CHILD(index1)[0], nr); - idm3b(CHILD(index2), nr); - idm3b(CHILD(index1)[0], nr); - } - } - return b; - } - case STRUCT_DIVISION: { - bool bint = true, bfrac = false; - idm1(CHILD(0), bfrac, bint); - idm1(CHILD(1), bfrac, bint); - if(bint || bfrac) { - Number nr(1, 1); - idm2(CHILD(0), bfrac, bint, nr); - idm2(CHILD(1), bfrac, bint, nr); - if((bint || bfrac) && !nr.isOne()) { - if(bint) nr.recip(); - - bool b_fail = false; - idm3_test(b_fail, CHILD(0), nr, !po.allow_factorization, po, top_parent); - if(b_fail) return false; - idm3_test(b_fail, CHILD(1), nr, !po.allow_factorization, po, top_parent); - if(b_fail) return false; - - idm3(CHILD(0), nr, !po.allow_factorization); - idm3(CHILD(1), nr, !po.allow_factorization); - return true; - } - } - break; - } - case STRUCT_INVERSE: { - bool bint = false, bfrac = false; - idm1(CHILD(0), bfrac, bint); - if(bint || bfrac) { - Number nr(1, 1); - idm2(CHILD(0), bfrac, bint, nr); - if((bint || bfrac) && !nr.isOne()) { - bool b_fail = false; - idm3_test(b_fail, CHILD(0), nr, !po.allow_factorization, po, top_parent); - if(b_fail) return false; - - setToChild(1, true); - idm3(*this, nr, !po.allow_factorization); - transform_nocopy(STRUCT_DIVISION, new MathStructure(nr)); - SWAP_CHILDREN(0, 1); - return true; - } - } - break; - } - case STRUCT_POWER: { - if(CHILD(1).isMinusOne()) { - bool bint = false, bfrac = false; - idm1(CHILD(0), bfrac, bint); - if(bint || bfrac) { - Number nr(1, 1); - idm2(CHILD(0), bfrac, bint, nr); - if((bint || bfrac) && !nr.isOne()) { - bool b_fail = false; - idm3_test(b_fail, CHILD(0), nr, !po.allow_factorization, po, top_parent); - if(b_fail) return false; - - idm3(CHILD(0), nr, !po.allow_factorization); - transform(STRUCT_MULTIPLICATION); - PREPEND(MathStructure(nr)); - return true; - } - } - break; - } - } - default: { - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) break; - if(CHILD(i).improve_division_multipliers(po, top_parent)) b = true; - } - return b; - } - } - return false; -} - -bool use_prefix_with_unit(Unit *u, const PrintOptions &po) { - if(!po.prefix && !po.use_unit_prefixes) {return u->referenceName() == "g" || u->referenceName() == "a";} - if(po.prefix) return true; - if(u->isCurrency()) return po.use_prefixes_for_currencies; - if(po.use_prefixes_for_all_units) return true; - return u->useWithPrefixesByDefault(); -} -bool use_prefix_with_unit(const MathStructure &mstruct, const PrintOptions &po) { - if(mstruct.isUnit()) return use_prefix_with_unit(mstruct.unit(), po); - if(mstruct.isUnit_exp()) return use_prefix_with_unit(mstruct[0].unit(), po); - return false; -} - -bool has_prefix(const MathStructure &mstruct) { - if(mstruct.isUnit()) return mstruct.prefix() != NULL; - for(size_t i = 0; i < mstruct.size(); i++) { - if(has_prefix(mstruct[i])) return true; - } - return false; -} - -void MathStructure::setPrefixes(const PrintOptions &po, MathStructure *parent, size_t pindex) { - switch(m_type) { - case STRUCT_MULTIPLICATION: { - bool b = false; - size_t i = SIZE, im = 0; - bool b_im = false; - for(size_t i2 = 0; i2 < SIZE; i2++) { - if(CHILD(i2).isUnit_exp()) { - if(CHILD(i2).unit_exp_prefix()) { - b = false; - return; - } - if(!b) { - if(use_prefix_with_unit(CHILD(i2), po)) { - b = true; - if(i > i2) {i = i2; b_im = false;} - } else if(i < i2) { - i = i2; - b_im = false; - } - } - } else if(CHILD(i2).isPower() && CHILD(i2)[0].isMultiplication()) { - for(size_t i3 = 0; i3 < CHILD(i2)[0].size(); i3++) { - if(CHILD(i2)[0][i3].isUnit_exp()) { - if(CHILD(i2)[0][i3].unit_exp_prefix()) { - b = false; - return; - } - if(!b) { - if(use_prefix_with_unit(CHILD(i2)[0][i3], po)) { - b = true; - if(i > i2) { - i = i2; - im = i3; - b_im = true; - } - break; - } else if(i < i2 || (i == i2 && im < i3)) { - i = i2; - im = i3; - b_im = true; - } - } - } - } - } - } - if(b) { - Number exp(1, 1); - Number exp2(1, 1); - bool b2 = false; - MathStructure *munit = NULL, *munit2 = NULL; - if(b_im) munit = &CHILD(i)[0][im]; - else munit = &CHILD(i); - if(CHILD(i).isPower()) { - if(CHILD(i)[1].isNumber() && CHILD(i)[1].number().isInteger() && !CHILD(i)[1].number().isZero()) { - if(b_im && munit->isPower()) { - if((*munit)[1].isNumber() && (*munit)[1].number().isInteger() && !(*munit)[1].number().isZero()) { - exp = CHILD(i)[1].number(); - exp *= (*munit)[1].number(); - } else { - b = false; - } - } else { - exp = CHILD(i)[1].number(); - } - } else { - b = false; - } - } - if(po.use_denominator_prefix && !exp.isNegative()) { - for(size_t i2 = i + 1; i2 < SIZE; i2++) { - if(CALCULATOR->aborted()) break; - if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isNegative()) { - if(CHILD(i2)[0].isUnit() && use_prefix_with_unit(CHILD(i2)[0], po)) { - munit2 = &CHILD(i2)[0]; - if(munit2->prefix() || !CHILD(i2)[1].number().isInteger()) { - break; - } - if(!b) { - b = true; - exp = CHILD(i2)[1].number(); - munit = munit2; - } else { - b2 = true; - exp2 = CHILD(i2)[1].number(); - } - break; - } else if(CHILD(i2)[0].isMultiplication()) { - bool b_break = false; - for(size_t im2 = 0; im2 < CHILD(i2)[0].size(); im2++) { - if(CHILD(i2)[0][im2].isUnit_exp() && use_prefix_with_unit(CHILD(i2)[0][im2], po) && (CHILD(i2)[0][im2].isUnit() || (CHILD(i2)[0][im2][1].isNumber() && (CHILD(i2)[0][im2][1].number().isPositive() || (!b && CHILD(i2)[0][im2][1].number().isNegative())) && CHILD(i2)[0][im2][1].number().isInteger()))) { - Number exp_multi(1); - if(CHILD(i2)[0][im2].isUnit()) { - munit2 = &CHILD(i2)[0][im2]; - } else { - munit2 = &CHILD(i2)[0][im2][0]; - exp_multi = CHILD(i2)[0][im2][1].number(); - } - b_break = true; - if(munit2->prefix() || !CHILD(i2)[1].number().isInteger()) { - break; - } - if(!b) { - b = true; - exp = CHILD(i2)[1].number(); - exp *= exp_multi; - i = i2; - } else { - b2 = true; - exp2 = CHILD(i2)[1].number(); - exp2 *= exp_multi; - } - break; - } - } - if(b_break) break; - } - } - } - } else if(exp.isNegative() && b) { - bool had_unit = false; - for(size_t i2 = i + 1; i2 < SIZE; i2++) { - if(CALCULATOR->aborted()) break; - bool b3 = false; - if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isPositive()) { - if(CHILD(i2)[0].isUnit()) { - if(!use_prefix_with_unit(CHILD(i2)[0], po)) { - had_unit = true; - } else { - munit2 = &CHILD(i2); - if(munit2->prefix() || !CHILD(i2)[1].number().isInteger()) { - break; - } - b3 = true; - exp2 = exp; - exp = CHILD(i2)[1].number(); - } - } else if(CHILD(i2)[0].isMultiplication()) { - bool b_break = false; - for(size_t im2 = 0; im2 < CHILD(i2)[0].size(); im2++) { - if(CHILD(i2)[0][im2].isUnit_exp() && (CHILD(i2)[0][im2].isUnit() || (CHILD(i2)[0][im2][1].isNumber() && CHILD(i2)[0][im2][1].number().isPositive() && CHILD(i2)[0][im2][1].number().isInteger()))) { - if(!use_prefix_with_unit(CHILD(i2)[0][im2], po)) { - had_unit = true; - } else { - Number exp_multi(1); - if(CHILD(i2)[0][im2].isUnit()) { - munit2 = &CHILD(i2)[0][im2]; - } else { - munit2 = &CHILD(i2)[0][im2][0]; - exp_multi = CHILD(i2)[0][im2][1].number(); - } - b_break = true; - if(munit2->prefix() || !CHILD(i2)[1].number().isInteger()) { - break; - } - exp2 = exp; - exp = CHILD(i2)[1].number(); - exp *= exp_multi; - b3 = true; - break; - } - } - } - if(b_break) break; - } - } else if(CHILD(i2).isUnit()) { - if(!use_prefix_with_unit(CHILD(i2), po)) { - had_unit = true; - } else { - if(CHILD(i2).prefix()) break; - exp2 = exp; - exp.set(1, 1, 0); - b3 = true; - munit2 = &CHILD(i2); - } - } - if(b3) { - if(po.use_denominator_prefix) { - b2 = true; - MathStructure *munit3 = munit; - munit = munit2; - munit2 = munit3; - } else { - munit = munit2; - } - had_unit = false; - break; - } - } - if(had_unit && !po.use_denominator_prefix) b = false; - } - Number exp10; - if(b) { - if(po.prefix) { - if(po.prefix != CALCULATOR->decimal_null_prefix && po.prefix != CALCULATOR->binary_null_prefix) { - if(munit->isUnit()) munit->setPrefix(po.prefix); - else (*munit)[0].setPrefix(po.prefix); - if(CHILD(0).isNumber()) { - CHILD(0).number() /= po.prefix->value(exp); - } else { - PREPEND(po.prefix->value(exp)); - CHILD(0).number().recip(); - } - } - } else if(po.use_unit_prefixes && CHILD(0).isNumber() && exp.isInteger()) { - exp10 = CHILD(0).number(); - exp10.abs(); - exp10.intervalToMidValue(); - if(exp10.isLessThanOrEqualTo(Number(1, 1, 1000)) && exp10.isGreaterThanOrEqualTo(Number(1, 1, -1000))) { - bool use_binary_prefix = (CALCULATOR->usesBinaryPrefixes() > 1 || (CALCULATOR->usesBinaryPrefixes() == 1 && ((munit->isUnit() && munit->unit()->baseUnit()->referenceName() == "bit") || (munit->isPower() && (*munit)[0].unit()->baseUnit()->referenceName() == "bit")))); - exp10.log(use_binary_prefix ? 2 : 10); - exp10.intervalToMidValue(); - exp10.floor(); - if(b2 && exp10.isPositive() && (CALCULATOR->usesBinaryPrefixes() > 1 || (CALCULATOR->usesBinaryPrefixes() == 1 && ((munit2->isUnit() && munit2->unit()->baseUnit()->referenceName() == "bit") || (munit2->isPower() && (*munit2)[0].unit()->baseUnit()->referenceName() == "bit"))))) b2 = false; - if(b2 && use_binary_prefix && CALCULATOR->usesBinaryPrefixes() == 1 && exp10.isNegative()) { - exp10.clear(); - } else if(b2) { - Number tmp_exp(exp10); - tmp_exp.setNegative(false); - Number e1(use_binary_prefix ? 10 : 3, 1, 0); - e1 *= exp; - Number e2(use_binary_prefix ? 10 : 3, 1, 0); - e2 *= exp2; - e2.setNegative(false); - int i4 = 0; - while(true) { - tmp_exp -= e1; - if(!tmp_exp.isPositive()) { - break; - } - if(exp10.isNegative()) i4++; - tmp_exp -= e2; - if(tmp_exp.isNegative()) { - break; - } - if(!exp10.isNegative()) i4++; - } - e2.setNegative(exp10.isNegative()); - e2 *= i4; - exp10 -= e2; - } - Prefix *p = (use_binary_prefix > 0 ? (Prefix*) CALCULATOR->getOptimalBinaryPrefix(exp10, exp) : (Prefix*) CALCULATOR->getOptimalDecimalPrefix(exp10, exp, po.use_all_prefixes)); - if(p) { - Number test_exp(exp10); - if(use_binary_prefix) test_exp -= ((BinaryPrefix*) p)->exponent(exp); - else test_exp -= ((DecimalPrefix*) p)->exponent(exp); - if(test_exp.isInteger()) { - if((exp10.isPositive() && exp10.compare(test_exp) == COMPARISON_RESULT_LESS) || (exp10.isNegative() && exp10.compare(test_exp) == COMPARISON_RESULT_GREATER)) { - CHILD(0).number() /= p->value(exp); - if(munit->isUnit()) munit->setPrefix(p); - else (*munit)[0].setPrefix(p); - } - } - } - } - } else if(!po.use_unit_prefixes) { - Prefix *p = NULL; - if((munit->isUnit() && munit->unit()->referenceName() == "g") || (munit->isPower() && (*munit)[0].unit()->referenceName() == "g")) { - p = CALCULATOR->getExactDecimalPrefix(3); - } else if((munit->isUnit() && munit->unit()->referenceName() == "a") || (munit->isPower() && (*munit)[0].unit()->referenceName() == "a")) { - p = CALCULATOR->getExactDecimalPrefix(2); - } - if(p) { - if(munit->isUnit()) munit->setPrefix(p); - else (*munit)[0].setPrefix(p); - if(CHILD(0).isNumber()) { - CHILD(0).number() /= p->value(exp); - } else { - PREPEND(p->value(exp)); - CHILD(0).number().recip(); - } - } - } - if(b2 && CHILD(0).isNumber() && (po.prefix || po.use_unit_prefixes) && (po.prefix != CALCULATOR->decimal_null_prefix && po.prefix != CALCULATOR->binary_null_prefix)) { - exp10 = CHILD(0).number(); - exp10.abs(); - exp10.intervalToMidValue(); - if(exp10.isLessThanOrEqualTo(Number(1, 1, 1000)) && exp10.isGreaterThanOrEqualTo(Number(1, 1, -1000))) { - bool use_binary_prefix = (CALCULATOR->usesBinaryPrefixes() > 1 || (CALCULATOR->usesBinaryPrefixes() == 1 && ((munit2->isUnit() && munit2->unit()->baseUnit()->referenceName() == "bit") || (munit2->isPower() && (*munit2)[0].unit()->baseUnit()->referenceName() == "bit")))); - exp10.log(use_binary_prefix ? 2 : 10); - exp10.intervalToMidValue(); - exp10.floor(); - Prefix *p = (use_binary_prefix > 0 ? (Prefix*) CALCULATOR->getOptimalBinaryPrefix(exp10, exp2) : (Prefix*) CALCULATOR->getOptimalDecimalPrefix(exp10, exp2, po.use_all_prefixes)); - if(p) { - Number test_exp(exp10); - if(use_binary_prefix) test_exp -= ((BinaryPrefix*) p)->exponent(exp2); - else test_exp -= ((DecimalPrefix*) p)->exponent(exp2); - if(test_exp.isInteger()) { - if((exp10.isPositive() && exp10.compare(test_exp) == COMPARISON_RESULT_LESS) || (exp10.isNegative() && exp10.compare(test_exp) == COMPARISON_RESULT_GREATER)) { - CHILD(0).number() /= p->value(exp2); - if(munit2->isUnit()) munit2->setPrefix(p); - else (*munit2)[0].setPrefix(p); - } - } - } - } - } - } - return; - } - break; - } - case STRUCT_UNIT: { - if(!o_prefix && (po.prefix && po.prefix != CALCULATOR->decimal_null_prefix && po.prefix != CALCULATOR->binary_null_prefix)) { - transform(STRUCT_MULTIPLICATION, m_one); - SWAP_CHILDREN(0, 1); - setPrefixes(po, parent, pindex); - } - return; - } - case STRUCT_POWER: { - if(CHILD(0).isUnit()) { - if(CHILD(1).isNumber() && CHILD(1).number().isReal() && !CHILD(0).prefix() && !o_prefix && (po.prefix && po.prefix != CALCULATOR->decimal_null_prefix && po.prefix != CALCULATOR->binary_null_prefix)) { - transform(STRUCT_MULTIPLICATION, m_one); - SWAP_CHILDREN(0, 1); - setPrefixes(po, parent, pindex); - } - return; - } - break; - } - default: {} - } - if(po.prefix || !has_prefix(*this)) { - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) break; - CHILD(i).setPrefixes(po, this, i + 1); - } - } -} -bool split_unit_powers(MathStructure &mstruct); -bool split_unit_powers(MathStructure &mstruct) { - bool b = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(CALCULATOR->aborted()) break; - if(split_unit_powers(mstruct[i])) { - mstruct.childUpdated(i + 1); - b = true; - } - } - if(mstruct.isPower() && mstruct[0].isMultiplication()) { - bool b2 = mstruct[1].isNumber(); - for(size_t i = 0; i < mstruct[0].size(); i++) { - if(mstruct[0][i].isPower() && (!b2 || !mstruct[0][i][1].isNumber())) return b; - } - MathStructure mpower(mstruct[1]); - mstruct.setToChild(1); - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isPower()) mstruct[i][1].number() *= mpower.number(); - else mstruct[i].raise(mpower); - } - mstruct.childrenUpdated(); - return true; - } - return b; -} -void MathStructure::postFormatUnits(const PrintOptions &po, MathStructure*, size_t) { - switch(m_type) { - case STRUCT_DIVISION: { - if(po.place_units_separately) { - vector nums; - bool b1 = false, b2 = false; - if(CHILD(0).isMultiplication()) { - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CHILD(0)[i].isUnit_exp()) { - nums.push_back(i); - } else { - b1 = true; - } - } - b1 = b1 && !nums.empty(); - } else if(CHILD(0).isUnit_exp()) { - b1 = true; - } - vector dens; - if(CHILD(1).isMultiplication()) { - for(size_t i = 0; i < CHILD(1).size(); i++) { - if(CHILD(1)[i].isUnit_exp()) { - dens.push_back(i); - } else { - b2 = true; - } - } - b2 = b2 && !dens.empty(); - } else if(CHILD(1).isUnit_exp()) { - if(CHILD(0).isUnit_exp()) { - b1 = false; - } else { - b2 = true; - } - } - if(b2 && !b1) b1 = true; - if(b1) { - MathStructure num = m_undefined; - if(CHILD(0).isUnit_exp()) { - num = CHILD(0); - CHILD(0).set(m_one); - } else if(nums.size() > 0) { - num = CHILD(0)[nums[0]]; - for(size_t i = 1; i < nums.size(); i++) { - num.multiply(CHILD(0)[nums[i]], i > 1); - } - for(size_t i = 0; i < nums.size(); i++) { - CHILD(0).delChild(nums[i] + 1 - i); - } - if(CHILD(0).size() == 1) { - CHILD(0).setToChild(1, true); - } - } - MathStructure den = m_undefined; - if(CHILD(1).isUnit_exp()) { - den = CHILD(1); - setToChild(1, true); - } else if(dens.size() > 0) { - den = CHILD(1)[dens[0]]; - for(size_t i = 1; i < dens.size(); i++) { - den.multiply(CHILD(1)[dens[i]], i > 1); - } - for(size_t i = 0; i < dens.size(); i++) { - CHILD(1).delChild(dens[i] + 1 - i); - } - if(CHILD(1).size() == 1) { - CHILD(1).setToChild(1, true); - } - } - if(num.isUndefined()) { - transform(STRUCT_DIVISION, den); - } else { - if(!den.isUndefined()) { - num.transform(STRUCT_DIVISION, den); - } - multiply(num, false); - } - if(CHILD(0).isDivision()) { - if(CHILD(0)[0].isMultiplication()) { - if(CHILD(0)[0].size() == 1) { - CHILD(0)[0].setToChild(1, true); - } else if(CHILD(0)[0].size() == 0) { - CHILD(0)[0] = 1; - } - } - if(CHILD(0)[1].isMultiplication()) { - if(CHILD(0)[1].size() == 1) { - CHILD(0)[1].setToChild(1, true); - } else if(CHILD(0)[1].size() == 0) { - CHILD(0).setToChild(1, true); - } - } else if(CHILD(0)[1].isOne()) { - CHILD(0).setToChild(1, true); - } - if(CHILD(0).isDivision() && CHILD(0)[1].isNumber() && CHILD(0)[0].isMultiplication() && CHILD(0)[0].size() > 1 && CHILD(0)[0][0].isNumber()) { - MathStructure *msave = new MathStructure; - if(CHILD(0)[0].size() == 2) { - msave->set(CHILD(0)[0][1]); - CHILD(0)[0].setToChild(1, true); - } else { - msave->set(CHILD(0)[0]); - CHILD(0)[0].setToChild(1, true); - msave->delChild(1); - } - if(isMultiplication()) { - insertChild_nocopy(msave, 2); - } else { - CHILD(0).multiply_nocopy(msave); - } - } - } - bool do_plural = po.short_multiplication; - CHILD(0).postFormatUnits(po, this, 1); - CHILD_UPDATED(0); - switch(CHILD(0).type()) { - case STRUCT_NUMBER: { - if(CHILD(0).isZero() || CHILD(0).number().isOne() || CHILD(0).number().isMinusOne() || CHILD(0).number().isFraction()) { - do_plural = false; - } - break; - } - case STRUCT_DIVISION: { - if(CHILD(0)[0].isNumber() && CHILD(0)[1].isNumber()) { - if(CHILD(0)[0].number().isLessThanOrEqualTo(CHILD(0)[1].number())) { - do_plural = false; - } - } - break; - } - case STRUCT_INVERSE: { - if(CHILD(0)[0].isNumber() && CHILD(0)[0].number().isGreaterThanOrEqualTo(1)) { - do_plural = false; - } - break; - } - default: {} - } - split_unit_powers(CHILD(1)); - switch(CHILD(1).type()) { - case STRUCT_UNIT: { - CHILD(1).setPlural(do_plural); - break; - } - case STRUCT_POWER: { - CHILD(1)[0].setPlural(do_plural); - break; - } - case STRUCT_MULTIPLICATION: { - if(po.limit_implicit_multiplication) CHILD(1)[0].setPlural(do_plural); - else CHILD(1)[CHILD(1).size() - 1].setPlural(do_plural); - break; - } - case STRUCT_DIVISION: { - switch(CHILD(1)[0].type()) { - case STRUCT_UNIT: { - CHILD(1)[0].setPlural(do_plural); - break; - } - case STRUCT_POWER: { - CHILD(1)[0][0].setPlural(do_plural); - break; - } - case STRUCT_MULTIPLICATION: { - if(po.limit_implicit_multiplication) CHILD(1)[0][0].setPlural(do_plural); - else CHILD(1)[0][CHILD(1)[0].size() - 1].setPlural(do_plural); - break; - } - default: {} - } - break; - } - default: {} - } - } - } else { - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) break; - CHILD(i).postFormatUnits(po, this, i + 1); - CHILD_UPDATED(i); - } - } - break; - } - case STRUCT_UNIT: { - b_plural = false; - break; - } - case STRUCT_MULTIPLICATION: { - if(SIZE > 1 && CHILD(1).isUnit_exp() && CHILD(0).isNumber()) { - bool do_plural = po.short_multiplication && !(CHILD(0).isZero() || CHILD(0).number().isOne() || CHILD(0).number().isMinusOne() || CHILD(0).number().isFraction()); - size_t i = 2; - for(; i < SIZE; i++) { - if(CALCULATOR->aborted()) break; - if(CHILD(i).isUnit()) { - CHILD(i).setPlural(false); - } else if(CHILD(i).isPower() && CHILD(i)[0].isUnit()) { - CHILD(i)[0].setPlural(false); - } else { - break; - } - } - if(do_plural) { - if(po.limit_implicit_multiplication) i = 1; - else i--; - if(CHILD(i).isUnit()) { - CHILD(i).setPlural(true); - } else { - CHILD(i)[0].setPlural(true); - } - } - } else if(SIZE > 0) { - int last_unit = -1; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) break; - if(CHILD(i).isUnit()) { - CHILD(i).setPlural(false); - if(!po.limit_implicit_multiplication || last_unit < 0) { - last_unit = i; - } - } else if(CHILD(i).isPower() && CHILD(i)[0].isUnit()) { - CHILD(i)[0].setPlural(false); - if(!po.limit_implicit_multiplication || last_unit < 0) { - last_unit = i; - } - } else if(last_unit >= 0) { - break; - } - } - if(po.short_multiplication && last_unit > 0) { - if(CHILD(last_unit).isUnit()) { - CHILD(last_unit).setPlural(true); - } else { - CHILD(last_unit)[0].setPlural(true); - } - } - } - break; - } - case STRUCT_POWER: { - if(CHILD(0).isUnit()) { - CHILD(0).setPlural(false); - break; - } - } - default: { - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) break; - CHILD(i).postFormatUnits(po, this, i + 1); - CHILD_UPDATED(i); - } - } - } -} -bool MathStructure::factorizeUnits() { - switch(m_type) { - case STRUCT_ADDITION: { - if(containsType(STRUCT_DATETIME, false, true, false) > 0) return false; - bool b = false; - MathStructure mstruct_units(*this); - MathStructure mstruct_new(*this); - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(CALCULATOR->aborted()) break; - if(mstruct_units[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct_units[i].size();) { - if(CALCULATOR->aborted()) break; - if(!mstruct_units[i][i2].isUnit_exp()) { - mstruct_units[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); - else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); - for(size_t i2 = 0; i2 < mstruct_new[i].size();) { - if(CALCULATOR->aborted()) break; - if(mstruct_new[i][i2].isUnit_exp()) { - mstruct_new[i].delChild(i2 + 1); - } else { - i2++; - } - } - if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); - else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); - } else if(mstruct_units[i].isUnit_exp()) { - mstruct_new[i].set(1, 1, 0); - } else { - mstruct_units[i].setUndefined(); - } - } - for(size_t i = 0; i < mstruct_units.size(); i++) { - if(CALCULATOR->aborted()) break; - if(!mstruct_units[i].isUndefined()) { - for(size_t i2 = i + 1; i2 < mstruct_units.size();) { - if(mstruct_units[i2] == mstruct_units[i]) { - mstruct_new[i].add(mstruct_new[i2], true); - mstruct_new.delChild(i2 + 1); - mstruct_units.delChild(i2 + 1); - b = true; - } else { - i2++; - } - } - if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); - else mstruct_new[i].multiply(mstruct_units[i], true); - } - } - if(b) { - if(mstruct_new.size() == 1) set(mstruct_new[0], true); - else set(mstruct_new, true); - return true; - } - } - default: { - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) break; - if(CHILD(i).factorizeUnits()) { - CHILD_UPDATED(i); - b = true; - } - } - return b; - } - } -} -void MathStructure::prefixCurrencies(const PrintOptions &po) { - if(isMultiplication()) { - int index = -1; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) break; - if(CHILD(i).isUnit_exp()) { - if(CHILD(i).isUnit() && CHILD(i).unit()->isCurrency()) { - const ExpressionName *ename = &CHILD(i).unit()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, CHILD(i).isPlural(), po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); - bool do_prefix = false; - if(ename->reference) do_prefix = (hasNegativeSign() ? CALCULATOR->place_currency_code_before_negative : CALCULATOR->place_currency_code_before); - else if(ename->abbreviation) do_prefix = (hasNegativeSign() ? CALCULATOR->place_currency_sign_before_negative : CALCULATOR->place_currency_sign_before); - if(!do_prefix || index >= 0) { - index = -1; - break; - } - index = i; - } else { - index = -1; - break; - } - } - } - if(index >= 0) { - v_order.insert(v_order.begin(), v_order[index]); - v_order.erase(v_order.begin() + (index + 1)); - } - } else { - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) break; - CHILD(i).prefixCurrencies(po); - } - } -} -void remove_multi_one(MathStructure &mstruct) { - if(mstruct.isMultiplication() && mstruct.size() > 1) { - if(mstruct[0].isOne() && !mstruct[1].isUnit_exp() && (mstruct.size() != 2 || !mstruct[1].isFunction() || mstruct[1].function()->referenceName() != "cis" || mstruct[1].size() != 1)) { - if(mstruct.size() == 2) mstruct.setToChild(2, true); - else mstruct.delChild(1); - } - } - for(size_t i = 0; i < mstruct.size(); i++) { - if(CALCULATOR->aborted()) break; - remove_multi_one(mstruct[i]); - } -} -bool unnegate_multiplier(MathStructure &mstruct, const PrintOptions &po) { - if(mstruct.isMultiplication() && mstruct.size() >= 2 && mstruct[0].isNumber() && mstruct[0].number().isNegative()) { - for(size_t i = 1; i < mstruct.size(); i++) { - if(CALCULATOR->aborted()) break; - if(mstruct[i].isAddition() || (mstruct[i].isPower() && mstruct[i][0].isAddition() && mstruct[i][1].isMinusOne())) { - MathStructure *mden; - if(mstruct[i].isAddition()) mden = &mstruct[i]; - else mden = &mstruct[i][0]; - bool b_pos = false, b_neg = false; - for(size_t i2 = 0; i2 < mden->size(); i2++) { - if((*mden)[i2].hasNegativeSign()) { - b_neg = true; - } else { - b_pos = true; - } - if(b_neg && b_pos) break; - } - if(b_neg && b_pos) { - for(size_t i2 = 0; i2 < mden->size(); i2++) { - if((*mden)[i2].isNumber()) { - (*mden)[i2].number().negate(); - } else if((*mden)[i2].isMultiplication() && (*mden)[i2].size() > 0) { - if((*mden)[i2][0].isNumber()) { - if((*mden)[i2][0].number().isMinusOne() && (*mden)[i2].size() > 1) { - if((*mden)[i2].size() == 2) (*mden)[i2].setToChild(2, true); - else (*mden)[i2].delChild(1); - } else (*mden)[i2][0].number().negate(); - } else { - (*mden)[i2].insertChild(m_minus_one, 1); - } - } else { - (*mden)[i2].negate(); - } - } - mden->sort(po, false); - if(mstruct[0].number().isMinusOne()) { - if(mstruct.size() == 2) mstruct.setToChild(2, true); - else mstruct.delChild(1); - } else { - mstruct[0].number().negate(); - } - return true; - } - } - } - } - bool b = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(CALCULATOR->aborted()) break; - if(unnegate_multiplier(mstruct[i], po)) { - b = true; - } - } - if(b) { - mstruct.sort(po, false); - return true; - } - return false; -} -Unit *default_angle_unit(const EvaluationOptions &eo) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {return CALCULATOR->getDegUnit();} - case ANGLE_UNIT_GRADIANS: {return CALCULATOR->getGraUnit();} - case ANGLE_UNIT_RADIANS: {return CALCULATOR->getRadUnit();} - default: {} - } - return NULL; -} - -bool remove_angle_unit(MathStructure &m, Unit *u) { - bool b_ret = false; - for(size_t i = 0; i < m.size(); i++) { - if(remove_angle_unit(m[i], u)) b_ret = true; - if(m.isFunction() && m.function()->getArgumentDefinition(i + 1) && m.function()->getArgumentDefinition(i + 1)->type() == ARGUMENT_TYPE_ANGLE) { - if(m[i].isMultiplication()) { - for(size_t i3 = 0; i3 < m[i].size(); i3++) { - if(m[i][i3].isUnit() && !m[i][i3].prefix() && m[i][i3].unit() == u) { - m[i].delChild(i3 + 1, true); - b_ret = true; - break; - } - } - } else if(m[i].isAddition()) { - bool b = true; - for(size_t i2 = 0; i2 < m[i].size(); i2++) { - bool b2 = false; - if(m[i][i2].isMultiplication()) { - for(size_t i3 = 0; i3 < m[i][i2].size(); i3++) { - if(m[i][i2][i3].isUnit() && !m[i][i2][i3].prefix() && m[i][i2][i3].unit() == u) { - b2 = true; - break; - } - } - } - if(!b2) { - b = false; - break; - } - } - if(b) { - b_ret = true; - for(size_t i2 = 0; i2 < m[i].size(); i2++) { - for(size_t i3 = 0; i3 < m[i][i2].size(); i3++) { - if(m[i][i2][i3].isUnit() && !m[i][i2][i3].prefix() && m[i][i2][i3].unit() == u) { - m[i][i2].delChild(i3 + 1, true); - break; - } - } - } - } - } - } - } - return b_ret; -} -bool MathStructure::removeDefaultAngleUnit(const EvaluationOptions &eo) { - Unit *u = default_angle_unit(eo); - if(!u) return false; - return remove_angle_unit(*this, u); -} -void MathStructure::format(const PrintOptions &po) { - if(!po.preserve_format) { - if(po.place_units_separately) { - factorizeUnits(); - } - sort(po); - setPrefixes(po); - unnegate_multiplier(*this, po); - fix_approximate_multiplier(*this, po); - if(po.improve_division_multipliers) { - if(improve_division_multipliers(po)) sort(po); - } - remove_multi_one(*this); - } - formatsub(po, NULL, 0, true, this); - if(!po.preserve_format) { - postFormatUnits(po); - if(po.sort_options.prefix_currencies) { - prefixCurrencies(po); - } - } -} - -bool MathStructure::complexToExponentialForm(const EvaluationOptions &eo) { - if(m_type == STRUCT_NUMBER && o_number.hasImaginaryPart()) { - EvaluationOptions eo2 = eo; - eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; - eo2.parse_options.angle_unit = ANGLE_UNIT_RADIANS; - MathStructure mabs(CALCULATOR->f_abs, this, NULL); - MathStructure marg(CALCULATOR->f_arg, this, NULL); - marg *= nr_one_i; - marg.eval(eo2); - set(CALCULATOR->v_e, true); - raise(marg); - mabs.eval(eo2); - if(!mabs.isOne()) multiply(mabs); - evalSort(false); - return true; - } - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).complexToExponentialForm(eo)) {b = true; CHILD_UPDATED(i);} - } - return b; -} -bool MathStructure::complexToPolarForm(const EvaluationOptions &eo) { - if(m_type == STRUCT_NUMBER && o_number.hasImaginaryPart()) { - MathStructure mabs(CALCULATOR->f_abs, this, NULL); - MathStructure marg(CALCULATOR->f_arg, this, NULL); - EvaluationOptions eo2 = eo; - eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; - mabs.eval(eo2); - marg.eval(eo2); - switch(eo2.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {marg.multiply(CALCULATOR->getDegUnit(), true);} break;} - case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {marg.multiply(CALCULATOR->getGraUnit(), true);} break;} - case ANGLE_UNIT_RADIANS: {if(CALCULATOR->getRadUnit()) {marg.multiply(CALCULATOR->getRadUnit(), true);} break;} - default: {break;} - } - set(marg, true); - transform(CALCULATOR->f_sin); - multiply(nr_one_i); - add_nocopy(new MathStructure(CALCULATOR->f_cos, &marg, NULL)); - if(!mabs.isOne()) multiply(mabs); - evalSort(true); - return true; - } else if(m_type == STRUCT_POWER && CHILD(0).isVariable() && CHILD(0).variable() == CALCULATOR->v_e && CHILD(1).isNumber() && CHILD(1).number().hasImaginaryPart() && !CHILD(1).number().hasRealPart()) { - MathStructure marg(CHILD(1).number().imaginaryPart()); - EvaluationOptions eo2 = eo; - eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; - switch(eo2.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {marg.calculateMultiply(Number(180, 1), eo2); marg.calculateDivide(CALCULATOR->v_pi, eo2); marg.multiply(CALCULATOR->getDegUnit(), true);} break;} - case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {marg.calculateMultiply(Number(200, 1), eo2); marg.calculateDivide(CALCULATOR->v_pi, eo2); marg.multiply(CALCULATOR->getGraUnit(), true);} break;} - case ANGLE_UNIT_RADIANS: {if(CALCULATOR->getRadUnit()) {marg.multiply(CALCULATOR->getRadUnit(), true);} break;} - default: {break;} - } - set(marg, true); - transform(CALCULATOR->f_sin); - multiply(nr_one_i); - add_nocopy(new MathStructure(CALCULATOR->f_cos, &marg, NULL)); - evalSort(true); - return true; - } else if(m_type == STRUCT_MULTIPLICATION && SIZE == 2 && CHILD(1).isPower() && CHILD(1)[0].isVariable() && CHILD(1)[0].variable() == CALCULATOR->v_e && CHILD(1)[1].isNumber() && CHILD(1)[1].number().hasImaginaryPart() && !CHILD(1)[1].number().hasRealPart() && CHILD(0).isNumber() && !CHILD(0).number().hasImaginaryPart()) { - MathStructure marg(CHILD(1)[1].number().imaginaryPart()); - EvaluationOptions eo2 = eo; - eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; - switch(eo2.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {marg.calculateMultiply(Number(180, 1), eo2); marg.calculateDivide(CALCULATOR->v_pi, eo2); marg.multiply(CALCULATOR->getDegUnit(), true);} break;} - case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {marg.calculateMultiply(Number(200, 1), eo2); marg.calculateDivide(CALCULATOR->v_pi, eo2); marg.multiply(CALCULATOR->getGraUnit(), true);} break;} - case ANGLE_UNIT_RADIANS: {if(CALCULATOR->getRadUnit()) {marg.multiply(CALCULATOR->getRadUnit(), true);} break;} - default: {break;} - } - CHILD(1).set(marg, true); - CHILD(1).transform(CALCULATOR->f_sin); - CHILD(1).multiply(nr_one_i); - CHILD(1).add_nocopy(new MathStructure(CALCULATOR->f_cos, &marg, NULL)); - CHILD_UPDATED(1) - evalSort(true); - return true; - } - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).complexToPolarForm(eo)) {b = true; CHILD_UPDATED(i);} - } - return b; -} -bool MathStructure::complexToCisForm(const EvaluationOptions &eo) { - if(m_type == STRUCT_NUMBER && o_number.hasImaginaryPart()) { - MathFunction *f = CALCULATOR->getActiveFunction("cis"); - if(!f) return false; - MathStructure mabs(CALCULATOR->f_abs, this, NULL); - MathStructure marg(CALCULATOR->f_arg, this, NULL); - EvaluationOptions eo2 = eo; - eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; - mabs.eval(eo2); - marg.eval(eo2); - switch(eo2.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {marg.multiply(CALCULATOR->getDegUnit(), true);} break;} - case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {marg.multiply(CALCULATOR->getGraUnit(), true);} break;} - default: {break;} - } - set(marg, true); - transform(f); - multiply(mabs); - evalSort(true); - return true; - } else if(m_type == STRUCT_POWER && CHILD(0).isVariable() && CHILD(0).variable() == CALCULATOR->v_e && CHILD(1).isNumber() && CHILD(1).number().hasImaginaryPart() && !CHILD(1).number().hasRealPart()) { - MathFunction *f = CALCULATOR->getActiveFunction("cis"); - if(!f) return false; - set(CHILD(1).number().imaginaryPart(), true); - EvaluationOptions eo2 = eo; - eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; - switch(eo2.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {calculateMultiply(Number(180, 1), eo2); calculateDivide(CALCULATOR->v_pi, eo2); multiply(CALCULATOR->getDegUnit(), true);} break;} - case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {calculateMultiply(Number(200, 1), eo2); calculateDivide(CALCULATOR->v_pi, eo2); multiply(CALCULATOR->getGraUnit(), true);} break;} - default: {break;} - } - transform(f); - multiply(m_one); - evalSort(true); - return true; - } else if(m_type == STRUCT_MULTIPLICATION && SIZE == 2 && CHILD(1).isPower() && CHILD(1)[0].isVariable() && CHILD(1)[0].variable() == CALCULATOR->v_e && CHILD(1)[1].isNumber() && CHILD(1)[1].number().hasImaginaryPart() && !CHILD(1)[1].number().hasRealPart() && CHILD(0).isNumber() && !CHILD(0).number().hasImaginaryPart()) { - MathFunction *f = CALCULATOR->getActiveFunction("cis"); - if(!f) return false; - CHILD(1).set(CHILD(1)[1].number().imaginaryPart(), true); - EvaluationOptions eo2 = eo; - eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; - switch(eo2.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {CHILD(1).calculateMultiply(Number(180, 1), eo2); CHILD(1).calculateDivide(CALCULATOR->v_pi, eo2); CHILD(1).multiply(CALCULATOR->getDegUnit(), true);} break;} - case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {CHILD(1).calculateMultiply(Number(200, 1), eo2); CHILD(1).calculateDivide(CALCULATOR->v_pi, eo2); CHILD(1).multiply(CALCULATOR->getGraUnit(), true);} break;} - default: {break;} - } - CHILD(1).transform(f); - CHILD_UPDATED(1) - return true; - } - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).complexToCisForm(eo)) {b = true; CHILD_UPDATED(i);} - } - return b; -} - -void MathStructure::formatsub(const PrintOptions &po, MathStructure *parent, size_t pindex, bool recursive, MathStructure *top_parent) { - - if(recursive) { - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) break; - if(i == 1 && m_type == STRUCT_POWER && po.number_fraction_format < FRACTION_FRACTIONAL && CHILD(1).isNumber() && CHILD(1).number().isRational() && !CHILD(1).number().isInteger() && CHILD(1).number().numeratorIsLessThan(10) && CHILD(1).number().numeratorIsGreaterThan(-10) && CHILD(1).number().denominatorIsLessThan(10)) { - PrintOptions po2 = po; - po2.number_fraction_format = FRACTION_FRACTIONAL; - CHILD(i).formatsub(po2, this, i + 1, false, top_parent); - } else { - CHILD(i).formatsub(po, this, i + 1, true, top_parent); - } - CHILD_UPDATED(i); - } - } - switch(m_type) { - case STRUCT_ADDITION: { - break; - } - case STRUCT_NEGATE: { - break; - } - case STRUCT_DIVISION: { - if(po.preserve_format) break; - if(CHILD(0).isAddition() && CHILD(0).size() > 0 && CHILD(0)[0].isNegate()) { - int imin = 1; - for(size_t i = 1; i < CHILD(0).size(); i++) { - if(CHILD(0)[i].isNegate()) { - imin++; - } else { - imin--; - } - } - bool b = CHILD(1).isAddition() && CHILD(1).size() > 0 && CHILD(1)[0].isNegate(); - if(b) { - imin++; - for(size_t i = 1; i < CHILD(1).size(); i++) { - if(CHILD(1)[i].isNegate()) { - imin++; - } else { - imin--; - } - } - } - if(imin > 0 || (imin == 0 && parent && parent->isNegate())) { - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CHILD(0)[i].isNegate()) { - CHILD(0)[i].setToChild(1, true); - } else { - CHILD(0)[i].transform(STRUCT_NEGATE); - } - } - if(b) { - for(size_t i = 0; i < CHILD(1).size(); i++) { - if(CHILD(1)[i].isNegate()) { - CHILD(1)[i].setToChild(1, true); - } else { - CHILD(1)[i].transform(STRUCT_NEGATE); - } - } - } else { - transform(STRUCT_NEGATE); - } - break; - } - } else if(CHILD(1).isAddition() && CHILD(1).size() > 0 && CHILD(1)[0].isNegate()) { - int imin = 1; - for(size_t i = 1; i < CHILD(1).size(); i++) { - if(CHILD(1)[i].isNegate()) { - imin++; - } else { - imin--; - } - } - if(imin > 0 || (imin == 0 && parent && parent->isNegate())) { - for(size_t i = 0; i < CHILD(1).size(); i++) { - if(CHILD(1)[i].isNegate()) { - CHILD(1)[i].setToChild(1, true); - } else { - CHILD(1)[i].transform(STRUCT_NEGATE); - } - } - transform(STRUCT_NEGATE); - } - } - break; - } - case STRUCT_INVERSE: { - if(po.preserve_format) break; - if((!parent || !parent->isMultiplication()) && CHILD(0).isAddition() && CHILD(0).size() > 0 && CHILD(0)[0].isNegate()) { - int imin = 1; - for(size_t i = 1; i < CHILD(0).size(); i++) { - if(CHILD(0)[i].isNegate()) { - imin++; - } else { - imin--; - } - } - if(imin > 0 || (imin == 0 && parent && parent->isNegate())) { - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CHILD(0)[i].isNegate()) { - CHILD(0)[i].setToChild(1, true); - } else { - CHILD(0)[i].transform(STRUCT_NEGATE); - } - } - transform(STRUCT_NEGATE); - } - } - break; - } - case STRUCT_MULTIPLICATION: { - if(po.preserve_format) break; - if(CHILD(0).isNegate()) { - if(CHILD(0)[0].isOne()) { - ERASE(0); - if(SIZE == 1) { - setToChild(1, true); - } - } else { - CHILD(0).setToChild(1, true); - } - transform(STRUCT_NEGATE); - CHILD(0).formatsub(po, this, 1, false, top_parent); - break; - } - - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) break; - if(CHILD(i).isInverse()) { - if(!po.negative_exponents || !CHILD(i)[0].isNumber()) { - b = true; - break; - } - } else if(CHILD(i).isDivision()) { - if(!CHILD(i)[0].isNumber() || !CHILD(i)[1].isNumber() || (!po.negative_exponents && CHILD(i)[0].number().isOne())) { - b = true; - break; - } - } - } - - if(b) { - MathStructure *den = new MathStructure(); - MathStructure *num = new MathStructure(); - num->setUndefined(); - short ds = 0, ns = 0; - MathStructure *mnum = NULL, *mden = NULL; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isInverse()) { - mden = &CHILD(i)[0]; - } else if(CHILD(i).isDivision()) { - mnum = &CHILD(i)[0]; - mden = &CHILD(i)[1]; - } else { - mnum = &CHILD(i); - } - if(mnum && !mnum->isOne()) { - if(ns > 0) { - if(mnum->isMultiplication() && num->isNumber()) { - for(size_t i2 = 0; i2 < mnum->size(); i2++) { - num->multiply((*mnum)[i2], true); - } - } else { - num->multiply(*mnum, ns > 1); - } - } else { - num->set(*mnum); - } - ns++; - mnum = NULL; - } - if(mden) { - if(ds > 0) { - if(mden->isMultiplication() && den->isNumber()) { - for(size_t i2 = 0; i2 < mden->size(); i2++) { - den->multiply((*mden)[i2], true); - } - } else { - den->multiply(*mden, ds > 1); - } - } else { - den->set(*mden); - } - ds++; - mden = NULL; - } - } - clear(true); - m_type = STRUCT_DIVISION; - if(num->isUndefined()) num->set(m_one); - APPEND_POINTER(num); - APPEND_POINTER(den); - num->formatsub(po, this, 1, false, top_parent); - den->formatsub(po, this, 2, false, top_parent); - formatsub(po, parent, pindex, false, top_parent); - break; - } - - size_t index = 0; - if(CHILD(0).isOne()) { - index = 1; - } - switch(CHILD(index).type()) { - case STRUCT_POWER: { - if(!CHILD(index)[0].isUnit_exp()) { - break; - } - } - case STRUCT_UNIT: { - if(index == 0) { - if(!parent || (!parent->isPower() && !parent->isMultiplication() && !parent->isInverse() && (!parent->isDivision() || pindex != 2))) { - PREPEND(m_one); - break; - } - } - break; - } - case STRUCT_FUNCTION: { - if(index == 1 && SIZE == 2 && CHILD(index).function()->referenceName() == "cis" && CHILD(index).size() == 1) break; - } - default: { - if(index == 1) { - ERASE(0); - if(SIZE == 1) { - setToChild(1, true); - } - break; - } - } - } - break; - } - case STRUCT_UNIT: { - if(po.preserve_format) break; - if(!parent || (!parent->isPower() && !parent->isMultiplication() && !parent->isInverse() && !(parent->isDivision() && pindex == 2))) { - multiply(m_one); - SWAP_CHILDREN(0, 1); - } - break; - } - case STRUCT_POWER: { - if(po.preserve_format) break; - if(!po.negative_exponents && CHILD(1).isNegate() && (!CHILD(0).isVector() || !CHILD(1).isMinusOne())) { - if(CHILD(1)[0].isOne()) { - m_type = STRUCT_INVERSE; - ERASE(1); - } else { - CHILD(1).setToChild(1, true); - transform(STRUCT_INVERSE); - } - formatsub(po, parent, pindex, true, top_parent); - break; - } else if(po.halfexp_to_sqrt && ((CHILD(1).isDivision() && CHILD(1)[0].isNumber() && CHILD(1)[0].number().isInteger() && CHILD(1)[1].isNumber() && CHILD(1)[1].number().isTwo() && ((!po.negative_exponents && (CHILD(0).countChildren() == 0 || CHILD(0).isFunction())) || CHILD(1)[0].isOne())) || (CHILD(1).isNumber() && CHILD(1).number().denominatorIsTwo() && ((!po.negative_exponents && (CHILD(0).countChildren() == 0 || CHILD(0).isFunction())) || CHILD(1).number().numeratorIsOne())) || (CHILD(1).isInverse() && CHILD(1)[0].isNumber() && CHILD(1)[0].number() == 2))) { - if(CHILD(1).isInverse() || (CHILD(1).isDivision() && CHILD(1)[0].number().isOne()) || (CHILD(1).isNumber() && CHILD(1).number().numeratorIsOne())) { - m_type = STRUCT_FUNCTION; - ERASE(1) - setFunction(CALCULATOR->f_sqrt); - } else { - if(CHILD(1).isNumber()) { - CHILD(1).number() -= nr_half; - } else { - Number nr = CHILD(1)[0].number(); - nr /= CHILD(1)[1].number(); - nr.floor(); - CHILD(1).set(nr); - } - if(CHILD(1).number().isOne()) { - setToChild(1, true); - if(parent && parent->isMultiplication()) { - parent->insertChild(MathStructure(CALCULATOR->f_sqrt, this, NULL), pindex + 1); - } else { - multiply(MathStructure(CALCULATOR->f_sqrt, this, NULL)); - } - } else { - if(parent && parent->isMultiplication()) { - parent->insertChild(MathStructure(CALCULATOR->f_sqrt, &CHILD(0), NULL), pindex + 1); - } else { - multiply(MathStructure(CALCULATOR->f_sqrt, &CHILD(0), NULL)); - } - } - } - formatsub(po, parent, pindex, false, top_parent); - break; - } else if(po.exp_to_root && CHILD(0).representsNonNegative(true) && ((CHILD(1).isDivision() && CHILD(1)[0].isNumber() && CHILD(1)[0].number().isInteger() && CHILD(1)[1].isNumber() && CHILD(1)[1].number().isGreaterThan(1) && CHILD(1)[1].number().isLessThan(10) && ((!po.negative_exponents && (CHILD(0).countChildren() == 0 || CHILD(0).isFunction())) || CHILD(1)[0].isOne())) || (CHILD(1).isNumber() && CHILD(1).number().isRational() && !CHILD(1).number().isInteger() && CHILD(1).number().denominatorIsLessThan(10) && ((!po.negative_exponents && (CHILD(0).countChildren() == 0 || CHILD(0).isFunction())) || CHILD(1).number().numeratorIsOne())) || (CHILD(1).isInverse() && CHILD(1)[0].isNumber() && CHILD(1)[0].number().isInteger() && CHILD(1)[0].number().isPositive() && CHILD(1)[0].number().isLessThan(10)))) { - Number nr_int, nr_num, nr_den; - if(CHILD(1).isNumber()) { - nr_num = CHILD(1).number().numerator(); - nr_den = CHILD(1).number().denominator(); - } else if(CHILD(1).isDivision()) { - nr_num.set(CHILD(1)[0].number()); - nr_den.set(CHILD(1)[1].number()); - } else if(CHILD(1).isInverse()) { - nr_num.set(1, 1, 0); - nr_den.set(CHILD(1)[0].number()); - } - if(!nr_num.isOne() && (nr_num - 1).isIntegerDivisible(nr_den)) { - nr_int = nr_num; - nr_int--; - nr_int.divide(nr_den); - nr_num = 1; - } - MathStructure mbase(CHILD(0)); - CHILD(1) = nr_den; - m_type = STRUCT_FUNCTION; - setFunction(CALCULATOR->f_root); - formatsub(po, parent, pindex, false, top_parent); - if(!nr_num.isOne()) { - raise(nr_num); - formatsub(po, parent, pindex, false, top_parent); - } - if(!nr_int.isZero()) { - if(!nr_int.isOne()) mbase.raise(nr_int); - multiply(mbase); - sort(po); - formatsub(po, parent, pindex, false, top_parent); - } - break; - } - if(CHILD(0).isUnit_exp() && (!parent || (!parent->isPower() && !parent->isMultiplication() && !parent->isInverse() && !(parent->isDivision() && pindex == 2)))) { - multiply(m_one); - SWAP_CHILDREN(0, 1); - } - break; - } - case STRUCT_FUNCTION: { - if(po.preserve_format) break; - if(o_function == CALCULATOR->f_root && SIZE == 2 && CHILD(1) == 3) { - ERASE(1) - setFunction(CALCULATOR->f_cbrt); - } else if(o_function == CALCULATOR->f_interval && SIZE == 2 && CHILD(0).isAddition() && CHILD(0).size() == 2 && CHILD(1).isAddition() && CHILD(1).size() == 2) { - MathStructure *mmid = NULL, *munc = NULL; - if(CHILD(0)[0].equals(CHILD(1)[0], true, true)) { - mmid = &CHILD(0)[0]; - if(CHILD(0)[1].isNegate() && CHILD(0)[1][0].equals(CHILD(1)[1], true, true)) munc = &CHILD(1)[1]; - if(CHILD(1)[1].isNegate() && CHILD(1)[1][0].equals(CHILD(0)[1], true, true)) munc = &CHILD(0)[1]; - } else if(CHILD(0)[1].equals(CHILD(1)[1], true, true)) { - mmid = &CHILD(0)[1]; - if(CHILD(0)[0].isNegate() && CHILD(0)[0][0].equals(CHILD(1)[0], true, true)) munc = &CHILD(1)[0]; - if(CHILD(1)[0].isNegate() && CHILD(1)[0][0].equals(CHILD(0)[0], true, true)) munc = &CHILD(0)[0]; - } else if(CHILD(0)[0].equals(CHILD(1)[1], true, true)) { - mmid = &CHILD(0)[0]; - if(CHILD(0)[1].isNegate() && CHILD(0)[1][0].equals(CHILD(1)[0], true, true)) munc = &CHILD(1)[0]; - if(CHILD(1)[0].isNegate() && CHILD(1)[0][0].equals(CHILD(0)[1], true, true)) munc = &CHILD(0)[1]; - } else if(CHILD(0)[1].equals(CHILD(1)[0], true, true)) { - mmid = &CHILD(0)[0]; - if(CHILD(0)[0].isNegate() && CHILD(0)[0][0].equals(CHILD(1)[1], true, true)) munc = &CHILD(1)[1]; - if(CHILD(1)[1].isNegate() && CHILD(1)[1][0].equals(CHILD(0)[0], true, true)) munc = &CHILD(0)[0]; - } - if(mmid && munc) { - setFunction(CALCULATOR->f_uncertainty); - mmid->ref(); - munc->ref(); - CLEAR - APPEND_POINTER(mmid) - APPEND_POINTER(munc) - APPEND(m_zero) - } - } - break; - } - case STRUCT_VARIABLE: { - if(o_variable == CALCULATOR->v_pinf || o_variable == CALCULATOR->v_minf) { - set(((KnownVariable*) o_variable)->get()); - } - break; - } - case STRUCT_NUMBER: { - bool force_fraction = false; - if(parent && parent->isMultiplication() && o_number.isRational()) { - for(size_t i = 0; i < parent->size(); i++) { - if((*parent)[i].isAddition()) { - force_fraction = true; - break; - } - } - } - if((o_number.isNegative() || ((parent || po.interval_display != INTERVAL_DISPLAY_SIGNIFICANT_DIGITS) && o_number.isInterval() && o_number.isNonPositive())) && (po.base != BASE_CUSTOM || !CALCULATOR->customOutputBase().isNegative())) { - if((((po.base != 2 || !po.twos_complement) && (po.base != 16 || !po.hexadecimal_twos_complement)) || !o_number.isInteger()) && (!o_number.isMinusInfinity() || (parent && parent->isAddition()))) { - o_number.negate(); - transform(STRUCT_NEGATE); - formatsub(po, parent, pindex, true, top_parent); - } - } else if(po.number_fraction_format == FRACTION_COMBINED && po.base != BASE_SEXAGESIMAL && po.base != BASE_TIME && o_number.isRational() && !o_number.isInteger() && (!po.show_ending_zeroes || !po.restrict_to_parent_precision || po.base == BASE_ROMAN_NUMERALS || po.base == BASE_BIJECTIVE_26 || ((!top_parent || !top_parent->isApproximate()) && !isApproximate()) || (o_number.denominatorIsLessThan(10) && o_number < 10 && o_number > -10))) { - if(o_number.isFraction()) { - Number num(o_number.numerator()); - Number den(o_number.denominator()); - clear(true); - if(num.isOne()) { - m_type = STRUCT_INVERSE; - } else { - m_type = STRUCT_DIVISION; - APPEND_NEW(num); - } - APPEND_NEW(den); - } else { - Number frac(o_number); - frac.frac(); - MathStructure *num = new MathStructure(frac.numerator()); - num->transform(STRUCT_DIVISION, frac.denominator()); - o_number.trunc(); - add_nocopy(num); - } - } else if((force_fraction || po.number_fraction_format == FRACTION_FRACTIONAL || po.base == BASE_ROMAN_NUMERALS || po.number_fraction_format == FRACTION_DECIMAL_EXACT) && po.base != BASE_SEXAGESIMAL && po.base != BASE_TIME && o_number.isRational() && !o_number.isInteger() && (force_fraction || !o_number.isApproximate())) { - InternalPrintStruct ips_n; - if(!force_fraction && (isApproximate() || (top_parent && top_parent->isApproximate()))) ips_n.parent_approximate = true; - if(po.show_ending_zeroes && po.restrict_to_parent_precision && ips_n.parent_approximate && po.base != BASE_ROMAN_NUMERALS && po.base != BASE_BIJECTIVE_26 && (o_number.numeratorIsGreaterThan(9) || o_number.numeratorIsLessThan(-9) || o_number.denominatorIsGreaterThan(9))) { - break; - } - ips_n.parent_precision = precision(); - if(top_parent && top_parent->precision() < 0 && top_parent->precision() < ips_n.parent_precision) ips_n.parent_precision = top_parent->precision(); - bool approximately_displayed = false; - PrintOptions po2 = po; - po2.is_approximate = &approximately_displayed; - if(!force_fraction && po.base != BASE_ROMAN_NUMERALS && po.base != BASE_BIJECTIVE_26 && po.number_fraction_format == FRACTION_DECIMAL_EXACT) { - po2.number_fraction_format = FRACTION_DECIMAL; - o_number.print(po2, ips_n); - if(!approximately_displayed) break; - approximately_displayed = false; - } - Number num(o_number.numerator()); - Number den(o_number.denominator()); - if(isApproximate()) { - num.setApproximate(); - den.setApproximate(); - } - num.print(po2, ips_n); - if(!approximately_displayed || po.base == BASE_ROMAN_NUMERALS || po.base == BASE_BIJECTIVE_26) { - den.print(po2, ips_n); - if(!approximately_displayed || po.base == BASE_ROMAN_NUMERALS || po.base == BASE_BIJECTIVE_26) { - clear(true); - if(num.isOne()) { - m_type = STRUCT_INVERSE; - } else { - m_type = STRUCT_DIVISION; - APPEND_NEW(num); - } - APPEND_NEW(den); - } - } - } else if(o_number.hasImaginaryPart()) { - if(o_number.hasRealPart()) { - Number re(o_number.realPart()); - Number im(o_number.imaginaryPart()); - MathStructure *mstruct = new MathStructure(im); - if(im.isOne()) { - mstruct->set(CALCULATOR->v_i); - } else { - mstruct->multiply_nocopy(new MathStructure(CALCULATOR->v_i)); - if(CALCULATOR->v_i->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name == "j") mstruct->swapChildren(1, 2); - } - o_number = re; - add_nocopy(mstruct); - formatsub(po, parent, pindex, true, top_parent); - } else { - Number im(o_number.imaginaryPart()); - if(im.isOne()) { - set(CALCULATOR->v_i, true); - } else if(im.isMinusOne()) { - set(CALCULATOR->v_i, true); - transform(STRUCT_NEGATE); - } else { - o_number = im; - multiply_nocopy(new MathStructure(CALCULATOR->v_i)); - if(CALCULATOR->v_i->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name == "j") SWAP_CHILDREN(0, 1); - } - formatsub(po, parent, pindex, true, top_parent); - } - } - break; - } - default: {} - } -} - -int namelen(const MathStructure &mstruct, const PrintOptions &po, const InternalPrintStruct&, bool *abbreviated = NULL) { - const string *str; - switch(mstruct.type()) { - case STRUCT_FUNCTION: { - const ExpressionName *ename = &mstruct.function()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); - str = &ename->name; - if(abbreviated) *abbreviated = ename->abbreviation; - break; - } - case STRUCT_VARIABLE: { - const ExpressionName *ename = &mstruct.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); - str = &ename->name; - if(abbreviated) *abbreviated = ename->abbreviation; - break; - } - case STRUCT_ABORTED: {} - case STRUCT_SYMBOLIC: { - str = &mstruct.symbol(); - if(abbreviated) *abbreviated = false; - break; - } - case STRUCT_UNIT: { - const ExpressionName *ename = &mstruct.unit()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, mstruct.isPlural(), po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); - str = &ename->name; - if(abbreviated) *abbreviated = ename->abbreviation; - break; - } - default: {if(abbreviated) *abbreviated = false; return 0;} - } - if(text_length_is_one(*str)) return 1; - return str->length(); -} - -bool MathStructure::needsParenthesis(const PrintOptions &po, const InternalPrintStruct &ips, const MathStructure &parent, size_t index, bool flat_division, bool) const { - switch(parent.type()) { - case STRUCT_MULTIPLICATION: { - switch(m_type) { - case STRUCT_MULTIPLICATION: {return true;} - case STRUCT_DIVISION: {return flat_division && (index < parent.size() || po.excessive_parenthesis);} - case STRUCT_INVERSE: {return flat_division;} - case STRUCT_ADDITION: {return true;} - case STRUCT_POWER: {return po.excessive_parenthesis;} - case STRUCT_NEGATE: {return po.excessive_parenthesis;} - case STRUCT_BITWISE_AND: {return true;} - case STRUCT_BITWISE_OR: {return true;} - case STRUCT_BITWISE_XOR: {return true;} - case STRUCT_BITWISE_NOT: {return po.excessive_parenthesis;} - case STRUCT_LOGICAL_AND: {return true;} - case STRUCT_LOGICAL_OR: {return true;} - case STRUCT_LOGICAL_XOR: {return true;} - case STRUCT_LOGICAL_NOT: {return po.excessive_parenthesis;} - case STRUCT_COMPARISON: {return true;} - case STRUCT_FUNCTION: {return o_function == CALCULATOR->f_uncertainty;} - case STRUCT_VECTOR: {return false;} - case STRUCT_NUMBER: {return o_number.isInfinite() || (o_number.hasImaginaryPart() && o_number.hasRealPart());} - case STRUCT_VARIABLE: {return false;} - case STRUCT_ABORTED: {return false;} - case STRUCT_SYMBOLIC: {return false;} - case STRUCT_UNIT: {return false;} - case STRUCT_UNDEFINED: {return po.excessive_parenthesis;} - case STRUCT_DATETIME: {return false;} - default: {return true;} - } - } - case STRUCT_INVERSE: {} - case STRUCT_DIVISION: { - switch(m_type) { - case STRUCT_MULTIPLICATION: {return flat_division || po.excessive_parenthesis;} - case STRUCT_DIVISION: {return flat_division || po.excessive_parenthesis;} - case STRUCT_INVERSE: {return flat_division || po.excessive_parenthesis;} - case STRUCT_ADDITION: {return flat_division || po.excessive_parenthesis;} - case STRUCT_POWER: {return flat_division && po.excessive_parenthesis;} - case STRUCT_NEGATE: {return flat_division && po.excessive_parenthesis;} - case STRUCT_BITWISE_AND: {return flat_division || po.excessive_parenthesis;} - case STRUCT_BITWISE_OR: {return flat_division || po.excessive_parenthesis;} - case STRUCT_BITWISE_XOR: {return flat_division || po.excessive_parenthesis;} - case STRUCT_BITWISE_NOT: {return flat_division && po.excessive_parenthesis;} - case STRUCT_LOGICAL_AND: {return flat_division || po.excessive_parenthesis;} - case STRUCT_LOGICAL_OR: {return flat_division || po.excessive_parenthesis;} - case STRUCT_LOGICAL_XOR: {return flat_division || po.excessive_parenthesis;} - case STRUCT_LOGICAL_NOT: {return flat_division && po.excessive_parenthesis;} - case STRUCT_COMPARISON: {return flat_division || po.excessive_parenthesis;} - case STRUCT_FUNCTION: {return o_function == CALCULATOR->f_uncertainty;} - case STRUCT_VECTOR: {return false;} - case STRUCT_NUMBER: {return (flat_division || po.excessive_parenthesis) && (o_number.isInfinite() || o_number.hasImaginaryPart());} - case STRUCT_VARIABLE: {return false;} - case STRUCT_ABORTED: {return false;} - case STRUCT_SYMBOLIC: {return false;} - case STRUCT_UNIT: {return false;} - case STRUCT_UNDEFINED: {return false;} - case STRUCT_DATETIME: {return false;} - default: {return true;} - } - } - case STRUCT_ADDITION: { - switch(m_type) { - case STRUCT_MULTIPLICATION: {return po.excessive_parenthesis;} - case STRUCT_DIVISION: {return flat_division && po.excessive_parenthesis;} - case STRUCT_INVERSE: {return flat_division && po.excessive_parenthesis;} - case STRUCT_ADDITION: {return true;} - case STRUCT_POWER: {return po.excessive_parenthesis;} - case STRUCT_NEGATE: {return index > 1 || po.excessive_parenthesis;} - case STRUCT_BITWISE_AND: {return true;} - case STRUCT_BITWISE_OR: {return true;} - case STRUCT_BITWISE_XOR: {return true;} - case STRUCT_BITWISE_NOT: {return false;} - case STRUCT_LOGICAL_AND: {return true;} - case STRUCT_LOGICAL_OR: {return true;} - case STRUCT_LOGICAL_XOR: {return true;} - case STRUCT_LOGICAL_NOT: {return false;} - case STRUCT_COMPARISON: {return true;} - case STRUCT_FUNCTION: {return false;} - case STRUCT_VECTOR: {return false;} - case STRUCT_NUMBER: {return o_number.isInfinite();} - case STRUCT_VARIABLE: {return false;} - case STRUCT_ABORTED: {return false;} - case STRUCT_SYMBOLIC: {return false;} - case STRUCT_UNIT: {return false;} - case STRUCT_UNDEFINED: {return false;} - case STRUCT_DATETIME: {return false;} - default: {return true;} - } - } - case STRUCT_POWER: { - switch(m_type) { - case STRUCT_MULTIPLICATION: {return true;} - case STRUCT_DIVISION: {return index == 1 || flat_division || po.excessive_parenthesis;} - case STRUCT_INVERSE: {return index == 1 || flat_division || po.excessive_parenthesis;} - case STRUCT_ADDITION: {return true;} - case STRUCT_POWER: {return true;} - case STRUCT_NEGATE: {return index == 1 || CHILD(0).needsParenthesis(po, ips, parent, index, flat_division);} - case STRUCT_BITWISE_AND: {return true;} - case STRUCT_BITWISE_OR: {return true;} - case STRUCT_BITWISE_XOR: {return true;} - case STRUCT_BITWISE_NOT: {return index == 1 || po.excessive_parenthesis;} - case STRUCT_LOGICAL_AND: {return true;} - case STRUCT_LOGICAL_OR: {return true;} - case STRUCT_LOGICAL_XOR: {return true;} - case STRUCT_LOGICAL_NOT: {return index == 1 || po.excessive_parenthesis;} - case STRUCT_COMPARISON: {return true;} - case STRUCT_FUNCTION: {return o_function == CALCULATOR->f_uncertainty;} - case STRUCT_VECTOR: {return false;} - case STRUCT_NUMBER: {return o_number.isInfinite() || o_number.hasImaginaryPart();} - case STRUCT_VARIABLE: {return false;} - case STRUCT_ABORTED: {return false;} - case STRUCT_SYMBOLIC: {return false;} - case STRUCT_UNIT: {return false;} - case STRUCT_UNDEFINED: {return false;} - default: {return true;} - } - } - case STRUCT_NEGATE: { - switch(m_type) { - case STRUCT_MULTIPLICATION: {return po.excessive_parenthesis;} - case STRUCT_DIVISION: {return po.excessive_parenthesis;} - case STRUCT_INVERSE: {return flat_division && po.excessive_parenthesis;} - case STRUCT_ADDITION: {return true;} - case STRUCT_POWER: {return true;} - case STRUCT_NEGATE: {return true;} - case STRUCT_BITWISE_AND: {return true;} - case STRUCT_BITWISE_OR: {return true;} - case STRUCT_BITWISE_XOR: {return true;} - case STRUCT_BITWISE_NOT: {return po.excessive_parenthesis;} - case STRUCT_LOGICAL_AND: {return true;} - case STRUCT_LOGICAL_OR: {return true;} - case STRUCT_LOGICAL_XOR: {return true;} - case STRUCT_LOGICAL_NOT: {return po.excessive_parenthesis;} - case STRUCT_COMPARISON: {return true;} - case STRUCT_FUNCTION: {return false;} - case STRUCT_VECTOR: {return false;} - case STRUCT_NUMBER: {return o_number.isInfinite() || (o_number.hasImaginaryPart() && o_number.hasRealPart());} - case STRUCT_VARIABLE: {return false;} - case STRUCT_ABORTED: {return false;} - case STRUCT_SYMBOLIC: {return false;} - case STRUCT_UNIT: {return false;} - case STRUCT_UNDEFINED: {return false;} - default: {return true;} - } - } - case STRUCT_LOGICAL_OR: {} - case STRUCT_LOGICAL_AND: {} - case STRUCT_LOGICAL_XOR: { - switch(m_type) { - case STRUCT_MULTIPLICATION: {return true;} - case STRUCT_DIVISION: {return flat_division;} - case STRUCT_INVERSE: {return flat_division;} - case STRUCT_ADDITION: {return true;} - case STRUCT_POWER: {return po.excessive_parenthesis;} - case STRUCT_NEGATE: {return po.excessive_parenthesis;} - case STRUCT_BITWISE_AND: {return true;} - case STRUCT_BITWISE_OR: {return true;} - case STRUCT_BITWISE_XOR: {return true;} - case STRUCT_BITWISE_NOT: {return false;} - case STRUCT_LOGICAL_AND: {return true;} - case STRUCT_LOGICAL_OR: {return true;} - case STRUCT_LOGICAL_XOR: {return true;} - case STRUCT_LOGICAL_NOT: {return false;} - case STRUCT_COMPARISON: {return false;} - case STRUCT_FUNCTION: {return false;} - case STRUCT_VECTOR: {return false;} - case STRUCT_NUMBER: {return po.excessive_parenthesis && o_number.isInfinite();} - case STRUCT_VARIABLE: {return false;} - case STRUCT_ABORTED: {return false;} - case STRUCT_SYMBOLIC: {return false;} - case STRUCT_UNIT: {return false;} - case STRUCT_UNDEFINED: {return false;} - case STRUCT_DATETIME: {return false;} - default: {return true;} - } - } - case STRUCT_BITWISE_AND: {} - case STRUCT_BITWISE_OR: {} - case STRUCT_BITWISE_XOR: { - switch(m_type) { - case STRUCT_MULTIPLICATION: {return true;} - case STRUCT_DIVISION: {return flat_division;} - case STRUCT_INVERSE: {return flat_division;} - case STRUCT_ADDITION: {return true;} - case STRUCT_POWER: {return po.excessive_parenthesis;} - case STRUCT_NEGATE: {return po.excessive_parenthesis;} - case STRUCT_BITWISE_AND: {return true;} - case STRUCT_BITWISE_OR: {return true;} - case STRUCT_BITWISE_XOR: {return true;} - case STRUCT_BITWISE_NOT: {return false;} - case STRUCT_LOGICAL_AND: {return true;} - case STRUCT_LOGICAL_OR: {return true;} - case STRUCT_LOGICAL_XOR: {return true;} - case STRUCT_LOGICAL_NOT: {return false;} - case STRUCT_COMPARISON: {return true;} - case STRUCT_FUNCTION: {return false;} - case STRUCT_VECTOR: {return false;} - case STRUCT_NUMBER: {return po.excessive_parenthesis && o_number.isInfinite();} - case STRUCT_VARIABLE: {return false;} - case STRUCT_ABORTED: {return false;} - case STRUCT_SYMBOLIC: {return false;} - case STRUCT_UNIT: {return false;} - case STRUCT_UNDEFINED: {return false;} - default: {return true;} - } - } - case STRUCT_COMPARISON: { - switch(m_type) { - case STRUCT_MULTIPLICATION: {return po.excessive_parenthesis;} - case STRUCT_DIVISION: {return flat_division && po.excessive_parenthesis;} - case STRUCT_INVERSE: {return flat_division && po.excessive_parenthesis;} - case STRUCT_ADDITION: {return po.excessive_parenthesis;} - case STRUCT_POWER: {return po.excessive_parenthesis;} - case STRUCT_NEGATE: {return po.excessive_parenthesis;} - case STRUCT_BITWISE_AND: {return true;} - case STRUCT_BITWISE_OR: {return true;} - case STRUCT_BITWISE_XOR: {return true;} - case STRUCT_BITWISE_NOT: {return false;} - case STRUCT_LOGICAL_AND: {return true;} - case STRUCT_LOGICAL_OR: {return true;} - case STRUCT_LOGICAL_XOR: {return true;} - case STRUCT_LOGICAL_NOT: {return false;} - case STRUCT_COMPARISON: {return true;} - case STRUCT_FUNCTION: {return false;} - case STRUCT_VECTOR: {return false;} - case STRUCT_NUMBER: {return po.excessive_parenthesis && o_number.isInfinite();} - case STRUCT_VARIABLE: {return false;} - case STRUCT_ABORTED: {return false;} - case STRUCT_SYMBOLIC: {return false;} - case STRUCT_UNIT: {return false;} - case STRUCT_UNDEFINED: {return false;} - case STRUCT_DATETIME: {return false;} - default: {return true;} - } - } - case STRUCT_LOGICAL_NOT: {} - case STRUCT_BITWISE_NOT: { - switch(m_type) { - case STRUCT_MULTIPLICATION: {return true;} - case STRUCT_DIVISION: {return true;} - case STRUCT_INVERSE: {return true;} - case STRUCT_ADDITION: {return true;} - case STRUCT_POWER: {return po.excessive_parenthesis;} - case STRUCT_NEGATE: {return po.excessive_parenthesis;} - case STRUCT_BITWISE_AND: {return true;} - case STRUCT_BITWISE_OR: {return true;} - case STRUCT_BITWISE_XOR: {return true;} - case STRUCT_BITWISE_NOT: {return true;} - case STRUCT_LOGICAL_AND: {return true;} - case STRUCT_LOGICAL_OR: {return true;} - case STRUCT_LOGICAL_XOR: {return true;} - case STRUCT_LOGICAL_NOT: {return true;} - case STRUCT_COMPARISON: {return true;} - case STRUCT_FUNCTION: {return po.excessive_parenthesis;} - case STRUCT_VECTOR: {return po.excessive_parenthesis;} - case STRUCT_NUMBER: {return po.excessive_parenthesis;} - case STRUCT_VARIABLE: {return po.excessive_parenthesis;} - case STRUCT_ABORTED: {return po.excessive_parenthesis;} - case STRUCT_SYMBOLIC: {return po.excessive_parenthesis;} - case STRUCT_UNIT: {return po.excessive_parenthesis;} - case STRUCT_UNDEFINED: {return po.excessive_parenthesis;} - default: {return true;} - } - } - case STRUCT_FUNCTION: { - return false; - } - case STRUCT_VECTOR: { - return false; - } - default: { - return true; - } - } -} - -int MathStructure::neededMultiplicationSign(const PrintOptions &po, const InternalPrintStruct &ips, const MathStructure &parent, size_t index, bool par, bool par_prev, bool flat_division, bool flat_power) const { - if(!po.short_multiplication || po.base > 10 || po.base < 2) return MULTIPLICATION_SIGN_OPERATOR; - if(index <= 1) return MULTIPLICATION_SIGN_NONE; - if(par_prev && par) return MULTIPLICATION_SIGN_NONE; - if(par_prev) { - if(isUnit_exp()) return MULTIPLICATION_SIGN_SPACE; - if(isUnknown_exp()) { - if(isSymbolic() || (isPower() && CHILD(0).isSymbolic())) return MULTIPLICATION_SIGN_SPACE; - return (namelen(isPower() ? CHILD(0) : *this, po, ips, NULL) > 1 ? MULTIPLICATION_SIGN_SPACE : MULTIPLICATION_SIGN_NONE); - } - if(isMultiplication() && SIZE > 0) { - if(CHILD(0).isUnit_exp()) return MULTIPLICATION_SIGN_SPACE; - if(CHILD(0).isUnknown_exp()) { - if(CHILD(0).isSymbolic() || (CHILD(0).isPower() && CHILD(0)[0].isSymbolic())) return MULTIPLICATION_SIGN_SPACE; - return (namelen(CHILD(0).isPower() ? CHILD(0)[0] : CHILD(0), po, ips, NULL) > 1 ? MULTIPLICATION_SIGN_SPACE : MULTIPLICATION_SIGN_NONE); - } - } else if(isDivision()) { - for(size_t i = 0; i < SIZE; i++) { - if(!CHILD(i).isUnit_exp()) { - return MULTIPLICATION_SIGN_OPERATOR; - } - } - return MULTIPLICATION_SIGN_SPACE; - } - return MULTIPLICATION_SIGN_OPERATOR; - } - int t = parent[index - 2].type(); - if(flat_power && t == STRUCT_POWER) return MULTIPLICATION_SIGN_OPERATOR; - if(par && t == STRUCT_POWER) return MULTIPLICATION_SIGN_SPACE; - if(par) return MULTIPLICATION_SIGN_NONE; - bool abbr_prev = false, abbr_this = false; - int namelen_this = namelen(*this, po, ips, &abbr_this); - int namelen_prev = namelen(parent[index - 2], po, ips, &abbr_prev); - switch(t) { - case STRUCT_MULTIPLICATION: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_INVERSE: {} - case STRUCT_DIVISION: {if(flat_division) return MULTIPLICATION_SIGN_OPERATOR; return MULTIPLICATION_SIGN_SPACE;} - case STRUCT_ADDITION: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_POWER: {if(flat_power) return MULTIPLICATION_SIGN_OPERATOR; break;} - case STRUCT_NEGATE: {break;} - case STRUCT_BITWISE_AND: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_BITWISE_OR: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_BITWISE_XOR: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_BITWISE_NOT: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_LOGICAL_AND: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_LOGICAL_OR: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_LOGICAL_XOR: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_LOGICAL_NOT: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_COMPARISON: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_FUNCTION: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_VECTOR: {break;} - case STRUCT_NUMBER: {break;} - case STRUCT_VARIABLE: {break;} - case STRUCT_ABORTED: {break;} - case STRUCT_SYMBOLIC: {break;} - case STRUCT_UNIT: { - if(m_type == STRUCT_UNIT) { - if(!po.limit_implicit_multiplication && !abbr_prev && !abbr_this) { - return MULTIPLICATION_SIGN_SPACE; - } - if(po.place_units_separately) { - return MULTIPLICATION_SIGN_OPERATOR_SHORT; - } else { - return MULTIPLICATION_SIGN_OPERATOR; - } - } else if(m_type == STRUCT_NUMBER) { - if(namelen_prev > 1) { - return MULTIPLICATION_SIGN_SPACE; - } else { - return MULTIPLICATION_SIGN_NONE; - } - } - //return MULTIPLICATION_SIGN_SPACE; - } - case STRUCT_UNDEFINED: {break;} - default: {return MULTIPLICATION_SIGN_OPERATOR;} - } - switch(m_type) { - case STRUCT_MULTIPLICATION: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_INVERSE: {} - case STRUCT_DIVISION: {return MULTIPLICATION_SIGN_SPACE;} - case STRUCT_ADDITION: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_POWER: {return CHILD(0).neededMultiplicationSign(po, ips, parent, index, par, par_prev, flat_division, flat_power);} - case STRUCT_NEGATE: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_BITWISE_AND: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_BITWISE_OR: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_BITWISE_XOR: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_BITWISE_NOT: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_LOGICAL_AND: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_LOGICAL_OR: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_LOGICAL_XOR: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_LOGICAL_NOT: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_COMPARISON: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_FUNCTION: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_VECTOR: {return MULTIPLICATION_SIGN_OPERATOR;} - case STRUCT_NUMBER: { - if(t == STRUCT_VARIABLE && parent[index - 2].variable() == CALCULATOR->v_i) return MULTIPLICATION_SIGN_NONE; - return MULTIPLICATION_SIGN_OPERATOR; - } - case STRUCT_VARIABLE: { - if(!o_variable->isRegistered() && o_variable->getName(1).name.length() > 0 && o_variable->getName(1).name[0] >= '0' && o_variable->getName(1).name[0] <= '9') return MULTIPLICATION_SIGN_OPERATOR; - } - case STRUCT_ABORTED: {} - case STRUCT_SYMBOLIC: { - if(po.limit_implicit_multiplication && t != STRUCT_NUMBER) return MULTIPLICATION_SIGN_OPERATOR; - if(t != STRUCT_NUMBER && ((namelen_prev > 1 || namelen_this > 1) || equals(parent[index - 2]))) return MULTIPLICATION_SIGN_OPERATOR; - if(namelen_this > 1 || (m_type == STRUCT_SYMBOLIC && !po.allow_non_usable)) return MULTIPLICATION_SIGN_SPACE; - return MULTIPLICATION_SIGN_NONE; - } - case STRUCT_UNIT: { - if((t == STRUCT_POWER && parent[index - 2][0].isUnit_exp()) || (o_unit == CALCULATOR->getDegUnit() && print(po) == SIGN_DEGREE)) { - return MULTIPLICATION_SIGN_NONE; - } - return MULTIPLICATION_SIGN_SPACE; - } - case STRUCT_UNDEFINED: {return MULTIPLICATION_SIGN_OPERATOR;} - default: {return MULTIPLICATION_SIGN_OPERATOR;} - } -} - -ostream& operator << (ostream &os, const MathStructure &mstruct) { - os << format_and_print(mstruct); - return os; -} -string MathStructure::print(const PrintOptions &po, const InternalPrintStruct &ips) const { - if(ips.depth == 0 && po.is_approximate) *po.is_approximate = false; - string print_str; - InternalPrintStruct ips_n = ips; - if(isApproximate()) ips_n.parent_approximate = true; - if(precision() >= 0 && (ips_n.parent_precision < 0 || precision() < ips_n.parent_precision)) ips_n.parent_precision = precision(); - switch(m_type) { - case STRUCT_NUMBER: { - print_str = o_number.print(po, ips_n); - break; - } - case STRUCT_ABORTED: {} - case STRUCT_SYMBOLIC: { - if(po.allow_non_usable) { - print_str = s_sym; - } else { - if((text_length_is_one(s_sym) && s_sym.find("\'") == string::npos) || s_sym.find("\"") != string::npos) { - print_str = "\'"; - print_str += s_sym; - print_str += "\'"; - } else { - print_str = "\""; - print_str += s_sym; - print_str += "\""; - } - } - break; - } - case STRUCT_DATETIME: { - print_str = "\""; - print_str += o_datetime->print(po); - print_str += "\""; - break; - } - case STRUCT_ADDITION: { - ips_n.depth++; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); - if(i > 0) { - if(CHILD(i).type() == STRUCT_NEGATE) { - if(po.spacious) print_str += " "; - if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MINUS, po.can_display_unicode_string_arg))) print_str += SIGN_MINUS; - else print_str += "-"; - if(po.spacious) print_str += " "; - ips_n.wrap = CHILD(i)[0].needsParenthesis(po, ips_n, *this, i + 1, true, true); - print_str += CHILD(i)[0].print(po, ips_n); - } else { - if(po.spacious) print_str += " "; - print_str += "+"; - if(po.spacious) print_str += " "; - ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); - print_str += CHILD(i).print(po, ips_n); - } - } else { - ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); - print_str += CHILD(i).print(po, ips_n); - } - } - break; - } - case STRUCT_NEGATE: { - if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MINUS, po.can_display_unicode_string_arg))) print_str += SIGN_MINUS; - else print_str = "-"; - ips_n.depth++; - ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); - print_str += CHILD(0).print(po, ips_n); - break; - } - case STRUCT_MULTIPLICATION: { - ips_n.depth++; - if(!po.preserve_format && SIZE == 2 && (CHILD(0).isNumber() || (CHILD(0).isNegate() && CHILD(0)[0].isNumber())) && CHILD(1).isFunction() && CHILD(1).size() == 1 && CHILD(1).function()->referenceName() == "cis" && (((CHILD(1)[0].isNumber() || (CHILD(1)[0].isNegate() && CHILD(1)[0][0].isNumber())) || (CHILD(1)[0].isMultiplication() && CHILD(1)[0].size() == 2 && (CHILD(1)[0][0].isNumber() || (CHILD(1)[0].isNegate() && CHILD(1)[0][0][0].isNumber())) && CHILD(1)[0][1].isUnit())) || (CHILD(1)[0].isNegate() && CHILD(1)[0][0].isMultiplication() && CHILD(1)[0][0].size() == 2 && CHILD(1)[0][0][0].isNumber() && CHILD(1)[0][0][1].isUnit()))) { - ips_n.wrap = false; - print_str += CHILD(0).print(po, ips_n); - print_str += " "; - print_str += "cis"; - print_str += " "; - ips_n.wrap = ((CHILD(1)[0].isMultiplication() && CHILD(1)[0][1].neededMultiplicationSign(po, ips_n, CHILD(1)[0], 2, false, false, false, false) != MULTIPLICATION_SIGN_NONE) || (CHILD(1)[0].isNegate() && CHILD(1)[0][0].isMultiplication() && CHILD(1)[0][0][1].neededMultiplicationSign(po, ips_n, CHILD(1)[0][0], 2, false, false, false, false) != MULTIPLICATION_SIGN_NONE)); - print_str += CHILD(1)[0].print(po, ips_n); - break; - } - bool par_prev = false; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); - ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); - if(!po.short_multiplication && i > 0) { - if(po.spacious) print_str += " "; - if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_DOT && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIDOT, po.can_display_unicode_string_arg))) print_str += SIGN_MULTIDOT; - else if(po.use_unicode_signs && (po.multiplication_sign == MULTIPLICATION_SIGN_DOT || po.multiplication_sign == MULTIPLICATION_SIGN_ALTDOT) && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MIDDLEDOT, po.can_display_unicode_string_arg))) print_str += SIGN_MIDDLEDOT; - else if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_X && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIPLICATION, po.can_display_unicode_string_arg))) print_str += SIGN_MULTIPLICATION; - else print_str += "*"; - if(po.spacious) print_str += " "; - } else if(i > 0) { - switch(CHILD(i).neededMultiplicationSign(po, ips_n, *this, i + 1, ips_n.wrap || (CHILD(i).isPower() && CHILD(i)[0].needsParenthesis(po, ips_n, CHILD(i), 1, true, true)), par_prev, true, true)) { - case MULTIPLICATION_SIGN_SPACE: {print_str += " "; break;} - case MULTIPLICATION_SIGN_OPERATOR: { - if(po.spacious) { - if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_DOT && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIDOT, po.can_display_unicode_string_arg))) print_str += " " SIGN_MULTIDOT " "; - else if(po.use_unicode_signs && (po.multiplication_sign == MULTIPLICATION_SIGN_DOT || po.multiplication_sign == MULTIPLICATION_SIGN_ALTDOT) && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MIDDLEDOT, po.can_display_unicode_string_arg))) print_str += " " SIGN_MIDDLEDOT " "; - else if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_X && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIPLICATION, po.can_display_unicode_string_arg))) print_str += " " SIGN_MULTIPLICATION " "; - else print_str += " * "; - break; - } - } - case MULTIPLICATION_SIGN_OPERATOR_SHORT: { - if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_DOT && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIDOT, po.can_display_unicode_string_arg))) print_str += SIGN_MULTIDOT; - else if(po.use_unicode_signs && (po.multiplication_sign == MULTIPLICATION_SIGN_DOT || po.multiplication_sign == MULTIPLICATION_SIGN_ALTDOT) && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MIDDLEDOT, po.can_display_unicode_string_arg))) print_str += SIGN_MIDDLEDOT; - else if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_X && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIPLICATION, po.can_display_unicode_string_arg))) print_str += SIGN_MULTIPLICATION; - else print_str += "*"; - break; - } - } - } - print_str += CHILD(i).print(po, ips_n); - par_prev = ips_n.wrap; - } - break; - } - case STRUCT_INVERSE: { - ips_n.depth++; - ips_n.division_depth++; - ips_n.wrap = false; - print_str = m_one.print(po, ips_n); - if(po.spacious) print_str += " "; - if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION, po.can_display_unicode_string_arg))) { - print_str += SIGN_DIVISION; - } else if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION_SLASH && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION_SLASH, po.can_display_unicode_string_arg))) { - print_str += SIGN_DIVISION_SLASH; - } else { - print_str += "/"; - } - if(po.spacious) print_str += " "; - ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); - print_str += CHILD(0).print(po, ips_n); - break; - } - case STRUCT_DIVISION: { - ips_n.depth++; - ips_n.division_depth++; - ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); - print_str = CHILD(0).print(po, ips_n); - if(po.spacious) print_str += " "; - if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION, po.can_display_unicode_string_arg))) { - print_str += SIGN_DIVISION; - } else if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION_SLASH && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION_SLASH, po.can_display_unicode_string_arg))) { - print_str += SIGN_DIVISION_SLASH; - } else { - print_str += "/"; - } - if(po.spacious) print_str += " "; - ips_n.wrap = CHILD(1).needsParenthesis(po, ips_n, *this, 2, true, true); - print_str += CHILD(1).print(po, ips_n); - break; - } - case STRUCT_POWER: { - ips_n.depth++; - ips_n.power_depth++; - ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); - print_str = CHILD(0).print(po, ips_n); - print_str += "^"; - ips_n.wrap = CHILD(1).needsParenthesis(po, ips_n, *this, 2, true, true); - PrintOptions po2 = po; - po2.show_ending_zeroes = false; - print_str += CHILD(1).print(po2, ips_n); - break; - } - case STRUCT_COMPARISON: { - ips_n.depth++; - ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); - print_str = CHILD(0).print(po, ips_n); - if(po.spacious) print_str += " "; - switch(ct_comp) { - case COMPARISON_EQUALS: { - if(po.use_unicode_signs && po.interval_display != INTERVAL_DISPLAY_INTERVAL && isApproximate() && containsInterval() && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_ALMOST_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_ALMOST_EQUAL; - else print_str += "="; - break; - } - case COMPARISON_NOT_EQUALS: { - if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_NOT_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_NOT_EQUAL; - else print_str += "!="; - break; - } - case COMPARISON_GREATER: {print_str += ">"; break;} - case COMPARISON_LESS: {print_str += "<"; break;} - case COMPARISON_EQUALS_GREATER: { - if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_GREATER_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_GREATER_OR_EQUAL; - else print_str += ">="; - break; - } - case COMPARISON_EQUALS_LESS: { - if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_LESS_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_LESS_OR_EQUAL; - else print_str += "<="; - break; - } - } - if(po.spacious) print_str += " "; - ips_n.wrap = CHILD(1).needsParenthesis(po, ips_n, *this, 2, true, true); - print_str += CHILD(1).print(po, ips_n); - break; - } - case STRUCT_BITWISE_AND: { - ips_n.depth++; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); - if(i > 0) { - if(po.spacious) print_str += " "; - print_str += "&"; - if(po.spacious) print_str += " "; - } - ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); - print_str += CHILD(i).print(po, ips_n); - } - break; - } - case STRUCT_BITWISE_OR: { - ips_n.depth++; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); - if(i > 0) { - if(po.spacious) print_str += " "; - print_str += "|"; - if(po.spacious) print_str += " "; - } - ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); - print_str += CHILD(i).print(po, ips_n); - } - break; - } - case STRUCT_BITWISE_XOR: { - ips_n.depth++; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); - if(i > 0) { - print_str += " "; - print_str += "xor"; - print_str += " "; - } - ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); - print_str += CHILD(i).print(po, ips_n); - } - break; - } - case STRUCT_BITWISE_NOT: { - print_str = "~"; - ips_n.depth++; - ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); - print_str += CHILD(0).print(po, ips_n); - break; - } - case STRUCT_LOGICAL_AND: { - ips_n.depth++; - if(!po.preserve_format && SIZE == 2 && CHILD(0).isComparison() && CHILD(1).isComparison() && CHILD(0).comparisonType() != COMPARISON_EQUALS && CHILD(0).comparisonType() != COMPARISON_NOT_EQUALS && CHILD(1).comparisonType() != COMPARISON_EQUALS && CHILD(1).comparisonType() != COMPARISON_NOT_EQUALS && CHILD(0)[0] == CHILD(1)[0]) { - ips_n.wrap = CHILD(0)[1].needsParenthesis(po, ips_n, CHILD(0), 2, true, true); - print_str += CHILD(0)[1].print(po, ips_n); - if(po.spacious) print_str += " "; - switch(CHILD(0).comparisonType()) { - case COMPARISON_LESS: {print_str += ">"; break;} - case COMPARISON_GREATER: {print_str += "<"; break;} - case COMPARISON_EQUALS_LESS: { - if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_GREATER_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_GREATER_OR_EQUAL; - else print_str += ">="; - break; - } - case COMPARISON_EQUALS_GREATER: { - if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_LESS_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_LESS_OR_EQUAL; - else print_str += "<="; - break; - } - default: {} - } - if(po.spacious) print_str += " "; - - ips_n.wrap = CHILD(0)[0].needsParenthesis(po, ips_n, CHILD(0), 1, true, true); - print_str += CHILD(0)[0].print(po, ips_n); - - if(po.spacious) print_str += " "; - switch(CHILD(1).comparisonType()) { - case COMPARISON_GREATER: {print_str += ">"; break;} - case COMPARISON_LESS: {print_str += "<"; break;} - case COMPARISON_EQUALS_GREATER: { - if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_GREATER_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_GREATER_OR_EQUAL; - else print_str += ">="; - break; - } - case COMPARISON_EQUALS_LESS: { - if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_LESS_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_LESS_OR_EQUAL; - else print_str += "<="; - break; - } - default: {} - } - if(po.spacious) print_str += " "; - - ips_n.wrap = CHILD(1)[1].needsParenthesis(po, ips_n, CHILD(1), 2, true, true); - print_str += CHILD(1)[1].print(po, ips_n); - - break; - } - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); - if(i > 0) { - if(po.spell_out_logical_operators) { - print_str += " "; - print_str += _("and"); - print_str += " "; - } else { - if(po.spacious) print_str += " "; - print_str += "&&"; - if(po.spacious) print_str += " "; - } - } - ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); - print_str += CHILD(i).print(po, ips_n); - } - break; - } - case STRUCT_LOGICAL_OR: { - ips_n.depth++; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); - if(i > 0) { - if(po.spell_out_logical_operators) { - print_str += " "; - print_str += _("or"); - print_str += " "; - } else { - if(po.spacious) print_str += " "; - print_str += "||"; - if(po.spacious) print_str += " "; - } - } - ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); - print_str += CHILD(i).print(po, ips_n); - } - break; - } - case STRUCT_LOGICAL_XOR: { - ips_n.depth++; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); - if(i > 0) { - print_str += " "; - print_str += "xor"; - print_str += " "; - } - ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); - print_str += CHILD(i).print(po, ips_n); - } - break; - } - case STRUCT_LOGICAL_NOT: { - print_str = "!"; - ips_n.depth++; - ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); - print_str += CHILD(0).print(po, ips_n); - break; - } - case STRUCT_VECTOR: { - ips_n.depth++; - print_str = "["; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); - if(i > 0) { - print_str += po.comma(); - if(po.spacious) print_str += " "; - } - ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); - print_str += CHILD(i).print(po, ips_n); - } - print_str += "]"; - break; - } - case STRUCT_UNIT: { - const ExpressionName *ename = &o_unit->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, b_plural, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); - if(o_prefix) print_str += o_prefix->name(po.abbreviate_names && ename->abbreviation, po.use_unicode_signs, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); - print_str += ename->name; - if(ename->suffix && !po.preserve_format && !po.use_reference_names) { - size_t i = print_str.rfind('_'); - if(i != string::npos && i + 5 <= print_str.length() && print_str.substr(print_str.length() - 4, 4) == "unit") { - if(i + 5 == print_str.length()) { - print_str = print_str.substr(0, i); - if(po.hide_underscore_spaces) gsub("_", " ", print_str); - } else { - print_str = print_str.substr(0, print_str.length() - 4); - } - } - } - if(po.hide_underscore_spaces && !ename->suffix) { - gsub("_", " ", print_str); - } - break; - } - case STRUCT_VARIABLE: { - const ExpressionName *ename = &o_variable->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); - print_str += ename->name; - if(ename->suffix && !po.preserve_format && !po.use_reference_names) { - size_t i = print_str.rfind('_'); - if(i != string::npos && i + 9 <= print_str.length() && print_str.substr(print_str.length() - 8, 8) == "constant") { - if(i + 9 == print_str.length()) { - print_str = print_str.substr(0, i); - if(po.hide_underscore_spaces) gsub("_", " ", print_str); - } else { - print_str = print_str.substr(0, print_str.length() - 8); - } - } - } - if(po.hide_underscore_spaces && !ename->suffix) { - gsub("_", " ", print_str); - } - break; - } - case STRUCT_FUNCTION: { - ips_n.depth++; - if(o_function == CALCULATOR->f_uncertainty && SIZE == 3 && CHILD(2).isZero()) { - MathStructure *mmid = NULL, *munc = NULL; - if(o_function == CALCULATOR->f_uncertainty) { - mmid = &CHILD(0); - munc = &CHILD(1); - } else if(CHILD(0)[0].equals(CHILD(1)[0], true, true)) { - mmid = &CHILD(0)[0]; - if(CHILD(0)[1].isNegate() && CHILD(0)[1][0].equals(CHILD(1)[1], true, true)) munc = &CHILD(1)[1]; - if(CHILD(1)[1].isNegate() && CHILD(1)[1][0].equals(CHILD(0)[1], true, true)) munc = &CHILD(0)[1]; - } else if(CHILD(0)[1].equals(CHILD(1)[1], true, true)) { - mmid = &CHILD(0)[1]; - if(CHILD(0)[0].isNegate() && CHILD(0)[0][0].equals(CHILD(1)[0], true, true)) munc = &CHILD(1)[0]; - if(CHILD(1)[0].isNegate() && CHILD(1)[0][0].equals(CHILD(0)[0], true, true)) munc = &CHILD(0)[0]; - } else if(CHILD(0)[0].equals(CHILD(1)[1], true, true)) { - mmid = &CHILD(0)[0]; - if(CHILD(0)[1].isNegate() && CHILD(0)[1][0].equals(CHILD(1)[0], true, true)) munc = &CHILD(1)[0]; - if(CHILD(1)[0].isNegate() && CHILD(1)[0][0].equals(CHILD(0)[1], true, true)) munc = &CHILD(0)[1]; - } else if(CHILD(0)[1].equals(CHILD(1)[0], true, true)) { - mmid = &CHILD(0)[0]; - if(CHILD(0)[0].isNegate() && CHILD(0)[0][0].equals(CHILD(1)[1], true, true)) munc = &CHILD(1)[1]; - if(CHILD(1)[1].isNegate() && CHILD(1)[1][0].equals(CHILD(0)[0], true, true)) munc = &CHILD(0)[0]; - } - if(mmid && munc) { - PrintOptions po2 = po; - po2.show_ending_zeroes = false; - po2.number_fraction_format = FRACTION_DECIMAL; - ips_n.wrap = !CHILD(0).isNumber(); - print_str += CHILD(0).print(po2, ips_n); - print_str += SIGN_PLUSMINUS; - ips_n.wrap = !CHILD(1).isNumber(); - print_str += CHILD(1).print(po2, ips_n); - break; - } - } - const ExpressionName *ename = &o_function->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); - print_str += ename->name; - if(po.hide_underscore_spaces && !ename->suffix) { - gsub("_", " ", print_str); - } - print_str += "("; - size_t argcount = SIZE; - if(o_function == CALCULATOR->f_signum && argcount > 1) { - argcount = 1; - } else if(o_function->maxargs() > 0 && o_function->minargs() < o_function->maxargs() && SIZE > (size_t) o_function->minargs()) { - while(true) { - string defstr = o_function->getDefaultValue(argcount); - Argument *arg = o_function->getArgumentDefinition(argcount); - remove_blank_ends(defstr); - if(defstr.empty()) break; - if(CHILD(argcount - 1).isUndefined() && defstr == "undefined") { - argcount--; - } else if(argcount > 1 && arg && arg->type() == ARGUMENT_TYPE_SYMBOLIC && defstr == "undefined" && CHILD(argcount - 1) == CHILD(0).find_x_var()) { - argcount--; - } else if(CHILD(argcount - 1).isVariable() && (!arg || arg->type() != ARGUMENT_TYPE_TEXT) && defstr == CHILD(argcount - 1).variable()->referenceName()) { - argcount--; - } else if(CHILD(argcount - 1).isInteger() && (!arg || arg->type() != ARGUMENT_TYPE_TEXT) && defstr.find_first_not_of(NUMBERS) == string::npos && CHILD(argcount - 1).number() == s2i(defstr)) { - argcount--; - } else if(CHILD(argcount - 1).isSymbolic() && arg && arg->type() == ARGUMENT_TYPE_TEXT && CHILD(argcount - 1).symbol() == defstr) { - argcount--; - } else { - break; - } - if(argcount == 0 || argcount == (size_t) o_function->minargs()) break; - } - } - for(size_t i = 0; i < argcount; i++) { - if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); - if(i > 0) { - print_str += po.comma(); - if(po.spacious) print_str += " "; - } - ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); - if(o_function == CALCULATOR->f_interval) { - PrintOptions po2 = po; - po2.show_ending_zeroes = false; - print_str += CHILD(i).print(po2, ips_n); - } else { - print_str += CHILD(i).print(po, ips_n); - } - } - print_str += ")"; - break; - } - case STRUCT_UNDEFINED: { - print_str = _("undefined"); - break; - } - } - if(CALCULATOR->aborted()) print_str = CALCULATOR->abortedMessage(); - if(ips.wrap) { - print_str.insert(0, "("); - print_str += ")"; - } - return print_str; -} - -MathStructure &MathStructure::flattenVector(MathStructure &mstruct) const { - if(!isVector()) { - mstruct = *this; - return mstruct; - } - MathStructure mstruct2; - mstruct.clearVector(); - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isVector()) { - CHILD(i).flattenVector(mstruct2); - for(size_t i2 = 0; i2 < mstruct2.size(); i2++) { - mstruct.addChild(mstruct2[i2]); - } - } else { - mstruct.addChild(CHILD(i)); - } - } - return mstruct; -} -bool MathStructure::rankVector(bool ascending) { - vector ranked; - vector ranked_equals_prev; - bool b; - for(size_t index = 0; index < SIZE; index++) { - b = false; - for(size_t i = 0; i < ranked.size(); i++) { - if(CALCULATOR->aborted()) return false; - ComparisonResult cmp = CHILD(index).compare(CHILD(ranked[i])); - if(COMPARISON_NOT_FULLY_KNOWN(cmp)) { - CALCULATOR->error(true, _("Unsolvable comparison at element %s when trying to rank vector."), i2s(index).c_str(), NULL); - return false; - } - if((ascending && cmp == COMPARISON_RESULT_GREATER) || cmp == COMPARISON_RESULT_EQUAL || (!ascending && cmp == COMPARISON_RESULT_LESS)) { - if(cmp == COMPARISON_RESULT_EQUAL) { - ranked.insert(ranked.begin() + i + 1, index); - ranked_equals_prev.insert(ranked_equals_prev.begin() + i + 1, true); - } else { - ranked.insert(ranked.begin() + i, index); - ranked_equals_prev.insert(ranked_equals_prev.begin() + i, false); - } - b = true; - break; - } - } - if(!b) { - ranked.push_back(index); - ranked_equals_prev.push_back(false); - } - } - int n_rep = 0; - for(long int i = (long int) ranked.size() - 1; i >= 0; i--) { - if(CALCULATOR->aborted()) return false; - if(ranked_equals_prev[i]) { - n_rep++; - } else { - if(n_rep) { - MathStructure v(i + 1 + n_rep, 1L, 0L); - v += i + 1; - v *= MathStructure(1, 2, 0); - for(; n_rep >= 0; n_rep--) { - CHILD(ranked[i + n_rep]) = v; - } - } else { - CHILD(ranked[i]).set(i + 1, 1L, 0L); - } - n_rep = 0; - } - } - return true; -} -bool MathStructure::sortVector(bool ascending) { - vector ranked_mstructs; - bool b; - for(size_t index = 0; index < SIZE; index++) { - b = false; - for(size_t i = 0; i < ranked_mstructs.size(); i++) { - if(CALCULATOR->aborted()) return false; - ComparisonResult cmp = CHILD(index).compare(*v_subs[ranked_mstructs[i]]); - if(COMPARISON_MIGHT_BE_LESS_OR_GREATER(cmp)) { - CALCULATOR->error(true, _("Unsolvable comparison at element %s when trying to sort vector."), i2s(index).c_str(), NULL); - return false; - } - if((ascending && COMPARISON_IS_EQUAL_OR_GREATER(cmp)) || (!ascending && COMPARISON_IS_EQUAL_OR_LESS(cmp))) { - ranked_mstructs.insert(ranked_mstructs.begin() + i, v_order[index]); - b = true; - break; - } - } - if(!b) { - ranked_mstructs.push_back(v_order[index]); - } - } - v_order = ranked_mstructs; - return true; -} -MathStructure &MathStructure::getRange(int start, int end, MathStructure &mstruct) const { - if(!isVector()) { - if(start > 1) { - mstruct.clear(); - return mstruct; - } else { - mstruct = *this; - return mstruct; - } - } - if(start < 1) start = 1; - else if(start > (long int) SIZE) { - mstruct.clear(); - return mstruct; - } - if(end < (int) 1 || end > (long int) SIZE) end = SIZE; - else if(end < start) end = start; - mstruct.clearVector(); - for(; start <= end; start++) { - mstruct.addChild(CHILD(start - 1)); - } - return mstruct; -} - -void MathStructure::resizeVector(size_t i, const MathStructure &mfill) { - if(i > SIZE) { - while(i > SIZE) { - APPEND(mfill); - } - } else if(i < SIZE) { - REDUCE(i) - } -} - -size_t MathStructure::rows() const { - if(m_type != STRUCT_VECTOR || SIZE == 0 || (SIZE == 1 && (!CHILD(0).isVector() || CHILD(0).size() == 0))) return 0; - return SIZE; -} -size_t MathStructure::columns() const { - if(m_type != STRUCT_VECTOR || SIZE == 0 || !CHILD(0).isVector()) return 0; - return CHILD(0).size(); -} -const MathStructure *MathStructure::getElement(size_t row, size_t column) const { - if(row == 0 || column == 0 || row > rows() || column > columns()) return NULL; - if(CHILD(row - 1).size() < column) return NULL; - return &CHILD(row - 1)[column - 1]; -} -MathStructure *MathStructure::getElement(size_t row, size_t column) { - if(row == 0 || column == 0 || row > rows() || column > columns()) return NULL; - if(CHILD(row - 1).size() < column) return NULL; - return &CHILD(row - 1)[column - 1]; -} -MathStructure &MathStructure::getArea(size_t r1, size_t c1, size_t r2, size_t c2, MathStructure &mstruct) const { - size_t r = rows(); - size_t c = columns(); - if(r1 < 1) r1 = 1; - else if(r1 > r) r1 = r; - if(c1 < 1) c1 = 1; - else if(c1 > c) c1 = c; - if(r2 < 1 || r2 > r) r2 = r; - else if(r2 < r1) r2 = r1; - if(c2 < 1 || c2 > c) c2 = c; - else if(c2 < c1) c2 = c1; - mstruct.clearMatrix(); mstruct.resizeMatrix(r2 - r1 + 1, c2 - c1 + 1, m_undefined); - for(size_t index_r = r1; index_r <= r2; index_r++) { - for(size_t index_c = c1; index_c <= c2; index_c++) { - mstruct[index_r - r1][index_c - c1] = CHILD(index_r - 1)[index_c - 1]; - } - } - return mstruct; -} -MathStructure &MathStructure::rowToVector(size_t r, MathStructure &mstruct) const { - if(r > rows()) { - mstruct = m_undefined; - return mstruct; - } - if(r < 1) r = 1; - mstruct = CHILD(r - 1); - return mstruct; -} -MathStructure &MathStructure::columnToVector(size_t c, MathStructure &mstruct) const { - if(c > columns()) { - mstruct = m_undefined; - return mstruct; - } - if(c < 1) c = 1; - mstruct.clearVector(); - for(size_t i = 0; i < SIZE; i++) { - mstruct.addChild(CHILD(i)[c - 1]); - } - return mstruct; -} -MathStructure &MathStructure::matrixToVector(MathStructure &mstruct) const { - if(!isVector()) { - mstruct = *this; - return mstruct; - } - mstruct.clearVector(); - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isVector()) { - for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { - mstruct.addChild(CHILD(i)[i2]); - } - } else { - mstruct.addChild(CHILD(i)); - } - } - return mstruct; -} -void MathStructure::setElement(const MathStructure &mstruct, size_t row, size_t column) { - if(row > rows() || column > columns() || row < 1 || column < 1) return; - CHILD(row - 1)[column - 1] = mstruct; - CHILD(row - 1).childUpdated(column); - CHILD_UPDATED(row - 1); -} -void MathStructure::addRows(size_t r, const MathStructure &mfill) { - if(r == 0) return; - size_t cols = columns(); - MathStructure mstruct; mstruct.clearVector(); - mstruct.resizeVector(cols, mfill); - for(size_t i = 0; i < r; i++) { - APPEND(mstruct); - } -} -void MathStructure::addColumns(size_t c, const MathStructure &mfill) { - if(c == 0) return; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isVector()) { - for(size_t i2 = 0; i2 < c; i2++) { - CHILD(i).addChild(mfill); - } - } - } - CHILDREN_UPDATED; -} -void MathStructure::addRow(const MathStructure &mfill) { - addRows(1, mfill); -} -void MathStructure::addColumn(const MathStructure &mfill) { - addColumns(1, mfill); -} -void MathStructure::resizeMatrix(size_t r, size_t c, const MathStructure &mfill) { - if(r > SIZE) { - addRows(r - SIZE, mfill); - } else if(r != SIZE) { - REDUCE(r); - } - size_t cols = columns(); - if(c > cols) { - addColumns(c - cols, mfill); - } else if(c != cols) { - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).resizeVector(c, mfill); - } - } -} -bool MathStructure::matrixIsSquare() const { - return rows() == columns(); -} - -bool MathStructure::isNumericMatrix() const { - if(!isMatrix()) return false; - for(size_t index_r = 0; index_r < SIZE; index_r++) { - for(size_t index_c = 0; index_c < CHILD(index_r).size(); index_c++) { - if(!CHILD(index_r)[index_c].isNumber() || CHILD(index_r)[index_c].isInfinity()) return false; - } - } - return true; -} - -//from GiNaC -int MathStructure::pivot(size_t ro, size_t co, bool symbolic) { - - size_t k = ro; - if(symbolic) { - while((k < SIZE) && (CHILD(k)[co].isZero())) ++k; - } else { - size_t kmax = k + 1; - Number mmax(CHILD(kmax)[co].number()); - mmax.abs(); - while(kmax < SIZE) { - if(CHILD(kmax)[co].number().isNegative()) { - Number ntmp(CHILD(kmax)[co].number()); - ntmp.negate(); - if(ntmp.isGreaterThan(mmax)) { - mmax = ntmp; - k = kmax; - } - } else if(CHILD(kmax)[co].number().isGreaterThan(mmax)) { - mmax = CHILD(kmax)[co].number(); - k = kmax; - } - ++kmax; - } - if(!mmax.isZero()) k = kmax; - } - if(k == SIZE) return -1; - if(k == ro) return 0; - - SWAP_CHILDREN(ro, k) - - return k; - -} - - -//from GiNaC -void determinant_minor(const MathStructure &mtrx, MathStructure &mdet, const EvaluationOptions &eo) { - size_t n = mtrx.size(); - if(n == 1) { - mdet = mtrx[0][0]; - return; - } - if(n == 2) { - mdet = mtrx[0][0]; - mdet.calculateMultiply(mtrx[1][1], eo); - mdet.add(mtrx[1][0], true); - mdet[mdet.size() - 1].calculateMultiply(mtrx[0][1], eo); - mdet[mdet.size() - 1].calculateNegate(eo); - mdet.calculateAddLast(eo); - return; - } - if(n == 3) { - mdet = mtrx[0][0]; - mdet.calculateMultiply(mtrx[1][1], eo); - mdet.calculateMultiply(mtrx[2][2], eo); - mdet.add(mtrx[0][0], true); - mdet[mdet.size() - 1].calculateMultiply(mtrx[1][2], eo); - mdet[mdet.size() - 1].calculateMultiply(mtrx[2][1], eo); - mdet[mdet.size() - 1].calculateNegate(eo); - mdet.calculateAddLast(eo); - mdet.add(mtrx[0][1], true); - mdet[mdet.size() - 1].calculateMultiply(mtrx[1][0], eo); - mdet[mdet.size() - 1].calculateMultiply(mtrx[2][2], eo); - mdet[mdet.size() - 1].calculateNegate(eo); - mdet.calculateAddLast(eo); - mdet.add(mtrx[0][2], true); - mdet[mdet.size() - 1].calculateMultiply(mtrx[1][0], eo); - mdet[mdet.size() - 1].calculateMultiply(mtrx[2][1], eo); - mdet.calculateAddLast(eo); - mdet.add(mtrx[0][1], true); - mdet[mdet.size() - 1].calculateMultiply(mtrx[1][2], eo); - mdet[mdet.size() - 1].calculateMultiply(mtrx[2][0], eo); - mdet.calculateAddLast(eo); - mdet.add(mtrx[0][2], true); - mdet[mdet.size() - 1].calculateMultiply(mtrx[1][1], eo); - mdet[mdet.size() - 1].calculateMultiply(mtrx[2][0], eo); - mdet[mdet.size() - 1].calculateNegate(eo); - mdet.calculateAddLast(eo); - return; - } - - std::vector Pkey; - Pkey.reserve(n); - std::vector Mkey; - Mkey.reserve(n - 1); - typedef std::map, class MathStructure> Rmap; - typedef std::map, class MathStructure>::value_type Rmap_value; - Rmap A; - Rmap B; - for(size_t r = 0; r < n; ++r) { - Pkey.erase(Pkey.begin(), Pkey.end()); - Pkey.push_back(r); - A.insert(Rmap_value(Pkey, mtrx[r][n - 1])); - } - for(long int c = n - 2; c >= 0; --c) { - Pkey.erase(Pkey.begin(), Pkey.end()); - Mkey.erase(Mkey.begin(), Mkey.end()); - for(size_t i = 0; i < n - c; ++i) Pkey.push_back(i); - size_t fc = 0; - do { - mdet.clear(); - for(size_t r = 0; r < n - c; ++r) { - if (mtrx[Pkey[r]][c].isZero()) continue; - Mkey.erase(Mkey.begin(), Mkey.end()); - for(size_t i = 0; i < n - c; ++i) { - if(i != r) Mkey.push_back(Pkey[i]); - } - mdet.add(mtrx[Pkey[r]][c], true); - mdet[mdet.size() - 1].calculateMultiply(A[Mkey], eo); - if(r % 2) mdet[mdet.size() - 1].calculateNegate(eo); - mdet.calculateAddLast(eo); - } - if(!mdet.isZero()) B.insert(Rmap_value(Pkey, mdet)); - for(fc = n - c; fc > 0; --fc) { - ++Pkey[fc-1]; - if(Pkey[fc - 1] < fc + c) break; - } - if(fc < n - c && fc > 0) { - for(size_t j = fc; j < n - c; ++j) Pkey[j] = Pkey[j - 1] + 1; - } - } while(fc); - A = B; - B.clear(); - } - return; -} - -//from GiNaC -int MathStructure::gaussianElimination(const EvaluationOptions &eo, bool det) { - - if(!isMatrix()) return 0; - bool isnumeric = isNumericMatrix(); - - size_t m = rows(); - size_t n = columns(); - int sign = 1; - - size_t r0 = 0; - for(size_t c0 = 0; c0 < n && r0 < m - 1; ++c0) { - int indx = pivot(r0, c0, true); - if(indx == -1) { - sign = 0; - if(det) return 0; - } - if(indx >= 0) { - if(indx > 0) sign = -sign; - for(size_t r2 = r0 + 1; r2 < m; ++r2) { - if(!CHILD(r2)[c0].isZero()) { - if(isnumeric) { - Number piv(CHILD(r2)[c0].number()); - piv /= CHILD(r0)[c0].number(); - for(size_t c = c0 + 1; c < n; ++c) { - CHILD(r2)[c].number() -= piv * CHILD(r0)[c].number(); - } - } else { - MathStructure piv(CHILD(r2)[c0]); - piv.calculateDivide(CHILD(r0)[c0], eo); - for(size_t c = c0 + 1; c < n; ++c) { - CHILD(r2)[c].add(piv, true); - CHILD(r2)[c][CHILD(r2)[c].size() - 1].calculateMultiply(CHILD(r0)[c], eo); - CHILD(r2)[c][CHILD(r2)[c].size() - 1].calculateNegate(eo); - CHILD(r2)[c].calculateAddLast(eo); - } - } - } - for(size_t c = r0; c <= c0; ++c) CHILD(r2)[c].clear(); - } - if(det) { - for(size_t c = r0 + 1; c < n; ++c) CHILD(r0)[c].clear(); - } - ++r0; - } - } - for(size_t r = r0 + 1; r < m; ++r) { - for(size_t c = 0; c < n; ++c) CHILD(r)[c].clear(); - } - - return sign; -} - -//from GiNaC -template -int permutation_sign(It first, It last) -{ - if (first == last) - return 0; - --last; - if (first == last) - return 0; - It flag = first; - int sign = 1; - - do { - It i = last, other = last; - --other; - bool swapped = false; - while (i != first) { - if (*i < *other) { - std::iter_swap(other, i); - flag = other; - swapped = true; - sign = -sign; - } else if (!(*other < *i)) - return 0; - --i; --other; - } - if (!swapped) - return sign; - ++flag; - if (flag == last) - return sign; - first = flag; - i = first; other = first; - ++other; - swapped = false; - while (i != last) { - if (*other < *i) { - std::iter_swap(i, other); - flag = other; - swapped = true; - sign = -sign; - } else if (!(*i < *other)) - return 0; - ++i; ++other; - } - if (!swapped) - return sign; - last = flag; - --last; - } while (first != last); - - return sign; -} - -//from GiNaC -MathStructure &MathStructure::determinant(MathStructure &mstruct, const EvaluationOptions &eo) const { - - if(!matrixIsSquare()) { - CALCULATOR->error(true, _("The determinant can only be calculated for square matrices."), NULL); - mstruct = m_undefined; - return mstruct; - } - - if(SIZE == 1) { - mstruct = CHILD(0)[0]; - } else if(isNumericMatrix()) { - - mstruct.set(1, 1, 0); - MathStructure mtmp(*this); - int sign = mtmp.gaussianElimination(eo, true); - for(size_t d = 0; d < SIZE; ++d) { - mstruct.number() *= mtmp[d][d].number(); - } - mstruct.number() *= sign; - - } else { - - typedef std::pair sizet_pair; - std::vector c_zeros; - for(size_t c = 0; c < CHILD(0).size(); ++c) { - size_t acc = 0; - for(size_t r = 0; r < SIZE; ++r) { - if(CHILD(r)[c].isZero()) ++acc; - } - c_zeros.push_back(sizet_pair(acc, c)); - } - - std::sort(c_zeros.begin(), c_zeros.end()); - std::vector pre_sort; - for(std::vector::const_iterator i = c_zeros.begin(); i != c_zeros.end(); ++i) { - pre_sort.push_back(i->second); - } - std::vector pre_sort_test(pre_sort); - - int sign = permutation_sign(pre_sort_test.begin(), pre_sort_test.end()); - - MathStructure result; - result.clearMatrix(); - result.resizeMatrix(SIZE, CHILD(0).size(), m_zero); - - size_t c = 0; - for(std::vector::const_iterator i = pre_sort.begin(); i != pre_sort.end(); ++i,++c) { - for(size_t r = 0; r < SIZE; ++r) result[r][c] = CHILD(r)[(*i)]; - } - mstruct.clear(); - - determinant_minor(result, mstruct, eo); - - if(sign != 1) { - mstruct.calculateMultiply(sign, eo); - } - - } - - mstruct.mergePrecision(*this); - return mstruct; - -} - -MathStructure &MathStructure::permanent(MathStructure &mstruct, const EvaluationOptions &eo) const { - if(!matrixIsSquare()) { - CALCULATOR->error(true, _("The permanent can only be calculated for square matrices."), NULL); - mstruct = m_undefined; - return mstruct; - } - if(b_approx) mstruct.setApproximate(); - mstruct.setPrecision(i_precision); - if(SIZE == 1) { - if(CHILD(0).size() >= 1) { - mstruct = CHILD(0)[0]; - } - } else if(SIZE == 2) { - mstruct = CHILD(0)[0]; - if(IS_REAL(mstruct) && IS_REAL(CHILD(1)[1])) { - mstruct.number() *= CHILD(1)[1].number(); - } else { - mstruct.calculateMultiply(CHILD(1)[1], eo); - } - if(IS_REAL(mstruct) && IS_REAL(CHILD(1)[0]) && IS_REAL(CHILD(0)[1])) { - mstruct.number() += CHILD(1)[0].number() * CHILD(0)[1].number(); - } else { - MathStructure mtmp = CHILD(1)[0]; - mtmp.calculateMultiply(CHILD(0)[1], eo); - mstruct.calculateAdd(mtmp, eo); - } - } else { - MathStructure mtrx; - mtrx.clearMatrix(); - mtrx.resizeMatrix(SIZE - 1, CHILD(0).size() - 1, m_undefined); - for(size_t index_c = 0; index_c < CHILD(0).size(); index_c++) { - for(size_t index_r2 = 1; index_r2 < SIZE; index_r2++) { - for(size_t index_c2 = 0; index_c2 < CHILD(index_r2).size(); index_c2++) { - if(index_c2 > index_c) { - mtrx.setElement(CHILD(index_r2)[index_c2], index_r2, index_c2); - } else if(index_c2 < index_c) { - mtrx.setElement(CHILD(index_r2)[index_c2], index_r2, index_c2 + 1); - } - } - } - MathStructure mdet; - mtrx.permanent(mdet, eo); - if(IS_REAL(mdet) && IS_REAL(CHILD(0)[index_c])) { - mdet.number() *= CHILD(0)[index_c].number(); - } else { - mdet.calculateMultiply(CHILD(0)[index_c], eo); - } - if(IS_REAL(mdet) && IS_REAL(mstruct)) { - mstruct.number() += mdet.number(); - } else { - mstruct.calculateAdd(mdet, eo); - } - } - } - return mstruct; -} -void MathStructure::setToIdentityMatrix(size_t n) { - clearMatrix(); - resizeMatrix(n, n, m_zero); - for(size_t i = 0; i < n; i++) { - CHILD(i)[i] = m_one; - } -} -MathStructure &MathStructure::getIdentityMatrix(MathStructure &mstruct) const { - mstruct.setToIdentityMatrix(columns()); - return mstruct; -} - -//modified algorithm from eigenmath -bool MathStructure::invertMatrix(const EvaluationOptions &eo) { - - if(!matrixIsSquare()) return false; - - if(isNumericMatrix()) { - - int d, i, j, n = SIZE; - - MathStructure idstruct; - Number mtmp; - idstruct.setToIdentityMatrix(n); - MathStructure mtrx(*this); - - for(d = 0; d < n; d++) { - if(mtrx[d][d].isZero()) { - for (i = d + 1; i < n; i++) { - if(!mtrx[i][d].isZero()) break; - } - - if(i == n) { - CALCULATOR->error(true, _("Inverse of singular matrix."), NULL); - return false; - } - - mtrx[i].ref(); - mtrx[d].ref(); - MathStructure *mptr = &mtrx[d]; - mtrx.setChild_nocopy(&mtrx[i], d + 1); - mtrx.setChild_nocopy(mptr, i + 1); - - idstruct[i].ref(); - idstruct[d].ref(); - mptr = &idstruct[d]; - idstruct.setChild_nocopy(&idstruct[i], d + 1); - idstruct.setChild_nocopy(mptr, i + 1); - - } - - mtmp = mtrx[d][d].number(); - mtmp.recip(); - - for(j = 0; j < n; j++) { - - if(j > d) { - mtrx[d][j].number() *= mtmp; - } - - idstruct[d][j].number() *= mtmp; - - } - - for(i = 0; i < n; i++) { - - if(i == d) continue; - - mtmp = mtrx[i][d].number(); - mtmp.negate(); - - for(j = 0; j < n; j++) { - - if(j > d) { - mtrx[i][j].number() += mtrx[d][j].number() * mtmp; - } - - idstruct[i][j].number() += idstruct[d][j].number() * mtmp; - - } - } - } - set_nocopy(idstruct); - MERGE_APPROX_AND_PREC(idstruct) - } else { - MathStructure *mstruct = new MathStructure(); - determinant(*mstruct, eo); - mstruct->calculateInverse(eo); - adjointMatrix(eo); - multiply_nocopy(mstruct, true); - calculateMultiplyLast(eo); - } - return true; -} - -bool MathStructure::adjointMatrix(const EvaluationOptions &eo) { - if(!matrixIsSquare()) return false; - if(SIZE == 1) {CHILD(0)[0].set(1, 1, 0); return true;} - MathStructure msave(*this); - for(size_t index_r = 0; index_r < SIZE; index_r++) { - for(size_t index_c = 0; index_c < CHILD(0).size(); index_c++) { - msave.cofactor(index_r + 1, index_c + 1, CHILD(index_r)[index_c], eo); - } - } - transposeMatrix(); - return true; -} -bool MathStructure::transposeMatrix() { - MathStructure msave(*this); - resizeMatrix(CHILD(0).size(), SIZE, m_undefined); - for(size_t index_r = 0; index_r < SIZE; index_r++) { - for(size_t index_c = 0; index_c < CHILD(0).size(); index_c++) { - CHILD(index_r)[index_c] = msave[index_c][index_r]; - } - } - return true; -} -MathStructure &MathStructure::cofactor(size_t r, size_t c, MathStructure &mstruct, const EvaluationOptions &eo) const { - if(r < 1) r = 1; - if(c < 1) c = 1; - if(SIZE == 1 || r > SIZE || c > CHILD(0).size()) { - mstruct = m_undefined; - return mstruct; - } - r--; c--; - mstruct.clearMatrix(); - mstruct.resizeMatrix(SIZE - 1, CHILD(0).size() - 1, m_undefined); - for(size_t index_r = 0; index_r < SIZE; index_r++) { - if(index_r != r) { - for(size_t index_c = 0; index_c < CHILD(0).size(); index_c++) { - if(index_c > c) { - if(index_r > r) { - mstruct[index_r - 1][index_c - 1] = CHILD(index_r)[index_c]; - } else { - mstruct[index_r][index_c - 1] = CHILD(index_r)[index_c]; - } - } else if(index_c < c) { - if(index_r > r) { - mstruct[index_r - 1][index_c] = CHILD(index_r)[index_c]; - } else { - mstruct[index_r][index_c] = CHILD(index_r)[index_c]; - } - } - } - } - } - MathStructure mstruct2; - mstruct = mstruct.determinant(mstruct2, eo); - if((r + c) % 2 == 1) { - mstruct.calculateNegate(eo); - } - return mstruct; -} - -void gatherInformation(const MathStructure &mstruct, vector &base_units, vector &alias_units, bool check_variables = false) { - switch(mstruct.type()) { - case STRUCT_UNIT: { - switch(mstruct.unit()->subtype()) { - case SUBTYPE_BASE_UNIT: { - for(size_t i = 0; i < base_units.size(); i++) { - if(base_units[i] == mstruct.unit()) { - return; - } - } - base_units.push_back(mstruct.unit()); - break; - } - case SUBTYPE_ALIAS_UNIT: { - for(size_t i = 0; i < alias_units.size(); i++) { - if(alias_units[i] == mstruct.unit()) { - return; - } - } - alias_units.push_back((AliasUnit*) (mstruct.unit())); - break; - } - case SUBTYPE_COMPOSITE_UNIT: { - gatherInformation(((CompositeUnit*) (mstruct.unit()))->generateMathStructure(), base_units, alias_units, check_variables); - break; - } - } - break; - } - case STRUCT_VARIABLE: { - if(check_variables && mstruct.variable()->isKnown()) gatherInformation(((KnownVariable*) mstruct.variable())->get(), base_units, alias_units, check_variables); - break; - } - case STRUCT_FUNCTION: { - if(mstruct.function() == CALCULATOR->f_stripunits) break; - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct.function()->getArgumentDefinition(i + 1) || mstruct.function()->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) { - gatherInformation(mstruct[i], base_units, alias_units, check_variables); - } - } - break; - } - default: { - for(size_t i = 0; i < mstruct.size(); i++) { - gatherInformation(mstruct[i], base_units, alias_units, check_variables); - } - break; - } - } - -} - -int MathStructure::isUnitCompatible(const MathStructure &mstruct) const { - if(!isMultiplication() && mstruct.isMultiplication()) return mstruct.isUnitCompatible(*this); - int b1 = mstruct.containsRepresentativeOfType(STRUCT_UNIT, true, true); - int b2 = containsRepresentativeOfType(STRUCT_UNIT, true, true); - if(b1 < 0 || b2 < 0) return -1; - if(b1 != b2) return false; - if(!b1) return true; - if(isMultiplication()) { - size_t unit_count1 = 0, unit_count2 = 0; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isUnit_exp()) unit_count1++; - else if(CHILD(i).containsRepresentativeOfType(STRUCT_UNIT, true, true) != 0) return -1; - } - if(mstruct.isMultiplication()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isUnit_exp()) unit_count2++; - else if(mstruct[i].containsRepresentativeOfType(STRUCT_UNIT, true, true) != 0) return -1; - } - } else if(mstruct.isUnit_exp()) { - if(unit_count1 > 1) return false; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isUnit_exp()) return CHILD(1) == mstruct; - } - } else { - return -1; - } - if(unit_count1 != unit_count2) return false; - size_t i2 = 0; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isUnit_exp()) { - for(; i2 < mstruct.size(); i2++) { - if(mstruct[i2].isUnit_exp()) { - if(CHILD(i) != mstruct[i2]) return false; - i2++; - break; - } - } - } - } - } else if(isUnit_exp()) { - if(mstruct.isUnit_exp()) return equals(mstruct); - } - return -1; -} - -bool MathStructure::syncUnits(bool sync_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo) { - if(SIZE == 0) return false; - vector base_units; - vector alias_units; - vector composite_units; - gatherInformation(*this, base_units, alias_units); - if(alias_units.empty() || base_units.size() + alias_units.size() == 1) return false; - CompositeUnit *cu; - bool b = false, do_erase = false; - for(size_t i = 0; i < alias_units.size(); ) { - do_erase = false; - if(alias_units[i]->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { - b = false; - cu = (CompositeUnit*) alias_units[i]->baseUnit(); - for(size_t i2 = 0; i2 < base_units.size(); i2++) { - if(cu->containsRelativeTo(base_units[i2])) { - for(size_t i3 = 0; i3 < composite_units.size(); i3++) { - if(composite_units[i3] == cu) { - b = true; - break; - } - } - if(!b) composite_units.push_back(cu); - do_erase = true; - break; - } - } - for(size_t i2 = 0; !do_erase && i2 < alias_units.size(); i2++) { - if(i != i2 && alias_units[i2]->baseUnit() != cu && cu->containsRelativeTo(alias_units[i2])) { - for(size_t i3 = 0; i3 < composite_units.size(); i3++) { - if(composite_units[i3] == cu) { - b = true; - break; - } - } - if(!b) composite_units.push_back(cu); - do_erase = true; - break; - } - } - } - if(do_erase) { - alias_units.erase(alias_units.begin() + i); - for(int i2 = 1; i2 <= (int) cu->countUnits(); i2++) { - b = false; - Unit *cub = cu->get(i2); - switch(cub->subtype()) { - case SUBTYPE_BASE_UNIT: { - for(size_t i3 = 0; i3 < base_units.size(); i3++) { - if(base_units[i3] == cub) { - b = true; - break; - } - } - if(!b) base_units.push_back(cub); - break; - } - case SUBTYPE_ALIAS_UNIT: { - for(size_t i3 = 0; i3 < alias_units.size(); i3++) { - if(alias_units[i3] == cub) { - b = true; - break; - } - } - if(!b) alias_units.push_back((AliasUnit*) cub); - break; - } - case SUBTYPE_COMPOSITE_UNIT: { - gatherInformation(((CompositeUnit*) cub)->generateMathStructure(), base_units, alias_units); - break; - } - } - } - i = 0; - } else { - i++; - } - } - - for(size_t i = 0; i < alias_units.size();) { - do_erase = false; - for(size_t i2 = 0; i2 < alias_units.size(); i2++) { - if(i != i2 && alias_units[i]->baseUnit() == alias_units[i2]->baseUnit()) { - if(alias_units[i2]->isParentOf(alias_units[i])) { - do_erase = true; - break; - } else if(!alias_units[i]->isParentOf(alias_units[i2])) { - b = false; - for(size_t i3 = 0; i3 < base_units.size(); i3++) { - if(base_units[i3] == alias_units[i2]->firstBaseUnit()) { - b = true; - break; - } - } - if(!b) base_units.push_back((Unit*) alias_units[i]->baseUnit()); - do_erase = true; - break; - } - } - } - if(do_erase) { - alias_units.erase(alias_units.begin() + i); - i = 0; - } else { - i++; - } - } - for(size_t i = 0; i < alias_units.size();) { - do_erase = false; - if(alias_units[i]->baseUnit()->subtype() == SUBTYPE_BASE_UNIT) { - for(size_t i2 = 0; i2 < base_units.size(); i2++) { - if(alias_units[i]->baseUnit() == base_units[i2]) { - do_erase = true; - break; - } - } - } - if(do_erase) { - alias_units.erase(alias_units.begin() + i); - i = 0; - } else { - i++; - } - } - b = false; - bool fcr = false; - for(size_t i = 0; i < composite_units.size(); i++) { - if(convert(composite_units[i], sync_nonlinear_relations, (found_nonlinear_relations || sync_nonlinear_relations) ? &fcr : NULL, calculate_new_functions, feo)) b = true; - } - if(dissolveAllCompositeUnits()) b = true; - for(size_t i = 0; i < base_units.size(); i++) { - if(convert(base_units[i], sync_nonlinear_relations, (found_nonlinear_relations || sync_nonlinear_relations) ? &fcr : NULL, calculate_new_functions, feo)) b = true; - } - for(size_t i = 0; i < alias_units.size(); i++) { - if(convert(alias_units[i], sync_nonlinear_relations, (found_nonlinear_relations || sync_nonlinear_relations) ? &fcr : NULL, calculate_new_functions, feo)) b = true; - } - if(b && sync_nonlinear_relations && fcr) CALCULATOR->error(false, _("Calculations involving conversion of units without proportional linear relationship (e.g. with multiple temperature units), might give unexpected results and is not recommended."), NULL); - if(fcr && found_nonlinear_relations) *found_nonlinear_relations = fcr; - return b; -} - -bool has_approximate_relation_to_base(Unit *u, bool do_intervals) { - if(u->subtype() == SUBTYPE_ALIAS_UNIT) { - if(((AliasUnit*) u)->isApproximate()) return do_intervals; - if(((AliasUnit*) u)->expression().find_first_not_of(NUMBER_ELEMENTS EXPS) != string::npos && !((AliasUnit*) u)->hasNonlinearExpression()) return true; - return has_approximate_relation_to_base(((AliasUnit*) u)->firstBaseUnit()); - } else if(u->subtype() == SUBTYPE_COMPOSITE_UNIT) { - for(size_t i = 1; i <= ((CompositeUnit*) u)->countUnits(); i++) { - if(has_approximate_relation_to_base(((CompositeUnit*) u)->get(i))) return true; - } - } - return false; -} - -bool MathStructure::testDissolveCompositeUnit(Unit *u) { - if(m_type == STRUCT_UNIT) { - if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) { - if(((CompositeUnit*) o_unit)->containsRelativeTo(u)) { - set(((CompositeUnit*) o_unit)->generateMathStructure()); - return true; - } - } else if(o_unit->subtype() == SUBTYPE_ALIAS_UNIT && o_unit->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { - if(((CompositeUnit*) (o_unit->baseUnit()))->containsRelativeTo(u)) { - if(convert(o_unit->baseUnit())) { - convert(u); - return true; - } - } - } - } - return false; -} -bool test_dissolve_cu(MathStructure &mstruct, Unit *u, bool convert_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo, Prefix *new_prefix = NULL) { - if(mstruct.isUnit()) { - if(mstruct.unit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { - if(((CompositeUnit*) mstruct.unit())->containsRelativeTo(u)) { - mstruct.set(((CompositeUnit*) mstruct.unit())->generateMathStructure()); - return true; - } - } else if(mstruct.unit()->subtype() == SUBTYPE_ALIAS_UNIT && mstruct.unit()->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { - if(((CompositeUnit*) (mstruct.unit()->baseUnit()))->containsRelativeTo(u)) { - if(mstruct.convert(mstruct.unit()->baseUnit(), convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo)) { - mstruct.convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); - return true; - } - } - } - } - return false; -} -bool MathStructure::testCompositeUnit(Unit *u) { - if(m_type == STRUCT_UNIT) { - if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) { - if(((CompositeUnit*) o_unit)->containsRelativeTo(u)) { - return true; - } - } else if(o_unit->subtype() == SUBTYPE_ALIAS_UNIT && o_unit->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { - if(((CompositeUnit*) (o_unit->baseUnit()))->containsRelativeTo(u)) { - return true; - } - } - } - return false; -} -bool MathStructure::dissolveAllCompositeUnits() { - switch(m_type) { - case STRUCT_UNIT: { - if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) { - set(((CompositeUnit*) o_unit)->generateMathStructure()); - return true; - } - break; - } - default: { - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).dissolveAllCompositeUnits()) { - CHILD_UPDATED(i); - b = true; - } - } - return b; - } - } - return false; -} -bool MathStructure::setPrefixForUnit(Unit *u, Prefix *new_prefix) { - if(m_type == STRUCT_UNIT && o_unit == u) { - if(o_prefix != new_prefix) { - Number new_value(1, 1); - if(o_prefix) new_value = o_prefix->value(); - if(new_prefix) new_value.divide(new_prefix->value()); - o_prefix = new_prefix; - multiply(new_value); - return true; - } - return false; - } - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).setPrefixForUnit(u, new_prefix)) { - CHILD_UPDATED(i); - b = true; - } - } - return b; -} - -bool searchSubMultiplicationsForComplexRelations(Unit *u, const MathStructure &mstruct) { - int b_c = -1; - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isUnit_exp()) { - if((mstruct[i].isUnit() && u->hasNonlinearRelationTo(mstruct[i].unit())) || (mstruct[i].isPower() && u->hasNonlinearRelationTo(mstruct[i][0].unit()))) { - return true; - } - } else if(b_c == -1 && mstruct[i].isMultiplication()) { - b_c = -3; - } - } - if(b_c == -3) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isMultiplication() && searchSubMultiplicationsForComplexRelations(u, mstruct[i])) return true; - } - } - return false; -} -bool MathStructure::convertToBaseUnits(bool convert_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo, bool avoid_approximate_variables) { - if(m_type == STRUCT_UNIT) { - if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) { - set(((CompositeUnit*) o_unit)->generateMathStructure()); - convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables); - return true; - } else if(o_unit->subtype() == SUBTYPE_ALIAS_UNIT) { - AliasUnit *au = (AliasUnit*) o_unit; - if(au->hasNonlinearRelationTo(au->baseUnit())) { - if(found_nonlinear_relations) *found_nonlinear_relations = true; - if(!convert_nonlinear_relations) { - if(!au->hasNonlinearExpression() && ((feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES) || !au->hasApproximateExpression(avoid_approximate_variables, false))) { - MathStructure mstruct_old(*this); - if(convert(au->firstBaseUnit(), false, NULL, calculate_new_functions, feo) && !equals(mstruct_old)) { - convertToBaseUnits(false, NULL, calculate_new_functions, feo, avoid_approximate_variables); - return true; - } - } - return false; - } - } - if((feo.approximation == APPROXIMATION_EXACT || feo.approximation == APPROXIMATION_EXACT_VARIABLES) && au->hasApproximateRelationTo(au->baseUnit(), avoid_approximate_variables, false)) { - MathStructure mstruct_old(*this); - if(convert(au->firstBaseUnit(), false, NULL, calculate_new_functions, feo) && !equals(mstruct_old)) { - convertToBaseUnits(false, NULL, calculate_new_functions, feo, avoid_approximate_variables); - return true; - } - return false; - } - if(convert(au->baseUnit(), convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo)) { - convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables); - return true; - } - } - return false; - } else if(m_type == STRUCT_MULTIPLICATION && (convert_nonlinear_relations || found_nonlinear_relations)) { - AliasUnit *complex_au = NULL; - if(convert_nonlinear_relations && convertToBaseUnits(false, NULL, calculate_new_functions, feo, avoid_approximate_variables)) { - convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables); - return true; - } - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return false; - if(CHILD(i).isUnit_exp() && CHILD(i).unit_exp_unit()->subtype() == SUBTYPE_ALIAS_UNIT) { - AliasUnit *au = (AliasUnit*) CHILD(i).unit_exp_unit(); - if(au && au->hasNonlinearRelationTo(au->baseUnit())) { - if(found_nonlinear_relations) { - *found_nonlinear_relations = true; - } - if(convert_nonlinear_relations) { - if(complex_au) { - complex_au = NULL; - convert_nonlinear_relations = false; - break; - } else { - complex_au = au; - } - } else { - break; - } - } - } - } - if(convert_nonlinear_relations && complex_au && ((feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES) || !complex_au->hasApproximateExpression(avoid_approximate_variables, false))) { - MathStructure mstruct_old(*this); - if(convert(complex_au->firstBaseUnit(), true, NULL, calculate_new_functions, feo) && !equals(mstruct_old)) { - convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables); - return true; - } - } - } else if(m_type == STRUCT_FUNCTION) { - if(o_function == CALCULATOR->f_stripunits) return false; - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return b; - if((!o_function->getArgumentDefinition(i + 1) || o_function->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) && CHILD(i).convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables)) { - CHILD_UPDATED(i); - b = true; - } - } - return b; - } - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return b; - if(CHILD(i).convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables)) { - CHILD_UPDATED(i); - b = true; - } - } - return b; -} -bool convert_approximate(MathStructure &m, Unit *u, const EvaluationOptions &feo, vector *vars, vector *uncs, vector *units, bool do_intervals); -bool convert_approximate(MathStructure &m, const MathStructure unit_mstruct, const EvaluationOptions &feo, vector *vars, vector *uncs, vector *units, bool do_intervals) { - bool b = false; - if(unit_mstruct.type() == STRUCT_UNIT) { - if(convert_approximate(m, unit_mstruct.unit(), feo, vars, uncs, units, do_intervals)) b = true; - } else { - for(size_t i = 0; i < unit_mstruct.size(); i++) { - if(convert_approximate(m, unit_mstruct[i], feo, vars, uncs, units, do_intervals)) b = true; - } - } - return b; -} -bool test_dissolve_cu_approximate(MathStructure &mstruct, Unit *u, const EvaluationOptions &feo, vector *vars, vector *uncs, vector *units, bool do_intervals) { - if(mstruct.isUnit()) { - if(mstruct.unit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { - if(((CompositeUnit*) mstruct.unit())->containsRelativeTo(u)) { - mstruct.set(((CompositeUnit*) mstruct.unit())->generateMathStructure()); - return true; - } - } else if(mstruct.unit()->subtype() == SUBTYPE_ALIAS_UNIT && mstruct.unit()->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { - if(((CompositeUnit*) (mstruct.unit()->baseUnit()))->containsRelativeTo(u)) { - if(convert_approximate(mstruct, mstruct.unit()->baseUnit(), feo, vars, uncs, units, do_intervals)) { - convert_approximate(mstruct, u, feo, vars, uncs, units, do_intervals); - return true; - } - } - } - } - return false; -} -bool convert_approximate(MathStructure &m, Unit *u, const EvaluationOptions &feo, vector *vars, vector *uncs, vector *units, bool do_intervals) { - bool b = false; - if(m.type() == STRUCT_UNIT && (m.unit() == u || m.prefix())) { - return false; - } - if(u->subtype() == SUBTYPE_COMPOSITE_UNIT && !(m.type() == STRUCT_UNIT && m.unit()->baseUnit() == u)) { - return convert_approximate(m, ((CompositeUnit*) u)->generateMathStructure(false, true), feo, vars, uncs, units, do_intervals); - } - if(m.type() == STRUCT_UNIT) { - if(u->hasApproximateRelationTo(m.unit(), feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES, true) || u->hasNonlinearRelationTo(m.unit())) { - return false; - } - if(!vars) return true; - if(m.unit()->baseUnit() != u->baseUnit() && test_dissolve_cu_approximate(m, u, feo, vars, uncs, units, do_intervals)) { - convert_approximate(m, u, feo, vars, uncs, units, do_intervals); - return true; - } - MathStructure *exp = new MathStructure(1, 1, 0); - MathStructure *mstruct = new MathStructure(1, 1, 0); - Unit *u_m = m.unit(); - if(u_m->subtype() == SUBTYPE_ALIAS_UNIT && do_intervals) { - for(size_t i = 0; i < units->size(); i++) { - if((*units)[i] == u_m) { - mstruct->set((*vars)[i]); - u_m = ((AliasUnit*) u_m)->firstBaseUnit(); - } - } - if(u_m == m.unit()) { - ((AliasUnit*) u_m)->convertToFirstBaseUnit(*mstruct, *exp); - if(mstruct->isNumber() && mstruct->number().isInterval()) { - uncs->push_back(mstruct->number().uncertainty()); - units->push_back(u_m); - Number nmid(mstruct->number()); - nmid.intervalToMidValue(); - nmid.setApproximate(false); - KnownVariable *v = new KnownVariable("", string("(") + format_and_print(nmid) + ")", nmid); - mstruct->set(v); - vars->push_back(v); - v->destroy(); - u_m = ((AliasUnit*) u_m)->firstBaseUnit(); - } else { - mstruct->set(1, 1, 0); - exp->set(1, 1, 0); - } - } - } - if(u->convert(u_m, *mstruct, *exp) && (do_intervals || (!mstruct->containsInterval(true, false, false, 1, true) && !exp->containsInterval(true, false, false, 1, true)))) { - m.setUnit(u); - if(!exp->isOne()) { - if(feo.calculate_functions) { - calculate_nondifferentiable_functions(*exp, feo, true, true, feo.interval_calculation != INTERVAL_CALCULATION_VARIANCE_FORMULA ? 0 : ((feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES) ? 2 : 1)); - } - if(do_intervals) exp->calculatesub(feo, feo, true); - m.raise_nocopy(exp); - } else { - exp->unref(); - } - if(!mstruct->isOne()) { - if(feo.calculate_functions) { - calculate_nondifferentiable_functions(*mstruct, feo, true, true, feo.interval_calculation != INTERVAL_CALCULATION_VARIANCE_FORMULA ? 0 : ((feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES) ? 2 : 1)); - } - if(do_intervals) mstruct->calculatesub(feo, feo, true); - m.multiply_nocopy(mstruct); - } else { - mstruct->unref(); - } - return true; - } else { - exp->unref(); - mstruct->unref(); - return false; - } - } else { - if(m.type() == STRUCT_FUNCTION) { - if(m.function() == CALCULATOR->f_stripunits) return b; - for(size_t i = 0; i < m.size(); i++) { - if(m.size() > 100 && CALCULATOR->aborted()) return b; - if((!m.function()->getArgumentDefinition(i + 1) || m.function()->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) && convert_approximate(m[i], u, feo, vars, uncs, units, do_intervals)) { - m.childUpdated(i + 1); - b = true; - } - } - return b; - } - for(size_t i = 0; i < m.size(); i++) { - if(m.size() > 100 && CALCULATOR->aborted()) return b; - if(convert_approximate(m[i], u, feo, vars, uncs, units, do_intervals)) { - m.childUpdated(i + 1); - b = true; - } - } - return b; - } - return b; -} - -bool contains_approximate_relation_to_base(const MathStructure &m, bool do_intervals) { - if(m.isUnit()) { - return has_approximate_relation_to_base(m.unit(), do_intervals); - } else if(m.isFunction() && m.function() == CALCULATOR->f_stripunits) { - return false; - } - for(size_t i = 0; i < m.size(); i++) { - if(contains_approximate_relation_to_base(m[i], do_intervals)) return true; - } - return false; -} - -bool sync_approximate_units(MathStructure &m, const EvaluationOptions &feo, vector *vars, vector *uncs, bool do_intervals) { - if(m.size() == 0) return false; - if(!contains_approximate_relation_to_base(m, do_intervals)) return false; - bool check_variables = (feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES); - vector base_units; - vector alias_units; - vector composite_units; - gatherInformation(m, base_units, alias_units, check_variables); - if(alias_units.empty() || base_units.size() + alias_units.size() == 1) return false; - CompositeUnit *cu; - bool b = false, do_erase = false; - for(size_t i = 0; i < alias_units.size(); ) { - do_erase = false; - if(alias_units[i]->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { - b = false; - cu = (CompositeUnit*) alias_units[i]->baseUnit(); - for(size_t i2 = 0; i2 < base_units.size(); i2++) { - if(cu->containsRelativeTo(base_units[i2])) { - for(size_t i3 = 0; i3 < composite_units.size(); i3++) { - if(composite_units[i3] == cu) { - b = true; - break; - } - } - if(!b) composite_units.push_back(cu); - do_erase = true; - break; - } - } - for(size_t i2 = 0; !do_erase && i2 < alias_units.size(); i2++) { - if(i != i2 && alias_units[i2]->baseUnit() != cu && cu->containsRelativeTo(alias_units[i2])) { - for(size_t i3 = 0; i3 < composite_units.size(); i3++) { - if(composite_units[i3] == cu) { - b = true; - break; - } - } - if(!b) composite_units.push_back(cu); - do_erase = true; - break; - } - } - } - if(do_erase) { - alias_units.erase(alias_units.begin() + i); - for(int i2 = 1; i2 <= (int) cu->countUnits(); i2++) { - b = false; - Unit *cub = cu->get(i2); - switch(cub->subtype()) { - case SUBTYPE_BASE_UNIT: { - for(size_t i3 = 0; i3 < base_units.size(); i3++) { - if(base_units[i3] == cub) { - b = true; - break; - } - } - if(!b) base_units.push_back(cub); - break; - } - case SUBTYPE_ALIAS_UNIT: { - for(size_t i3 = 0; i3 < alias_units.size(); i3++) { - if(alias_units[i3] == cub) { - b = true; - break; - } - } - if(!b) alias_units.push_back((AliasUnit*) cub); - break; - } - case SUBTYPE_COMPOSITE_UNIT: { - gatherInformation(((CompositeUnit*) cub)->generateMathStructure(), base_units, alias_units, check_variables); - break; - } - } - } - i = 0; - } else { - i++; - } - } - - for(size_t i = 0; i < alias_units.size();) { - do_erase = false; - for(size_t i2 = 0; i2 < alias_units.size(); i2++) { - if(i != i2 && alias_units[i]->baseUnit() == alias_units[i2]->baseUnit()) { - if(alias_units[i2]->isParentOf(alias_units[i])) { - do_erase = true; - break; - } else if(!alias_units[i]->isParentOf(alias_units[i2])) { - b = false; - for(size_t i3 = 0; i3 < base_units.size(); i3++) { - if(base_units[i3] == alias_units[i2]->firstBaseUnit()) { - b = true; - break; - } - } - if(!b) base_units.push_back((Unit*) alias_units[i]->baseUnit()); - do_erase = true; - break; - } - } - } - if(do_erase) { - alias_units.erase(alias_units.begin() + i); - i = 0; - } else { - i++; - } - } - for(size_t i = 0; i < alias_units.size();) { - do_erase = false; - if(alias_units[i]->baseUnit()->subtype() == SUBTYPE_BASE_UNIT) { - for(size_t i2 = 0; i2 < base_units.size(); i2++) { - if(alias_units[i]->baseUnit() == base_units[i2]) { - do_erase = true; - break; - } - } - } - if(do_erase) { - alias_units.erase(alias_units.begin() + i); - i = 0; - } else { - i++; - } - } - b = false; - vector units; - for(size_t i = 0; i < composite_units.size(); i++) { - if(convert_approximate(m, composite_units[i], feo, vars, uncs, &units, do_intervals)) b = true; - } - if(m.dissolveAllCompositeUnits()) b = true; - for(size_t i = 0; i < base_units.size(); i++) { - if(convert_approximate(m, base_units[i], feo, vars, uncs, &units, do_intervals)) b = true; - } - for(size_t i = 0; i < alias_units.size(); i++) { - if(convert_approximate(m, alias_units[i], feo, vars, uncs, &units, do_intervals)) b = true; - } - return b; -} - - -bool MathStructure::convert(Unit *u, bool convert_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo, Prefix *new_prefix) { - if(m_type == STRUCT_ADDITION && containsType(STRUCT_DATETIME, false, true, false) > 0) return false; - bool b = false; - if(m_type == STRUCT_UNIT && o_unit == u) { - if((new_prefix || o_prefix) && o_prefix != new_prefix) { - Number new_value(1, 1); - if(o_prefix) new_value = o_prefix->value(); - if(new_prefix) new_value.divide(new_prefix->value()); - o_prefix = new_prefix; - multiply(new_value); - return true; - } - return false; - } - if(u->subtype() == SUBTYPE_COMPOSITE_UNIT && !(m_type == STRUCT_UNIT && o_unit->baseUnit() == u)) { - return convert(((CompositeUnit*) u)->generateMathStructure(false, true), convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo); - } - if(m_type == STRUCT_UNIT) { - if(u->hasNonlinearRelationTo(o_unit)) { - if(found_nonlinear_relations) *found_nonlinear_relations = true; - if(!convert_nonlinear_relations) return false; - } - if(o_unit->baseUnit() != u->baseUnit() && test_dissolve_cu(*this, u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix)) { - convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); - return true; - } - MathStructure *exp = new MathStructure(1, 1, 0); - MathStructure *mstruct = new MathStructure(1, 1, 0); - if(o_prefix) { - mstruct->set(o_prefix->value()); - } - if(u->convert(o_unit, *mstruct, *exp) && (feo.approximation != APPROXIMATION_EXACT || (!mstruct->isApproximate() && !exp->isApproximate()))) { - setUnit(u); - o_prefix = new_prefix; - if(new_prefix) { - divide(new_prefix->value()); - } - if(!exp->isOne()) { - if(calculate_new_functions) exp->calculateFunctions(feo, true, false); - raise_nocopy(exp); - } else { - exp->unref(); - } - if(!mstruct->isOne()) { - if(calculate_new_functions) mstruct->calculateFunctions(feo, true, false); - multiply_nocopy(mstruct); - } else { - mstruct->unref(); - } - return true; - } else { - exp->unref(); - mstruct->unref(); - return false; - } - } else { - if(convert_nonlinear_relations || found_nonlinear_relations) { - if(m_type == STRUCT_MULTIPLICATION) { - long int b_c = -1; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isUnit_exp()) { - Unit *u2 = CHILD(i).isPower() ? CHILD(i)[0].unit() : CHILD(i).unit(); - if(u->hasNonlinearRelationTo(u2)) { - if(found_nonlinear_relations) *found_nonlinear_relations = true; - - b_c = i; - break; - } - } else if(CHILD(i).isMultiplication()) { - b_c = -3; - } - } - if(b_c == -3) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isMultiplication()) { - if(searchSubMultiplicationsForComplexRelations(u, CHILD(i))) { - if(!convert_nonlinear_relations) { - *found_nonlinear_relations = true; - break; - } - flattenMultiplication(*this); - return convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); - } - } - } - } - if(convert_nonlinear_relations && b_c >= 0) { - if(flattenMultiplication(*this)) return convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); - MathStructure mstruct(1, 1); - MathStructure mstruct2(1, 1); - if(SIZE == 2) { - if(b_c == 0) mstruct = CHILD(1); - else mstruct = CHILD(0); - if(mstruct.isUnit_exp()) { - mstruct2 = mstruct; - mstruct.set(1, 1, 0); - } - } else if(SIZE > 2) { - mstruct = *this; - size_t nr_of_del = 0; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isUnit_exp()) { - mstruct.delChild(i + 1 - nr_of_del); - nr_of_del++; - if((long int) i != b_c) { - if(mstruct2.isOne()) mstruct2 = CHILD(i); - else mstruct2.multiply(CHILD(i), true); - } - } - } - if(mstruct.size() == 1) mstruct.setToChild(1); - else if(mstruct.size() == 0) mstruct.set(1, 1, 0); - } - MathStructure exp(1, 1); - Unit *u2; - bool b_p = false; - if(CHILD(b_c).isPower()) { - if(CHILD(b_c)[0].unit()->baseUnit() != u->baseUnit()) { - if(CHILD(b_c)[0].unit()->subtype() != SUBTYPE_BASE_UNIT && (CHILD(b_c)[0].unit()->subtype() != SUBTYPE_ALIAS_UNIT || ((AliasUnit*) CHILD(b_c)[0].unit())->firstBaseUnit()->subtype() != SUBTYPE_COMPOSITE_UNIT)) { - convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo); - } else { - return false; - } - convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); - return true; - } - exp = CHILD(b_c)[1]; - u2 = CHILD(b_c)[0].unit(); - if(CHILD(b_c)[0].prefix()) b_p = true; - } else { - if(CHILD(b_c).unit()->baseUnit() != u->baseUnit()) { - if(CHILD(b_c).unit()->subtype() != SUBTYPE_BASE_UNIT && (CHILD(b_c).unit()->subtype() != SUBTYPE_ALIAS_UNIT || ((AliasUnit*) CHILD(b_c).unit())->firstBaseUnit()->subtype() != SUBTYPE_COMPOSITE_UNIT)) { - convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo); - } else { - return false; - } - convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); - return true; - } - u2 = CHILD(b_c).unit(); - if(CHILD(b_c).prefix()) b_p = true; - } - size_t efc = 0, mfc = 0; - if(calculate_new_functions) { - efc = exp.countFunctions(); - mfc = mstruct.countFunctions(); - } - if(u->convert(u2, mstruct, exp)) { - if(feo.approximation == APPROXIMATION_EXACT && !isApproximate() && (mstruct.isApproximate() || exp.isApproximate())) return false; - if(b_p) { - unformat(feo); - return convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); - } - set(u); - if(!exp.isOne()) { - if(calculate_new_functions && exp.countFunctions() > efc) exp.calculateFunctions(feo, true, false); - raise(exp); - } - if(!mstruct2.isOne()) { - multiply(mstruct2); - } - if(!mstruct.isOne()) { - if(calculate_new_functions && mstruct.countFunctions() > mfc) mstruct.calculateFunctions(feo, true, false); - multiply(mstruct); - } - return true; - } - return false; - } - } else if(m_type == STRUCT_POWER) { - if(CHILD(0).isUnit() && u->hasNonlinearRelationTo(CHILD(0).unit())) { - if(found_nonlinear_relations) *found_nonlinear_relations = true; - if(convert_nonlinear_relations) { - if(CHILD(0).unit()->baseUnit() != u->baseUnit()) { - if(CHILD(0).unit()->subtype() != SUBTYPE_BASE_UNIT && (CHILD(0).unit()->subtype() != SUBTYPE_ALIAS_UNIT || ((AliasUnit*) CHILD(0).unit())->firstBaseUnit()->subtype() != SUBTYPE_COMPOSITE_UNIT)) { - convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo); - } else { - return false; - } - convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); - return true; - } - MathStructure exp(CHILD(1)); - MathStructure mstruct(1, 1); - if(CHILD(0).prefix()) { - mstruct.set(CHILD(0).prefix()->value()); - mstruct.raise(exp); - } - size_t efc = 0; - if(calculate_new_functions) { - efc = exp.countFunctions(); - } - if(u->convert(CHILD(0).unit(), mstruct, exp)) { - if(feo.approximation == APPROXIMATION_EXACT && !isApproximate() && (mstruct.isApproximate() || exp.isApproximate())) return false; - set(u); - if(!exp.isOne()) { - if(calculate_new_functions && exp.countFunctions() > efc) exp.calculateFunctions(feo, true, false); - raise(exp); - } - if(!mstruct.isOne()) { - if(calculate_new_functions) mstruct.calculateFunctions(feo, true, false); - multiply(mstruct); - } - return true; - } - return false; - } - } - } - /*if(m_type == STRUCT_MULTIPLICATION || m_type == STRUCT_POWER) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).convert(u, false, found_nonlinear_relations, calculate_new_functions, feo, new_prefix)) { - CHILD_UPDATED(i); - b = true; - } - } - return b; - }*/ - } - if(m_type == STRUCT_FUNCTION) { - if(o_function == CALCULATOR->f_stripunits) return b; - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return b; - if((!o_function->getArgumentDefinition(i + 1) || o_function->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) && CHILD(i).convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix)) { - CHILD_UPDATED(i); - b = true; - } - } - return b; - } - for(size_t i = 0; i < SIZE; i++) { - if(CALCULATOR->aborted()) return b; - if(CHILD(i).convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix)) { - CHILD_UPDATED(i); - b = true; - } - } - return b; - } - return b; -} -bool MathStructure::convert(const MathStructure unit_mstruct, bool convert_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo) { - bool b = false; - if(unit_mstruct.type() == STRUCT_UNIT) { - if(convert(unit_mstruct.unit(), convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, feo.keep_prefixes ? unit_mstruct.prefix() : NULL)) b = true; - } else { - for(size_t i = 0; i < unit_mstruct.size(); i++) { - if(convert(unit_mstruct[i], convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo)) b = true; - } - } - return b; -} - -int MathStructure::contains(const MathStructure &mstruct, bool structural_only, bool check_variables, bool check_functions, bool loose_equals) const { - if(mstruct.isUnit() && mstruct.prefix() == NULL && m_type == STRUCT_UNIT) return mstruct.unit() == o_unit; - if(equals(mstruct, loose_equals, loose_equals)) return 1; - if(structural_only) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).contains(mstruct, structural_only, check_variables, check_functions, loose_equals)) return 1; - } - if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { - return ((KnownVariable*) o_variable)->get().contains(mstruct, structural_only, check_variables, check_functions, loose_equals); - } else if(m_type == STRUCT_FUNCTION && check_functions) { - if(function_value) { - return function_value->contains(mstruct, structural_only, check_variables, check_functions, loose_equals); - } - } - } else { - int ret = 0; - if(m_type != STRUCT_FUNCTION) { - for(size_t i = 0; i < SIZE; i++) { - int retval = CHILD(i).contains(mstruct, structural_only, check_variables, check_functions, loose_equals); - if(retval == 1) return 1; - else if(retval < 0) ret = retval; - } - } - if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { - return ((KnownVariable*) o_variable)->get().contains(mstruct, structural_only, check_variables, check_functions, loose_equals); - } else if(m_type == STRUCT_FUNCTION && check_functions) { - if(function_value) { - return function_value->contains(mstruct, structural_only, check_variables, check_functions, loose_equals); - } - return -1; - } else if(isAborted()) { - return -1; - } - return ret; - } - return 0; -} -size_t MathStructure::countOccurrences(const MathStructure &mstruct) const { - if(mstruct.isUnit() && mstruct.prefix() == NULL && m_type == STRUCT_UNIT && mstruct.unit() == o_unit) return 1; - if(equals(mstruct, true, true)) return 1; - size_t i_occ = 0; - for(size_t i = 0; i < SIZE; i++) { - i_occ += CHILD(i).countOccurrences(mstruct); - } - return i_occ; -} -int MathStructure::containsFunction(MathFunction *f, bool structural_only, bool check_variables, bool check_functions) const { - if(m_type == STRUCT_FUNCTION && o_function == f) return 1; - if(structural_only) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).containsFunction(f, structural_only, check_variables, check_functions)) return 1; - } - if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { - return ((KnownVariable*) o_variable)->get().containsFunction(f, structural_only, check_variables, check_functions); - } else if(m_type == STRUCT_FUNCTION && check_functions) { - if(function_value) { - return function_value->containsFunction(f, structural_only, check_variables, check_functions); - } - } - } else { - int ret = 0; - if(m_type != STRUCT_FUNCTION) { - for(size_t i = 0; i < SIZE; i++) { - int retval = CHILD(i).containsFunction(f, structural_only, check_variables, check_functions); - if(retval == 1) return 1; - else if(retval < 0) ret = retval; - } - } - if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { - return ((KnownVariable*) o_variable)->get().containsFunction(f, structural_only, check_variables, check_functions); - } else if(m_type == STRUCT_FUNCTION && check_functions) { - if(function_value) { - return function_value->containsFunction(f, structural_only, check_variables, check_functions); - } - return -1; - } else if(isAborted()) { - return -1; - } - return ret; - } - return 0; -} -int contains_interval_var(const MathStructure &m, bool structural_only, bool check_variables, bool check_functions, int ignore_high_precision_interval, bool include_interval_function) { - if(m.type() == STRUCT_NUMBER) { - if(m.number().isInterval(false)) { - if(ignore_high_precision_interval != 0) { - if(m.number().precision(true) > (ignore_high_precision_interval < 0 ? (ignore_high_precision_interval == -1 ? PRECISION + 29 : PRECISION - ignore_high_precision_interval) : PRECISION + (10 * ignore_high_precision_interval))) return 0; - } - return 1; - } else if(CALCULATOR->usesIntervalArithmetic() && m.number().precision() >= 0) { - if(ignore_high_precision_interval != 0) { - if(m.number().precision() > (ignore_high_precision_interval < 0 ? (ignore_high_precision_interval == -1 ? PRECISION + 29 : PRECISION - ignore_high_precision_interval) : PRECISION + (10 * ignore_high_precision_interval))) return 0; - } - return 1; - } - } - if(include_interval_function && m.type() == STRUCT_FUNCTION && (m.function() == CALCULATOR->f_interval || m.function() == CALCULATOR->f_uncertainty)) return 1; - if(structural_only) { - for(size_t i = 0; i < m.size(); i++) { - if(contains_interval_var(m[i], structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function)) return 1; - } - if(m.type() == STRUCT_VARIABLE && check_variables && m.variable()->isKnown()) { - return contains_interval_var(((KnownVariable*) m.variable())->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); - } else if(m.type() == STRUCT_FUNCTION && check_functions) { - if(m.functionValue()) { - return contains_interval_var(*m.functionValue(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); - } - } - } else { - int ret = 0; - if(m.type() != STRUCT_FUNCTION) { - for(size_t i = 0; i < m.size(); i++) { - int retval = contains_interval_var(m[i], structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); - if(retval == 1) return 1; - else if(retval < 0) ret = retval; - } - } - if(m.type() == STRUCT_VARIABLE && check_variables && m.variable()->isKnown()) { - return contains_interval_var(((KnownVariable*) m.variable())->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); - } else if(m.type() == STRUCT_FUNCTION && check_functions) { - if(m.functionValue()) { - return contains_interval_var(*m.functionValue(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); - } - return -1; - } else if(m.isAborted()) { - return -1; - } - return ret; - } - return 0; -} -int MathStructure::containsInterval(bool structural_only, bool check_variables, bool check_functions, int ignore_high_precision_interval, bool include_interval_function) const { - if(m_type == STRUCT_NUMBER && o_number.isInterval(false)) { - if(ignore_high_precision_interval != 0) { - if(o_number.precision(true) > (ignore_high_precision_interval < 0 ? (ignore_high_precision_interval == -1 ? PRECISION + 29 : PRECISION - ignore_high_precision_interval) : PRECISION + (10 * ignore_high_precision_interval))) return 0; - } - return 1; - } - if(include_interval_function && m_type == STRUCT_FUNCTION && (o_function == CALCULATOR->f_interval || o_function == CALCULATOR->f_uncertainty)) return 1; - if(structural_only) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).containsInterval(structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function)) return 1; - } - if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { - if(ignore_high_precision_interval == -1 && o_variable->isBuiltin()) { - return 0; - } - return contains_interval_var(((KnownVariable*) o_variable)->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); - } else if(m_type == STRUCT_FUNCTION && check_functions) { - if(function_value) { - return function_value->containsInterval(structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); - } - } - } else { - int ret = 0; - if(m_type != STRUCT_FUNCTION) { - for(size_t i = 0; i < SIZE; i++) { - int retval = CHILD(i).containsInterval(structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); - if(retval == 1) return 1; - else if(retval < 0) ret = retval; - } - } - if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { - if(ignore_high_precision_interval == -1 && o_variable->isBuiltin()) { - return 0; - } - return contains_interval_var(((KnownVariable*) o_variable)->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); - } else if(m_type == STRUCT_FUNCTION && check_functions) { - if(function_value) { - return function_value->containsInterval(structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); - } - return -1; - } else if(isAborted()) { - return -1; - } - return ret; - } - return 0; -} -int MathStructure::containsInfinity(bool structural_only, bool check_variables, bool check_functions) const { - if(m_type == STRUCT_NUMBER && o_number.includesInfinity(false)) { - return 1; - } - if(structural_only) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).containsInfinity(structural_only, check_variables, check_functions)) return 1; - } - if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { - return ((KnownVariable*) o_variable)->get().containsInfinity(structural_only, check_variables, check_functions); - } else if(m_type == STRUCT_FUNCTION && check_functions) { - if(function_value) { - return function_value->containsInfinity(structural_only, check_variables, check_functions); - } - } - } else { - int ret = 0; - if(m_type != STRUCT_FUNCTION) { - for(size_t i = 0; i < SIZE; i++) { - int retval = CHILD(i).containsInfinity(structural_only, check_variables, check_functions); - if(retval == 1) return 1; - else if(retval < 0) ret = retval; - } - } - if(m_type == STRUCT_VARIABLE && check_variables && o_variable->isKnown()) { - return ((KnownVariable*) o_variable)->get().containsInfinity(structural_only, check_variables, check_functions); - } else if(m_type == STRUCT_FUNCTION && check_functions) { - if(function_value) { - return function_value->containsInfinity(structural_only, check_variables, check_functions); - } - return -1; - } else if(isAborted()) { - return -1; - } - return ret; - } - return 0; -} - -int MathStructure::containsRepresentativeOf(const MathStructure &mstruct, bool check_variables, bool check_functions) const { - if(equals(mstruct)) return 1; - int ret = 0; - if(m_type != STRUCT_FUNCTION) { - for(size_t i = 0; i < SIZE; i++) { - int retval = CHILD(i).containsRepresentativeOf(mstruct, check_variables, check_functions); - if(retval == 1) return 1; - else if(retval < 0) ret = retval; - } - } - if(m_type == STRUCT_VARIABLE && check_variables) { - if(o_variable->isKnown()) return ((KnownVariable*) o_variable)->get().containsRepresentativeOf(mstruct, check_variables, check_functions); - else return ((UnknownVariable*) o_variable)->interval().containsRepresentativeOf(mstruct, check_variables, check_functions); - } else if(m_type == STRUCT_FUNCTION && check_functions) { - if(function_value) { - return function_value->containsRepresentativeOf(mstruct, check_variables, check_functions); - } - if(!mstruct.isNumber() && (o_function->isBuiltin() || representsNumber())) { - for(size_t i = 0; i < SIZE; i++) { - int retval = CHILD(i).containsRepresentativeOf(mstruct, check_variables, check_functions); - if(retval != 0) return -1; - } - return 0; - } - return -1; - } else if(isAborted()) { - return -1; - } - return ret; -} - -int MathStructure::containsType(StructureType mtype, bool structural_only, bool check_variables, bool check_functions) const { - if(m_type == mtype) return 1; - if(structural_only) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).containsType(mtype, true, check_variables, check_functions)) return 1; - } - if(check_variables && m_type == STRUCT_VARIABLE && o_variable->isKnown()) { - return ((KnownVariable*) o_variable)->get().containsType(mtype, false, check_variables, check_functions); - } else if(check_functions && m_type == STRUCT_FUNCTION) { - if(function_value) { - return function_value->containsType(mtype, false, check_variables, check_functions); - } - } - return 0; - } else { - int ret = 0; - if(m_type != STRUCT_FUNCTION) { - for(size_t i = 0; i < SIZE; i++) { - int retval = CHILD(i).containsType(mtype, false, check_variables, check_functions); - if(retval == 1) return 1; - else if(retval < 0) ret = retval; - } - } - if(check_variables && m_type == STRUCT_VARIABLE) { - if(o_variable->isKnown()) return ((KnownVariable*) o_variable)->get().containsType(mtype, false, check_variables, check_functions); - else if(!((UnknownVariable*) o_variable)->interval().isUndefined()) return ((UnknownVariable*) o_variable)->interval().containsType(mtype, false, check_variables, check_functions); - else if(mtype == STRUCT_UNIT) return -1; - } else if(check_functions && m_type == STRUCT_FUNCTION) { - if(function_value) { - return function_value->containsType(mtype, false, check_variables, check_functions); - } - if(mtype == STRUCT_UNIT) { - if(o_function == CALCULATOR->f_stripunits) return 0; - if(o_function->subtype() == SUBTYPE_USER_FUNCTION || o_function == CALCULATOR->f_register || o_function == CALCULATOR->f_stack || o_function == CALCULATOR->f_load) return -1; - // (eo.parse_options.angle_unit == ANGLE_UNIT_NONE && (o_function == CALCULATOR->f_asin || o_function == CALCULATOR->f_acos || o_function == CALCULATOR->f_atan || o_function == CALCULATOR->f_radtodef)) - if(o_function == CALCULATOR->f_ln || o_function == CALCULATOR->f_logn || o_function == CALCULATOR->f_arg || o_function == CALCULATOR->f_gamma || o_function == CALCULATOR->f_beta || o_function == CALCULATOR->f_factorial || o_function == CALCULATOR->f_besselj || o_function == CALCULATOR->f_bessely || o_function == CALCULATOR->f_erf || o_function == CALCULATOR->f_erfc || o_function == CALCULATOR->f_li || o_function == CALCULATOR->f_Li || o_function == CALCULATOR->f_Ei || o_function == CALCULATOR->f_Si || o_function == CALCULATOR->f_Ci || o_function == CALCULATOR->f_Shi || o_function == CALCULATOR->f_Chi || o_function == CALCULATOR->f_signum || o_function == CALCULATOR->f_heaviside || o_function == CALCULATOR->f_lambert_w || o_function == CALCULATOR->f_sinc || o_function == CALCULATOR->f_sin || o_function == CALCULATOR->f_cos || o_function == CALCULATOR->f_tan || o_function == CALCULATOR->f_sinh || o_function == CALCULATOR->f_cosh || o_function == CALCULATOR->f_tanh || o_function == CALCULATOR->f_asinh || o_function == CALCULATOR->f_acosh || o_function == CALCULATOR->f_atanh || o_function == CALCULATOR->f_asin || o_function == CALCULATOR->f_acos || o_function == CALCULATOR->f_atan) return 0; - int ret = 0; - for(size_t i = 0; i < SIZE; i++) { - int ret_i = CHILD(i).containsType(mtype, false, check_variables, check_functions); - if(ret_i > 0) return ret_i; - else if(ret_i < 0) ret = ret_i; - } - return ret; - } - return -1; - } else if(isAborted()) { - return -1; - } - return ret; - } -} -int MathStructure::containsRepresentativeOfType(StructureType mtype, bool check_variables, bool check_functions) const { - if(m_type == mtype) return 1; - int ret = 0; - if(m_type != STRUCT_FUNCTION) { - for(size_t i = 0; i < SIZE; i++) { - int retval = CHILD(i).containsRepresentativeOfType(mtype, check_variables, check_functions); - if(retval == 1) return 1; - else if(retval < 0) ret = retval; - } - } - if(check_variables && m_type == STRUCT_VARIABLE && o_variable->isKnown()) { - return ((KnownVariable*) o_variable)->get().containsRepresentativeOfType(mtype, check_variables, check_functions); - } else if(check_functions && m_type == STRUCT_FUNCTION) { - if(function_value) { - return function_value->containsRepresentativeOfType(mtype, check_variables, check_functions); - } - } - if(m_type == STRUCT_SYMBOLIC || m_type == STRUCT_VARIABLE || m_type == STRUCT_FUNCTION || m_type == STRUCT_ABORTED) { - if(representsNumber(false)) { - if(mtype == STRUCT_UNIT) return -1; - return mtype == STRUCT_NUMBER; - } else { - return -1; - } - } - return ret; -} -bool MathStructure::containsUnknowns() const { - if(isUnknown()) return true; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).containsUnknowns()) return true; - } - return false; -} -bool MathStructure::containsDivision() const { - if(m_type == STRUCT_DIVISION || m_type == STRUCT_INVERSE || (m_type == STRUCT_POWER && CHILD(1).hasNegativeSign())) return true; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).containsDivision()) return true; - } - return false; -} -size_t MathStructure::countFunctions(bool count_subfunctions) const { - size_t c = 0; - if(isFunction()) { - if(!count_subfunctions) return 1; - c = 1; - } - for(size_t i = 0; i < SIZE; i++) { - c += CHILD(i).countFunctions(); - } - return c; -} -void MathStructure::findAllUnknowns(MathStructure &unknowns_vector) { - if(!unknowns_vector.isVector()) unknowns_vector.clearVector(); - switch(m_type) { - case STRUCT_VARIABLE: { - if(o_variable->isKnown()) { - break; - } - } - case STRUCT_SYMBOLIC: { - bool b = false; - for(size_t i = 0; i < unknowns_vector.size(); i++) { - if(equals(unknowns_vector[i])) { - b = true; - break; - } - } - if(!b) unknowns_vector.addChild(*this); - break; - } - default: { - for(size_t i = 0; i < SIZE; i++) { - CHILD(i).findAllUnknowns(unknowns_vector); - } - } - } -} -bool MathStructure::replace(const MathStructure &mfrom, const MathStructure &mto, bool once_only, bool exclude_function_arguments) { - if(b_protected) b_protected = false; - if(equals(mfrom, true, true)) { - set(mto); - return true; - } - if(mfrom.size() > 0 && mfrom.type() == m_type && SIZE > mfrom.size() && (mfrom.isAddition() || mfrom.isMultiplication() || mfrom.isLogicalAnd() || mfrom.isLogicalOr())) { - bool b = true; - size_t i2 = 0; - for(size_t i = 0; i < mfrom.size(); i++) { - b = false; - for(; i2 < SIZE; i2++) { - if(CHILD(i2).equals(mfrom[i], true, true)) {b = true; break;} - } - if(!b) break; - } - if(b) { - i2 = 0; - for(size_t i = 0; i < mfrom.size(); i++) { - for(; i2 < SIZE; i2++) { - if(CHILD(i2).equals(mfrom[i], true, true)) {ERASE(i2); break;} - } - } - if(SIZE == 1) setToChild(1); - else if(SIZE == 0) clear(); - else if(!once_only) replace(mfrom, mto, once_only, exclude_function_arguments); - if(mfrom.isAddition()) add(mto); - else if(mfrom.isMultiplication()) multiply(mto); - else if(mfrom.isLogicalAnd()) transform(STRUCT_LOGICAL_AND, mto); - else if(mfrom.isLogicalOr()) transform(STRUCT_LOGICAL_OR, mto); - return true; - } - } - if(exclude_function_arguments && m_type == STRUCT_FUNCTION) return false; - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).replace(mfrom, mto, once_only, exclude_function_arguments)) { - b = true; - CHILD_UPDATED(i); - if(once_only) return true; - } - } - return b; -} -bool MathStructure::replace(Variable *v, const MathStructure &mto) { - if(b_protected) b_protected = false; - if(m_type == STRUCT_VARIABLE && o_variable == v) { - set(mto); - return true; - } - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).replace(v, mto)) { - b = true; - CHILD_UPDATED(i); - } - } - return b; -} -bool MathStructure::calculateReplace(const MathStructure &mfrom, const MathStructure &mto, const EvaluationOptions &eo, bool exclude_function_arguments) { - if(equals(mfrom, true, true)) { - set(mto); - return true; - } - if(mfrom.size() > 0 && mfrom.type() == m_type && SIZE > mfrom.size() && (mfrom.isAddition() || mfrom.isMultiplication() || mfrom.isLogicalAnd() || mfrom.isLogicalOr())) { - bool b = true; - size_t i2 = 0; - for(size_t i = 0; i < mfrom.size(); i++) { - b = false; - for(; i2 < SIZE; i2++) { - if(CHILD(i2).equals(mfrom[i], true, true)) {b = true; break;} - } - if(!b) break; - } - if(b) { - i2 = 0; - for(size_t i = 0; i < mfrom.size(); i++) { - for(; i2 < SIZE; i2++) { - if(CHILD(i2).equals(mfrom[i], true, true)) {ERASE(i2); break;} - } - } - if(SIZE == 1) setToChild(1); - else if(SIZE == 0) clear(); - else calculateReplace(mfrom, mto, eo, exclude_function_arguments); - if(mfrom.isAddition()) add(mto); - else if(mfrom.isMultiplication()) multiply(mto); - else if(mfrom.isLogicalAnd()) transform(STRUCT_LOGICAL_AND, mto); - else if(mfrom.isLogicalOr()) transform(STRUCT_LOGICAL_OR, mto); - calculatesub(eo, eo, false); - return true; - } - } - if(exclude_function_arguments && m_type == STRUCT_FUNCTION) return false; - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).calculateReplace(mfrom, mto, eo, exclude_function_arguments)) { - b = true; - CHILD_UPDATED(i); - } - } - if(b) { - calculatesub(eo, eo, false); - } - return b; -} - -bool MathStructure::replace(const MathStructure &mfrom1, const MathStructure &mto1, const MathStructure &mfrom2, const MathStructure &mto2) { - if(equals(mfrom1, true, true)) { - set(mto1); - return true; - } - if(equals(mfrom2, true, true)) { - set(mto2); - return true; - } - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).replace(mfrom1, mto1, mfrom2, mto2)) { - b = true; - CHILD_UPDATED(i); - } - } - return b; -} -bool MathStructure::removeType(StructureType mtype) { - if(m_type == mtype || (m_type == STRUCT_POWER && CHILD(0).type() == mtype)) { - set(1); - return true; - } - bool b = false; - if(m_type == STRUCT_MULTIPLICATION) { - for(long int i = 0; i < (long int) SIZE; i++) { - if(CHILD(i).removeType(mtype)) { - if(CHILD(i).isOne()) { - ERASE(i); - i--; - } else { - CHILD_UPDATED(i); - } - b = true; - } - } - if(SIZE == 0) { - set(1); - } else if(SIZE == 1) { - setToChild(1, true); - } - } else { - if(m_type == STRUCT_FUNCTION) { - if(mtype != STRUCT_UNIT || (o_function != CALCULATOR->f_sqrt && o_function != CALCULATOR->f_root && o_function != CALCULATOR->f_cbrt)) return b; - } - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).removeType(mtype)) { - b = true; - CHILD_UPDATED(i); - } - } - } - return b; -} - -MathStructure MathStructure::generateVector(MathStructure x_mstruct, const MathStructure &min, const MathStructure &max, int steps, MathStructure *x_vector, const EvaluationOptions &eo) const { - if(steps < 1) { - steps = 1; - } - MathStructure x_value(min); - MathStructure y_value; - MathStructure y_vector; - y_vector.clearVector(); - if(steps > 1000000) { - CALCULATOR->error(true, _("Too many data points"), NULL); - return y_vector; - } - MathStructure step(max); - step.calculateSubtract(min, eo); - step.calculateDivide(steps - 1, eo); - if(!step.isNumber() || step.number().isNegative()) { - CALCULATOR->error(true, _("The selected min and max do not result in a positive, finite number of data points"), NULL); - return y_vector; - } - y_vector.resizeVector(steps, m_zero); - if(x_vector) x_vector->resizeVector(steps, m_zero); - for(int i = 0; i < steps; i++) { - if(x_vector) { - (*x_vector)[i] = x_value; - } - y_value = *this; - y_value.replace(x_mstruct, x_value); - y_value.eval(eo); - y_vector[i] = y_value; - if(x_value.isNumber()) x_value.number().add(step.number()); - else x_value.calculateAdd(step, eo); - if(CALCULATOR->aborted()) { - y_vector.resizeVector(i, m_zero); - if(x_vector) x_vector->resizeVector(i, m_zero); - return y_vector; - } - } - return y_vector; -} -MathStructure MathStructure::generateVector(MathStructure x_mstruct, const MathStructure &min, const MathStructure &max, const MathStructure &step, MathStructure *x_vector, const EvaluationOptions &eo) const { - MathStructure x_value(min); - MathStructure y_value; - MathStructure y_vector; - y_vector.clearVector(); - if(min != max) { - MathStructure mtest(max); - mtest.calculateSubtract(min, eo); - if(!step.isZero()) mtest.calculateDivide(step, eo); - if(step.isZero() || !mtest.isNumber() || mtest.number().isNegative()) { - CALCULATOR->error(true, _("The selected min, max and step size do not result in a positive, finite number of data points"), NULL); - return y_vector; - } else if(mtest.number().isGreaterThan(1000000)) { - CALCULATOR->error(true, _("Too many data points"), NULL); - return y_vector; - } - mtest.number().round(); - unsigned int steps = mtest.number().uintValue(); - y_vector.resizeVector(steps, m_zero); - if(x_vector) x_vector->resizeVector(steps, m_zero); - } - ComparisonResult cr = max.compare(x_value); - size_t i = 0; - while(COMPARISON_IS_EQUAL_OR_LESS(cr)) { - if(x_vector) { - if(i >= x_vector->size()) x_vector->addChild(x_value); - else (*x_vector)[i] = x_value; - } - y_value = *this; - y_value.replace(x_mstruct, x_value); - y_value.eval(eo); - if(i >= y_vector.size()) y_vector.addChild(y_value); - else y_vector[i] = y_value; - if(x_value.isNumber()) x_value.number().add(step.number()); - else x_value.calculateAdd(step, eo); - cr = max.compare(x_value); - if(CALCULATOR->aborted()) { - y_vector.resizeVector(i, m_zero); - if(x_vector) x_vector->resizeVector(i, m_zero); - return y_vector; - } - i++; - } - y_vector.resizeVector(i, m_zero); - if(x_vector) x_vector->resizeVector(i, m_zero); - return y_vector; -} -MathStructure MathStructure::generateVector(MathStructure x_mstruct, const MathStructure &x_vector, const EvaluationOptions &eo) const { - MathStructure y_value; - MathStructure y_vector; - y_vector.clearVector(); - for(size_t i = 1; i <= x_vector.countChildren(); i++) { - if(CALCULATOR->aborted()) { - y_vector.clearVector(); - return y_vector; - } - y_value = *this; - y_value.replace(x_mstruct, x_vector.getChild(i)); - y_value.eval(eo); - y_vector.addChild(y_value); - } - return y_vector; -} - -void remove_zero_mul(MathStructure &m); -void remove_zero_mul(MathStructure &m) { - if(m.isMultiplication()) { - for(size_t i = 0; i < m.size(); i++) { - if(m[i].isZero()) { - m.clear(true); - return; - } - } - } - for(size_t i = 0; i < m.size(); i++) { - remove_zero_mul(m[i]); - } -} -bool MathStructure::differentiate(const MathStructure &x_var, const EvaluationOptions &eo) { - if(CALCULATOR->aborted()) { - transform(CALCULATOR->f_diff); - addChild(x_var); - addChild(m_one); - addChild(m_undefined); - return false; - } - if(equals(x_var)) { - set(m_one); - return true; - } - if(containsRepresentativeOf(x_var, true, true) == 0) { - clear(true); - return true; - } - switch(m_type) { - case STRUCT_ADDITION: { - for(size_t i = 0; i < SIZE;) { - if(CHILD(i).differentiate(x_var, eo)) { - CHILD_UPDATED(i); - if(SIZE > 1 && CHILD(i).isZero()) {ERASE(i);} - else i++; - } else i++; - } - if(SIZE == 1) SET_CHILD_MAP(0) - break; - } - case STRUCT_LOGICAL_AND: { - bool b = true; - for(size_t i = 0; i < SIZE; i++) { - if(!CHILD(i).isComparison()) {b = false; break;} - } - if(b) { - MathStructure mtest(*this); - mtest.setType(STRUCT_MULTIPLICATION); - if(mtest.differentiate(x_var, eo) && mtest.containsFunction(CALCULATOR->f_diff, true) <= 0) { - set(mtest); - break; - } - } - } - case STRUCT_COMPARISON: { - if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) { - if(!CHILD(1).isZero()) CHILD(0) -= CHILD(1); - SET_CHILD_MAP(0) - if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_LESS) negate(); - MathStructure mstruct(*this); - MathStructure mstruct2(*this); - transform(CALCULATOR->f_heaviside); - transform(CALCULATOR->f_dirac); - mstruct2.transform(CALCULATOR->f_dirac); - multiply(mstruct2); - if(ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_EQUALS_LESS) multiply_nocopy(new MathStructure(2, 1, 0)); - else multiply_nocopy(new MathStructure(-2, 1, 0)); - mstruct.differentiate(x_var, eo); - multiply(mstruct); - return true; - } - transform(CALCULATOR->f_diff); - addChild(x_var); - addChild(m_one); - addChild(m_undefined); - return false; - } - case STRUCT_UNIT: {} - case STRUCT_NUMBER: { - clear(true); - break; - } - case STRUCT_POWER: { - if(SIZE < 1) { - clear(true); - break; - } else if(SIZE < 2) { - setToChild(1, true); - return differentiate(x_var, eo); - } - bool x_in_base = CHILD(0).containsRepresentativeOf(x_var, true, true) != 0; - bool x_in_exp = CHILD(1).containsRepresentativeOf(x_var, true, true) != 0; - if(x_in_base && !x_in_exp) { - MathStructure *exp_mstruct = new MathStructure(CHILD(1)); - if(!CHILD(1).isNumber() || !CHILD(1).number().add(-1)) CHILD(1) += m_minus_one; - if(CHILD(0) == x_var) { - multiply_nocopy(exp_mstruct); - } else { - MathStructure *base_mstruct = new MathStructure(CHILD(0)); - multiply_nocopy(exp_mstruct); - base_mstruct->differentiate(x_var, eo); - multiply_nocopy(base_mstruct); - } - } else if(!x_in_base && x_in_exp) { - MathStructure *exp_mstruct = new MathStructure(CHILD(1)); - exp_mstruct->differentiate(x_var, eo); - if(CHILD(0).isVariable() && CHILD(0).variable() == CALCULATOR->v_e) { - multiply_nocopy(exp_mstruct); - } else { - MathStructure *mstruct = new MathStructure(CALCULATOR->f_ln, &CHILD(0), NULL); - multiply_nocopy(mstruct); - multiply_nocopy(exp_mstruct); - } - } else if(x_in_base && x_in_exp) { - MathStructure *exp_mstruct = new MathStructure(CHILD(1)); - MathStructure *base_mstruct = new MathStructure(CHILD(0)); - exp_mstruct->differentiate(x_var, eo); - base_mstruct->differentiate(x_var, eo); - base_mstruct->divide(CHILD(0)); - base_mstruct->multiply(CHILD(1)); - MathStructure *mstruct = new MathStructure(CALCULATOR->f_ln, &CHILD(0), NULL); - mstruct->multiply_nocopy(exp_mstruct); - mstruct->add_nocopy(base_mstruct); - multiply_nocopy(mstruct); - } else { - clear(true); - } - break; - } - case STRUCT_FUNCTION: { - if(o_function == CALCULATOR->f_sqrt && SIZE == 1) { - MathStructure *base_mstruct = new MathStructure(CHILD(0)); - raise(m_minus_one); - multiply(nr_half); - base_mstruct->differentiate(x_var, eo); - multiply_nocopy(base_mstruct); - } else if(o_function == CALCULATOR->f_root && THIS_VALID_ROOT) { - MathStructure *base_mstruct = new MathStructure(CHILD(0)); - MathStructure *mexp = new MathStructure(CHILD(1)); - mexp->negate(); - mexp->add(m_one); - raise_nocopy(mexp); - divide(CHILD(0)[1]); - base_mstruct->differentiate(x_var, eo); - multiply_nocopy(base_mstruct); - } else if(o_function == CALCULATOR->f_cbrt && SIZE == 1) { - MathStructure *base_mstruct = new MathStructure(CHILD(0)); - raise(Number(-2, 1, 0)); - divide(nr_three); - base_mstruct->differentiate(x_var, eo); - multiply_nocopy(base_mstruct); - } else if((o_function == CALCULATOR->f_ln && SIZE == 1) || (o_function == CALCULATOR->f_logn && SIZE == 2 && CHILD(1).isVariable() && CHILD(1).variable() == CALCULATOR->v_e)) { - if(CHILD(0) == x_var) { - setToChild(1, true); - inverse(); - } else { - MathStructure *mstruct = new MathStructure(CHILD(0)); - setToChild(1, true); - inverse(); - mstruct->differentiate(x_var, eo); - multiply_nocopy(mstruct); - } - } else if(o_function == CALCULATOR->f_logn && SIZE == 2) { - MathStructure *mstruct = new MathStructure(CALCULATOR->f_ln, &CHILD(1), NULL); - setFunction(CALCULATOR->f_ln); - ERASE(1) - divide_nocopy(mstruct); - return differentiate(x_var, eo); - } else if(o_function == CALCULATOR->f_beta && SIZE == 2) { - MathStructure mstruct(CHILD(0)); - setToChild(1, true); - inverse(); - mstruct.differentiate(x_var, eo); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_arg && SIZE == 1) { - MathStructure mstruct(CHILD(0)); - setFunction(CALCULATOR->f_dirac); - mstruct.differentiate(x_var, eo); - multiply(mstruct); - multiply(CALCULATOR->v_pi); - negate(); - } else if(o_function == CALCULATOR->f_gamma && SIZE == 1) { - MathStructure mstruct(CHILD(0)); - MathStructure mstruct2(*this); - mstruct2.setFunction(CALCULATOR->f_digamma); - multiply(mstruct2); - mstruct.differentiate(x_var, eo); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_factorial && SIZE == 1) { - MathStructure mstruct(CHILD(0)); - CHILD(0) += m_one; - MathStructure mstruct2(*this); - mstruct2.setFunction(CALCULATOR->f_digamma); - multiply(mstruct2); - mstruct.differentiate(x_var, eo); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_besselj && SIZE == 2 && CHILD(0).isInteger()) { - MathStructure mstruct(CHILD(1)); - MathStructure mstruct2(*this); - CHILD(0) += m_minus_one; - mstruct2[0] += m_one; - subtract(mstruct2); - mstruct.differentiate(x_var, eo); - multiply(mstruct); - multiply(nr_half); - } else if(o_function == CALCULATOR->f_bessely && SIZE == 2 && CHILD(0).isInteger()) { - MathStructure mstruct(CHILD(1)); - MathStructure mstruct2(*this); - CHILD(0) += m_minus_one; - mstruct2[0] += m_one; - subtract(mstruct2); - mstruct.differentiate(x_var, eo); - multiply(mstruct); - multiply(nr_half); - } else if(o_function == CALCULATOR->f_erf && SIZE == 1) { - MathStructure mdiff(CHILD(0)); - MathStructure mexp(CHILD(0)); - mexp ^= nr_two; - mexp.negate(); - set(CALCULATOR->v_e, true); - raise(mexp); - multiply(nr_two); - multiply(CALCULATOR->v_pi); - LAST ^= Number(-1, 2); - mdiff.differentiate(x_var, eo); - multiply(mdiff); - } else if(o_function == CALCULATOR->f_erfc && SIZE == 1) { - MathStructure mdiff(CHILD(0)); - MathStructure mexp(CHILD(0)); - mexp ^= nr_two; - mexp.negate(); - set(CALCULATOR->v_e, true); - raise(mexp); - multiply(Number(-2, 1)); - multiply(CALCULATOR->v_pi); - LAST ^= Number(-1, 2); - mdiff.differentiate(x_var, eo); - multiply(mdiff); - } else if(o_function == CALCULATOR->f_li && SIZE == 1) { - setFunction(CALCULATOR->f_ln); - MathStructure mstruct(CHILD(0)); - inverse(); - mstruct.differentiate(x_var, eo); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_Li && SIZE == 2) { - CHILD(0) += m_minus_one; - MathStructure mstruct(CHILD(1)); - divide(mstruct); - mstruct.differentiate(x_var, eo); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_Ei && SIZE == 1) { - MathStructure mexp(CALCULATOR->v_e); - mexp ^= CHILD(0); - MathStructure mdiff(CHILD(0)); - mdiff.differentiate(x_var, eo); - mexp *= mdiff; - setToChild(1, true); - inverse(); - multiply(mexp); - } else if(o_function == CALCULATOR->f_Si && SIZE == 1) { - setFunction(CALCULATOR->f_sinc); - CHILD_UPDATED(0) - MathStructure mdiff(CHILD(0)); - mdiff.differentiate(x_var, eo); - multiply(mdiff); - } else if(o_function == CALCULATOR->f_Ci && SIZE == 1) { - setFunction(CALCULATOR->f_cos); - MathStructure marg(CHILD(0)); - MathStructure mdiff(CHILD(0)); - CHILD(0) *= CALCULATOR->getRadUnit(); - mdiff.differentiate(x_var, eo); - divide(marg); - multiply(mdiff); - } else if(o_function == CALCULATOR->f_Shi && SIZE == 1) { - setFunction(CALCULATOR->f_sinh); - MathStructure marg(CHILD(0)); - MathStructure mdiff(CHILD(0)); - mdiff.differentiate(x_var, eo); - divide(marg); - multiply(mdiff); - } else if(o_function == CALCULATOR->f_Chi && SIZE == 1) { - setFunction(CALCULATOR->f_cosh); - MathStructure marg(CHILD(0)); - MathStructure mdiff(CHILD(0)); - mdiff.differentiate(x_var, eo); - divide(marg); - multiply(mdiff); - } else if(o_function == CALCULATOR->f_abs && SIZE == 1) { - MathStructure mstruct(CHILD(0)); - inverse(); - multiply(mstruct); - mstruct.differentiate(x_var, eo); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_signum && SIZE == 2) { - MathStructure mstruct(CHILD(0)); - ERASE(1) - setFunction(CALCULATOR->f_dirac); - multiply_nocopy(new MathStructure(2, 1, 0)); - mstruct.differentiate(x_var, eo); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_heaviside && SIZE == 1) { - MathStructure mstruct(CHILD(0)); - setFunction(CALCULATOR->f_dirac); - mstruct.differentiate(x_var, eo); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_lambert_w && SIZE >= 1) { - MathStructure *mstruct = new MathStructure(*this); - MathStructure *mstruct2 = new MathStructure(CHILD(0)); - mstruct->add(m_one); - mstruct->multiply(CHILD(0)); - mstruct2->differentiate(x_var, eo); - multiply_nocopy(mstruct2); - divide_nocopy(mstruct); - } else if(o_function == CALCULATOR->f_sin && SIZE == 1) { - setFunction(CALCULATOR->f_cos); - MathStructure mstruct(CHILD(0)); - mstruct.calculateDivide(CALCULATOR->getRadUnit(), eo); - if(mstruct != x_var) { - mstruct.differentiate(x_var, eo); - multiply(mstruct); - } - } else if(o_function == CALCULATOR->f_cos && SIZE == 1) { - setFunction(CALCULATOR->f_sin); - MathStructure mstruct(CHILD(0)); - negate(); - mstruct.calculateDivide(CALCULATOR->getRadUnit(), eo); - if(mstruct != x_var) { - mstruct.differentiate(x_var, eo); - multiply(mstruct); - } - } else if(o_function == CALCULATOR->f_tan && SIZE == 1) { - setFunction(CALCULATOR->f_tan); - MathStructure mstruct(CHILD(0)); - raise(2); - add(nr_one); - mstruct.differentiate(x_var, eo); - multiply(mstruct, true); - if(CALCULATOR->getRadUnit()) divide(CALCULATOR->getRadUnit()); - } else if(o_function == CALCULATOR->f_sinh && SIZE == 1) { - setFunction(CALCULATOR->f_cosh); - MathStructure mstruct(CHILD(0)); - mstruct.differentiate(x_var, eo); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_cosh && SIZE == 1) { - setFunction(CALCULATOR->f_sinh); - MathStructure mstruct(CHILD(0)); - mstruct.differentiate(x_var, eo); - multiply(mstruct, true); - } else if(o_function == CALCULATOR->f_tanh && SIZE == 1) { - setFunction(CALCULATOR->f_tanh); - MathStructure mstruct(CHILD(0)); - raise(2); - negate(); - add(nr_one); - mstruct.differentiate(x_var, eo); - multiply(mstruct, true); - } else if(o_function == CALCULATOR->f_asin && SIZE == 1) { - MathStructure mstruct(CHILD(0)); - mstruct.differentiate(x_var, eo); - SET_CHILD_MAP(0); - raise(2); - negate(); - add(m_one); - raise(Number(-1, 2)); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_acos && SIZE == 1) { - MathStructure mstruct(CHILD(0)); - mstruct.differentiate(x_var, eo); - SET_CHILD_MAP(0); - raise(2); - negate(); - add(m_one); - raise(Number(-1, 2)); - negate(); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_atan && SIZE == 1) { - MathStructure mstruct(CHILD(0)); - mstruct.differentiate(x_var, eo); - SET_CHILD_MAP(0); - raise(2); - add(m_one); - raise(m_minus_one); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_asinh && SIZE == 1) { - MathStructure mstruct(CHILD(0)); - mstruct.differentiate(x_var, eo); - SET_CHILD_MAP(0); - raise(2); - add(m_one); - raise(Number(-1, 2)); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_acosh && SIZE == 1) { - MathStructure mstruct(CHILD(0)); - mstruct.differentiate(x_var, eo); - SET_CHILD_MAP(0); - MathStructure mfac(*this); - add(m_minus_one); - raise(Number(-1, 2)); - mfac.add(m_one); - mfac.raise(Number(-1, 2)); - multiply(mfac); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_atanh && SIZE == 1) { - MathStructure mstruct(CHILD(0)); - mstruct.differentiate(x_var, eo); - SET_CHILD_MAP(0); - raise(2); - negate(); - add(m_one); - raise(m_minus_one); - multiply(mstruct); - } else if(o_function == CALCULATOR->f_sinc && SIZE == 1) { - // diff(x)*(cos(x)/x-sin(x)/x^2) - MathStructure m_cos(CALCULATOR->f_cos, &CHILD(0), NULL); - if(CALCULATOR->getRadUnit()) m_cos[0].multiply(CALCULATOR->getRadUnit()); - m_cos.divide(CHILD(0)); - MathStructure m_sin(CALCULATOR->f_sin, &CHILD(0), NULL); - if(CALCULATOR->getRadUnit()) m_sin[0].multiply(CALCULATOR->getRadUnit()); - MathStructure mstruct(CHILD(0)); - mstruct.raise(Number(-2, 1, 0)); - m_sin.multiply(mstruct); - MathStructure mdiff(CHILD(0)); - mdiff.differentiate(x_var, eo); - set(m_sin); - negate(); - add(m_cos); - multiply(mdiff); - } else if(o_function == CALCULATOR->f_stripunits && SIZE == 1) { - CHILD(0).differentiate(x_var, eo); - } else if(o_function == CALCULATOR->f_integrate && SIZE >= 4 && CHILD(3) == x_var && CHILD(1).isUndefined() && CHILD(2).isUndefined()) { - SET_CHILD_MAP(0); - } else if(o_function == CALCULATOR->f_diff && (SIZE == 3 || (SIZE == 4 && CHILD(3).isUndefined())) && CHILD(1) == x_var) { - CHILD(2) += m_one; - } else if(o_function == CALCULATOR->f_diff && SIZE == 2 && CHILD(1) == x_var) { - APPEND(MathStructure(2, 1, 0)); - } else if(o_function == CALCULATOR->f_diff && SIZE == 1 && x_var == (Variable*) CALCULATOR->v_x) { - APPEND(x_var); - APPEND(MathStructure(2, 1, 0)); - } else { - if(!eo.calculate_functions || !calculateFunctions(eo, false)) { - transform(CALCULATOR->f_diff); - addChild(x_var); - addChild(m_one); - addChild(m_undefined); - return false; - } else { - return differentiate(x_var, eo); - } - } - break; - } - case STRUCT_MULTIPLICATION: { - MathStructure mstruct, vstruct; - size_t idiv = 0; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isPower() && CHILD(i)[1].isNumber() && CHILD(i)[1].number().isNegative()) { - if(idiv == 0) { - if(CHILD(i)[1].isMinusOne()) { - vstruct = CHILD(i)[0]; - } else { - vstruct = CHILD(i); - vstruct[1].number().negate(); - } - } else { - if(CHILD(i)[1].isMinusOne()) { - vstruct.multiply(CHILD(i)[0], true); - } else { - vstruct.multiply(CHILD(i), true); - vstruct[vstruct.size() - 1][1].number().negate(); - } - } - idiv++; - } - } - if(idiv == SIZE) { - set(-1, 1); - MathStructure mdiv(vstruct); - mdiv ^= MathStructure(2, 1, 0); - mdiv.inverse(); - multiply(mdiv); - MathStructure diff_u(vstruct); - diff_u.differentiate(x_var, eo); - multiply(diff_u, true); - break; - } else if(idiv > 0) { - idiv = 0; - for(size_t i = 0; i < SIZE; i++) { - if(!CHILD(i).isPower() || !CHILD(i)[1].isNumber() || !CHILD(i)[1].number().isNegative()) { - if(idiv == 0) { - mstruct = CHILD(i); - } else { - mstruct.multiply(CHILD(i), true); - } - idiv++; - } - } - MathStructure mdiv(vstruct); - mdiv ^= MathStructure(2, 1, 0); - MathStructure diff_v(vstruct); - diff_v.differentiate(x_var, eo); - MathStructure diff_u(mstruct); - diff_u.differentiate(x_var, eo); - vstruct *= diff_u; - mstruct *= diff_v; - set_nocopy(vstruct, true); - subtract(mstruct); - divide(mdiv); - break; - } - if(SIZE > 2) { - mstruct.set(*this); - mstruct.delChild(mstruct.size()); - MathStructure mstruct2(LAST); - MathStructure mstruct3(mstruct); - mstruct.differentiate(x_var, eo); - mstruct2.differentiate(x_var, eo); - mstruct *= LAST; - mstruct2 *= mstruct3; - set(mstruct, true); - add(mstruct2); - } else { - mstruct = CHILD(0); - MathStructure mstruct2(CHILD(1)); - mstruct.differentiate(x_var, eo); - mstruct2.differentiate(x_var, eo); - mstruct *= CHILD(1); - mstruct2 *= CHILD(0); - set(mstruct, true); - add(mstruct2); - } - break; - } - case STRUCT_SYMBOLIC: { - if(representsNumber(true)) { - clear(true); - } else { - transform(CALCULATOR->f_diff); - addChild(x_var); - addChild(m_one); - addChild(m_undefined); - return false; - } - break; - } - case STRUCT_VARIABLE: { - if(eo.calculate_variables && o_variable->isKnown()) { - if(eo.approximation != APPROXIMATION_EXACT || !o_variable->isApproximate()) { - set(((KnownVariable*) o_variable)->get(), true); - unformat(eo); - return differentiate(x_var, eo); - } else { - transform(CALCULATOR->f_diff); - addChild(x_var); - addChild(m_one); - addChild(m_undefined); - return false; - } - } - } - default: { - transform(CALCULATOR->f_diff); - addChild(x_var); - addChild(m_one); - addChild(m_undefined); - return false; - } - } - remove_zero_mul(*this); - return true; -} - -bool integrate_info(const MathStructure &mstruct, const MathStructure &x_var, MathStructure &madd, MathStructure &mmul, MathStructure &mexp, bool radunit = false, bool mexp_as_x2 = false, bool mexp_as_fx = false) { - if(radunit && mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[1] == CALCULATOR->getRadUnit()) return integrate_info(mstruct[0], x_var, madd, mmul, mexp, false, mexp_as_x2, mexp_as_fx); - madd.clear(); - if(mexp_as_x2 || mexp_as_fx) mexp = m_zero; - else mexp = m_one; - mmul = m_zero; - if(!mexp_as_fx && mstruct == x_var) { - if(radunit) return false; - mmul = m_one; - return true; - } else if(mexp_as_x2 && mstruct.isPower()) { - if(radunit) return false; - if(mstruct[1].isNumber() && mstruct[1].number().isTwo() && mstruct[0] == x_var) { - mexp = m_one; - return true; - } - } else if(!mexp_as_fx && !mexp_as_x2 && mstruct.isPower() && mstruct[1].containsRepresentativeOf(x_var, true, true) == 0) { - if(radunit) return false; - if(mstruct[0] == x_var) { - mexp = mstruct[1]; - mmul = m_one; - return true; - } - } else if(mstruct.isMultiplication() && mstruct.size() >= 2) { - bool b_x = false; - bool b_rad = false; - bool b2 = false; - size_t i_x = 0, i_rad = 0; - for(size_t i = 0; i < mstruct.size(); i++) { - if(!b_x && !mexp_as_fx && mstruct[i] == x_var) { - b_x = true; - i_x = i; - } else if(!b_x && mexp_as_x2 && mstruct[i].isPower() && mstruct[i][1].isNumber() && mstruct[i][1].number().isTwo() && mstruct[i][0] == x_var) { - b_x = true; - b2 = true; - i_x = i; - } else if(!b_x && !mexp_as_fx && !mexp_as_x2 && mstruct[i].isPower() && mstruct[i][0] == x_var && mstruct[i][1].containsRepresentativeOf(x_var, true, true) == 0) { - b_x = true; - i_x = i; - mexp = mstruct[i][1]; - } else if(mstruct[i].containsRepresentativeOf(x_var, true, true) != 0) { - if(!b_x && mexp_as_fx && (mexp.isZero() || mexp == mstruct[i])) { - mexp = mstruct[i]; - b_x = true; - i_x = i; - } else { - return false; - } - } else if(!b_rad && radunit && mstruct[i] == CALCULATOR->getRadUnit()) { - b_rad = true; - i_rad = i; - } - } - if(!b_x || (radunit && !b_rad)) return false; - if(mstruct.size() == 1 || (radunit && mstruct.size() == 2)) { - if(b2) mexp = m_one; - else mmul = m_one; - } else if(mstruct.size() == 2) { - if(b2) { - if(i_x == 1) mexp = mstruct[0]; - else mexp = mstruct[1]; - } else { - if(i_x == 1) mmul = mstruct[0]; - else mmul = mstruct[1]; - } - } else if(radunit && mstruct.size() == 3) { - if((i_x == 1 && i_rad == 2) || (i_x == 2 && i_rad == 1)) { - if(b2) mexp = mstruct[0]; - else mmul = mstruct[0]; - } else if((i_x == 0 && i_rad == 2) || (i_x == 2 && i_rad == 0)) { - if(b2) mexp = mstruct[1]; - else mmul = mstruct[1]; - } else { - if(b2) mexp = mstruct[2]; - else mmul = mstruct[2]; - } - } else { - if(b2) { - mexp = mstruct; - mexp.delChild(i_x + 1, true); - if(radunit) { - mexp.delChild(i_rad < i_x ? i_rad + 1 : i_rad, true); - } - } else { - mmul = mstruct; - mmul.delChild(i_x + 1, true); - if(radunit) { - mmul.delChild(i_rad < i_x ? i_rad + 1 : i_rad, true); - } - } - } - return true; - } else if(mstruct.isAddition()) { - mmul.setType(STRUCT_ADDITION); - if(mexp_as_x2) mexp.setType(STRUCT_ADDITION); - madd.setType(STRUCT_ADDITION); - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mexp_as_fx && mstruct[i] == x_var) { - if(mexp_as_x2 || mexp.isOne()) mmul.addChild(m_one); - else return false; - } else if(mexp_as_x2 && mstruct[i].isPower() && mstruct[i][1].isNumber() && mstruct[i][1].number().isTwo() && mstruct[i][0] == x_var) { - mexp.addChild(m_one); - } else if(!mexp_as_fx && !mexp_as_x2 && mstruct[i].isPower() && mstruct[i][0] == x_var && mstruct[i][1].containsRepresentativeOf(x_var, true, true) == 0) { - if(mmul.size() == 0) { - mexp = mstruct[i][1]; - } else if(mexp != mstruct[i][1]) { - return false; - } - mmul.addChild(m_one); - } else if(mstruct[i].isMultiplication()) { - bool b_x = false; - bool b_rad = false; - bool b2 = false; - size_t i_x = 0, i_rad = 0; - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - if(!b_x && !mexp_as_fx && mstruct[i][i2] == x_var) { - if(!mexp_as_x2 && !mexp.isOne()) return false; - i_x = i2; - b_x = true; - } else if(!b_x && mexp_as_x2 && mstruct[i][i2].isPower() && mstruct[i][i2][1].isNumber() && mstruct[i][i2][1].number().isTwo() && mstruct[i][i2][0] == x_var) { - b2 = true; - i_x = i2; - b_x = true; - } else if(!b_x && !mexp_as_fx && !mexp_as_x2 && mstruct[i][i2].isPower() && mstruct[i][i2][0] == x_var && mstruct[i][i2][1].containsRepresentativeOf(x_var, true, true) == 0) { - if(mmul.size() == 0) { - mexp = mstruct[i][i2][1]; - } else if(mexp != mstruct[i][i2][1]) { - return false; - } - i_x = i2; - b_x = true; - } else if(mstruct[i][i2].containsRepresentativeOf(x_var, true, true) != 0) { - if(!b_x && mexp_as_fx && (mexp.isZero() || mexp == mstruct[i][i2])) { - mexp = mstruct[i][i2]; - i_x = i2; - b_x = true; - } else { - return false; - } - } else if(!b_rad && radunit && mstruct[i][i2] == CALCULATOR->getRadUnit()) { - b_rad = true; - i_rad = i2; - } - } - if(radunit && !b_rad) return false; - if(b_x) { - if(mstruct[i].size() == 1) { - if(b2) mexp.addChild(m_one); - else mmul.addChild(m_one); - } else if(radunit && mstruct[i].size() == 2) { - if(b2) mexp.addChild(m_one); - else mmul.addChild(m_one); - } else { - if(b2) { - mexp.addChild(mstruct[i]); - mexp[mexp.size() - 1].delChild(i_x + 1, true); - if(radunit) mexp[mexp.size() - 1].delChild(i_rad < i_x ? i_rad + 1 : i_rad, true); - mexp.childUpdated(mexp.size()); - } else { - mmul.addChild(mstruct[i]); - mmul[mmul.size() - 1].delChild(i_x + 1, true); - if(radunit) mmul[mmul.size() - 1].delChild(i_rad < i_x ? i_rad + 1 : i_rad, true); - mmul.childUpdated(mmul.size()); - } - } - } else { - madd.addChild(mstruct[i]); - if(radunit) { - madd[madd.size() - 1].delChild(i_rad + 1, true); - } - } - } else if(radunit && mstruct[i] == CALCULATOR->getRadUnit()) { - madd.addChild(mstruct[i]); - } else if(radunit || mstruct[i].containsRepresentativeOf(x_var, true, true) != 0) { - if(!radunit && mexp_as_fx && (mexp.isZero() || mexp == mstruct[i])) { - mexp = mstruct[i]; - mmul.addChild(m_one); - } else { - return false; - } - } else { - madd.addChild(mstruct[i]); - } - } - if(mmul.size() == 0 && (!mexp_as_x2 || mexp.size() == 0)) { - mmul.clear(); - if(mexp_as_x2) mexp.clear(); - return false; - } - if(mmul.size() == 0) mmul.clear(); - else if(mmul.size() == 1) mmul.setToChild(1); - if(mexp_as_x2) { - if(mexp.size() == 0) mexp.clear(); - else if(mexp.size() == 1) mexp.setToChild(1); - } - if(madd.size() == 0) madd.clear(); - else if(madd.size() == 1) madd.setToChild(1); - return true; - } else if(!radunit && mexp_as_fx && mstruct.contains(x_var, true)) { - mexp = mstruct; - mmul = m_one; - return true; - } - return false; -} - -bool test_absln_comp_cmplx(const MathStructure &mstruct) { - return false; - if(mstruct.number().isComplex() && (!mstruct.number().hasRealPart() || mstruct.number().hasPositiveSign()) && mstruct.number().internalImaginary()->isPositive()) return true; - if(mstruct.isPower() && mstruct[1].isNumber() && mstruct[1].number().numeratorIsOne() && mstruct[0].representsNonComplex(true)) return true; - if(mstruct.isMultiplication()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct[i].representsNonNegative(true)) { - if(!test_absln_comp_cmplx(mstruct[i])) { - return false; - } - } - } - return true; - } else if(mstruct.isAddition()) { - for(size_t i = 0; i < mstruct.size(); i++) { - if(!mstruct[i].representsNonNegative(true)) { - if(!test_absln_comp_cmplx(mstruct[i])) { - return false; - } - } - } - return true; - } - return false; -} - -bool transform_absln(MathStructure &mstruct, int use_abs, bool definite_integral, const MathStructure &x_var, const EvaluationOptions &eo) { - if(use_abs != 0 && (mstruct.representsNonComplex(true) || test_absln_comp_cmplx(mstruct))) { - if(mstruct.representsNonPositive(true)) { - mstruct.negate(); - } else if(!mstruct.representsNonNegative(true)) { - mstruct.transform(CALCULATOR->f_abs); - } - mstruct.transform(CALCULATOR->f_ln); - } else if(use_abs != 0 && !mstruct.representsComplex(true)) { - if(definite_integral) use_abs = -1; - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mtest(mstruct); - EvaluationOptions eo2 = eo; - eo2.expand = true; - eo2.approximation = APPROXIMATION_APPROXIMATE; - eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; - mtest.eval(eo2); - CALCULATOR->endTemporaryStopMessages(); - if(mtest.representsNonComplex(true) || test_absln_comp_cmplx(mtest)) { - if(mstruct.representsNonPositive(true)) { - mstruct.negate(); - } else if(!mtest.representsNonNegative(true)) { - mstruct.transform(CALCULATOR->f_abs); - } - mstruct.transform(CALCULATOR->f_ln); - } else if(mtest.representsComplex(true)) { - mstruct.transform(CALCULATOR->f_ln); - } else { - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - CALCULATOR->beginTemporaryStopMessages(); - KnownVariable *var = new KnownVariable("", format_and_print(x_var), ((UnknownVariable*) x_var.variable())->interval()); - mtest.replace(x_var, var); - mtest.eval(eo2); - CALCULATOR->endTemporaryStopMessages(); - if(mtest.representsNonComplex(true) || test_absln_comp_cmplx(mtest)) { - if(mstruct.representsNonPositive(true)) { - mstruct.negate(); - } else if(!mtest.representsNonNegative(true)) { - mstruct.transform(CALCULATOR->f_abs); - } - mstruct.transform(CALCULATOR->f_ln); - } else if(use_abs > 0) { - CALCULATOR->error(false, "Integral assumed real", NULL); - mstruct.transform(CALCULATOR->f_abs); - mstruct.transform(CALCULATOR->f_ln); - } else { - mstruct.transform(CALCULATOR->f_ln); - } - var->destroy(); - } else if(use_abs > 0) { - CALCULATOR->error(false, "Integral assumed real", NULL); - mstruct.transform(CALCULATOR->f_abs); - mstruct.transform(CALCULATOR->f_ln); - } else { - mstruct.transform(CALCULATOR->f_ln); - } - } - } else { - mstruct.transform(CALCULATOR->f_ln); - } - return true; -} -bool test_real(MathStructure &mstruct, int use_abs, bool definite_integral, const MathStructure &x_var, const EvaluationOptions &eo) { - if(use_abs != 0 && mstruct.representsNonComplex(true)) { - return true; - } else if(use_abs != 0 && !mstruct.representsComplex(true)) { - MathStructure m_interval(m_undefined); - if(x_var.isVariable() && !x_var.variable()->isKnown()) m_interval = ((UnknownVariable*) x_var.variable())->interval(); - if(definite_integral) use_abs = -1; - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mtest(mstruct); - EvaluationOptions eo2 = eo; - eo2.expand = true; - eo2.approximation = APPROXIMATION_APPROXIMATE; - eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; - mtest.eval(eo2); - CALCULATOR->endTemporaryStopMessages(); - if(mtest.representsNonComplex(true)) { - return true; - } else if(mtest.representsComplex(true)) { - return false; - } else { - if(!m_interval.isUndefined()) { - CALCULATOR->beginTemporaryStopMessages(); - mtest.replace(x_var, m_interval); - mtest.eval(eo2); - CALCULATOR->endTemporaryStopMessages(); - if((use_abs > 0 && !mtest.representsComplex(true)) || (use_abs < 0 && mtest.representsNonComplex(true))) { - if(use_abs > 0 && !mtest.representsNonComplex(true)) CALCULATOR->error(false, "Integral assumed real", NULL); - return true; - } else { - return false; - } - } else if(use_abs < 0) { - return false; - } else { - CALCULATOR->error(false, "Integral assumed real", NULL); - return true; - } - } - } - return false; -} - -bool check_zero_div(const MathStructure &m, const MathStructure &x_var, const EvaluationOptions &eo, bool top = true) { - if(top && (!x_var.isVariable() || x_var.variable()->isKnown() || ((UnknownVariable*) x_var.variable())->interval().isUndefined())) return true; - if(m.isPower() && m[1].compare(m_zero) == COMPARISON_RESULT_GREATER && m[0].contains(x_var, true) > 0 && COMPARISON_MIGHT_BE_EQUAL(m[0].compare(m_zero))) return false; - for(size_t i = 0; i < m.size(); i++) { - if(!check_zero_div(m[i], x_var, eo)) return false; - } - /*if(m.isFunction() && m.size() == 1 && (m.function() == CALCULATOR->f_tan || m.function() == CALCULATOR->f_tanh) && m[0].contains(x_var, true) > 0) { - EvaluationOptions eo2 = eo; - eo2.approximation = APPROXIMATION_APPROXIMATE; - eo2.interval_calculation = INTERVAL_CALCULATION_INTERVAL_ARITHMETIC; - eo2.assume_denominators_nonzero = false; - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mfunc(m); - mfunc.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - bool b = mfunc.calculateFunctions(eo2); - CALCULATOR->endTemporaryStopMessages(); - if(!b) return false; - }*/ - return true; -} - -int integrate_function(MathStructure &mstruct, const MathStructure &x_var, const EvaluationOptions &eo, const MathStructure &mpow, const MathStructure &mfac, const MathStructure &mpowadd, const MathStructure &mpowmul, int use_abs, bool definite_integral, int max_part_depth, vector *parent_parts) { - if(mpow.containsRepresentativeOf(x_var, true, true) != 0) return false; - if(!mpowadd.isZero() || !mpowmul.isOne()) { - if(!mfac.isOne() || !mpow.isMinusOne()) return false; - if((mstruct.function() == CALCULATOR->f_sin || mstruct.function() == CALCULATOR->f_cos || mstruct.function() == CALCULATOR->f_sinh || mstruct.function() == CALCULATOR->f_cosh || mstruct.function() == CALCULATOR->f_ln) && mstruct.size() == 1) { - MathStructure mexp, mmul, madd; - if(integrate_info(mstruct[0], x_var, madd, mmul, mexp, (mstruct.function() == CALCULATOR->f_sin || mstruct.function() == CALCULATOR->f_cos))) { - if(mexp.isOne()) { - bool neg_equals = false; - if((mstruct.function() == CALCULATOR->f_sin || mstruct.function() == CALCULATOR->f_cos || mstruct.function() == CALCULATOR->f_cosh) && mpowadd != mpowmul) { - MathStructure mpowaddneg(mpowadd); - mpowaddneg.calculateNegate(eo); - neg_equals = (mpowaddneg == mpowmul); - } - if(mstruct.function() == CALCULATOR->f_sin) { - if(mpowadd == mpowmul || neg_equals) { - //1/(c*sin(ax+b)+c)=2*sin((a x + b)/2)*(sin((a x + b)/2)+cos((a x + b)/2))/(a*(c*sin((a x + b))+c)) - MathStructure mdiv(mstruct); - mstruct[0] *= nr_half; - MathStructure msin(mstruct); - MathStructure mcos(mstruct); - mcos.setFunction(CALCULATOR->f_cos); - mstruct *= nr_two; - if(mpowadd != mpowmul) msin.negate(); - msin += mcos; - mstruct *= msin; - mdiv *= mpowmul; - mdiv += mpowadd; - if(!mmul.isOne()) mdiv *= mmul; - mstruct /= mdiv; - return true; - } else { - //1/(d*sin(ax+b)+c)=(2 atan((c*tan((a x + b)/2)+d)/sqrt(c^2-d^2)))/(a*sqrt(c^2-d^2)) - if(definite_integral && x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure mtest(mstruct[0]); - mtest[0] /= CALCULATOR->getRadUnit(); - mtest[0] /= CALCULATOR->v_pi; - mtest[0] /= nr_two; - mtest[0].transform(CALCULATOR->f_abs); - mtest[0].transform(CALCULATOR->f_frac); - if(COMPARISON_MIGHT_BE_EQUAL(mtest.compare(nr_half))) return -1; - } - mstruct.setFunction(CALCULATOR->f_tan); - mstruct[0] *= nr_half; - mstruct *= mpowadd; - mstruct += mpowmul; - MathStructure msqrtc2md2(mpowadd); - if(!mpowadd.isOne()) msqrtc2md2 ^= nr_two; - MathStructure mmpowmul2(mpowmul); - if(!mpowmul.isOne()) mmpowmul2 ^= nr_two; - mmpowmul2.negate(); - msqrtc2md2 += mmpowmul2; - msqrtc2md2 ^= Number(-1, 2, 0); - mstruct *= msqrtc2md2; - mstruct.transform(CALCULATOR->f_atan); - mstruct *= msqrtc2md2; - if(!mmul.isOne()) mstruct /= mmul; - mstruct *= nr_two; - return true; - } - } else if(mstruct.function() == CALCULATOR->f_cos) { - if(mpowadd == mpowmul) { - //1/(c*cos(ax+b)+c)=tan((a x + b)/2)/(ac) - mstruct[0] *= nr_half; - mstruct.setFunction(CALCULATOR->f_tan); - if(!mpowadd.isOne()) mstruct /= mpowadd; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } else if(neg_equals) { - //1/(c*cos(ax+b)-c)=cos((a x + b)/2)/(ac*sin((a x + b)/2)) - mstruct[0] *= nr_half; - MathStructure msin(mstruct); - msin.setFunction(CALCULATOR->f_sin); - mstruct /= msin; - if(!mpowmul.isOne()) mstruct /= mpowmul; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } else { - //1/(d*cos(ax+b)+c)=-(2*atanh(((c-d)*tan((a x + b)/2))/sqrt(d^2-c^2)))/(a*sqrt(d^2-c^2)) - if(definite_integral && x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure mtest(mstruct[0]); - mtest[0] /= CALCULATOR->getRadUnit(); - mtest[0] /= CALCULATOR->v_pi; - mtest[0] /= nr_two; - mtest[0].transform(CALCULATOR->f_abs); - mtest[0].transform(CALCULATOR->f_frac); - if(COMPARISON_MIGHT_BE_EQUAL(mtest.compare(nr_half))) return -1; - } - mstruct.setFunction(CALCULATOR->f_tan); - mstruct[0] *= nr_half; - mstruct *= mpowadd; - mstruct.last() -= mpowmul; - mstruct.childUpdated(mstruct.size()); - MathStructure msqrtc2md2(mpowadd); - if(!mpowadd.isOne()) msqrtc2md2 ^= nr_two; - msqrtc2md2.negate(); - MathStructure mmpowmul2(mpowmul); - if(!mpowmul.isOne()) mmpowmul2 ^= nr_two; - msqrtc2md2 += mmpowmul2; - msqrtc2md2 ^= Number(-1, 2, 0); - mstruct *= msqrtc2md2; - mstruct.transform(CALCULATOR->f_atanh); - mstruct *= msqrtc2md2; - if(!mmul.isOne()) mstruct /= mmul; - mstruct *= Number(-2, 1); - return true; - } - } else if(mstruct.function() == CALCULATOR->f_sinh) { - //1/(d*sinh(ax+b)+c)=(2 atan((-c*tan((a x + b)/2)+d)/sqrt(-c^2-d^2)))/(a*sqrt(-c^2-d^2)) - mstruct.setFunction(CALCULATOR->f_tanh); - mstruct[0] *= nr_half; - mstruct *= mpowadd; - mstruct.negate(); - mstruct += mpowmul; - MathStructure msqrtc2md2(mpowadd); - if(!mpowadd.isOne()) msqrtc2md2 ^= nr_two; - msqrtc2md2.negate(); - MathStructure mmpowmul2(mpowmul); - if(!mpowmul.isOne()) mmpowmul2 ^= nr_two; - mmpowmul2.negate(); - msqrtc2md2 += mmpowmul2; - msqrtc2md2 ^= Number(-1, 2, 0); - mstruct *= msqrtc2md2; - mstruct.transform(CALCULATOR->f_atan); - mstruct *= msqrtc2md2; - if(!mmul.isOne()) mstruct /= mmul; - mstruct *= nr_two; - return true; - } else if(mstruct.function() == CALCULATOR->f_cosh) { - if(mpowadd == mpowmul) { - //1/(c*cosh(ax+b)+c)=tanh((a x + b)/2)/(ac) - mstruct[0] *= nr_half; - mstruct.setFunction(CALCULATOR->f_tanh); - if(!mpowadd.isOne()) mstruct /= mpowadd; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } else if(neg_equals) { - //1/(c*cosh(ax+b)-c)=-cosh((a x + b)/2)/(ac*sinh((a x + b)/2)) - mstruct[0] *= nr_half; - MathStructure msin(mstruct); - msin.setFunction(CALCULATOR->f_sinh); - mstruct.negate(); - mstruct /= msin; - if(!mpowmul.isOne()) mstruct /= mpowmul; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } else { - //1/(d*cos(ax+b)+c)=-(2*atan(((c-d)*tanh((a x + b)/2))/sqrt(d^2-c^2)))/(a*sqrt(d^2-c^2)) - mstruct.setFunction(CALCULATOR->f_tanh); - mstruct[0] *= nr_half; - mstruct *= mpowadd; - mstruct.last() -= mpowmul; - mstruct.childUpdated(mstruct.size()); - MathStructure msqrtc2md2(mpowadd); - if(!mpowadd.isOne()) msqrtc2md2 ^= nr_two; - msqrtc2md2.negate(); - MathStructure mmpowmul2(mpowmul); - if(!mpowmul.isOne()) mmpowmul2 ^= nr_two; - msqrtc2md2 += mmpowmul2; - msqrtc2md2 ^= Number(-1, 2, 0); - mstruct *= msqrtc2md2; - mstruct.transform(CALCULATOR->f_atan); - mstruct *= msqrtc2md2; - if(!mmul.isOne()) mstruct /= mmul; - mstruct *= Number(-2, 1); - return true; - } - } else if(mstruct.function() == CALCULATOR->f_ln) { - //1/(d*ln(ax+b)+c)=(e^(-c/d)*Ei(c/d+ln(ax+b)))/(a*d) - MathStructure mpadm(mpowadd); - if(!mpowmul.isOne()) mpadm /= mpowmul; - mstruct += mpadm; - mstruct.transform(CALCULATOR->f_Ei); - mpadm.negate(); - mstruct *= CALCULATOR->v_e; - mstruct.last() ^= mpadm; - mstruct.childUpdated(mstruct.size()); - if(!mmul.isOne()) mstruct /= mmul; - if(!mpowmul.isOne()) mstruct /= mpowmul; - return true; - } - } else if(mstruct.function() == CALCULATOR->f_ln && madd.isZero()) { - //1/(d*ln(ax^b)+c)=(x*(ax^b)^(-1/b)*e^(-c/(bd))*Ei((c+d*ln(ax^b))/(bd)))/(bd) - MathStructure mem(mexp); - if(!mpowmul.isOne()) mem *= mpowmul; - mem.inverse(); - MathStructure marg(mstruct[0]); - mexp.inverse(); - mexp.negate(); - marg ^= mexp; - MathStructure mexpe(CALCULATOR->v_e); - if(!mpowadd.isZero()) { - MathStructure mepow(mpowadd); - mepow.negate(); - mepow *= mem; - mexpe ^= mepow; - } - if(!mpowmul.isOne()) mstruct *= mpowmul; - if(!mpowadd.isZero()) mstruct += mpowadd; - mstruct *= mem; - mstruct.transform(CALCULATOR->f_Ei); - if(!mpowadd.isZero()) mstruct *= mexpe; - mstruct *= marg; - mstruct *= x_var; - mstruct *= mem; - return true; - } - } - } - return false; - } - if(mstruct.function() == CALCULATOR->f_ln && mstruct.size() == 1) { - if(mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_abs && mstruct[0].size() == 1 && mpow.isOne() && mfac.isOne() && mstruct[0][0].representsNonComplex(true)) { - MathStructure mexp, mmul, madd; - if(integrate_info(mstruct[0][0], x_var, madd, mmul, mexp) && mexp.isOne()) { - MathStructure marg(mstruct[0][0]); - MathStructure ln_x(CALCULATOR->f_ln, &marg, NULL); - MathStructure ln_mx(ln_x); - ln_mx[0].negate(); - MathStructure sgn_x(ln_x); - sgn_x.setFunction(CALCULATOR->f_signum); - sgn_x.addChild(m_zero); - mstruct = ln_x; - mstruct -= ln_mx; - mstruct *= sgn_x; - mstruct += ln_mx; - mstruct += ln_x; - mstruct -= nr_two; - mstruct *= marg; - mstruct *= nr_half; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } - } - if(mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_root && VALID_ROOT(mstruct[0]) && mpow.isOne() && mfac.isOne() && (!definite_integral || COMPARISON_IS_NOT_EQUAL(mstruct[0][0].compare(m_zero)))) { - MathStructure mexp, mmul, madd; - if(integrate_info(mstruct[0][0], x_var, madd, mmul, mexp) && mexp.isOne()) { - if(madd.isZero()) { - if(mmul.isZero()) { - mstruct *= x_var; - mstruct += x_var; - mstruct.last().divide(mstruct[0][1]); - mstruct.childUpdated(mstruct.size()); - mstruct.last().negate(); - return true; - } - MathStructure mterm(mstruct[0]); - mterm ^= nr_two; - mterm *= mstruct[0]; - mterm.inverse(); - if(!mmul.isOne()) mterm *= mmul; - mterm *= x_var; - mterm.last() ^= nr_two; - mterm *= Number(-1, 3); - mstruct *= x_var; - mstruct += mterm; - return true; - } - MathStructure mterm1(x_var); - if(!mmul.isOne()) mterm1 *= mmul; - if(!madd.isOne()) mterm1 /= madd; - mterm1 += m_one; - if(!transform_absln(mterm1, use_abs, definite_integral, x_var, eo)) return -1; - if(!mmul.isOne()) mterm1 /= mmul; - if(!madd.isOne()) mterm1 *= madd; - mterm1 /= mstruct[0][1]; - MathStructure mterm2(x_var); - mterm2 /= mstruct[0][1]; - mstruct *= x_var; - mstruct += mterm1; - mstruct -= mterm2; - return true; - } - } - MathStructure mexp, mmul, madd; - if(integrate_info(mstruct[0], x_var, madd, mmul, mexp, false, false, true) && (mexp == x_var || (mexp.isPower() && mexp[0] == x_var && ((mexp[1] == x_var && madd.isZero() && mpow.isOne() && (!definite_integral || x_var.representsNonNegative(true))) || mexp[1].containsRepresentativeOf(x_var, true, true) == 0)) || (mpow.isOne() && madd.isZero() && mexp.isFunction() && mexp.function() == CALCULATOR->f_root && VALID_ROOT(mexp) && mexp[0] == x_var) || (mpow.isOne() && madd.isZero() && mexp.isPower() && mexp[1].isInteger() && mexp[0].isFunction() && mexp[0].function() == CALCULATOR->f_root && VALID_ROOT(mexp[0]) && mexp[0][0] == x_var))) { - bool b_root = false; - if(mexp == x_var) mexp.set(1, 1, 0); - else if(mexp.isPower() && mexp[0] == x_var) mexp.setToChild(2); - else if(mexp.isPower()) {mexp[0].setToChild(2); mexp[0].number().recip(); mexp[0].number() *= mexp[1].number(); mexp.setToChild(1); b_root = true;} - else {mexp.setToChild(2); mexp.number().recip(); b_root = true;} - bool do_if = false; - if(definite_integral && x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure mtest(((UnknownVariable*) x_var.variable())->interval()); - mtest.eval(eo); - if(mtest.isNumber()) { - MathStructure mtest2(mstruct[0]); - mtest2.replace(x_var, mtest.number().lowerEndPoint()); - mtest2.eval(eo); - do_if = mtest2.isZero(); - if(!do_if) { - mtest2 = mstruct[0]; - mtest2.replace(x_var, mtest.number().upperEndPoint()); - mtest2.eval(eo); - do_if = mtest2.isZero(); - } - } - } - MathStructure mif; - MathStructure marg(mstruct[0]); - bool b = false; - if(mexp == x_var) { - if(mfac.isOne()) { - mstruct *= x_var; - MathStructure mterm(x_var); - mterm.transform(CALCULATOR->f_ln); - mterm *= nr_two; - mterm += m_one; - mterm *= x_var; - mterm.last() ^= nr_two; - mterm *= Number(-1, 4); - mstruct += mterm; - b = true; - } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { - if(mfac == x_var) mexp.set(1, 1, 0); - else mexp = mfac[1]; - MathStructure mexpp1(mexp); - mexpp1 += m_one; - MathStructure mexpp2(mexp); - mexpp2 += nr_two; - MathStructure mterm1(x_var); - mterm1.transform(CALCULATOR->f_ln); - mterm1 *= x_var; - mterm1 *= mexpp2; - MathStructure mterm2(x_var); - mterm2 *= mexpp1; - mstruct.negate(); - mexpp2 ^= nr_two; - mstruct *= mexpp2; - mstruct += mterm1; - mstruct += mterm2; - mstruct *= x_var; - mstruct.last() ^= mexpp1; - mexpp2 *= mexpp1; - mstruct /= mexpp2; - mstruct.negate(); - b = true; - } - } else if(mfac.isOne() && (mexp.isOne() || madd.isZero())) { - if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-1)) { - if(mpow.isOne()) { - if(madd.isZero()) { - mstruct -= mexp; - mstruct.multiply(x_var); - b = true; - } else { - MathStructure marg(mstruct[0]); - mstruct *= marg; - mstruct -= marg; - if(!mmul.isOne()) mstruct.divide(mmul); - b = true; - } - } else if(mpow.number().isTwo()) { - MathStructure marg(mstruct[0]); - MathStructure mterm2(mstruct); - mstruct ^= mpow; - mterm2 *= Number(-2, 1); - if(mexp.isOne()) { - mterm2 += nr_two; - } else { - mterm2 *= mexp; - mterm2 += mexp; - mterm2.last() ^= nr_two; - mterm2.last() *= nr_two; - } - mstruct += mterm2; - if(madd.isZero()) { - mstruct.multiply(x_var); - } else { - mstruct *= marg; - if(!mmul.isOne()) mstruct /= mmul; - } - b = true; - } else if(mpow.number().isMinusOne()) { - if(mexp.isOne()) { - mstruct.setFunction(CALCULATOR->f_li); - if(!mmul.isOne()) mstruct /= mmul; - b = true; - } - } else { - unsigned long int n = mpow.number().uintValue(); - MathStructure marg(mstruct[0]); - Number nfac(mpow.number()); - nfac.factorial(); - for(size_t i = 0; i <= n; i++) { - MathStructure mterm(CALCULATOR->f_ln, &marg, NULL); - mterm ^= Number(i); - mterm *= nfac; - Number ifac(i); - ifac.factorial(); - mterm /= ifac; - MathStructure m1pow(mexp); - m1pow.negate(); - m1pow ^= Number(n - i); - mterm *= m1pow; - if(i == 0) mstruct = mterm; - else mstruct += mterm; - } - if(madd.isZero()) { - mstruct.multiply(x_var); - } else { - mstruct *= marg; - if(!mmul.isOne()) mstruct /= mmul; - } - b = true; - } - } - } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { - MathStructure mfacexp(1, 1, 0); - if(mfac != x_var) mfacexp = mfac[1]; - if(mfacexp.isMinusOne()) { - if(mpow.isMinusOne()) { - if(mexp.isOne() && madd.isZero()) { - mstruct.transform(CALCULATOR->f_ln); - b = true; - } - } else if(madd.isZero()) { - MathStructure mpowp1(mpow); - mpowp1 += m_one; - mstruct ^= mpowp1; - mstruct /= mpowp1; - if(!mexp.isOne()) mstruct /= mexp; - b = true; - } else if(mpow.isOne()) { - MathStructure m_axcb(x_var); - if(!mexp.isOne()) m_axcb ^= mexp; - if(!mmul.isOne()) m_axcb *= mmul; - if(!madd.isZero()) m_axcb /= madd; - mstruct *= m_axcb; - mstruct.last().negate(); - mstruct.last().transform(CALCULATOR->f_ln); - MathStructure mterm2(m_axcb); - mterm2 += m_one; - mterm2.transform(CALCULATOR->f_Li); - mterm2.insertChild(nr_two, 1); - mstruct += mterm2; - if(!mexp.isOne()) mstruct /= mexp; - b = true; - } - do_if = do_if && !madd.isZero(); - } else if(madd.isZero()) { - if(mpow.isOne()) { - mfacexp += m_one; - mstruct *= mfacexp; - mstruct -= mexp; - mstruct *= x_var; - mstruct.last() ^= mfacexp; - mfacexp ^= Number(-2, 1); - mstruct *= mfacexp; - mstruct.childrenUpdated(); - b = true; - } else if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100)) { - if(mpow.isMinusOne()) { - if(mexp.isOne()) { - MathStructure mmulfac(mmul); - if(!mmul.isOne()) { - mmulfac *= x_var; - mmulfac ^= mfacexp; - mmulfac[1].negate(); - mmulfac *= x_var; - mmulfac.last() ^= mfacexp; - mmulfac.childrenUpdated(true); - } - mfacexp += m_one; - mstruct *= mfacexp; - mstruct.transform(CALCULATOR->f_Ei); - if(!mmul.isOne()) { - mstruct *= mmulfac; - mstruct /= mmul; - } - b = true; - } else { - MathStructure mepow(mstruct); - mfacexp += m_one; - mstruct *= mfacexp; - mstruct /= mexp; - mstruct.transform(CALCULATOR->f_Ei); - mepow.negate(); - mepow += x_var; - mepow.last().transform(CALCULATOR->f_ln); - mepow.last() *= mexp; - mepow *= mfacexp; - mepow /= mexp; - MathStructure memul(CALCULATOR->v_e); - memul ^= mepow; - mstruct *= memul; - mstruct /= mexp; - b = true; - } - } else if(mpow.number().isNegative()) { - if(mexp.isOne()) { - MathStructure mpowp1(mpow); - mpowp1 += m_one; - MathStructure mpowp1n(mpowp1); - mpowp1n.negate(); - MathStructure mterm(mstruct); - mstruct ^= mpowp1; - mstruct *= x_var; - mstruct.last() ^= mfacexp; - if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - mfacexp += m_one; - mstruct *= mfacexp; - mstruct /= mpowp1n; - mterm ^= mpowp1; - mterm *= x_var; - mterm.last() ^= mfacexp; - mterm /= mpowp1n; - mstruct -= mterm; - mstruct.childrenUpdated(true); - b = true; - } - } else { - MathStructure mterm(mstruct); - mstruct ^= mpow; - mstruct.last() += nr_minus_one; - mstruct *= x_var; - mstruct.last() ^= mfacexp; - if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - mstruct *= mpow; - mfacexp += m_one; - mstruct /= mfacexp; - mstruct.negate(); - mstruct *= mexp; - mterm ^= mpow; - mterm *= x_var; - mterm.last() ^= mfacexp; - mterm /= mfacexp; - mstruct += mterm; - mstruct.childrenUpdated(true); - b = true; - } - } - } else if(mfac == x_var && mexp.isOne()) { - if(mpow.isOne()) { - MathStructure mterm2(x_var); - if(!mmul.isOne()) mterm2 *= mmul; - mterm2 += madd; - mterm2.last() *= Number(-2, 1); - mterm2 *= x_var; - if(!mmul.isOne()) mterm2 /= mmul; - mterm2 *= Number(-1, 4); - MathStructure marg(x_var); - if(!mmul.isOne()) marg *= mmul; - marg += madd; - mstruct *= marg; - marg.last() *= nr_minus_one; - mstruct *= marg; - if(!mmul.isOne()) { - mstruct *= mmul; - mstruct.last() ^= Number(-2, 1); - } - mstruct *= nr_half; - mstruct += mterm2; - mstruct.childrenUpdated(true); - b = true; - if(do_if) mif = mterm2; - } - } - } else if(!b_root && mfac.isFunction() && mfac.function() == CALCULATOR->f_ln && mfac.size() == 1 && madd.isZero() && mpow.isOne()) { - MathStructure mexp2, mmul2, madd2; - if(integrate_info(mfac[0], x_var, madd2, mmul2, mexp2) && madd2.isZero()) { - MathStructure mterm2(mfac); - mterm2.negate(); - mterm2 += nr_two; - if(!mexp2.isOne()) { - mterm2.last() *= mexp2; - mterm2.childUpdated(mterm2.size()); - } - if(!mexp.isOne()) mterm2 *= mexp; - mstruct *= mfac; - mstruct.last() -= mexp2; - mstruct.childUpdated(mstruct.size()); - mstruct += mterm2; - mstruct *= x_var; - b = true; - } - } - if(b) { - if(do_if) { - mstruct.transform(CALCULATOR->f_if); - mstruct.insertChild(mif, 1); - mstruct.insertChild(marg, 1); - mstruct.addChild(m_zero); - mstruct[0].transform(COMPARISON_EQUALS, m_zero); - } - return true; - } - } - } else if(mstruct.function() == CALCULATOR->f_lambert_w && (mstruct.size() == 1 || (mstruct.size() == 2 && mstruct[1].isZero()))) { - if(mfac == x_var && mpow.isOne() && mstruct[0] == x_var) { - MathStructure mthis(mstruct); - mstruct ^= nr_two; - mstruct *= nr_two; - mstruct += nr_one; - mstruct *= mthis; - mstruct.last() *= nr_two; - mstruct.last() += nr_minus_one; - mstruct *= x_var; - mstruct.last() ^= nr_two; - mstruct *= mthis; - mstruct.last() ^= Number(-2, 1); - mstruct *= Number(1, 8); - return true; - } else if(mfac.isPower() && mfac[0] == x_var && mfac[1].isMinusOne() && mpow.isOne() && mstruct[0] == x_var) { - MathStructure mthis(mstruct); - mstruct += nr_two; - mstruct *= mthis; - mstruct *= nr_half; - return true; - } else if((mpow.isOne() || (mpow.isNumber() && mpow.number().isTwo())) && mfac.isOne()) { - MathStructure mexp, mmul, madd; - if(integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { - if(mpow.isOne()) { - MathStructure mthis(mstruct); - mstruct ^= nr_two; - mstruct -= mthis; - mstruct += m_one; - mstruct *= mthis[0]; - mstruct /= mthis; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } else { - MathStructure mthis(mstruct); - mstruct ^= nr_three; - mstruct += mthis; - mstruct.last() ^= nr_two; - mstruct.last() *= Number(-2, 1); - mstruct += mthis; - mstruct.last() *= Number(4, 1); - mstruct += Number(-4, 1); - mstruct *= mthis[0]; - mstruct /= mthis; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } - } - } - return false; - } else if(mstruct.function() == CALCULATOR->f_signum && mstruct.size() == 2) { - if(mstruct[0].representsNonComplex(true) && mpow.isNumber() && mpow.number().isRational() && mpow.number().isPositive()) { - MathStructure minteg(x_var); - if(!mfac.isOne()) { - minteg = mfac; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - } - if(!mpow.number().isInteger()) { - MathStructure mmul(-1, 1, 0); - Number nr_frac(mpow.number()); - Number nr_int(mpow.number()); - nr_frac.frac(); - nr_int.trunc(); - mmul ^= nr_frac; - if(nr_int.isEven()) mmul += nr_minus_one; - else mmul += m_one; - mstruct *= mmul; - mstruct -= mmul[0]; - if(nr_int.isEven()) mstruct += nr_minus_one; - else mstruct += m_one; - if(nr_int.isEven()) mstruct.negate(); - mstruct /= nr_two; - } else if(mpow.number().isEven()) { - mstruct ^= nr_two; - mstruct += nr_three; - mstruct *= Number(1, 4); - } - mstruct *= minteg; - return true; - } - } else if(mstruct.function() == CALCULATOR->f_dirac && mstruct.size() == 1 && mstruct[0].representsNonComplex(true)) { - MathStructure mexp, mmul, madd; - if(mpow.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { - if(mfac == x_var && madd.representsNonZero()) { - mstruct.setFunction(CALCULATOR->f_heaviside); - if(!mmul.isOne()) { - mmul ^= nr_two; - mstruct /= mmul; - } - mstruct *= madd; - mstruct.negate(); - return true; - } else if(mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0 && madd.representsNonZero()) { - mstruct.setFunction(CALCULATOR->f_heaviside); - madd.negate(); - madd ^= mfac[1]; - mstruct *= madd; - if(mmul.isOne()) { - mexp = mfac[1]; - mexp += m_one; - mexp.negate(); - mmul ^= mexp; - mstruct *= mmul; - } - return true; - } else if(mfac.isOne()) { - mstruct.setFunction(CALCULATOR->f_heaviside); - if(!mmul.isOne()) mstruct /= mmul; - return true; - } - } - return false; - } else if(mstruct.function() == CALCULATOR->f_arg && mstruct.size() == 1 && mstruct[0].representsNonComplex(true)) { - MathStructure mexp, mmul, madd; - if(mpow.representsPositive() && integrate_info(mstruct[0], x_var, madd, mmul, mexp)) { - MathStructure minteg(x_var); - if(!mfac.isOne()) { - minteg = mfac; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - } - mstruct.setFunction(CALCULATOR->f_signum); - mstruct += nr_minus_one; - mstruct *= CALCULATOR->v_pi; - if(!mpow.isOne()) { - mstruct.last() ^= mpow; - mstruct.childUpdated(mstruct.size()); - } - mstruct *= Number(-1, 2); - mstruct *= minteg; - return true; - } - return false; - } else if(mstruct.function() == CALCULATOR->f_heaviside && mstruct.size() == 1) { - MathStructure mexp, mmul, madd; - if(mpow.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { - if(mfac.isOne()) { - if(mmul.representsNonNegative()) { - MathStructure mfacn(x_var); - if(!madd.isZero()) { - if(!mmul.isOne()) madd /= mmul; - mfacn += madd; - } - mstruct *= mfacn; - return true; - } else if(mmul.representsNegative()) { - if(madd.isZero()) { - mstruct[0] = x_var; - mstruct *= x_var; - mstruct.negate(); - mstruct += x_var; - return true; - } - mstruct.setToChild(1); - mmul.negate(); - madd.negate(); - mstruct /= mmul; - MathStructure mfacn(x_var); - mfacn *= mmul; - mfacn += madd; - mfacn.transform(CALCULATOR->f_heaviside); - mstruct *= mfacn; - mstruct += x_var; - return true; - } - } - } - return false; - } else if(mstruct.function() == CALCULATOR->f_sinc && mstruct.size() == 1) { - MathStructure mexp, mmul, madd; - if(mfac.isOne() && mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-2) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { - if(mpow.isOne()) { - mstruct.setFunction(CALCULATOR->f_Si); - if(!mmul.isOne()) mstruct.divide(mmul); - return true; - } - } - } else if(mstruct.function() == CALCULATOR->f_sin && mstruct.size() == 1) { - MathStructure mexp, mmul, madd; - if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-2) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp, true)) { - if(mfac.isOne() && mexp.isOne()) { - if(mpow.isOne()) { - mstruct.setFunction(CALCULATOR->f_cos); - mstruct.multiply(m_minus_one); - if(!mmul.isOne()) mstruct.divide(mmul); - } else if(mpow.number().isTwo()) { - if(!madd.isZero()) { - mstruct[0] = x_var; - mstruct[0] *= CALCULATOR->getRadUnit(); - } - mstruct[0] *= nr_two; - mstruct /= 4; - if(madd.isZero() && !mmul.isOne()) mstruct /= mmul; - mstruct.negate(); - MathStructure xhalf(x_var); - xhalf *= nr_half; - mstruct += xhalf; - if(!madd.isZero()) { - MathStructure marg(x_var); - if(!mmul.isOne()) marg *= mmul; - marg += madd; - mstruct.replace(x_var, marg); - if(!mmul.isOne()) mstruct.divide(mmul); - } - } else if(mpow.number().isMinusOne()) { - MathStructure mcot(mstruct); - mcot.setFunction(CALCULATOR->f_tan); - mcot.inverse(); - mstruct.inverse(); - mstruct += mcot; - if(!transform_absln(mstruct, use_abs, definite_integral, x_var, eo)) return -1; - if(!mmul.isOne()) mstruct.divide(mmul); - mstruct.negate(); - } else if(mpow.number() == -2) { - mstruct.setFunction(CALCULATOR->f_tan); - mstruct.inverse(); - mstruct.negate(); - if(!mmul.isOne()) mstruct.divide(mmul); - } else { - MathStructure mbak(mstruct); - MathStructure nm1(mpow); - nm1 += nr_minus_one; - mstruct ^= nm1; - MathStructure mcos(mbak); - mcos.setFunction(CALCULATOR->f_cos); - mstruct *= mcos; - mstruct.negate(); - mmul *= mpow; - mstruct /= mmul; - MathStructure minteg(mbak); - MathStructure nm2(mpow); - nm2 += Number(-2, 1); - minteg ^= nm2; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - minteg *= nm1; - minteg /= mpow; - mstruct += minteg; - } - return true; - } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { - MathStructure mfacexp(1, 1, 0); - if(mfac != x_var) mfacexp = mfac[1]; - if(mfacexp.isMinusOne() && !mexp.isZero()) { - if(madd.isZero()) { - if(mpow.isOne()) { - mstruct[0] /= CALCULATOR->getRadUnit(); - mstruct.setFunction(CALCULATOR->f_Si); - if(!mexp.isOne()) mstruct /= mexp; - return true; - } else if(mpow.number().isTwo()) { - mstruct[0] *= nr_two; - mstruct[0] /= CALCULATOR->getRadUnit(); - mstruct.setFunction(CALCULATOR->f_Ci); - if(!mexp.isOne()) mstruct /= mexp; - mstruct.negate(); - mstruct += x_var; - if(!transform_absln(mstruct.last(), use_abs, definite_integral, x_var, eo)) return -1; - mstruct *= nr_half; - return true; - } else if(mpow.number() == 3) { - mstruct[0] /= CALCULATOR->getRadUnit(); - mstruct.setFunction(CALCULATOR->f_Si); - MathStructure mterm2(mstruct); - mstruct[0] *= nr_three; - mterm2 *= Number(-3, 1); - mstruct += mterm2; - if(!mexp.isOne()) mstruct /= mexp; - mstruct *= Number(-1, 4); - return true; - } - } else if(mpow.isOne()) { - MathStructure mterm2; - mstruct = x_var; - if(!mexp.isOne()) mstruct ^= mexp; - if(!mmul.isOne()) mstruct *= mmul; - mstruct.transform(CALCULATOR->f_Si); - if(CALCULATOR->getRadUnit()) madd *= CALCULATOR->getRadUnit(); - mstruct *= MathStructure(CALCULATOR->f_cos, &madd, NULL); - mterm2 = x_var; - if(!mexp.isOne()) mterm2 ^= mexp; - if(!mmul.isOne()) mterm2 *= mmul; - mterm2.transform(CALCULATOR->f_Ci); - mterm2 *= MathStructure(CALCULATOR->f_sin, &madd, NULL); - mstruct += mterm2; - if(!mexp.isOne()) mstruct /= mexp; - return true; - } - } else if(mexp.isOne() && mpow.isOne()) { - if(mfacexp.isOne()) { - MathStructure mterm2(mstruct); - mterm2.setFunction(CALCULATOR->f_cos); - mterm2 *= x_var; - if(!mmul.isOne()) { - mterm2 /= mmul; - mmul ^= nr_two; - mstruct /= mmul; - } - mstruct -= mterm2; - return true; - } else if(mfacexp.isInteger() && mfacexp.number().isPositive() && mfacexp.number().isLessThan(100)) { - mstruct.setFunction(CALCULATOR->f_cos); - MathStructure mterm2(mstruct); - mterm2 *= x_var; - mterm2.last() ^= mfacexp; - mterm2.childUpdated(mterm2.size()); - if(!mmul.isOne()) mterm2 /= mmul; - mstruct *= x_var; - mstruct.last() ^= mfacexp; - mstruct.childUpdated(mstruct.size()); - mstruct.last().last() += nr_minus_one; - if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - mstruct *= mfacexp; - if(!mmul.isOne()) mstruct /= mmul; - mstruct -= mterm2; - return true; - } else if(madd.isZero() && mfacexp.isInteger() && mfacexp.number().isNegative() && mfacexp.number().isGreaterThan(-100)) { - mfacexp += m_one; - MathStructure mterm2(mstruct); - mterm2 *= x_var; - mterm2.last() ^= mfacexp; - mterm2.childUpdated(mterm2.size()); - mterm2 /= mfacexp; - mstruct.setFunction(CALCULATOR->f_cos); - mstruct *= x_var; - mstruct.last() ^= mfacexp; - mstruct.childUpdated(mstruct.size()); - if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - mstruct /= mfacexp; - mstruct.negate(); - if(!mmul.isOne()) mstruct *= mmul; - mstruct += mterm2; - return true; - } - } else if(mexp.isOne() && mpow.number().isTwo()) { - if(mfacexp.isOne()) { - MathStructure mterm2(mstruct); - MathStructure mterm3(x_var); - mterm3 ^= nr_two; - mterm3 *= Number(1, 4); - mterm2[0] *= nr_two; - mterm2 *= x_var; - if(!mmul.isOne()) mterm2 /= mmul; - mterm2 *= Number(-1, 4); - mstruct.setFunction(CALCULATOR->f_cos); - mstruct[0] *= nr_two; - if(!mmul.isOne()) { - mmul ^= nr_two; - mstruct /= mmul; - } - mstruct *= Number(-1, 8); - mstruct += mterm2; - mstruct += mterm3; - mstruct.childrenUpdated(true); - return true; - } else if(mfacexp.number().isTwo()) { - MathStructure mterm2(mstruct); - MathStructure mterm3(x_var); - mterm3 ^= nr_three; - mterm3 *= Number(1, 6); - mterm2[0] *= nr_two; - MathStructure mterm21(1, 8, 0); - if(!mmul.isOne()) { - mterm21 *= mmul; - mterm21.last() ^= Number(-3, 1); - } - MathStructure mterm22(x_var); - mterm22 ^= 2; - if(!mmul.isOne()) mterm22 /= mmul; - mterm22 *= Number(-1, 4); - mterm21 += mterm22; - mterm2 *= mterm21; - mstruct.setFunction(CALCULATOR->f_cos); - mstruct[0] *= nr_two; - mstruct *= x_var; - if(!mmul.isOne()) { - mmul ^= nr_two; - mstruct /= mmul; - } - mstruct *= Number(-1, 4); - mstruct += mterm2; - mstruct += mterm3; - mstruct.childrenUpdated(true); - return true; - } - } - } else if(mexp.isOne() && mfac.isFunction()) { - if(mfac.function() == CALCULATOR->f_sin && mfac.size() == 1 && mpow.isOne()) { - MathStructure mexpf, mmulf, maddf; - if(integrate_info(mfac[0], x_var, maddf, mmulf, mexpf, true) && mexpf.isOne() && mmul != mmulf) { - MathStructure mterm2(mstruct); - mterm2[0] += mfac[0]; - mstruct[0] -= mfac[0]; - MathStructure mden1(mmul); - mden1 -= mmulf; - mden1 *= nr_two; - MathStructure mden2(mmul); - mden2 += mmulf; - mden2 *= nr_two; - mterm2 /= mden2; - mstruct /= mden1; - mstruct -= mterm2; - return true; - } - } else if(mfac.function() == CALCULATOR->f_cos && mfac.size() == 1) { - if(mstruct[0] == mfac[0]) { - UnknownVariable *var = new UnknownVariable("", format_and_print(mstruct)); - MathStructure mtest(var); - if(!mpow.isOne()) mtest ^= mpow; - CALCULATOR->beginTemporaryStopMessages(); - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(mstruct); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(mstruct); - } - if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mtest.replace(var, mstruct); - var->destroy(); - mstruct = mtest; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } else if(mpow.isOne()) { - MathStructure mexpf, mmulf, maddf; - if(integrate_info(mfac[0], x_var, maddf, mmulf, mexpf, true) && mexpf.isOne()) { - if(mmul != mmulf) { - mstruct.setFunction(CALCULATOR->f_cos); - MathStructure mterm2(mstruct); - mterm2[0] += mfac[0]; - mstruct[0] -= mfac[0]; - MathStructure mden1(mmul); - mden1 -= mmulf; - mden1 *= nr_two; - MathStructure mden2(mmul); - mden2 += mmulf; - mden2 *= nr_two; - mterm2 /= mden2; - mstruct /= mden1; - mstruct.negate(); - mstruct -= mterm2; - return true; - } else if(madd == maddf) { - mstruct ^= nr_two; - if(!mmul.isOne()) mstruct /= mmul; - mstruct *= nr_half; - return true; - } else { - MathStructure mterm2(mfac); - mterm2[0].add(mstruct[0]); - mterm2.childUpdated(1); - if(!mmul.isOne()) mterm2 /= mmul; - mterm2 *= Number(-1, 4); - mstruct[0] = maddf; - mstruct[0] -= madd; - mstruct[0] *= CALCULATOR->getRadUnit(); - mstruct.childUpdated(1); - mstruct *= x_var; - mstruct *= Number(-1, 2); - mstruct += mterm2; - return true; - } - } - } - } - } - } - } else if(mstruct.function() == CALCULATOR->f_cos && mstruct.size() == 1) { - MathStructure mexp, mmul, madd; - if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-2) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp, true)) { - if(mfac.isOne() && mexp.isOne()) { - if(mpow.isOne()) { - mstruct.setFunction(CALCULATOR->f_sin); - if(!mmul.isOne()) mstruct.divide(mmul); - } else if(mpow.number().isTwo()) { - mstruct.setFunction(CALCULATOR->f_sin); - if(!madd.isZero()) { - mstruct[0] = x_var; - mstruct[0] *= CALCULATOR->getRadUnit(); - } - mstruct[0] *= nr_two; - mstruct /= 4; - if(madd.isZero() && !mmul.isOne()) mstruct /= mmul; - MathStructure xhalf(x_var); - xhalf *= nr_half; - mstruct += xhalf; - if(!madd.isZero()) { - MathStructure marg(x_var); - if(!mmul.isOne()) marg *= mmul; - marg += madd; - mstruct.replace(x_var, marg); - if(!mmul.isOne()) mstruct.divide(mmul); - } - } else if(mpow.number().isMinusOne()) { - MathStructure mtan(mstruct); - mtan.setFunction(CALCULATOR->f_tan); - mstruct.inverse(); - mstruct += mtan; - if(!transform_absln(mstruct, use_abs, definite_integral, x_var, eo)) return -1; - if(!mmul.isOne()) mstruct.divide(mmul); - } else if(mpow.number() == -2) { - mstruct.setFunction(CALCULATOR->f_tan); - if(!mmul.isOne()) mstruct.divide(mmul); - } else { - MathStructure mbak(mstruct); - MathStructure nm1(mpow); - nm1 += nr_minus_one; - mstruct ^= nm1; - MathStructure msin(mbak); - msin.setFunction(CALCULATOR->f_sin); - mstruct *= msin; - mmul *= mpow; - mstruct /= mmul; - MathStructure minteg(mbak); - MathStructure nm2(mpow); - nm2 += Number(-2, 1); - minteg ^= nm2; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - minteg *= nm1; - minteg /= mpow; - mstruct += minteg; - } - return true; - } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { - MathStructure mfacexp(1, 1, 0); - if(mfac != x_var) mfacexp = mfac[1]; - if(mfacexp.isMinusOne() && !mexp.isZero()) { - if(madd.isZero()) { - if(mpow.isOne()) { - mstruct[0] /= CALCULATOR->getRadUnit(); - mstruct.setFunction(CALCULATOR->f_Ci); - if(!mexp.isOne()) mstruct /= mexp; - return true; - } else if(mpow.number().isTwo()) { - mstruct[0] *= nr_two; - mstruct[0] /= CALCULATOR->getRadUnit(); - mstruct.setFunction(CALCULATOR->f_Ci); - if(!mexp.isOne()) mstruct /= mexp; - mstruct += x_var; - mstruct.last().transform(CALCULATOR->f_ln); - mstruct *= nr_half; - return true; - } else if(mpow.number() == 3) { - mstruct[0] /= CALCULATOR->getRadUnit(); - mstruct.setFunction(CALCULATOR->f_Ci); - MathStructure mterm2(mstruct); - mstruct[0] *= nr_three; - mterm2 *= Number(3, 1); - mstruct += mterm2; - if(!mexp.isOne()) mstruct /= mexp; - mstruct *= Number(1, 4); - return true; - } - } else if(mpow.isOne()) { - MathStructure mterm2; - mstruct = x_var; - if(!mexp.isOne()) mstruct ^= mexp; - if(!mmul.isOne()) mstruct *= mmul; - mstruct.transform(CALCULATOR->f_Ci); - if(CALCULATOR->getRadUnit()) madd *= CALCULATOR->getRadUnit(); - mstruct *= MathStructure(CALCULATOR->f_cos, &madd, NULL); - mterm2 = x_var; - if(!mexp.isOne()) mterm2 ^= mexp; - if(!mmul.isOne()) mterm2 *= mmul; - mterm2.transform(CALCULATOR->f_Si); - mterm2 *= MathStructure(CALCULATOR->f_sin, &madd, NULL); - mstruct -= mterm2; - if(!mexp.isOne()) mstruct /= mexp; - return true; - } - } else if(mexp.isOne() && mpow.isOne()) { - if(mfacexp.isOne()) { - MathStructure mterm2(mstruct); - mterm2.setFunction(CALCULATOR->f_sin); - mterm2 *= x_var; - if(!mmul.isOne()) { - mterm2 /= mmul; - mmul ^= nr_two; - mstruct /= mmul; - } - mstruct += mterm2; - return true; - } else if(mfacexp.isInteger() && mfacexp.number().isPositive() && mfacexp.number().isLessThan(100)) { - mstruct.setFunction(CALCULATOR->f_sin); - MathStructure mterm2(mstruct); - mterm2 *= x_var; - mterm2.last() ^= mfacexp; - if(!mmul.isOne()) mterm2 /= mmul; - mstruct *= x_var; - mstruct.last() ^= mfacexp; - mstruct.last().last() += nr_minus_one; - if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - mstruct *= mfacexp; - if(!mmul.isOne()) mstruct /= mmul; - mstruct.negate(); - mstruct += mterm2; - mstruct.childrenUpdated(true); - return true; - } else if(madd.isZero() && mfacexp.isInteger() && mfacexp.number().isNegative() && mfacexp.number().isGreaterThan(-100)) { - mfacexp += m_one; - MathStructure mterm2(mstruct); - mterm2 *= x_var; - mterm2.last() ^= mfacexp; - mterm2.childUpdated(mterm2.size()); - mterm2 /= mfacexp; - mstruct.setFunction(CALCULATOR->f_sin); - mstruct *= x_var; - mstruct.last() ^= mfacexp; - mstruct.childUpdated(mstruct.size()); - if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - mstruct /= mfacexp; - if(!mmul.isOne()) mstruct *= mmul; - mstruct += mterm2; - return true; - } - } else if(mexp.isOne() && mpow.number().isTwo()) { - if(mfacexp.isOne()) { - MathStructure mterm2(mstruct); - mterm2.setFunction(CALCULATOR->f_sin); - MathStructure mterm3(x_var); - mterm3 ^= nr_two; - mterm3 *= Number(1, 4); - mterm2[0] *= nr_two; - mterm2 *= x_var; - if(!mmul.isOne()) mterm2 /= mmul; - mterm2 *= Number(1, 4); - mstruct[0] *= nr_two; - if(!mmul.isOne()) { - mmul ^= nr_two; - mstruct /= mmul; - } - mstruct *= Number(1, 8); - mstruct += mterm2; - mstruct += mterm3; - return true; - } else if(mfacexp.number().isTwo()) { - MathStructure mterm2(mstruct); - mterm2.setFunction(CALCULATOR->f_sin); - MathStructure mterm3(x_var); - mterm3 ^= nr_three; - mterm3 *= Number(1, 6); - mterm2[0] *= nr_two; - MathStructure mterm21(-1, 8, 0); - if(!mmul.isOne()) { - mterm21 *= mmul; - mterm21.last() ^= Number(-3, 1); - } - MathStructure mterm22(x_var); - mterm22 ^= 2; - if(!mmul.isOne()) mterm22 /= mmul; - mterm22 *= Number(1, 4); - mterm21 += mterm22; - mterm2 *= mterm21; - mstruct[0] *= nr_two; - mstruct *= x_var; - if(!mmul.isOne()) { - mmul ^= nr_two; - mstruct /= mmul; - } - mstruct *= Number(1, 4); - mstruct += mterm2; - mstruct += mterm3; - mstruct.childrenUpdated(true); - return true; - } - } - } else if(mexp.isOne() && mfac.isFunction()) { - if(mfac.function() == CALCULATOR->f_cos && mfac.size() == 1 && mpow.isOne()) { - MathStructure mexpf, mmulf, maddf; - if(integrate_info(mfac[0], x_var, maddf, mmulf, mexpf, true) && mexpf.isOne() && mmulf != mmul) { - mstruct.setFunction(CALCULATOR->f_sin); - MathStructure mterm2(mstruct); - mterm2[0] += mfac[0]; - mstruct[0] -= mfac[0]; - MathStructure mden1(mmul); - mden1 -= mmulf; - mden1 *= nr_two; - MathStructure mden2(mmul); - mden2 += mmulf; - mden2 *= nr_two; - mterm2 /= mden2; - mstruct /= mden1; - mstruct += mterm2; - mstruct.childrenUpdated(true); - return true; - } - } else if(mfac.function() == CALCULATOR->f_sin && mfac.size() == 1) { - if(mstruct[0] == mfac[0]) { - UnknownVariable *var = new UnknownVariable("", format_and_print(mstruct)); - MathStructure mtest(var); - if(!mpow.isOne()) mtest ^= mpow; - mtest.negate(); - CALCULATOR->beginTemporaryStopMessages(); - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(mstruct); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(mstruct); - } - if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mtest.replace(var, mstruct); - var->destroy(); - mstruct = mtest; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } - } - } - } - } else if(mstruct.function() == CALCULATOR->f_tan && mstruct.size() == 1) { - MathStructure mexp, mmul, madd; - if(mfac.isOne() && mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-1) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp, true) && mexp.isOne() && (!definite_integral || mstruct[0].representsNonComplex(true))) { - if(mpow.isOne()) { - mstruct.setFunction(CALCULATOR->f_cos); - if(!transform_absln(mstruct, use_abs, definite_integral, x_var, eo)) return -1; - mstruct.negate(); - if(!mmul.isOne()) mstruct.divide(mmul); - } else if(mpow.number().isMinusOne()) { - mstruct.setFunction(CALCULATOR->f_sin); - if(!transform_absln(mstruct, use_abs, definite_integral, x_var, eo)) return -1; - if(!mmul.isOne()) mstruct.divide(mmul); - } else if(mpow.number().isTwo()) { - MathStructure marg(x_var); - if(!mmul.isOne()) marg *= mmul; - marg += madd; - mstruct -= marg; - if(!mmul.isOne()) mstruct.divide(mmul); - } else { - MathStructure minteg(mstruct); - MathStructure nm1(mpow); - nm1 += nr_minus_one; - mstruct ^= nm1; - mmul *= nm1; - mstruct /= mmul; - MathStructure nm2(mpow); - nm2 += Number(-2, 1); - minteg ^= nm2; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - mstruct -= minteg; - } - return true; - } - } else if(mstruct.function() == CALCULATOR->f_asin && mstruct.size() == 1) { - MathStructure mexp, mmul, madd; - if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp)) { - if(definite_integral && !madd.isZero() && (!mmul.representsNonComplex(true) || !mexp.representsInteger()) && COMPARISON_MIGHT_BE_EQUAL(x_var.compare(m_zero))) return false; - if(mexp.isOne() && mfac.isOne()) { - if(mpow.isOne()) { - MathStructure marg(mstruct[0]); - if(!madd.isZero()) mstruct[0] = x_var; - mstruct.multiply(x_var); - MathStructure mterm(x_var); - mterm ^= nr_two; - if(madd.isZero() && !mmul.isOne()) { - MathStructure mmul2(mmul); - mmul2 ^= nr_two; - mterm *= mmul2; - } - mterm.negate(); - mterm += m_one; - mterm ^= nr_half; - if(madd.isZero() && !mmul.isOne()) mterm /= mmul; - mstruct.add(mterm); - if(!madd.isZero()) { - mstruct.replace(x_var, marg); - if(!mmul.isOne()) mstruct.divide(mmul); - } - return true; - } else if(mpow.isMinusOne()) { - mstruct.transform(CALCULATOR->f_Ci); - if(!mmul.isOne()) mstruct /= mmul; - return true; - } else if(mpow.number() == -2) { - MathStructure mterm(mstruct[0]); - mterm ^= nr_two; - mterm.negate(); - mterm += m_one; - mterm ^= nr_half; - mterm /= mstruct; - mstruct.transform(CALCULATOR->f_Si); - mstruct += mterm; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } else if(mpow.number().isPositive() && madd.isZero()) { - MathStructure mpowm1(mpow); - if(mpow == nr_two) mpowm1.set(1, 1, 0, true); - else mpowm1 += nr_minus_one; - MathStructure mterm(x_var); - mterm ^= nr_two; - if(!mmul.isOne()) { - mterm *= mmul; - mterm.last() ^= nr_two; - } - mterm.negate(); - mterm += m_one; - mterm ^= nr_half; - mterm *= mstruct; - if(!mpowm1.isOne()) mterm.last() ^= mpowm1; - mterm *= mpow; - if(!mmul.isOne()) mterm /= mmul; - MathStructure minteg; - if(mpowm1.isOne()) { - minteg = x_var; - } else { - minteg = mstruct; - minteg ^= mpow; - minteg.last() += Number(-2, 1); - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - } - minteg *= mpow; - if(!mpowm1.isOne()) minteg *= mpowm1; - mstruct ^= mpow; - mstruct *= x_var; - mstruct += mterm; - mstruct -= minteg; - return true; - } else if(madd.isZero()) { - MathStructure mpowp1(mpow); - mpowp1 += m_one; - MathStructure mpowp2(mpow); - mpowp2 += nr_two; - MathStructure mterm(x_var); - mterm ^= nr_two; - if(!mmul.isOne()) { - mterm *= mmul; - mterm.last() ^= nr_two; - } - mterm.negate(); - mterm += m_one; - mterm ^= nr_half; - mterm *= mstruct; - mterm.last() ^= mpowp1; - mterm /= mpowp1; - if(!mmul.isOne()) mterm /= mmul; - MathStructure minteg(mstruct); - minteg ^= mpowp2; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - minteg /= mpowp1; - minteg /= mpowp2; - mstruct ^= mpowp2; - mstruct *= x_var; - mstruct /= mpowp1; - mstruct /= mpowp2; - mstruct += mterm; - mstruct -= minteg; - return true; - } - } else if(mexp.isOne() && (mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0))) { - MathStructure mfacexp(1, 1, 0); - if(mfac != x_var) mfacexp = mfac[1]; - if(mpow.isOne()) { - if(mfacexp.isOne()) { - MathStructure mterm2(mstruct[0]); - mterm2 ^= nr_two; - mterm2.negate(); - mterm2 += m_one; - mterm2 ^= nr_half; - MathStructure mfac2(x_var); - if(!mmul.isOne()) mfac2 *= mmul; - if(!madd.isZero()) { - mfac2 += madd; - mfac2.last() *= Number(-3, 1); - } - mterm2 *= mfac2; - MathStructure mfac1(x_var); - mfac1 ^= nr_two; - if(!mmul.isOne()) { - mfac1 *= mmul; - mfac1.last() ^= nr_two; - } - mfac1 *= nr_two; - if(!madd.isZero()) { - mfac1 += madd; - mfac1.last() ^= nr_two; - mfac1.last() *= Number(-2, 1); - } - mfac1 += nr_minus_one; - mstruct *= mfac1; - mstruct += mterm2; - if(!mmul.isOne()) { - mstruct *= mmul; - mstruct.last() ^= Number(-2, 1); - } - mstruct *= Number(1, 4); - return true; - } else if(mfacexp == nr_two && madd.isZero()) { - mstruct *= x_var; - mstruct.last() ^= nr_three; - mstruct *= Number(1, 3); - MathStructure mterm(x_var); - mterm ^= nr_two; - if(!mmul.isOne()) { - mterm *= mmul; - mterm.last() ^= nr_two; - } - MathStructure mfac1(mterm); - mfac1 += nr_two; - mterm.negate(); - mterm += m_one; - mterm ^= nr_half; - mterm *= mfac1; - if(!mmul.isOne()) { - mmul ^= Number(-3, 1); - mterm *= mmul; - } - mterm *= Number(1, 9); - mstruct += mterm; - return true; - } else if(!mfacexp.isMinusOne() && madd.isZero()) { - mfacexp += m_one; - MathStructure minteg(x_var); - minteg ^= nr_two; - if(!mmul.isOne()) { - minteg *= mmul; - minteg.last() ^= nr_two; - } - minteg.negate(); - minteg += m_one; - minteg ^= Number(-1, 2); - minteg *= x_var; - minteg.last() ^= mfacexp; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - if(minteg.containsFunction(CALCULATOR->f_integrate) <= 0) { - if(!mmul.isOne()) minteg *= mmul; - minteg /= mfacexp; - mstruct *= x_var; - mstruct.last() ^= mfacexp; - mstruct /= mfacexp; - mstruct -= minteg; - return true; - } - } - } - } - } - } else if(mstruct.function() == CALCULATOR->f_acos && mstruct.size() == 1) { - MathStructure mexp, mmul, madd; - if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp)) { - if(definite_integral && !madd.isZero() && (!mmul.representsNonComplex(true) || !mexp.representsInteger()) && COMPARISON_MIGHT_BE_EQUAL(x_var.compare(m_zero))) return false; - if(mexp.isOne() && mfac.isOne()) { - if(mpow.isOne()) { - MathStructure marg(mstruct[0]); - if(!madd.isZero()) mstruct[0] = x_var; - mstruct.multiply(x_var); - MathStructure mterm(x_var); - mterm ^= nr_two; - if(madd.isZero() && !mmul.isOne()) { - MathStructure mmul2(mmul); - mmul2 ^= nr_two; - mterm *= mmul2; - } - mterm.negate(); - mterm += m_one; - mterm ^= nr_half; - if(madd.isZero() && !mmul.isOne()) mterm /= mmul; - mstruct.subtract(mterm); - if(!madd.isZero()) { - mstruct.replace(x_var, marg); - if(!mmul.isOne()) mstruct.divide(mmul); - } - return true; - } else if(mpow.isMinusOne()) { - mstruct.transform(CALCULATOR->f_Si); - mstruct.negate(); - if(!mmul.isOne()) mstruct /= mmul; - return true; - } else if(mpow.number() == -2) { - MathStructure mterm(mstruct[0]); - mterm ^= nr_two; - mterm.negate(); - mterm += m_one; - mterm ^= nr_half; - mterm /= mstruct; - mstruct.transform(CALCULATOR->f_Ci); - mstruct.negate(); - mstruct += mterm; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } else if(mpow.number().isPositive() && madd.isZero()) { - MathStructure mpowm1(mpow); - if(mpow == nr_two) mpowm1.set(1, 1, 0, true); - else mpowm1 += nr_minus_one; - MathStructure mterm(x_var); - mterm ^= nr_two; - if(!mmul.isOne()) { - mterm *= mmul; - mterm.last() ^= nr_two; - } - mterm.negate(); - mterm += m_one; - mterm ^= nr_half; - mterm *= mstruct; - if(!mpowm1.isOne()) mterm.last() ^= mpowm1; - mterm *= mpow; - if(!mmul.isOne()) mterm /= mmul; - MathStructure minteg; - if(mpowm1.isOne()) { - minteg = x_var; - } else { - minteg = mstruct; - minteg ^= mpow; - minteg.last() += Number(-2, 1); - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - } - minteg *= mpow; - if(!mpowm1.isOne()) minteg *= mpowm1; - mstruct ^= mpow; - mstruct *= x_var; - mstruct -= mterm; - mstruct -= minteg; - return true; - } else if(madd.isZero()) { - MathStructure mpowp1(mpow); - mpowp1 += m_one; - MathStructure mpowp2(mpow); - mpowp2 += nr_two; - MathStructure mterm(x_var); - mterm ^= nr_two; - if(!mmul.isOne()) { - mterm *= mmul; - mterm.last() ^= nr_two; - } - mterm.negate(); - mterm += m_one; - mterm ^= nr_half; - mterm *= mstruct; - mterm.last() ^= mpowp1; - mterm /= mpowp1; - if(!mmul.isOne()) mterm /= mmul; - MathStructure minteg(mstruct); - minteg ^= mpowp2; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - minteg /= mpowp1; - minteg /= mpowp2; - mstruct ^= mpowp2; - mstruct *= x_var; - mstruct /= mpowp1; - mstruct /= mpowp2; - mstruct -= mterm; - mstruct -= minteg; - return true; - } - } else if(mexp.isOne() && (mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0))) { - MathStructure mfacexp(1, 1, 0); - if(mfac != x_var) mfacexp = mfac[1]; - if(mpow.isOne()) { - if(mfacexp.isOne()) { - MathStructure mterm2(mstruct[0]); - MathStructure mterm3(mstruct); - mterm2 ^= nr_two; - mterm2.negate(); - mterm2 += m_one; - mterm2 ^= nr_half; - MathStructure mfac2(x_var); - if(!mmul.isOne()) { - mfac2 *= mmul; - } - mfac2.negate(); - if(!madd.isZero()) { - mfac2 += madd; - mfac2.last() *= nr_three; - } - mterm2 *= mfac2; - mterm3.setFunction(CALCULATOR->f_asin); - MathStructure mfac3(1, 1, 0); - if(!madd.isZero()) { - mfac3 += madd; - mfac3.last() ^= nr_two; - mfac3.last() *= nr_two; - } - mterm3 *= mfac3; - mstruct *= x_var; - mstruct.last() ^= nr_two; - if(!mmul.isOne()) { - mstruct *= mmul; - mstruct.last() ^= nr_two; - } - mstruct *= nr_two; - mstruct += mterm2; - mstruct += mterm3; - if(!mmul.isOne()) { - mstruct *= mmul; - mstruct.last() ^= Number(-2, 1); - } - mstruct *= Number(1, 4); - return true; - } else if(mfacexp == nr_two && madd.isZero()) { - mstruct *= x_var; - mstruct.last() ^= nr_three; - mstruct *= Number(1, 3); - MathStructure mterm(x_var); - mterm ^= nr_two; - if(!mmul.isOne()) { - mterm *= mmul; - mterm.last() ^= nr_two; - } - MathStructure mfac1(mterm); - mfac1 += nr_two; - mterm.negate(); - mterm += m_one; - mterm ^= nr_half; - mterm *= mfac1; - if(!mmul.isOne()) { - mmul ^= Number(-3, 1); - mterm *= mmul; - } - mterm *= Number(-1, 9); - mstruct += mterm; - return true; - } else if(!mfacexp.isMinusOne() && madd.isZero()) { - mfacexp += m_one; - MathStructure minteg(x_var); - minteg ^= nr_two; - if(!mmul.isOne()) { - minteg *= mmul; - minteg.last() ^= nr_two; - } - minteg.negate(); - minteg += m_one; - minteg ^= Number(-1, 2); - minteg *= x_var; - minteg.last() ^= mfacexp; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - if(minteg.containsFunction(CALCULATOR->f_integrate) <= 0) { - if(!mmul.isOne()) minteg *= mmul; - minteg /= mfacexp; - mstruct *= x_var; - mstruct.last() ^= mfacexp; - mstruct /= mfacexp; - mstruct += minteg; - return true; - } - } - } - } - } - } else if(mstruct.function() == CALCULATOR->f_atan && mstruct.size() == 1) { - MathStructure mexp, mmul, madd; - if(mpow.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && (!definite_integral || x_var.representsNonZero(true) || madd.representsReal(true))) { - if(!mexp.isOne()) { - if(mexp.isMinusOne() && mfac.isOne() && madd.isZero()) { - mstruct *= x_var; - MathStructure mterm(x_var); - mterm ^= nr_two; - mterm += mmul; - if(!mmul.isOne()) mterm.last() ^= nr_two; - mterm.transform(CALCULATOR->f_ln); - if(!mmul.isOne()) mterm *= mmul; - mterm *= nr_half; - mstruct += mterm; - return true; - } - } else if(mfac.isOne()) { - MathStructure marg(mstruct[0]); - mstruct.multiply(marg); - MathStructure mterm(marg); - mterm ^= nr_two; - mterm += m_one; - if(!transform_absln(mterm, use_abs, definite_integral, x_var, eo)) return -1; - mterm *= Number(-1, 2); - mstruct += mterm; - if(!mmul.isOne()) mstruct.divide(mmul); - return true; - } else if(madd.isZero() && (mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0))) { - MathStructure mfacexp(1, 1, 0); - if(mfac != x_var) mfacexp = mfac[1]; - if(mfacexp.isMinusOne()) { - mstruct.setFunction(CALCULATOR->f_Li); - mstruct.insertChild(nr_two, 1); - MathStructure mterm(mstruct); - mstruct[1] *= nr_minus_i; - mterm[1] *= nr_one_i; - mterm.negate(); - mstruct += mterm; - mstruct *= nr_one_i; - mstruct *= nr_half; - return true; - } else if(mfacexp.isOne()) { - MathStructure mterm1(x_var); - mterm1 ^= nr_two; - mterm1 *= mstruct; - mterm1 *= nr_half; - MathStructure mterm2(x_var); - if(!mmul.isOne()) mterm2 /= mmul; - mterm2 *= nr_minus_half; - if(!mmul.isOne()) {mstruct *= mmul; mstruct.last() ^= Number(-2, 1);} - mstruct *= nr_half; - mstruct += mterm1; - mstruct += mterm2; - return true; - } else { - mfacexp += m_one; - MathStructure mxexp(x_var); - mxexp ^= mfacexp; - MathStructure minteg(x_var); - minteg ^= nr_two; - if(!mmul.isOne()) {minteg *= mmul; minteg.last() ^= nr_two;} - minteg += m_one; - if(!definite_integral || COMPARISON_IS_NOT_EQUAL(minteg.compare(m_zero))) { - minteg ^= nr_minus_one; - minteg *= mxexp; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - minteg /= mfacexp; - if(!mmul.isOne()) minteg *= mmul; - mstruct *= mxexp; - mstruct /= mfacexp; - mstruct -= minteg; - return true; - } - } - } - } - } else if(mstruct.function() == CALCULATOR->f_sinh && mstruct.size() == 1) { - if(mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_ln && mstruct[0].size() == 1 && (!definite_integral || COMPARISON_IS_NOT_EQUAL(mstruct[0][0].compare(m_zero)))) { - MathStructure mtest(mstruct[0][0]); - mtest *= Number(-2, 1); - mtest.inverse(); - mtest.add(mstruct[0][0]); - mtest.last() *= nr_half; - if(!mpow.isOne()) mtest ^= mpow; - if(!mfac.isOne()) mtest *= mfac; - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mstruct.set(mtest, true); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - } - MathStructure mexp, mmul, madd; - if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp)) { - if(mfac.isOne() && mexp.isOne()) { - if(mpow.isOne()) { - mstruct.setFunction(CALCULATOR->f_cosh); - if(!mmul.isOne()) mstruct.divide(mmul); - } else if(mpow.number().isTwo()) { - MathStructure marg(mstruct[0]); - if(!madd.isZero()) mstruct[0] = x_var; - mstruct[0] *= nr_two; - mstruct /= 4; - if(madd.isZero() && !mmul.isOne()) mstruct /= mmul; - MathStructure xhalf(x_var); - xhalf *= nr_half; - mstruct -= xhalf; - if(!madd.isZero()) { - mstruct.replace(x_var, marg); - if(!mmul.isOne()) mstruct.divide(mmul); - } - } else if(mpow.number().isMinusOne()) { - mstruct.setFunction(CALCULATOR->f_tanh); - mstruct[0] *= nr_half; - if(!transform_absln(mstruct, use_abs, definite_integral, x_var, eo)) return -1; - if(!mmul.isOne()) mstruct.divide(mmul); - } else if(mpow.number().isPositive()) { - MathStructure mbak(mstruct); - MathStructure nm1(mpow); - nm1 += nr_minus_one; - mstruct ^= nm1; - MathStructure mcos(mbak); - mcos.setFunction(CALCULATOR->f_cosh); - mstruct *= mcos; - mmul *= mpow; - mstruct /= mmul; - MathStructure minteg(mbak); - MathStructure nm2(mpow); - nm2 += Number(-2, 1); - minteg ^= nm2; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - minteg *= nm1; - minteg /= mpow; - mstruct -= minteg; - } else { - MathStructure mbak(mstruct); - MathStructure np1(mpow); - np1 += m_one; - MathStructure np2(mpow); - np2 += nr_two; - mstruct ^= np1; - MathStructure mcos(mbak); - mcos.setFunction(CALCULATOR->f_cosh); - mstruct *= mcos; - mstruct /= np1; - if(!mmul.isOne()) mstruct /= mmul; - MathStructure minteg(mbak); - minteg ^= np2; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - minteg *= np2; - minteg /= np1; - mstruct -= minteg; - } - return true; - } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { - MathStructure mfacexp(1, 1, 0); - if(mfac != x_var) mfacexp = mfac[1]; - if(mfacexp.isMinusOne() && !mexp.isZero()) { - if(madd.isZero()) { - if(mpow.isOne()) { - mstruct.setFunction(CALCULATOR->f_Shi); - if(!mexp.isOne()) mstruct /= mexp; - return true; - } else if(mpow.number().isTwo()) { - mstruct[0] *= nr_two; - mstruct.setFunction(CALCULATOR->f_Chi); - if(!mexp.isOne()) mstruct /= mexp; - mstruct += x_var; - mstruct.last().transform(CALCULATOR->f_ln); - mstruct.last().negate(); - mstruct *= nr_half; - return true; - } else if(mpow.number() == 3) { - mstruct.setFunction(CALCULATOR->f_Shi); - MathStructure mterm2(mstruct); - mstruct[0] *= nr_three; - mterm2 *= Number(-3, 1); - mstruct += mterm2; - if(!mexp.isOne()) mstruct /= mexp; - mstruct *= Number(1, 4); - return true; - } - } else if(mpow.isOne()) { - MathStructure mterm2; - mstruct = x_var; - if(!mexp.isOne()) mstruct ^= mexp; - if(!mmul.isOne()) mstruct *= mmul; - mstruct.transform(CALCULATOR->f_Shi); - mstruct *= MathStructure(CALCULATOR->f_cosh, &madd, NULL); - mterm2 = x_var; - if(!mexp.isOne()) mterm2 ^= mexp; - if(!mmul.isOne()) mterm2 *= mmul; - mterm2.transform(CALCULATOR->f_Chi); - mterm2 *= MathStructure(CALCULATOR->f_sinh, &madd, NULL); - mstruct += mterm2; - if(!mexp.isOne()) mstruct /= mexp; - return true; - } - } else if(mexp.isOne() && mpow.isOne()) { - if(mfacexp.isOne()) { - MathStructure mterm2(mstruct); - mterm2.setFunction(CALCULATOR->f_cosh); - mterm2 *= x_var; - if(!mmul.isOne()) { - mterm2 /= mmul; - mmul ^= nr_two; - mstruct /= mmul; - } - mstruct.negate(); - mstruct += mterm2; - return true; - } else if(mfacexp.isInteger() && mfacexp.number().isPositive() && mfacexp.number().isLessThan(100)) { - mstruct.setFunction(CALCULATOR->f_cosh); - MathStructure mterm2(mstruct); - mterm2 *= x_var; - mterm2.last() ^= mfacexp; - if(!mmul.isOne()) mterm2 /= mmul; - mstruct *= x_var; - mstruct.last() ^= mfacexp; - mstruct.last().last() += nr_minus_one; - if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - mstruct *= mfacexp; - if(!mmul.isOne()) mstruct /= mmul; - mstruct.negate(); - mstruct += mterm2; - mstruct.childrenUpdated(true); - return true; - } else if(madd.isZero() && mfacexp.isInteger() && mfacexp.number().isNegative() && mfacexp.number().isGreaterThan(-100)) { - mfacexp += m_one; - MathStructure mterm2(mstruct); - mterm2 *= x_var; - mterm2.last() ^= mfacexp; - mterm2.childUpdated(mterm2.size()); - mterm2 /= mfacexp; - mstruct.setFunction(CALCULATOR->f_cosh); - mstruct *= x_var; - mstruct.last() ^= mfacexp; - mstruct.childUpdated(mstruct.size()); - if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - mstruct /= mfacexp; - mstruct.negate(); - if(!mmul.isOne()) mstruct *= mmul; - mstruct += mterm2; - return true; - } - } - } else if(mfac.isFunction() && mexp.isOne()) { - if(mfac.function() == CALCULATOR->f_sinh && mfac.size() == 1 && mpow.isOne()) { - MathStructure mexpf, mmulf, maddf; - if(integrate_info(mfac[0], x_var, maddf, mmulf, mexpf) && mexpf.isOne() && mmul != mmulf) { - MathStructure mterm2(mstruct); - mterm2[0] += mfac[0]; - mstruct[0] -= mfac[0]; - MathStructure mden1(mmul); - mden1 -= mmulf; - mden1 *= nr_two; - MathStructure mden2(mmul); - mden2 += mmulf; - mden2 *= nr_two; - mterm2 /= mden2; - mstruct /= mden1; - mstruct.negate(); - mstruct += mterm2; - return true; - } - } else if(mfac.function() == CALCULATOR->f_cosh && mfac.size() == 1) { - if(mstruct[0] == mfac[0]) { - UnknownVariable *var = new UnknownVariable("", format_and_print(mstruct)); - MathStructure mtest(var); - if(!mpow.isOne()) mtest ^= mpow; - CALCULATOR->beginTemporaryStopMessages(); - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(mstruct); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(mstruct); - } - if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mtest.replace(var, mstruct); - var->destroy(); - mstruct = mtest; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } - } - } - } - } else if(mstruct.function() == CALCULATOR->f_cosh && mstruct.size() == 1) { - if(mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_ln && mstruct[0].size() == 1 && (!definite_integral || COMPARISON_IS_NOT_EQUAL(mstruct[0][0].compare(m_zero)))) { - MathStructure mtest(mstruct[0][0]); - mtest *= nr_two; - mtest.inverse(); - mtest.add(mstruct[0][0]); - mtest.last() *= nr_half; - if(!mpow.isOne()) mtest ^= mpow; - if(!mfac.isOne()) mtest *= mfac; - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mstruct.set(mtest, true); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - } - MathStructure mexp, mmul, madd; - if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp)) { - if(mfac.isOne() && mexp.isOne()) { - if(mpow.isOne()) { - mstruct.setFunction(CALCULATOR->f_sinh); - if(!mmul.isOne()) mstruct.divide(mmul); - return true; - } else if(mpow.number().isTwo()) { - MathStructure marg(mstruct[0]); - if(!madd.isZero()) mstruct[0] = x_var; - mstruct.setFunction(CALCULATOR->f_sinh); - mstruct[0] *= nr_two; - mstruct /= 4; - if(madd.isZero() && !mmul.isOne()) mstruct /= mmul; - MathStructure xhalf(x_var); - xhalf *= nr_half; - mstruct += xhalf; - if(!madd.isZero()) { - mstruct.replace(x_var, marg); - if(!mmul.isOne()) mstruct.divide(mmul); - } - return true; - } else if(mpow.number().isMinusOne()) { - mstruct.setFunction(CALCULATOR->f_sinh); - mstruct.transform(STRUCT_FUNCTION); - mstruct.setFunction(CALCULATOR->f_atan); - if(!mmul.isOne()) mstruct.divide(mmul); - return true; - } else if(mpow.number().isPositive()) { - MathStructure mbak(mstruct); - MathStructure nm1(mpow); - nm1 += nr_minus_one; - mstruct ^= nm1; - MathStructure msin(mbak); - msin.setFunction(CALCULATOR->f_sinh); - mstruct *= msin; - mmul *= mpow; - mstruct /= mmul; - MathStructure minteg(mbak); - MathStructure nm2(mpow); - nm2 += Number(-2, 1); - minteg ^= nm2; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - minteg *= nm1; - minteg /= mpow; - mstruct += minteg; - return true; - } else { - MathStructure mbak(mstruct); - MathStructure np1(mpow); - np1 += m_one; - MathStructure np2(mpow); - np2 += nr_two; - mstruct ^= np1; - MathStructure mcos(mbak); - mcos.setFunction(CALCULATOR->f_sinh); - mstruct *= mcos; - mstruct /= np1; - if(!mmul.isOne()) mstruct /= mmul; - mstruct.negate(); - MathStructure minteg(mbak); - minteg ^= np2; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - minteg *= np2; - minteg /= np1; - mstruct += minteg; - return true; - } - } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { - MathStructure mfacexp(1, 1, 0); - if(mfac != x_var) mfacexp = mfac[1]; - if(mfacexp.isMinusOne() && !mexp.isZero()) { - if(madd.isZero()) { - if(mpow.isOne()) { - mstruct.setFunction(CALCULATOR->f_Chi); - if(!mexp.isOne()) mstruct /= mexp; - return true; - } else if(mpow.number().isTwo()) { - mstruct[0] *= nr_two; - mstruct.setFunction(CALCULATOR->f_Chi); - if(!mexp.isOne()) mstruct /= mexp; - mstruct += x_var; - mstruct.last().transform(CALCULATOR->f_ln); - mstruct *= nr_half; - return true; - } else if(mpow.number() == 3) { - mstruct.setFunction(CALCULATOR->f_Chi); - MathStructure mterm2(mstruct); - mstruct[0] *= nr_three; - mterm2 *= nr_three; - mstruct += mterm2; - if(!mexp.isOne()) mstruct /= mexp; - mstruct *= Number(1, 4); - return true; - } - } else if(mpow.isOne()) { - MathStructure mterm2; - mstruct = x_var; - if(!mexp.isOne()) mstruct ^= mexp; - if(!mmul.isOne()) mstruct *= mmul; - mstruct.transform(CALCULATOR->f_Shi); - mstruct *= MathStructure(CALCULATOR->f_sinh, &madd, NULL); - mterm2 = x_var; - if(!mexp.isOne()) mterm2 ^= mexp; - if(!mmul.isOne()) mterm2 *= mmul; - mterm2.transform(CALCULATOR->f_Chi); - mterm2 *= MathStructure(CALCULATOR->f_cosh, &madd, NULL); - mstruct += mterm2; - if(!mexp.isOne()) mstruct /= mexp; - return true; - } - } else if(mexp.isOne() && mpow.isOne()) { - if(mfacexp.isOne()) { - MathStructure mterm2(mstruct); - mterm2.setFunction(CALCULATOR->f_sinh); - mterm2 *= x_var; - if(!mmul.isOne()) { - mterm2 /= mmul; - mmul ^= nr_two; - mstruct /= mmul; - } - mstruct.negate(); - mstruct += mterm2; - return true; - } else if(mfacexp.isInteger() && mfacexp.number().isPositive() && mfacexp.number().isLessThan(100)) { - mstruct.setFunction(CALCULATOR->f_sinh); - MathStructure mterm2(mstruct); - mterm2 *= x_var; - mterm2.last() ^= mfacexp; - if(!mmul.isOne()) mterm2 /= mmul; - mstruct *= x_var; - mstruct.last() ^= mfacexp; - mstruct.last().last() += nr_minus_one; - if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - mstruct *= mfacexp; - if(!mmul.isOne()) mstruct /= mmul; - mstruct.negate(); - mstruct += mterm2; - mstruct.childrenUpdated(true); - return true; - } else if(madd.isZero() && mfacexp.isInteger() && mfacexp.number().isNegative() && mfacexp.number().isGreaterThan(-100)) { - mfacexp += m_one; - MathStructure mterm2(mstruct); - mterm2 *= x_var; - mterm2.last() ^= mfacexp; - mterm2.childUpdated(mterm2.size()); - mterm2 /= mfacexp; - mstruct.setFunction(CALCULATOR->f_sinh); - mstruct *= x_var; - mstruct.last() ^= mfacexp; - mstruct.childUpdated(mstruct.size()); - if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - mstruct /= mfacexp; - mstruct.negate(); - if(!mmul.isOne()) mstruct *= mmul; - mstruct += mterm2; - return true; - } - } - } else if(mfac.isFunction() && mexp.isOne()) { - if(mfac.function() == CALCULATOR->f_cosh && mfac.size() == 1 && mpow.isOne()) { - MathStructure mexpf, mmulf, maddf; - if(integrate_info(mfac[0], x_var, maddf, mmulf, mexpf) && mexpf.isOne() && mmulf != mmul) { - mstruct.setFunction(CALCULATOR->f_sinh); - MathStructure mterm2(mstruct); - mterm2[0] += mfac[0]; - mstruct[0] -= mfac[0]; - MathStructure mden1(mmul); - mden1 -= mmulf; - mden1 *= nr_two; - MathStructure mden2(mmul); - mden2 += mmulf; - mden2 *= nr_two; - mterm2 /= mden2; - mstruct /= mden1; - mstruct += mterm2; - mstruct.childrenUpdated(true); - return true; - } - } else if(mfac.function() == CALCULATOR->f_sinh && mfac.size() == 1) { - if(mstruct[0] == mfac[0]) { - UnknownVariable *var = new UnknownVariable("", format_and_print(mstruct)); - MathStructure mtest(var); - if(!mpow.isOne()) mtest ^= mpow; - CALCULATOR->beginTemporaryStopMessages(); - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(mstruct); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(mstruct); - } - if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mtest.replace(var, mstruct); - var->destroy(); - mstruct = mtest; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } - } - } - } - } else if(mstruct.function() == CALCULATOR->f_tanh && mstruct.size() == 1) { - if(mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_ln && mstruct[0].size() == 1 && (!definite_integral || COMPARISON_IS_NOT_EQUAL(mstruct[0][0].compare(m_zero)))) { - MathStructure mtest(mstruct[0][0]); - mtest ^= nr_two; - mtest += m_one; - mtest.inverse(); - mtest *= Number(-2, 1); - mtest += m_one; - if(!mpow.isOne()) mtest ^= mpow; - if(!mfac.isOne()) mtest *= mfac; - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mstruct.set(mtest, true); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - } - MathStructure mexp, mmul, madd; - if(mfac.isOne() && mpow.isInteger() && mpow.number().isLessThanOrEqualTo(10) && mpow.number().isGreaterThanOrEqualTo(-1) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne() && (!definite_integral || madd.representsNonComplex(true) || x_var.representsNonZero())) { - if(mpow.isOne()) { - mstruct.setFunction(CALCULATOR->f_cosh); - mstruct.transform(STRUCT_FUNCTION); - mstruct.setFunction(CALCULATOR->f_ln); - if(!mmul.isOne()) mstruct.divide(mmul); - } else if(mpow.number().isTwo()) { - MathStructure marg(mstruct[0]); - if(!madd.isZero()) mstruct[0] = x_var; - if(madd.isZero() && !mmul.isOne()) mstruct /= mmul; - mstruct.negate(); - mstruct += x_var; - if(!madd.isZero()) { - mstruct.replace(x_var, marg); - if(!mmul.isOne()) mstruct.divide(mmul); - } - } else if(mpow.number().isMinusOne()) { - mstruct.setFunction(CALCULATOR->f_sinh); - if(!transform_absln(mstruct, use_abs, definite_integral, x_var, eo)) return -1; - if(!mmul.isOne()) mstruct.divide(mmul); - } else { - MathStructure minteg(mstruct); - MathStructure nm1(mpow); - nm1 += nr_minus_one; - mstruct ^= nm1; - mmul *= nm1; - mstruct /= mmul; - mstruct.negate(); - MathStructure nm2(mpow); - nm2 += Number(-2, 1); - minteg ^= nm2; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - mstruct += minteg; - } - return true; - } - } else if(mstruct.function() == CALCULATOR->f_asinh && mstruct.size() == 1) { - MathStructure mexp, mmul, madd; - if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { - if(definite_integral && !madd.representsNonComplex(true) && COMPARISON_MIGHT_BE_EQUAL(x_var.compare(m_zero))) return false; - if(mfac.isOne()) { - if(mpow.isOne()) { - MathStructure marg(mstruct[0]); - if(!madd.isZero()) mstruct[0] = x_var; - mstruct.multiply(x_var); - MathStructure mterm(x_var); - mterm ^= nr_two; - if(madd.isZero() && !mmul.isOne()) { - MathStructure mmul2(mmul); - mmul2 ^= nr_two; - mterm *= mmul2; - } - mterm += m_one; - mterm ^= nr_half; - if(madd.isZero() && !mmul.isOne()) mterm /= mmul; - mstruct.subtract(mterm); - if(!madd.isZero()) { - mstruct.replace(x_var, marg); - if(!mmul.isOne()) mstruct.divide(mmul); - } - return true; - } else if(mpow.isMinusOne()) { - mstruct.transform(CALCULATOR->f_Chi); - if(!mmul.isOne()) mstruct /= mmul; - return true; - } else if(mpow.number() == -2) { - MathStructure mterm(mstruct[0]); - mterm ^= nr_two; - mterm += m_one; - mterm ^= nr_half; - mterm /= mstruct; - mstruct.transform(CALCULATOR->f_Shi); - mstruct -= mterm; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } else if(madd.isZero()) { - if(mpow.number().isPositive()) { - MathStructure mpowm1(mpow); - if(mpow == nr_two) mpowm1.set(1, 1, 0, true); - else mpowm1 += nr_minus_one; - MathStructure mterm(mstruct); - if(!mpowm1.isOne()) mterm ^= mpowm1; - MathStructure mfac1(x_var); - mfac1 ^= nr_two; - if(!mmul.isOne()) { - mfac1 *= mmul; - mfac1.last() ^= nr_two; - } - mfac1 += m_one; - mfac1 ^= nr_half; - mterm *= mfac1; - mterm *= mpow; - if(!mmul.isOne()) mterm /= mmul; - MathStructure minteg; - if(mpowm1.isOne()) { - minteg = x_var; - } else { - minteg = mstruct; - minteg ^= mpow; - minteg.last() += Number(-2, 1); - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - } - minteg *= mpow; - if(!mpowm1.isOne()) minteg *= mpowm1; - mstruct ^= mpow; - mstruct *= x_var; - mstruct -= mterm; - mstruct += minteg; - return true; - } else { - MathStructure mpowp1(mpow); - mpowp1 += m_one; - MathStructure mpowp2(mpow); - mpowp2 += nr_two; - MathStructure mterm(mstruct); - mterm ^= mpowp1; - MathStructure mfac1(x_var); - mfac1 ^= nr_two; - if(!mmul.isOne()) { - mfac1 *= mmul; - mfac1.last() ^= nr_two; - } - mfac1 += m_one; - mfac1 ^= nr_half; - mterm *= mfac1; - if(!mmul.isOne()) mterm /= mmul; - mterm /= mpowp1; - MathStructure minteg(mstruct); - minteg ^= mpowp2; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - minteg /= mpowp1; - minteg /= mpowp2; - mstruct ^= mpowp2; - mstruct *= x_var; - mstruct /= mpowp1; - mstruct /= mpowp2; - mstruct.negate(); - mstruct += mterm; - mstruct += minteg; - return true; - } - } - } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { - MathStructure mfacexp(1, 1, 0); - if(mfac != x_var) mfacexp = mfac[1]; - if(mpow.isOne()) { - if(mfacexp.isOne()) { - MathStructure mterm2(mstruct[0]); - mterm2 ^= nr_two; - mterm2 += m_one; - mterm2 ^= nr_half; - MathStructure mfac2(x_var); - if(!mmul.isOne()) mfac2 *= mmul; - mfac2.negate(); - if(!madd.isZero()) { - mfac2 += madd; - mfac2.last() *= nr_three; - } - mterm2 *= mfac2; - MathStructure mfac1(x_var); - mfac1 ^= nr_two; - if(!mmul.isOne()) { - mfac1 *= mmul; - mfac1.last() ^= nr_two; - } - mfac1 *= nr_two; - if(!madd.isZero()) { - mfac1 += madd; - mfac1.last() ^= nr_two; - mfac1.last() *= Number(-2, 1); - } - mfac1 += m_one; - mstruct *= mfac1; - mstruct += mterm2; - if(!mmul.isOne()) { - mstruct *= mmul; - mstruct.last() ^= Number(-2, 1); - } - mstruct *= Number(1, 4); - return true; - } else if(mfacexp == nr_two && madd.isZero()) { - mstruct *= x_var; - mstruct.last() ^= nr_three; - mstruct *= Number(1, 3); - MathStructure mterm(x_var); - mterm ^= nr_two; - if(!mmul.isOne()) { - mterm *= mmul; - mterm.last() ^= nr_two; - } - MathStructure mfac1(mterm); - mfac1 += Number(-2, 1); - mterm += m_one; - mterm ^= nr_half; - mterm *= mfac1; - if(!mmul.isOne()) { - mmul ^= Number(-3, 1); - mterm *= mmul; - } - mterm *= Number(-1, 9); - mstruct += mterm; - return true; - } else if(!mfacexp.isMinusOne() && madd.isZero()) { - mfacexp += m_one; - MathStructure minteg(x_var); - minteg ^= nr_two; - if(!mmul.isOne()) { - minteg *= mmul; - minteg.last() ^= nr_two; - } - minteg += m_one; - minteg ^= Number(-1, 2); - minteg *= x_var; - minteg.last() ^= mfacexp; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - if(minteg.containsFunction(CALCULATOR->f_integrate) <= 0) { - if(!mmul.isOne()) minteg *= mmul; - minteg /= mfacexp; - mstruct *= x_var; - mstruct.last() ^= mfacexp; - mstruct /= mfacexp; - mstruct -= minteg; - return true; - } - } - } - } - } - } else if(mstruct.function() == CALCULATOR->f_acosh && mstruct.size() == 1) { - MathStructure mexp, mmul, madd; - if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { - if(definite_integral && (!mmul.representsNonComplex(true) || !x_var.representsNonComplex(true))) return false; - if(mfac.isOne()) { - if(mpow.isOne()) { - MathStructure marg(mstruct[0]); - if(!madd.isZero()) mstruct[0] = x_var; - MathStructure mterm(mstruct[0]); - MathStructure msqrt2(mstruct[0]); - mstruct.multiply(x_var); - mterm += m_one; - mterm ^= nr_half; - msqrt2 += m_minus_one; - msqrt2 ^= nr_half; - mterm *= msqrt2; - if(madd.isZero() && !mmul.isOne()) { - mterm /= mmul; - } - mstruct.subtract(mterm); - if(!madd.isZero()) { - mstruct.replace(x_var, marg); - if(!mmul.isOne()) mstruct.divide(mmul); - } - return true; - } else if(mpow.isMinusOne()) { - mstruct.transform(CALCULATOR->f_Shi); - if(!mmul.isOne()) mstruct /= mmul; - return true; - } else if(mpow.number() == -2) { - MathStructure msqrt(mstruct[0]); - msqrt += m_one; - msqrt.inverse(); - msqrt *= mstruct[0]; - msqrt.last() += nr_minus_one; - msqrt ^= nr_half; - MathStructure macosh(mstruct); - mstruct.transform(CALCULATOR->f_Chi); - mstruct *= macosh; - mstruct *= msqrt; - mstruct += x_var; - if(!mmul.isOne()) mstruct.last() *= mmul; - mstruct.last().negate(); - if(!madd.isZero()) mstruct -= madd; - mstruct += m_one; - mstruct /= macosh; - mstruct /= msqrt; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } else if(madd.isZero()) { - if(mpow.number().isPositive()) { - MathStructure mpowm1(mpow); - if(mpow == nr_two) mpowm1.set(1, 1, 0, true); - else mpowm1 += nr_minus_one; - MathStructure mterm(mstruct); - if(!mpowm1.isOne()) mterm ^= mpowm1; - MathStructure mfac1(x_var); - if(!mmul.isOne()) mfac1 *= mmul; - mfac1 += m_one; - mfac1 ^= nr_half; - MathStructure mfac2(x_var); - if(!mmul.isOne()) mfac2 *= mmul; - mfac2 += nr_minus_one; - mfac2 ^= nr_half; - mterm *= mfac1; - mterm *= mfac2; - mterm *= mpow; - if(!mmul.isOne()) mterm /= mmul; - MathStructure minteg; - if(mpowm1.isOne()) { - minteg = x_var; - } else { - minteg = mstruct; - minteg ^= mpow; - minteg.last() += Number(-2, 1); - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - } - minteg *= mpow; - if(!mpowm1.isOne()) minteg *= mpowm1; - mstruct ^= mpow; - mstruct *= x_var; - mstruct -= mterm; - mstruct += minteg; - return true; - } else { - MathStructure mpowp1(mpow); - mpowp1 += m_one; - MathStructure mpowp2(mpow); - mpowp2 += nr_two; - MathStructure mterm(mstruct); - mterm ^= mpowp1; - MathStructure mfac1(x_var); - if(!mmul.isOne()) mfac1 *= mmul; - mfac1 += m_one; - mfac1 ^= nr_half; - MathStructure mfac2(x_var); - if(!mmul.isOne()) mfac2 *= mmul; - mfac2 += nr_minus_one; - mfac2 ^= nr_half; - mterm *= mfac1; - mterm *= mfac2; - if(!mmul.isOne()) mterm /= mmul; - mterm /= mpowp1; - MathStructure minteg(mstruct); - minteg ^= mpowp2; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - minteg /= mpowp1; - minteg /= mpowp2; - mstruct ^= mpowp2; - mstruct *= x_var; - mstruct /= mpowp1; - mstruct /= mpowp2; - mstruct.negate(); - mstruct += mterm; - mstruct += minteg; - return true; - } - } - } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { - MathStructure mfacexp(1, 1, 0); - if(mfac != x_var) mfacexp = mfac[1]; - if(mpow.isOne()) { - if(mfacexp.isOne()) { - MathStructure mterm2(mstruct[0]); - MathStructure mterm2b(mstruct[0]); - mterm2 += nr_minus_one; - mterm2 ^= nr_half; - mterm2b += m_one; - mterm2b ^= nr_half; - mterm2 *= mterm2b; - MathStructure mfac2(x_var); - if(!mmul.isOne()) { - mfac2 *= mmul; - } - mfac2.negate(); - if(!madd.isZero()) { - mfac2 += madd; - mfac2.last() *= nr_three; - } - mterm2 *= mfac2; - MathStructure mfac1(x_var); - mfac1 ^= nr_two; - if(!mmul.isOne()) { - mfac1 *= mmul; - mfac1.last() ^= nr_two; - } - mfac1 *= nr_two; - if(!madd.isZero()) { - mfac1 += madd; - mfac1.last() ^= nr_two; - mfac1.last() *= Number(-2, 1); - } - mfac1 += nr_minus_one; - mstruct *= mfac1; - mstruct += mterm2; - if(!mmul.isOne()) { - mstruct *= mmul; - mstruct.last() ^= Number(-2, 1); - } - mstruct *= Number(1, 4); - return true; - } else if(mfacexp == nr_two && madd.isZero()) { - mstruct *= x_var; - mstruct.last() ^= nr_three; - mstruct *= Number(1, 3); - MathStructure mterm(x_var); - if(!mmul.isOne()) mterm *= mmul; - mterm += m_one; - mterm ^= nr_half; - MathStructure mfac1(x_var); - if(!mmul.isOne()) mfac1 *= mmul; - mfac1 += nr_minus_one; - mfac1 ^= nr_half; - mterm *= mfac1; - MathStructure mfac2(x_var); - mfac2 ^= nr_two; - if(!mmul.isOne()) { - mfac2 *= mmul; - mfac2.last() ^= nr_two; - } - mfac2 += nr_two; - mterm *= mfac2; - if(!mmul.isOne()) { - mmul ^= Number(-3, 1); - mterm *= mmul; - } - mterm *= Number(-1, 9); - mstruct += mterm; - return true; - } else if(!mfacexp.isMinusOne() && madd.isZero()) { - mfacexp += m_one; - MathStructure minteg(x_var); - if(!mmul.isOne()) minteg *= mmul; - minteg += m_one; - minteg ^= Number(-1, 2); - MathStructure mfac1(x_var); - if(!mmul.isOne()) mfac1 *= mmul; - mfac1 += nr_minus_one; - mfac1 ^= Number(-1, 2); - minteg *= mfac1; - minteg *= x_var; - minteg.last() ^= mfacexp; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - if(minteg.containsFunction(CALCULATOR->f_integrate) <= 0) { - if(!mmul.isOne()) minteg *= mmul; - minteg /= mfacexp; - mstruct *= x_var; - mstruct.last() ^= mfacexp; - mstruct /= mfacexp; - mstruct -= minteg; - return true; - } - } - } - } - } - } else if(mstruct.function() == CALCULATOR->f_atanh && mstruct.size() == 1) { - MathStructure mexp, mmul, madd; - if(mpow.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp)) { - if(!mexp.isOne()) { - if(mexp.isMinusOne() && mfac.isOne() && madd.isZero()) { - mstruct *= x_var; - if(madd.isZero()) { - MathStructure mterm(mmul); - if(!mmul.isOne()) mterm ^= nr_two; - mterm.negate(); - mterm += x_var; - mterm.last() ^= nr_two; - mterm.transform(CALCULATOR->f_ln); - if(!mmul.isOne()) mterm *= mmul; - mterm *= nr_half; - mstruct += mterm; - } else { - MathStructure mterm1(x_var); - mterm1 *= madd; - mterm1 += mmul; - MathStructure mterm2(mterm1); - mterm1 += x_var; - mterm2 -= x_var; - mterm1.transform(CALCULATOR->f_ln); - mterm2.transform(CALCULATOR->f_ln); - mterm1 *= mmul; - mterm2 *= mmul; - madd *= nr_two; - madd += nr_two; - mterm1 /= madd; - madd[0].negate(); - mterm2 /= madd; - mstruct += mterm1; - mstruct += mterm2; - } - return true; - } - } else if(mfac.isOne()) { - MathStructure marg(mstruct[0]); - mstruct.multiply(marg); - MathStructure mterm(marg); - mterm ^= nr_two; - mterm.negate(); - mterm += m_one; - mterm.transform(CALCULATOR->f_ln); - mterm *= nr_half; - mstruct.add(mterm); - if(!mmul.isOne()) mstruct.divide(mmul); - return true; - } else if(madd.isZero() && (mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].isInteger()))) { - MathStructure mfacexp(1, 1, 0); - if(mfac != x_var) mfacexp = mfac[1]; - if(mfacexp.isMinusOne()) { - mstruct.setFunction(CALCULATOR->f_Li); - mstruct.insertChild(nr_two, 1); - MathStructure mterm(mstruct); - mterm[1].negate(); - mterm.negate(); - mstruct += mterm; - mstruct *= nr_half; - return true; - } else if(mfacexp.isOne()) { - MathStructure mterm1(x_var); - mterm1 ^= nr_two; - mterm1 *= mstruct; - mterm1 *= nr_half; - MathStructure mterm2(x_var); - if(!mmul.isOne()) mterm2 /= mmul; - mterm2 *= nr_half; - if(!mmul.isOne()) {mstruct *= mmul; mstruct.last() ^= Number(-2, 1);} - mstruct *= nr_minus_half; - mstruct += mterm1; - mstruct += mterm2; - return true; - } else { - mfacexp += m_one; - MathStructure mxexp(x_var); - mxexp ^= mfacexp; - MathStructure minteg(x_var); - minteg ^= nr_two; - if(!mmul.isOne()) {minteg *= mmul; minteg.last() ^= nr_two;} - minteg.negate(); - minteg += m_one; - if(!definite_integral || COMPARISON_IS_NOT_EQUAL(minteg.compare(m_zero))) { - minteg ^= nr_minus_one; - minteg *= mxexp; - if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; - minteg /= mfacexp; - if(!mmul.isOne()) minteg *= mmul; - mstruct *= mxexp; - mstruct /= mfacexp; - mstruct -= minteg; - return true; - } - } - } - } - } else if(mstruct.function() == CALCULATOR->f_root && VALID_ROOT(mstruct)) { - MathStructure madd, mmul, mexp; - if(mpow.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { - if(mfac.isOne()) { - MathStructure np1(mstruct[1]); - mstruct.multiply(mstruct[0]); - np1.inverse(); - np1 += m_one; - if(!mmul.isOne()) np1 *= mmul; - mstruct.divide(np1); - return true; - } else if(mfac == x_var) { - MathStructure nm1(mstruct[1]); - nm1.inverse(); - nm1 += m_one; - MathStructure mnum(x_var); - mnum *= nm1; - if(!mmul.isOne()) mnum *= mmul; - if(!madd.isZero()) mnum -= madd; - MathStructure mden(mstruct[1]); - mden.inverse(); - mden += nr_two; - mden *= nm1; - if(!mmul.isOne()) { - mden *= mmul; - mden.last() ^= nr_two; - } - mstruct.multiply(mstruct[0]); - mstruct *= mnum; - mstruct /= mden; - return true; - } - } - } else if(mstruct.function() == CALCULATOR->f_erfc && mstruct.size() == 1) { - MathStructure mtest(mstruct); - mtest.setFunction(CALCULATOR->f_erf); - mtest.negate(); - mtest += m_one; - if(!mpow.isOne()) mtest ^= mpow; - if(!mfac.isOne()) mtest *= mfac; - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth - 1, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate, true) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mstruct = mtest; - return true; - } - CALCULATOR->endTemporaryStopMessages(); - } else if(mstruct.function() == CALCULATOR->f_erf && mstruct.size() == 1) { - MathStructure madd, mmul, mexp; - if(mpow.isOne() && mfac.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { - MathStructure mterm2(CALCULATOR->v_e); - mterm2 ^= mstruct[0]; - mterm2.last() ^= nr_two; - mterm2.last().negate(); - mterm2 *= CALCULATOR->v_pi; - mterm2.last() ^= Number(-1, 2); - if(!mmul.isOne()) mterm2 /= mmul; - if(madd.isZero()) { - mstruct *= x_var; - } else { - mstruct *= madd; - if(!mmul.isOne()) { - mstruct.last() /= mmul; - mstruct.childrenUpdated(); - } - mstruct.last() += x_var; - } - mstruct += mterm2; - return true; - } - } else if(mstruct.function() == CALCULATOR->f_digamma && mstruct.size() == 1) { - MathStructure madd, mmul, mexp; - if(mpow.isOne() && mfac.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { - mstruct.setFunction(CALCULATOR->f_gamma); - mstruct.transform(CALCULATOR->f_ln); - if(!mmul.isOne()) mstruct /= mmul; - return true; - } - } else if(mstruct.function() == CALCULATOR->f_li && mstruct.size() == 1) { - MathStructure madd, mmul, mexp; - if(mpow.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { - if(mfac.isOne()) { - MathStructure mEi(mstruct); - mstruct *= mEi[0]; - mEi.setFunction(CALCULATOR->f_ln); - mEi *= nr_two; - mEi.transform(CALCULATOR->f_Ei); - mstruct -= mEi; - if(!mmul.isOne()) mstruct /= mmul; - return true; - } else if(madd.isZero() && mfac.isPower() && mfac[0] == x_var && mfac[1].isMinusOne()) { - MathStructure mln(mstruct); - mln.setFunction(CALCULATOR->f_ln); - mstruct *= mln; - mstruct -= mln[0]; - return true; - } - } - } else if(mstruct.function() == CALCULATOR->f_diff && (mstruct.size() == 3 || (mstruct.size() == 4 && mstruct[3].isUndefined())) && mstruct[1] == x_var) { - if(!mpow.isOne() || !mfac.isOne()) return false; - if(mstruct[2].isOne()) { - mstruct.setToChild(1, true); - } else { - mstruct[2] += m_minus_one; - } - return true; - } else if(mstruct.function() == CALCULATOR->f_diff && mstruct.size() == 2 && mstruct[1] == x_var) { - if(!mpow.isOne() || !mfac.isOne()) return false; - mstruct.setToChild(1, true); - return true; - } else { - return false; - } - if(mstruct.size() == 0) return false; - bool by_parts_tested = false; - - if(mfac.isOne() && (mstruct.function() == CALCULATOR->f_ln || mstruct.function() == CALCULATOR->f_asin || mstruct.function() == CALCULATOR->f_acos || mstruct.function() == CALCULATOR->f_atan || mstruct.function() == CALCULATOR->f_asinh || mstruct.function() == CALCULATOR->f_acosh || mstruct.function() == CALCULATOR->f_atanh)) { - by_parts_tested = true; - //integrate by parts - if(max_part_depth > 0) { - MathStructure minteg(mstruct); - if(!mpow.isOne()) minteg ^= mpow; - CALCULATOR->beginTemporaryStopMessages(); - if(minteg.differentiate(x_var, eo) && minteg.containsFunction(CALCULATOR->f_diff, true) <= 0 && (!definite_integral || check_zero_div(minteg, x_var, eo))) { - minteg *= x_var; - EvaluationOptions eo2 = eo; - eo2.expand = true; - eo2.combine_divisions = false; - eo2.sync_units = false; - minteg.evalSort(true); - minteg.calculateFunctions(eo); - minteg.calculatesub(eo2, eo2, true); - do_simplification(minteg, eo2, true, false, false, true, true); - if(minteg.integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth - 1, parent_parts) > 0 && minteg.containsFunction(CALCULATOR->f_integrate, true) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - if(!mpow.isOne()) mstruct ^= mpow; - mstruct.multiply(x_var); - mstruct.subtract(minteg); - return true; - } - } - CALCULATOR->endTemporaryStopMessages(); - } - } - MathStructure madd, mmul, mexp; - if(integrate_info(mstruct[0], x_var, madd, mmul, mexp, false, false, true) && !mexp.isZero()) { - if(mexp.isPower() && (mexp[1] == x_var || (mexp[1].isMultiplication() && mexp[1].size() >= 2 && mexp[1].last() == x_var)) && mfac.isPower() && (mfac[1] == x_var || (mfac[1].isMultiplication() && mfac[1].size() >= 2 && mfac[1].last() == x_var)) && (mfac[0] == mexp[0] || (mfac[0].isNumber() && mfac[0].number().isRational() && mexp[0].isNumber() && mexp[0].number().isRational() && mexp[1] == mfac[1])) && mexp[0].containsRepresentativeOf(x_var, true, true) == 0) { - Number pow1(1, 1), pow2; - MathStructure morig(mexp); - bool b = true; - if(mfac[1].isMultiplication()) { - if(!mexp[1].isMultiplication()) { - if(mfac[1].size() != 2 || !mfac[1][0].isNumber()) b = false; - else {pow2 = mfac[1][0].number(); pow2--;} - } else { - for(size_t i = 0; i < mexp[1].size() - 1; i++) { - if(i == 0 && mexp[1][i].isNumber()) { - pow1 = mexp[1][i].number(); - } else if(mfac[1][i].containsRepresentativeOf(x_var, true, true) != 0) { - b = false; - break; - } - } - if(b) { - if(mexp[1] == mfac[1]) { - pow1.set(1, 1); - } else if(mfac[1].size() - (mfac[1][0].isNumber() ? 1 : 0) != mexp[1].size() - (mexp[1][0].isNumber() ? 1 : 0)) { - b = false; - } else if(b) { - for(size_t i = 0; i < mfac[1].size() - 1; i++) { - if(i == 0 && mfac[1][i].isNumber()) { - pow2 = mfac[1][i].number(); - pow2--; - } else if(mfac[1][i] != mexp[1][i + (mexp[1][0].isNumber() ? 1 : 0) - (mfac[1][0].isNumber() ? 1 : 0)]) { - b = false; - break; - } - } - } - } - } - } else if(mexp[1].isMultiplication()) { - if(mexp[1].size() != 2 || !mexp[1][0].isNumber()) b = false; - else pow1 = mexp[1][0].number(); - } - if(b && !pow1.isOne()) morig[1].delChild(1, true); - if(b && mfac[0] != mexp[0]) { - bool b1 = mfac[0].number() < mexp[0].number(); - if(mfac[0].number().isFraction() || mexp[0].number().isFraction()) b1 = !b1; - Number nlog(b1 ? mexp[0].number() : mfac[0].number()); - nlog.log(b1 ? mfac[0].number() : mexp[0].number()); - if(!nlog.isInteger()) { - nlog.round(); - b = nlog.isInteger() && (b1 ? ((mfac[0].number() ^ nlog) == mexp[0].number()) : ((mfac[0].number() ^ nlog) == mexp[0].number())); - } - if(b) { - if(b1) { - pow1 = nlog; - morig = mfac; - } else { - pow2 = nlog; - pow2--; - } - } - } - if(b) { - UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(morig) + RIGHT_PARENTHESIS); - MathStructure mtest(var); - if(!pow1.isOne()) mtest ^= pow1; - if(!mmul.isOne()) mtest *= mmul; - if(!madd.isZero()) mtest += madd; - mtest.transform(mstruct.function()); - if(!mpow.isOne()) mtest ^= mpow; - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(morig); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(morig); - } - if(!pow2.isZero()) { - mtest *= var; - if(!pow2.isOne()) mtest.last() ^= pow2; - mtest.swapChildren(1, 2); - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mstruct.set(mtest, true); - mstruct.replace(var, morig); - if(morig[0] != CALCULATOR->v_e) mstruct.divide_nocopy(new MathStructure(CALCULATOR->f_ln, &morig[0], NULL)); - if(morig[1].isMultiplication()) { - morig[1].delChild(morig[1].size(), true); - mstruct /= morig[1]; - } - var->destroy(); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } - } else if(mexp == x_var && !madd.isZero() && (mfac.isOne() || mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].isInteger()))) { - MathStructure morig(x_var); - if(!mmul.isOne()) morig *= mmul; - morig += madd; - UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(morig) + RIGHT_PARENTHESIS); - MathStructure mtest(var); - mtest.transform(mstruct.function()); - if(!mpow.isOne()) mtest ^= mpow; - if(!mfac.isOne()) { - MathStructure mrepl(var); - mrepl -= madd; - mrepl /= mmul; - MathStructure mfacnew(mfac); - mfacnew.replace(x_var, mrepl); - mtest *= mfacnew; - } - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(morig); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(morig); - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mstruct.set(mtest, true); - mstruct.replace(var, morig); - if(!mmul.isOne()) mstruct /= mmul; - var->destroy(); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } else if(mfac.isOne() && (mexp.isPower() && mexp[0] == x_var && mexp[1].isNumber() && !mexp[1].number().isInteger() && mexp[1].number().isRational())) { - Number num(mexp[1].number().numerator()); - Number den(mexp[1].number().denominator()); - if(num.isPositive() || num.isMinusOne()) { - MathStructure morig(x_var); - if(num.isNegative()) den.negate(); - Number den_inv(den); - den_inv.recip(); - morig ^= den_inv; - UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(morig) + RIGHT_PARENTHESIS); - Number den_m1(den); - den_m1--; - MathStructure mtest(var); - if(!num.isOne() && !num.isMinusOne()) mtest ^= num; - if(!mmul.isOne()) mtest *= mmul; - if(!madd.isZero()) mtest += madd; - mtest.transform(mstruct.function()); - if(!mpow.isOne()) mtest ^= mpow; - mtest *= var; - if(!den_m1.isOne()) { - mtest.last() ^= den_m1; - mtest.childUpdated(mtest.size()); - } - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(morig); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(morig); - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mstruct.set(mtest, true); - mstruct.replace(var, morig); - mstruct.multiply(den); - var->destroy(); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } - } else if((mfac.isOne() || mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].isInteger())) && (mexp.isPower() && mexp[0] != x_var && mexp[1].isNumber())) { - MathStructure madd2, mmul2, mexp2; - if(integrate_info(mexp[0], x_var, madd2, mmul2, mexp2) && (!madd.isZero() || mexp != x_var) && mexp2.isOne()) { - UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(mexp[0]) + RIGHT_PARENTHESIS); - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(mexp[0]); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(mexp[0]); - } - MathStructure mtest(var); - mtest ^= mexp[1]; - if(!mmul.isOne()) mtest *= mmul; - if(!madd.isZero()) mtest += madd; - mtest.transform(mstruct.function()); - if(!mpow.isOne()) mtest ^= mpow; - if(!mfac.isOne()) { - mtest *= var; - if(!madd2.isZero()) { - mtest.last() -= madd2; - mtest.childUpdated(mtest.size()); - } - if(mfac.isPower()) { - mtest.last() ^= mfac[1]; - mtest.childUpdated(mtest.size()); - } - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mstruct.set(mtest, true); - mstruct.replace(var, mexp[0]); - if(!mmul2.isOne()) { - mstruct /= mmul2; - if(!mfac.isOne()) { - if(mfac.isPower()) mmul2 ^= mfac[1]; - mstruct /= mmul2; - } - } - var->destroy(); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } - } - } - if(mstruct[0].isAddition()) { - bool b = true; - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].containsType(STRUCT_ADDITION, true) == 1) { - b = false; - break; - } - } - if(b) { - MathStructure mtest(mstruct); - if(mtest[0].factorize(eo, false, 0, 0, false, false, NULL, x_var, true, true)) { - if(integrate_function(mtest, x_var, eo, mpow, mfac, mpowadd, mpowmul, use_abs, definite_integral, max_part_depth, parent_parts)) { - mstruct = mtest; - return true; - } - } - } - } - if(!mfac.isOne()) return false; - MathStructure *m_func = NULL, *m_pow = NULL; - if(mstruct[0].isFunction() && mstruct[0].contains(x_var, true) > 0) { - m_func = &mstruct[0]; - } else if(mstruct[0].isPower() && mstruct[0][0].isFunction() && mstruct[0][0].contains(x_var, true) > 0) { - m_func = &mstruct[0][0]; - } else if(mstruct[0].isPower() && mstruct[0][1].contains(x_var, true) > 0) { - m_pow = &mstruct[0]; - } else if(mstruct[0].isMultiplication()) { - for(size_t i = 0; i < mstruct[0].size(); i++) { - if(mstruct[0][i].isFunction() && mstruct[0][i].contains(x_var, true) > 0) { - m_func = &mstruct[0][i]; - } else if(mstruct[0][i].isPower() && mstruct[0][i][0].isFunction() && mstruct[0][i][0].contains(x_var, true) > 0) { - m_func = &mstruct[0][i][0]; - } else if(mstruct[0][i].isPower() && mstruct[0][i][1].contains(x_var, true) > 0) { - m_pow = &mstruct[0][i]; - } - } - } else if(mstruct[0].isAddition()) { - for(size_t i2 = 0; i2 < mstruct[0].size(); i2++) { - if(mstruct[0][i2].isFunction() && mstruct[0][i2].contains(x_var, true) > 0) { - m_func = &mstruct[0][i2]; - } else if(mstruct[0][i2].isPower() && mstruct[0][i2][0].isFunction() && mstruct[0][i2][0].contains(x_var, true) > 0) { - m_func = &mstruct[0][i2][0]; - } else if(mstruct[0][i2].isPower() && mstruct[0][i2][1].contains(x_var, true) > 0) { - m_pow = &mstruct[0][i2]; - } else if(mstruct[0][i2].isMultiplication()) { - for(size_t i = 0; i < mstruct[0][i2].size(); i++) { - if(mstruct[0][i2][i].isFunction() && mstruct[0][i2][i].contains(x_var, true) > 0) { - m_func = &mstruct[0][i2][i]; - } else if(mstruct[0][i2][i].isPower() && mstruct[0][i2][i][0].isFunction() && mstruct[0][i2][i][0].contains(x_var, true) > 0) { - m_func = &mstruct[0][i2][i][0]; - } else if(mstruct[0][i2][i].isPower() && mstruct[0][i2][i][1].contains(x_var, true) > 0) { - m_pow = &mstruct[0][i2][i]; - } - } - } - } - } - if(m_func && m_pow) return false; - if(m_func) { - if((m_func->function() == CALCULATOR->f_ln || m_func->function() == CALCULATOR->f_asin || m_func->function() == CALCULATOR->f_acos || m_func->function() == CALCULATOR->f_asinh || m_func->function() == CALCULATOR->f_acosh) && m_func->size() == 1 && integrate_info((*m_func)[0], x_var, madd, mmul, mexp) && mexp.isOne()) { - MathStructure m_orig(*m_func); - UnknownVariable *var = new UnknownVariable("", format_and_print(m_orig)); - MathStructure mtest(mstruct); - if(!mpow.isOne()) mtest ^= mpow; - mtest[0].replace(m_orig, var, (*m_func)[0].containsInterval()); - if(mtest[0].containsRepresentativeOf(x_var, true, true) == 0) { - if(m_func->function() == CALCULATOR->f_ln) { - MathStructure m_epow(CALCULATOR->v_e); - m_epow ^= var; - mtest *= m_epow; - } else if(m_func->function() == CALCULATOR->f_asin) { - MathStructure m_cos(var); - if(CALCULATOR->getRadUnit()) m_cos *= CALCULATOR->getRadUnit(); - m_cos.transform(CALCULATOR->f_cos); - mtest *= m_cos; - } else if(m_func->function() == CALCULATOR->f_acos) { - MathStructure m_sin(var); - if(CALCULATOR->getRadUnit()) m_sin *= CALCULATOR->getRadUnit(); - m_sin.transform(CALCULATOR->f_sin); - mtest *= m_sin; - mmul.negate(); - } else if(m_func->function() == CALCULATOR->f_asinh) { - MathStructure m_cos(var); - m_cos.transform(CALCULATOR->f_cosh); - mtest *= m_cos; - } else if(m_func->function() == CALCULATOR->f_acosh) { - MathStructure m_sin(var); - m_sin.transform(CALCULATOR->f_sinh); - mtest *= m_sin; - } - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(m_orig); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(m_orig); - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mstruct.set(mtest, true); - mstruct.replace(var, m_orig); - if(!mmul.isOne()) mstruct /= mmul; - var->destroy(); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - } - var->destroy(); - } - } - if(m_pow) { - if((*m_pow)[0].containsRepresentativeOf(x_var, true, true) == 0 && integrate_info((*m_pow)[1], x_var, madd, mmul, mexp) && mexp.isOne()) { - if(definite_integral && ((*m_pow)[0].compare(m_zero) != COMPARISON_RESULT_LESS)) return false; - MathStructure m_orig(*m_pow); - UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(m_orig) + RIGHT_PARENTHESIS); - MathStructure mtest(mstruct); - mtest[0].replace(m_orig, var, m_pow->containsInterval()); - if(mtest[0].containsRepresentativeOf(x_var, true, true) == 0) { - if(!mpow.isOne()) mtest ^= mpow; - mtest /= var; - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(m_orig); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(m_orig); - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mstruct.set(mtest, true); - mstruct.replace(var, m_orig); - MathStructure m_ln(CALCULATOR->f_ln, &m_orig[0], NULL); - mstruct /= m_ln; - if(!mmul.isOne()) mstruct /= mmul; - var->destroy(); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - } - var->destroy(); - } - } - if(!by_parts_tested && mstruct[0].function() != CALCULATOR->f_sin && mstruct[0].function() != CALCULATOR->f_cos && mstruct[0].function() != CALCULATOR->f_tan && mstruct[0].function() != CALCULATOR->f_sinh && mstruct[0].function() != CALCULATOR->f_cosh && mstruct[0].function() != CALCULATOR->f_tanh) { - //integrate by parts - if(max_part_depth > 0) { - MathStructure minteg(mstruct); - if(!mpow.isOne()) minteg ^= mpow; - CALCULATOR->beginTemporaryStopMessages(); - if(minteg.differentiate(x_var, eo) && minteg.containsFunction(CALCULATOR->f_diff, true) <= 0 && (!definite_integral || check_zero_div(minteg, x_var, eo))) { - minteg *= x_var; - EvaluationOptions eo2 = eo; - eo2.expand = true; - eo2.combine_divisions = false; - eo2.sync_units = false; - minteg.evalSort(true); - minteg.calculateFunctions(eo); - minteg.calculatesub(eo2, eo2, true); - do_simplification(minteg, eo2, true, false, false, true, true); - if(minteg.integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth - 1, parent_parts) > 0 && minteg.containsFunction(CALCULATOR->f_integrate, true) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - if(!mpow.isOne()) mstruct ^= mpow; - mstruct.multiply(x_var); - mstruct.subtract(minteg); - return true; - } - } - CALCULATOR->endTemporaryStopMessages(); - } - } - return false; -} - -#define CANNOT_INTEGRATE {MathStructure minteg(CALCULATOR->f_integrate, this, &m_undefined, &m_undefined, &x_var, &m_zero, NULL); set(minteg); return false;} -#define CANNOT_INTEGRATE_INTERVAL {MathStructure minteg(CALCULATOR->f_integrate, this, &m_undefined, &m_undefined, &x_var, &m_zero, NULL); set(minteg); return -1;} - -bool MathStructure::decomposeFractions(const MathStructure &x_var, const EvaluationOptions &eo) { - MathStructure mtest2; - bool b = false; - int mmul_i = 0; - if(isPower()) { - if(CHILD(1).isMinusOne() && CHILD(0).isMultiplication() && CHILD(0).size() >= 2) { - mtest2 = CHILD(0); - b = true; - } - } else if(isMultiplication() && SIZE == 2) { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isPower() && CHILD(i)[1].isMinusOne() && (CHILD(i)[0].isPower() || CHILD(i)[0].isMultiplication())) { - mtest2 = CHILD(i)[0]; - b = true; - } else if(CHILD(i) == x_var) { - mmul_i = 1; - } else if(CHILD(i).isPower() && CHILD(i)[0] == x_var && CHILD(i)[1].isInteger() && CHILD(i)[1].number().isPositive() && CHILD(i)[1].number().isLessThan(100)) { - mmul_i = CHILD(i)[1].number().intValue(); - } - } - if(mmul_i == 0) b = false; - } - if(b) { - if(!mtest2.isMultiplication()) mtest2.transform(STRUCT_MULTIPLICATION); - MathStructure mfacs, mnew; - mnew.setType(STRUCT_ADDITION); - mfacs.setType(STRUCT_ADDITION); - vector i_degrees; - i_degrees.resize(mtest2.size(), 1); - for(size_t i = 0; i < mtest2.size() && b; i++) { - if(CALCULATOR->aborted()) return false; - MathStructure mfactor = mtest2[i]; - if(mtest2[i].isPower()) { - if(!mtest2[i][1].isInteger() || !mtest2[i][1].number().isPositive() || mtest2[i][1].isOne() || mtest2[i][1].number().isGreaterThan(100)) { - b = false; - break; - } - mfactor = mtest2[i][0]; - } - if(mfactor.isAddition()) { - bool b2 = false; - for(size_t i2 = 0; i2 < mfactor.size() && b; i2++) { - if(mfactor[i2].isMultiplication()) { - bool b_x = false; - for(size_t i3 = 0; i3 < mfactor[i2].size() && b; i3++) { - if(!b_x && mfactor[i2][i3].isPower() && mfactor[i2][i3][0] == x_var) { - if(!mfactor[i2][i3][1].isInteger() || !mfactor[i2][i3][1].number().isPositive() || mfactor[i2][i3][1].isOne() || mfactor[i2][i3][1].number().isGreaterThan(100)) { - b = false; - } else if(mfactor[i2][i3][1].number().intValue() > i_degrees[i]) { - i_degrees[i] = mfactor[i2][i3][1].number().intValue(); - } - b_x = true; - } else if(!b_x && mfactor[i2][i3] == x_var) { - b_x = true; - } else if(mfactor[i2][i3].containsRepresentativeOf(x_var, true, true) != 0) { - b = false; - } - } - if(!b_x) b2 = true; - } else if(mfactor[i2].isPower() && mfactor[i2][0] == x_var) { - if(!mfactor[i2][1].isInteger() || !mfactor[i2][1].number().isPositive() || mfactor[i2][1].isOne() || mfactor[i2][1].number().isGreaterThan(100)) { - b = false; - } else if(mfactor[i2][1].number().intValue() > i_degrees[i]) { - i_degrees[i] = mfactor[i2][1].number().intValue(); - } - } else if(mfactor[i2] == x_var) { - } else if(mfactor[i2].containsRepresentativeOf(x_var, true, true) != 0) { - b = false; - } else { - b2 = true; - } - } - if(!b2) b = false; - } else if(mfactor != x_var) { - b = false; - } - } - MathStructure mtest3, mnums3; - mnums3.clearVector(); - mtest3.clearVector(); - if(b) { - UnknownVariable *var = new UnknownVariable("", string("a")); - var->setAssumptions(new Assumptions()); - MathStructure mvar(var); - for(size_t i = 0; i < mtest2.size(); i++) { - if(CALCULATOR->aborted()) return false; - if(i_degrees[i] == 1) { - MathStructure mnum(1, 1, 0); - if(mtest2.size() != 1) { - mnum = mtest2; - mnum.delChild(i + 1, true); - } - MathStructure mx(mtest2[i]); - mx.transform(COMPARISON_EQUALS, m_zero); - mx.replace(x_var, mvar); - mx.isolate_x(eo, mvar); - mx.calculatesub(eo, eo, true); - if(mx.isLogicalOr()) mx.setToChild(1); - if(!mx.isComparison() || mx.comparisonType() != COMPARISON_EQUALS || mx[0] != var) {b = false; break;} - mx.setToChild(2); - if(mtest2.size() != 1) { - mfacs.addChild(mnum); - mnum.replace(x_var, mx); - mnum.inverse(); - } - if(mmul_i > 0) { - mx ^= Number(mmul_i, 1); - if(mtest2.size() == 1) mnum = mx; - else mnum *= mx; - } - mnum.calculatesub(eo, eo, true); - if(mtest2.size() == 1) mfacs.addChild(mnum); - else mfacs.last() *= mnum; - mnums3.addChild(mnum); - mtest3.addChild(mtest2[i]); - } - } - var->destroy(); - } - if(b) { - vector vars; - bool b_solve = false; - for(size_t i = 0; i < mtest2.size(); i++) { - if(CALCULATOR->aborted()) return false; - if(mtest2[i].isPower()) { - int i_exp = mtest2[i][1].number().intValue(); - for(int i_exp_n = mtest2[i][1].number().intValue() - (i_degrees[i] == 1 ? 1 : 0); i_exp_n > 0; i_exp_n--) { - if(i_exp_n == 1) { - mtest3.addChild(mtest2[i][0]); - } else { - mtest3.addChild(mtest2[i]); - if(i_exp_n != i_exp) mtest3.last()[1].number() = i_exp_n; - } - if(i_exp == i_exp_n) { - if(mtest2.size() > 1) { - mfacs.addChild(mtest2); - mfacs.last().delChild(i + 1, true); - } - } else { - mfacs.addChild(mtest2); - if(i_exp - i_exp_n == 1) mfacs.last()[i].setToChild(1); - else mfacs.last()[i][1].number() = i_exp - i_exp_n; - } - if(i_degrees[i] == 1) { - UnknownVariable *var = new UnknownVariable("", string("a") + i2s(mtest3.size())); - var->setAssumptions(new Assumptions()); - mnums3.addChild_nocopy(new MathStructure(var)); - vars.push_back(var); - } else { - mnums3.addChild_nocopy(new MathStructure()); - mnums3.last().setType(STRUCT_ADDITION); - for(int i2 = 1; i2 <= i_degrees[i]; i2++) { - UnknownVariable *var = new UnknownVariable("", string("a") + i2s(mtest3.size()) + i2s(i2)); - var->setAssumptions(new Assumptions()); - if(i2 == 1) { - mnums3.last().addChild_nocopy(new MathStructure(var)); - } else { - mnums3.last().addChild_nocopy(new MathStructure(var)); - mnums3.last().last() *= x_var; - if(i2 > 2) mnums3.last().last().last() ^= Number(i2 - 1, 1); - } - vars.push_back(var); - } - } - if(i_exp != i_exp_n || mtest2.size() > 1) mfacs.last() *= mnums3.last(); - else mfacs.addChild(mnums3.last()); - b_solve = true; - } - } else if(i_degrees[i] > 1) { - mtest3.addChild(mtest2[i]); - if(mtest2.size() > 1) { - mfacs.addChild(mtest2); - mfacs.last().delChild(i + 1, true); - } - mnums3.addChild_nocopy(new MathStructure()); - mnums3.last().setType(STRUCT_ADDITION); - for(int i2 = 1; i2 <= i_degrees[i]; i2++) { - UnknownVariable *var = new UnknownVariable("", string("a") + i2s(mtest3.size()) + i2s(i2)); - var->setAssumptions(new Assumptions()); - if(i2 == 1) { - mnums3.last().addChild_nocopy(new MathStructure(var)); - } else { - mnums3.last().addChild_nocopy(new MathStructure(var)); - mnums3.last().last() *= x_var; - if(i2 > 2) mnums3.last().last().last() ^= Number(i2 - 1, 1); - } - vars.push_back(var); - } - if(mtest2.size() > 1) mfacs.last() *= mnums3.last(); - else mfacs.addChild(mnums3.last()); - b_solve = true; - } - } - if(b_solve) { - mfacs.childrenUpdated(true); - MathStructure mfac_expand(mfacs); - mfac_expand.calculatesub(eo, eo, true); - size_t i_degree = 0; - if(mfac_expand.isAddition()) { - i_degree = mfac_expand.degree(x_var).uintValue(); - if(i_degree >= 100 || i_degree <= 0) b = false; - } - if(i_degree == 0) b = false; - if(b) { - MathStructure m_eqs; - m_eqs.resizeVector(i_degree + 1, m_zero); - for(size_t i = 0; i < m_eqs.size(); i++) { - for(size_t i2 = 0; i2 < mfac_expand.size();) { - if(CALCULATOR->aborted()) return false; - bool b_add = false; - if(i == 0) { - if(!mfac_expand[i2].contains(x_var)) b_add = true; - } else { - if(mfac_expand[i2].isMultiplication() && mfac_expand[i2].size() >= 2) { - for(size_t i3 = 0; i3 < mfac_expand[i2].size(); i3++) { - if(i == 1 && mfac_expand[i2][i3] == x_var) b_add = true; - else if(i > 1 && mfac_expand[i2][i3].isPower() && mfac_expand[i2][i3][0] == x_var && mfac_expand[i2][i3][1] == i) b_add = true; - if(b_add) { - mfac_expand[i2].delChild(i3 + 1, true); - break; - } - } - - } else { - if(i == 1 && mfac_expand[i2] == x_var) b_add = true; - else if(i > 1 && mfac_expand[i2].isPower() && mfac_expand[i2][0] == x_var && mfac_expand[i2][1] == i) b_add = true; - if(b_add) mfac_expand[i2].set(1, 1, 0); - } - } - if(b_add) { - if(m_eqs[i].isZero()) m_eqs[i] = mfac_expand[i2]; - else m_eqs[i].add(mfac_expand[i2], true); - mfac_expand.delChild(i2 + 1); - } else { - i2++; - } - } - } - if(mfac_expand.size() == 0 && m_eqs.size() >= vars.size()) { - for(size_t i = 0; i < m_eqs.size(); i++) { - if(!m_eqs[i].isZero()) { - m_eqs[i].transform(COMPARISON_EQUALS, i == (size_t) mmul_i ? m_one : m_zero); - } - } - for(size_t i = 0; i < m_eqs.size();) { - if(m_eqs[i].isZero()) { - m_eqs.delChild(i + 1); - if(i == (size_t) mmul_i) b = false; - } else { - i++; - } - } - if(b) { - MathStructure vars_m; - vars_m.clearVector(); - for(size_t i = 0; i < vars.size(); i++) { - vars_m.addChild_nocopy(new MathStructure(vars[i])); - } - for(size_t i = 0; i < m_eqs.size() && b; i++) { - for(size_t i2 = 0; i2 < vars_m.size(); i2++) { - if(m_eqs[i].isComparison() && m_eqs[i][0].contains(vars_m[i2], true)) { - if(CALCULATOR->aborted() || m_eqs[i].countTotalChildren() > 1000) return false; - m_eqs[i].isolate_x(eo, vars_m[i2]); - if(CALCULATOR->aborted() || m_eqs[i].countTotalChildren() > 10000) return false; - m_eqs[i].calculatesub(eo, eo, true); - if(m_eqs[i].isLogicalOr()) m_eqs[i].setToChild(1); - if(m_eqs[i].isComparison() && m_eqs[i].comparisonType() == COMPARISON_EQUALS && m_eqs[i][0] == vars_m[i2]) { - for(size_t i3 = 0; i3 < m_eqs.size(); i3++) { - if(i3 != i) { - if(CALCULATOR->aborted()) return false; - m_eqs[i3][0].calculateReplace(vars_m[i2], m_eqs[i][1], eo); - if(CALCULATOR->aborted()) return false; - m_eqs[i3][1].calculateReplace(vars_m[i2], m_eqs[i][1], eo); - } - } - vars_m.delChild(i2 + 1); - } else { - b = false; - } - break; - } - } - } - for(size_t i = 0; i < m_eqs.size();) { - if(CALCULATOR->aborted()) return false; - m_eqs[i].calculatesub(eo, eo); - if(m_eqs[i].isZero()) {b = false; break;} - if(m_eqs[i].isOne()) m_eqs.delChild(i + 1); - else i++; - } - if(b && vars_m.size() == 0) { - for(size_t i = 0; i < vars.size(); i++) { - for(size_t i2 = 0; i2 < m_eqs.size(); i2++) { - if(m_eqs[i2][0] == vars[i]) { - mnums3.replace(vars[i], m_eqs[i2][1]); - break; - } - } - } - } else { - b = false; - } - } - } else { - b = false; - } - } - } - for(size_t i = 0; i < vars.size(); i++) { - vars[i]->destroy(); - } - if(b) { - for(size_t i = 0; i < mnums3.size(); i++) { - mnums3.calculatesub(eo, eo, true); - if(!mnums3[i].isZero()) { - if(mnums3[i].isOne()) { - mnew.addChild(mtest3[i]); - mnew.last().inverse(); - } else { - mnew.addChild(mnums3[i]); - mnew.last() /= mtest3[i]; - } - } - } - } - if(b) { - if(mnew.size() == 0) mnew.clear(); - else if(mnew.size() == 1) mnew.setToChild(1); - mnew.childrenUpdated(); - if(equals(mnew, true)) return false; - set(mnew, true); - return true; - } - } - } - return false; -} - -bool expand_partial_fractions(MathStructure &m, const EvaluationOptions &eo, bool do_simplify = true) { - MathStructure mtest(m); - if(do_simplify) { - mtest.simplify(eo); - mtest.calculatesub(eo, eo, true); - } - if(mtest.isPower() && mtest[1].representsNegative()) { - MathStructure x_var = mtest[0].find_x_var(); - if(!x_var.isUndefined() && mtest[0].factorize(eo, false, 0, 0, false, false, NULL, x_var)) { - if(mtest.decomposeFractions(x_var, eo) && mtest.isAddition()) { - m = mtest; - return true; - } - } - } else if(mtest.isMultiplication()) { - for(size_t i = 0; i < mtest.size(); i++) { - if(mtest[i].isPower() && mtest[i][1].isMinusOne() && mtest[i][0].isAddition()) { - MathStructure x_var = mtest[i][0].find_x_var(); - if(!x_var.isUndefined()) { - MathStructure mfac(mtest); - mfac.delChild(i + 1, true); - bool b_poly = true; - if(mfac.contains(x_var, true)) { - MathStructure mquo, mrem; - b_poly = polynomial_long_division(mfac, mtest[i][0], x_var, mquo, mrem, eo, true); - if(b_poly && !mquo.isZero()) { - m = mquo; - if(!mrem.isZero()) { - m += mrem; - m.last() *= mtest[i]; - m.childrenUpdated(); - } - expand_partial_fractions(m, eo, false); - return true; - } - } - if(b_poly && mtest[i][0].factorize(eo, false, 0, 0, false, false, NULL, x_var)) { - MathStructure mmul(1, 1, 0); - while(mtest[i][0].isMultiplication() && mtest[i][0].size() >= 2 && !mtest[i][0][0].containsRepresentativeOf(x_var, true)) { - if(mmul.isOne()) { - mmul = mtest[i][0][0]; - mmul.calculateInverse(eo); - } else { - mmul *= mtest[i][0][0]; - mmul.last().calculateInverse(eo); - mmul.calculateMultiplyLast(eo); - } - mtest[i][0].delChild(1, true); - } - for(size_t i2 = 0; i2 < mtest.size();) { - if(i2 != i && !mtest[i2].containsRepresentativeOf(x_var, true)) { - if(mmul.isOne()) { - mmul = mtest[i2]; - } else { - mmul.calculateMultiply(mtest[i2], eo); - } - if(mtest.size() == 2) { - mtest.setToChild(i + 1, true); - break; - } else { - mtest.delChild(i2 + 1); - if(i2 < i) i--; - } - } else { - i2++; - } - } - if(mtest.decomposeFractions(x_var, eo) && mtest.isAddition()) { - m = mtest; - if(!mmul.isOne()) { - for(size_t i2 = 0; i2 < m.size(); i2++) { - m[i2].calculateMultiply(mmul, eo); - } - } - return true; - } - } - } - } - } - } else { - bool b = false; - for(size_t i = 0; i < mtest.size(); i++) { - if(expand_partial_fractions(mtest[i], eo, false)) { - b = true; - } - } - if(b) { - m = mtest; - m.calculatesub(eo, eo, false); - return true; - } - } - return false; -} -bool MathStructure::expandPartialFractions(const EvaluationOptions &eo) { - return expand_partial_fractions(*this, eo, true); -} - -int contains_unsolved_integrate(const MathStructure &mstruct, MathStructure *this_mstruct, MathStructure *parent_parts); -int contains_unsolved_integrate(const MathStructure &mstruct, MathStructure *this_mstruct, vector *parent_parts) { - if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_integrate) { - if(this_mstruct->equals(mstruct[0], true)) return 3; - for(size_t i = 0; i < parent_parts->size(); i++) { - if(mstruct[0].equals(*(*parent_parts)[i], true)) return 2; - } - return 1; - } - int ret = 0; - for(size_t i = 0; i < mstruct.size(); i++) { - int ret_i = contains_unsolved_integrate(mstruct[i], this_mstruct, parent_parts); - if(ret_i == 1) { - return 1; - } else if(ret_i > ret) { - ret = ret_i; - } - } - return ret; -} - -bool fix_abs_x(MathStructure &mstruct, const MathStructure &x_var, const EvaluationOptions &eo, bool definite_integral) { - bool b = false; - if(mstruct.isFunction() && mstruct.size() == 1 && mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_abs && mstruct[0].size() == 1) { - if(!definite_integral && (mstruct.function() == CALCULATOR->f_sin || mstruct.function() == CALCULATOR->f_tan || mstruct.function() == CALCULATOR->f_sinh || mstruct.function() == CALCULATOR->f_tanh || mstruct.function() == CALCULATOR->f_asin || mstruct.function() == CALCULATOR->f_atan || mstruct.function() == CALCULATOR->f_asinh || mstruct.function() == CALCULATOR->f_atanh) && mstruct[0][0].representsNonComplex(true)) { - mstruct[0].setToChild(1, true); - mstruct.multiply_nocopy(new MathStructure(CALCULATOR->f_signum, &mstruct[0], &m_zero, NULL)); - mstruct.evalSort(false); - b = true; - } else if((mstruct.function() == CALCULATOR->f_cos || mstruct.function() == CALCULATOR->f_cosh) && mstruct[0][0].representsNonComplex(true)) { - mstruct[0].setToChild(1, true); - b = true; - } else if(mstruct.function() == CALCULATOR->f_ln) { - if(mstruct[0][0].representsNonComplex(true)) { - b = true; - } else { - MathStructure mtest(mstruct[0][0]); - transform_absln(mtest, -1, false, x_var, eo); - b = !mtest.isFunction() || mtest.function() != CALCULATOR->f_ln || (mtest.size() >= 0 && mtest[0].isFunction() && mtest[0].function() == CALCULATOR->f_abs); - } - if(b) { - mstruct[0].setToChild(1, true); - mstruct[0] ^= nr_two; - mstruct /= nr_two; - } - } - } - for(size_t i = 0; i < mstruct.size(); i++) { - if(fix_abs_x(mstruct[i], x_var, eo, definite_integral)) b = true; - } - return b; -} -MathStructure *find_abs_x(MathStructure &mstruct, const MathStructure &x_var, const MathStructure *parent = NULL, int level = 0) { - if(mstruct.isFunction()) { - if(((mstruct.function() == CALCULATOR->f_abs && mstruct.size() == 1) || (mstruct.function() == CALCULATOR->f_root && VALID_ROOT(mstruct) && mstruct[1].number().isOdd())) && mstruct[0].contains(x_var, true) > 0 && mstruct[0].representsNonComplex(true)) { - return &mstruct[0]; - } - if((!parent || parent->isMultiplication() || parent->isAddition()) && level <= 2 && mstruct.function() == CALCULATOR->f_ln && mstruct.size() == 1) { - if((mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_root) || (mstruct[0].isPower() && mstruct[0][1].isInteger() && mstruct[0][0].isFunction() && mstruct[0][0].function() == CALCULATOR->f_root)) return NULL; - if(mstruct[0].isMultiplication() && mstruct[0].size() == 2 && ((mstruct[0][1].isFunction() && mstruct[0][1].function() == CALCULATOR->f_root) || (mstruct[0][1].isPower() && mstruct[0][1][1].isInteger() && mstruct[0][1][0].isFunction() && mstruct[0][1][0].function() == CALCULATOR->f_root))) return NULL; - } - } - for(size_t i = 0; i < mstruct.size(); i++) { - MathStructure *m = find_abs_x(mstruct[i], x_var, &mstruct, level + 1); - if(m) return m; - } - return NULL; -} -bool fix_sgn_x(MathStructure &mstruct, const MathStructure &x_var, const EvaluationOptions &eo) { - if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_signum && mstruct.size() == 2) { - MathStructure mtest(mstruct); - KnownVariable *var = new KnownVariable("", format_and_print(x_var), ((UnknownVariable*) x_var.variable())->interval()); - mtest.replace(x_var, var); - CALCULATOR->beginTemporaryStopMessages(); - mtest.eval(eo); - var->destroy(); - if(!CALCULATOR->endTemporaryStopMessages() && !mtest.isFunction()) { - mstruct.set(mtest); - return true; - } - } - bool b = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(fix_sgn_x(mstruct[i], x_var, eo)) b = true; - } - return b; -} -bool replace_abs_x(MathStructure &mstruct, const MathStructure &marg, bool b_minus, const MathStructure *parent = NULL, int level = 0) { - if(mstruct.isFunction()) { - if(mstruct.function() == CALCULATOR->f_abs && mstruct.size() == 1 && mstruct[0].equals(marg, true)) { - mstruct.setToChild(1); - if(b_minus) mstruct.negate(); - return true; - } else if(mstruct.function() == CALCULATOR->f_root && VALID_ROOT(mstruct) && mstruct[1].number().isOdd() && mstruct[0].equals(marg, true)) { - if(b_minus) mstruct[0].negate(); - mstruct[1].number().recip(); - mstruct.setType(STRUCT_POWER); - mstruct.childrenUpdated(); - if(b_minus) mstruct.negate(); - return true; - } - if((!parent || parent->isMultiplication() || parent->isAddition()) && level <= 2 && mstruct.function() == CALCULATOR->f_ln && mstruct.size() == 1) { - if((mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_root) || (mstruct[0].isPower() && mstruct[0][1].isInteger() && mstruct[0][0].isFunction() && mstruct[0][0].function() == CALCULATOR->f_root)) return false; - if(mstruct[0].isMultiplication() && mstruct[0].size() == 2 && ((mstruct[0][1].isFunction() && mstruct[0][1].function() == CALCULATOR->f_root) || (mstruct[0][1].isPower() && mstruct[0][1][1].isInteger() && mstruct[0][1][0].isFunction() && mstruct[0][1][0].function() == CALCULATOR->f_root))) return false; - } - } - if(mstruct.isPower() && mstruct[1].isInteger() && mstruct[1].number().isOdd() && mstruct[0].isFunction() && mstruct[0].function() == CALCULATOR->f_root && VALID_ROOT(mstruct[0]) && mstruct[0][1].number().isOdd() && mstruct[0][0].equals(marg, true)) { - mstruct[1].number().divide(mstruct[0][1].number()); - mstruct[0].setToChild(1, true); - if(mstruct[1].number().isOne()) mstruct.setToChild(1, true); - if(b_minus) mstruct[0].negate(); - mstruct.childrenUpdated(); - if(b_minus) mstruct.negate(); - return true; - } - bool b = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(replace_abs_x(mstruct[i], marg, b_minus, &mstruct, level + 1)) { - mstruct.childUpdated(i + 1); - b = true; - } - } - return b; -} - -bool test_sign_zero(const MathStructure &m, const MathStructure &x_var, const MathStructure &mzero, const EvaluationOptions &eo) { - if(m.contains(x_var, true) <= 0) return false; - if(m.isMultiplication()) { - for(size_t i = 0; i < m.size(); i++) { - if(m[i].isPower() && m[i][1].representsNegative() && test_sign_zero(m[i][0], x_var, mzero, eo)) return true; - } - } - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mtest(m); - mtest.replace(x_var, mzero); - mtest.transform(COMPARISON_EQUALS, m_zero); - mtest.eval(eo); - return !CALCULATOR->endTemporaryStopMessages() && mtest.isOne(); -} - -void do_signum(MathStructure &m1, const MathStructure &marg) { - /*m1 *= marg; - m1 *= marg; - m1.last().transform(CALCULATOR->f_abs); - m1.last().inverse();*/ - m1 *= MathStructure(CALCULATOR->f_signum, &marg, &m_zero, NULL); -} -bool try_sign(MathStructure &m1, MathStructure &m2, const MathStructure &marg, const MathStructure &x_var, const MathStructure &mzero, const EvaluationOptions &eo, bool *test_zero = NULL) { - if(m1.equals(m2, true)) return true; - if(m1.isNumber() && m1.number().isReal() && m2.isNumber() && m2.number().isReal()) { - m2.number().negate(); - if(m1.number().equals(m2.number(), true)) { - m2.number().negate(); - if(!test_sign_zero(m1, x_var, mzero, eo)) { - if(!test_zero) return false; - *test_zero = true; - } - if(!test_zero || !(*test_zero)) do_signum(m1, marg); - return true; - } - m2.number().negate(); - return false; - } - if(m1.type() != m2.type()) { - if((m1.isMultiplication() && m1.size() == 2 && m1[0].isMinusOne() && try_sign(m1[1], m2, marg, x_var, mzero, eo)) || (m2.isMultiplication() && m2.size() == 2 && m2[0].isMinusOne() && try_sign(m1, m2[1], marg, x_var, mzero, eo))) { - if(!test_sign_zero(m1, x_var, mzero, eo)) { - if(!test_zero) return false; - *test_zero = true; - } - if(!test_zero || !(*test_zero)) do_signum(m1, marg); - return true; - } - return false; - } - if(m1.size() == 0) return false; - if(m1.size() != m2.size()) { - if(m1.isMultiplication() && ((m1.size() == m2.size() + 1 && m1[0].isMinusOne()) || (m2.size() == m1.size() + 1 && m2[0].isMinusOne()))) { - if(m1.size() > m2.size()) { - for(size_t i = 0; i < m2.size(); i++) { - if(!try_sign(m1[i + 1], m2[i], marg, x_var, mzero, eo)) return false; - } - } else { - for(size_t i = 0; i < m1.size(); i++) { - if(!try_sign(m1[i], m2[i + 1], marg, x_var, mzero, eo)) return false; - } - } - if(!test_sign_zero(m1, x_var, mzero, eo)) { - if(!test_zero) return false; - *test_zero = true; - } - if(!test_zero || !(*test_zero)) do_signum(m1, marg); - return true; - } - return false; - } - if(m1.isFunction() && m1.function() != m2.function()) return false; - if(m1.isComparison() && m1.comparisonType() != m2.comparisonType()) return false; - if(m1.isMultiplication() && m1.size() > 1 && m1[0].isNumber() && !m1[0].equals(m2[0], true)) { - if(!m1[0].isNumber()) return false; - m2[0].number().negate(); - if(m1[0].number().equals(m2[0].number(), true)) { - m2[0].number().negate(); - for(size_t i = 1; i < m1.size(); i++) { - if(!try_sign(m1[i], m2[i], marg, x_var, mzero, eo)) return false; - } - if(!test_sign_zero(m1, x_var, mzero, eo)) { - if(!test_zero) return false; - *test_zero = true; - } - if(!test_zero || !(*test_zero)) do_signum(m1, marg); - return true; - } - m2[0].number().negate(); - return false; - }/* else if(m1.isPower()) { - bool b_tz = false; - if(!try_sign(m1[0], m2[0], marg, x_var, mzero, eo, &b_tz) || b_tz) return false; - if(!try_sign(m1[1], m2[1], marg, x_var, mzero, eo, &b_tz)) return false; - if(b_tz && (test_sign_zero(m1[1], x_var, mzero, eo) || !test_sign_zero(m1[0], x_var, mzero, eo))) return false; - return true; - }*/ - bool b_tz = false; - bool b_equal = false; - for(size_t i = 0; i < m1.size(); i++) { - if(!b_equal && m1.isAddition() && m1[i].equals(m2[i], true)) b_equal = true; - else if(!try_sign(m1[i], m2[i], marg, x_var, mzero, eo, m1.isAddition() ? &b_tz : NULL)) return false; - if(b_tz && b_equal) break; - } - if(b_tz) { - if(!test_sign_zero(m1, x_var, mzero, eo)) { - if(!test_zero) return false; - *test_zero = true; - } - if(!test_zero || !(*test_zero)) do_signum(m1, marg); - } - return true; -} -bool contains_imaginary(const MathStructure &m) { - if(m.isNumber()) return m.number().hasImaginaryPart(); - if(m.isVariable() && m.variable()->isKnown()) return contains_imaginary(((KnownVariable*) m.variable())->get()); - for(size_t i = 0; i < m.size(); i++) { - if(contains_imaginary(m[i])) return true; - } - return false; -} - -int MathStructure::integrate(const MathStructure &x_var, const EvaluationOptions &eo_pre, bool simplify_first, int use_abs, bool definite_integral, bool try_abs, int max_part_depth, vector *parent_parts) { - if(CALCULATOR->aborted()) CANNOT_INTEGRATE - EvaluationOptions eo = eo_pre; - eo.protected_function = CALCULATOR->f_integrate; - EvaluationOptions eo2 = eo; - eo2.expand = true; - eo2.combine_divisions = false; - eo2.sync_units = false; - EvaluationOptions eo_t = eo; - eo_t.approximation = APPROXIMATION_TRY_EXACT; - eo_t.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; - if(simplify_first) { - unformat(eo_pre); - calculateFunctions(eo2); - calculatesub(eo2, eo2); - if(CALCULATOR->aborted()) CANNOT_INTEGRATE - } - bool recalc = false; - - if(fix_abs_x(*this, x_var, eo, definite_integral)) recalc = true; - - MathStructure *mfound = NULL; - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - if(fix_sgn_x(*this, x_var, eo_t)) recalc = true; - while(true) { - mfound = find_abs_x(*this, x_var); - if(mfound) { - MathStructure m_interval(*mfound); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - CALCULATOR->beginTemporaryStopMessages(); - m_interval.eval(eo_t); - if(!CALCULATOR->endTemporaryStopMessages()) break; - if(m_interval.representsNonNegative(true)) { - replace_abs_x(*this, MathStructure(*mfound), false); - recalc = true; - } else if(m_interval.representsNegative(true)) { - replace_abs_x(*this, MathStructure(*mfound), true); - recalc = true; - } else { - break; - } - } else { - break; - } - } - } - if(recalc) calculatesub(eo2, eo2); - if(equals(x_var)) { - raise(2); - multiply(MathStructure(1, 2, 0)); - return true; - } - if(containsRepresentativeOf(x_var, true, true) == 0) { - multiply(x_var); - return true; - } - - if(m_type == STRUCT_ADDITION) { - bool b = false; - MathStructure mbak(*this); - for(size_t i = 0; i < SIZE; i++) { - int bint = CHILD(i).integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts); - if(bint < 0) { - set(mbak); - CANNOT_INTEGRATE_INTERVAL - } - if(bint > 0) b = true; - CHILD_UPDATED(i); - } - if(!b) return false; - return true; - } else if(m_type == STRUCT_MULTIPLICATION) { - MathStructure mstruct; - bool b = false; - for(size_t i = 0; i < SIZE;) { - if(CHILD(i).containsRepresentativeOf(x_var, true, true) == 0) { - if(b) { - mstruct *= CHILD(i); - } else { - mstruct = CHILD(i); - b = true; - } - ERASE(i); - } else { - i++; - } - } - if(b) { - if(SIZE == 1) { - setToChild(1, true); - } else if(SIZE == 0) { - set(mstruct, true); - return true; - } - if(integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) { - multiply(mstruct); - CANNOT_INTEGRATE_INTERVAL - } - multiply(mstruct); - return true; - } - for(size_t i = 0; i < SIZE; i++) { - if((CHILD(i).isFunction() && CHILD(i).function() == CALCULATOR->f_abs && CHILD(i).size() == 1) || (CHILD(i).isPower() && CHILD(i)[0].isFunction() && CHILD(i)[0].function() == CALCULATOR->f_abs && CHILD(i)[0].size() == 1 && CHILD(i)[1].representsOdd())) { - if(definite_integral) CANNOT_INTEGRATE - bool b = (m_type == STRUCT_POWER ? CHILD(0)[0].representsNonComplex(true) : CHILD(0).representsNonComplex(true)); - if(!b && !(m_type == STRUCT_POWER ? CHILD(0)[0].representsComplex(true) : CHILD(0).representsComplex(true))) { - MathStructure mtest(m_type == STRUCT_POWER ? CHILD(0)[0] : CHILD(0)); - CALCULATOR->beginTemporaryStopMessages(); - mtest.eval(eo_t); - CALCULATOR->endTemporaryStopMessages(); - b = mtest.representsNonComplex(true); - if(!b && !mtest.representsComplex(true)) { - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - CALCULATOR->beginTemporaryStopMessages(); - mtest.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - mtest.eval(eo_t); - CALCULATOR->endTemporaryStopMessages(); - b = mtest.representsNonComplex(true); - if(!b && !mtest.representsComplex(true) && !contains_imaginary(mtest) && !contains_imaginary(((UnknownVariable*) x_var.variable())->interval())) { - CALCULATOR->error(false, "Integral assumed real", NULL); - b = true; - } - } else if(!contains_imaginary(mtest)) { - CALCULATOR->error(false, "Integral assumed real", NULL); - b = true; - } - } - } - if(b) { - MathStructure mmul(CHILD(i).isPower() ? CHILD(i)[0] : CHILD(i)); - if(CHILD(i).isPower()) CHILD(i)[0].setToChild(1, true); - else CHILD(i).setToChild(1, true); - mmul.inverse(); - mmul *= CHILD(i).isPower() ? CHILD(i)[0] : CHILD(i); - if(integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) { - multiply(mmul); - CANNOT_INTEGRATE_INTERVAL - } - multiply(mmul); - return true; - } - } - } - } else if((m_type == STRUCT_FUNCTION && o_function == CALCULATOR->f_abs && SIZE == 1) || (m_type == STRUCT_POWER && CHILD(0).isFunction() && CHILD(0).function() == CALCULATOR->f_abs && CHILD(0).size() == 1 && CHILD(1).representsOdd())) { - bool b = (m_type == STRUCT_POWER ? CHILD(0)[0].representsNonComplex(true) : CHILD(0).representsNonComplex(true)); - if(!b && !(m_type == STRUCT_POWER ? CHILD(0)[0].representsComplex(true) : CHILD(0).representsComplex(true))) { - MathStructure mtest(m_type == STRUCT_POWER ? CHILD(0)[0] : CHILD(0)); - CALCULATOR->beginTemporaryStopMessages(); - mtest.eval(eo_t); - CALCULATOR->endTemporaryStopMessages(); - b = mtest.representsNonComplex(true); - if(!b && !mtest.representsComplex(true)) { - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - CALCULATOR->beginTemporaryStopMessages(); - mtest.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - mtest.eval(eo_t); - CALCULATOR->endTemporaryStopMessages(); - b = mtest.representsNonComplex(true); - if(!b && !mtest.representsComplex(true) && !contains_imaginary(mtest) && !contains_imaginary(((UnknownVariable*) x_var.variable())->interval())) { - CALCULATOR->error(false, "Integral assumed real", NULL); - b = true; - } - } else if(!contains_imaginary(mtest)) { - CALCULATOR->error(false, "Integral assumed real", NULL); - b = true; - } - } - } - if(b) { - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - if(fix_sgn_x(*this, x_var, eo_t)) recalc = true; - while(true) { - mfound = find_abs_x(*this, x_var); - if(mfound) { - MathStructure m_interval(*mfound); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - CALCULATOR->beginTemporaryStopMessages(); - m_interval.eval(eo_t); - if(!CALCULATOR->endTemporaryStopMessages()) break; - if(m_interval.representsNonNegative(true)) { - replace_abs_x(*this, MathStructure(*mfound), false); - recalc = true; - } else if(m_interval.representsNegative(true)) { - replace_abs_x(*this, MathStructure(*mfound), true); - recalc = true; - } else { - break; - } - } else { - break; - } - } - } - if(m_type == STRUCT_FUNCTION && CHILD(0).isFunction() && (CHILD(0).function() == CALCULATOR->f_sin || CHILD(0).function() == CALCULATOR->f_cos) && CHILD(0).size() == 1) { - MathStructure madd, mmul, mexp; - if(integrate_info(CHILD(0)[0], x_var, madd, mmul, mexp, true) && mexp.isOne() && madd.isZero()) { - setToChild(1, true); - MathStructure mdivpi(x_var); - if(!mmul.isOne()) mdivpi *= mmul; - mdivpi /= CALCULATOR->v_pi; - if(o_function == CALCULATOR->f_cos) mdivpi += nr_half; - mdivpi.transform(CALCULATOR->f_floor); - if(o_function == CALCULATOR->f_sin) setFunction(CALCULATOR->f_cos); - else setFunction(CALCULATOR->f_sin); - CHILD(0) += mdivpi; - CHILD(0).last() *= CALCULATOR->v_pi; - CHILD(0).last() *= CALCULATOR->getRadUnit(); - CHILD(0).last().negate(); - CHILD(0).childUpdated(CHILD(0).size()); - CHILD_UPDATED(0) - if(o_function == CALCULATOR->f_cos) negate(); - if(!mmul.isOne()) divide(mmul); - add(mdivpi); - LAST *= nr_two; - if(!mmul.isOne()) LAST /= mmul; - CHILD_UPDATED(SIZE - 1) - return true; - } - } - MathStructure mstruct(m_type == STRUCT_POWER ? CHILD(0) : *this); - if(m_type != STRUCT_POWER || (CHILD(1).isInteger() && !CHILD(1).number().isMinusOne() && CHILD(1).number().isOdd())) { - MathStructure mexp, mmul, madd; - if(integrate_info(m_type == STRUCT_POWER ? CHILD(0)[0] : CHILD(0), x_var, madd, mmul, mexp) && mexp.isOne()) { - MathStructure mpowp1(m_type == STRUCT_POWER ? CHILD(1) : nr_two); - if(m_type == STRUCT_POWER) { - mpowp1 += m_one; - setToChild(1, true); - } - MathStructure msgn(*this); - msgn.setFunction(CALCULATOR->f_signum); - setToChild(1, true); - raise(mpowp1); - divide(mmul); - divide(mpowp1); - multiply(msgn); - return true; - } - } - if(definite_integral) CANNOT_INTEGRATE - MathStructure mmul; - MathStructure mbak(*this); - if(isPower()) { - mmul = CHILD(0); - CHILD(0).setToChild(1, true); - mmul.inverse(); - mmul *= CHILD(0); - } else { - mmul = *this; - setToChild(1, true); - mmul.inverse(); - mmul *= *this; - } - int b_int = integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts); - if(b_int <= 0) { - set(mbak); - if(b_int < 0) CANNOT_INTEGRATE_INTERVAL - CANNOT_INTEGRATE - } - multiply(mmul); - return true; - } - } - mfound = try_abs ? find_abs_x(*this, x_var) : NULL; - if(mfound) { - MathStructure mtest(*this); - MathStructure mtest_m(mtest); - if(!replace_abs_x(mtest, *mfound, false) || !replace_abs_x(mtest_m, *mfound, true)) CANNOT_INTEGRATE - eo_t.isolate_x = true; - eo_t.isolate_var = &x_var; - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mpos(*mfound); - mpos.transform(COMPARISON_EQUALS_GREATER, m_zero); - mpos.eval(eo_t); - UnknownVariable *var_p = NULL, *var_m = NULL; - if(!CALCULATOR->endTemporaryStopMessages() && mpos.isComparison() && (mpos.comparisonType() == COMPARISON_EQUALS_GREATER || mpos.comparisonType() == COMPARISON_EQUALS_LESS) && mpos[0] == x_var && mpos[1].isNumber()) { - var_p = new UnknownVariable("", format_and_print(x_var)); - var_m = new UnknownVariable("", format_and_print(x_var)); - Number nr_interval_p, nr_interval_m; - if(x_var.isVariable() && !x_var.variable()->isKnown() && ((UnknownVariable*) x_var.variable())->interval().isNumber() && ((UnknownVariable*) x_var.variable())->interval().number().isInterval() && ((UnknownVariable*) x_var.variable())->interval().number().isReal() && ((UnknownVariable*) x_var.variable())->interval().number().upperEndPoint().isGreaterThanOrEqualTo(mpos[1].number()) && ((UnknownVariable*) x_var.variable())->interval().number().lowerEndPoint().isLessThanOrEqualTo(mpos[1].number())) { - if(mpos.comparisonType() == COMPARISON_EQUALS_GREATER) { - nr_interval_p.setInterval(mpos[1].number(), ((UnknownVariable*) x_var.variable())->interval().number().upperEndPoint()); - nr_interval_m.setInterval(((UnknownVariable*) x_var.variable())->interval().number().lowerEndPoint(), mpos[1].number()); - } else { - nr_interval_m.setInterval(mpos[1].number(), ((UnknownVariable*) x_var.variable())->interval().number().upperEndPoint()); - nr_interval_p.setInterval(((UnknownVariable*) x_var.variable())->interval().number().lowerEndPoint(), mpos[1].number()); - } - } else { - - if(mpos.comparisonType() == COMPARISON_EQUALS_GREATER) { - nr_interval_p.setInterval(mpos[1].number(), nr_plus_inf); - nr_interval_m.setInterval(nr_minus_inf, mpos[1].number()); - } else { - nr_interval_m.setInterval(mpos[1].number(), nr_plus_inf); - nr_interval_p.setInterval(nr_minus_inf, mpos[1].number()); - } - } - var_p->setInterval(nr_interval_p); - var_m->setInterval(nr_interval_m); - mtest.replace(x_var, var_p); - mtest_m.replace(x_var, var_m); - } - int bint1 = mtest.integrate(var_p ? var_p : x_var, eo, true, use_abs, true, definite_integral, max_part_depth, parent_parts); - if(var_p) { - mtest.replace(var_p, x_var); - var_p->destroy(); - } - if(bint1 <= 0 || mtest.containsFunction(CALCULATOR->f_integrate, true) > 0) { - if(var_m) var_m->destroy(); - if(bint1 < 0) CANNOT_INTEGRATE_INTERVAL - CANNOT_INTEGRATE; - } - int bint2 = mtest_m.integrate(var_m ? var_m : x_var, eo, true, use_abs, false, definite_integral, max_part_depth, parent_parts); - if(var_m) { - mtest_m.replace(var_m, x_var); - var_m->destroy(); - } - if(bint2 < 0) CANNOT_INTEGRATE_INTERVAL - if(bint2 == 0 || mtest_m.containsFunction(CALCULATOR->f_integrate, true) > 0) CANNOT_INTEGRATE; - MathStructure m1(mtest), m2(mtest_m); - CALCULATOR->beginTemporaryStopMessages(); - MathStructure mzero(*mfound); - mzero.transform(COMPARISON_EQUALS, m_zero); - mzero.eval(eo_t); - if(!CALCULATOR->endTemporaryStopMessages() && mzero.isComparison() && mzero.comparisonType() == COMPARISON_EQUALS && mzero[0] == x_var) { - mzero.setToChild(2); - CALCULATOR->beginTemporaryStopMessages(); - m1.calculatesub(eo2, eo2, true); - m2.calculatesub(eo2, eo2, true); - m1.evalSort(true, true); - m2.evalSort(true, true); - eo_t.test_comparisons = true; - eo_t.isolate_x = false; - eo_t.isolate_var = NULL; - if((definite_integral && m1.equals(m2, true)) || (!definite_integral && try_sign(m1, m2, *mfound, x_var, mzero, eo_t))) { - set(m1, true); - CALCULATOR->endTemporaryStopMessages(true); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - } - /*MathStructure mcmp(*mfound); - mcmp.transform(COMPARISON_EQUALS_GREATER, m_zero); - set(mtest); - multiply(mcmp); - mcmp.setComparisonType(COMPARISON_LESS); - mtest_m *= mcmp; - add(mtest_m);*/ - /*eo2.test_comparisons = true; - calculatesub(eo2, eo2, true);*/ - - ///return true; - } - - switch(m_type) { - case STRUCT_UNIT: {} - case STRUCT_NUMBER: { - multiply(x_var); - break; - } - case STRUCT_POWER: { - if(CHILD(1).isNumber() || CHILD(1).containsRepresentativeOf(x_var, true, true) == 0) { - bool b_minusone = (CHILD(1).isNumber() && CHILD(1).number().isMinusOne()); - MathStructure madd, mmul, mmul2, mexp; - if(CHILD(0).isFunction()) { - MathStructure mbase(CHILD(0)); - int bint = integrate_function(mbase, x_var, eo, CHILD(1), m_one, m_zero, m_one, use_abs, definite_integral, max_part_depth, parent_parts); - if(bint < 0) CANNOT_INTEGRATE_INTERVAL - if(bint) { - set(mbase, true); - return true; - } - } else if(integrate_info(CHILD(0), x_var, madd, mmul, mmul2, false, true)) { - if(mmul2.isZero()) { - if(madd.isZero() && mmul.isOne()) { - if(b_minusone) { - if(!transform_absln(CHILD(0), use_abs, definite_integral, x_var, eo)) CANNOT_INTEGRATE_INTERVAL - SET_CHILD_MAP(0); - } else { - CHILD(1) += m_one; - MathStructure mstruct(CHILD(1)); - divide(mstruct); - } - return true; - } else if(b_minusone) { - if(!transform_absln(CHILD(0), use_abs, definite_integral, x_var, eo)) CANNOT_INTEGRATE_INTERVAL - SET_CHILD_MAP(0); - if(!mmul.isOne()) divide(mmul); - return true; - } else { - if(definite_integral && !madd.isZero() && (!x_var.representsNonComplex(true) || !mmul.representsNonComplex(true)) && !CHILD(1).representsInteger() && COMPARISON_MIGHT_BE_EQUAL(x_var.compare(m_zero)) && !COMPARISON_IS_EQUAL_OR_LESS(madd.compare(m_zero))) CANNOT_INTEGRATE - mexp = CHILD(1); - mexp += m_one; - SET_CHILD_MAP(0); - raise(mexp); - if(!mmul.isOne()) mexp *= mmul; - divide(mexp); - return true; - } - } else if(mmul.isZero() && !madd.isZero() && CHILD(1).number().denominatorIsTwo()) { - MathStructure mmulsqrt2(mmul2); - if(!mmul2.isOne()) mmulsqrt2 ^= nr_half; - Number num(CHILD(1).number().numerator()); - if(num.isOne()) { - MathStructure mthis(*this); - add(x_var); - if(!mmul2.isOne()) LAST *= mmulsqrt2; - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mthis); CANNOT_INTEGRATE_INTERVAL} - multiply(madd); - mthis *= x_var; - if(!mmul2.isOne()) mthis *= mmulsqrt2; - add(mthis); - multiply(nr_half); - if(!mmul2.isOne()) divide(mmulsqrt2); - childrenUpdated(true); - return true; - } else if(num == 3) { - MathStructure mterm3(*this); - CHILD(1).number().set(1, 2, 0, true); - MathStructure mterm2(*this); - add(x_var); - if(!mmul2.isOne()) LAST *= mmulsqrt2; - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mterm3); CANNOT_INTEGRATE_INTERVAL} - multiply(madd); - LAST ^= nr_two; - multiply(Number(3, 8, 0), true); - mterm2 *= x_var; - if(!mmul2.isOne()) mterm2 *= mmulsqrt2; - mterm2 *= madd; - mterm2 *= Number(3, 8, 0); - mterm3 *= x_var; - if(!mmul2.isOne()) mterm3 *= mmulsqrt2; - mterm3 *= Number(1, 4, 0); - add(mterm2); - add(mterm3); - if(!mmul2.isOne()) divide(mmulsqrt2); - return true; - } else if(num == 5) { - CHILD(1).number().set(1, 2, 0, true); - MathStructure mterm2(*this); - MathStructure mterm3(*this); - MathStructure mterm4(*this); - multiply(x_var); - LAST ^= Number(5, 1); - if(!mmul2.isOne()) { - multiply(mmul2, true); - LAST ^= nr_two; - } - multiply(Number(1, 6), true); - if(!mmul2.isOne()) mterm2 *= mmulsqrt2; - mterm2 += x_var; - if(!mmul2.isOne()) mterm2[mterm2.size() - 1] *= mmul2; - if(!transform_absln(mterm2, use_abs, definite_integral, x_var, eo)) {set(mterm3); CANNOT_INTEGRATE_INTERVAL} - mterm2 *= madd; - mterm2.last() ^= nr_three; - if(!mmul2.isOne()) mterm2 /= mmulsqrt2; - mterm2 *= Number(5, 16); - mterm3 *= x_var; - mterm3 *= madd; - mterm3.last() ^= nr_two; - mterm3 *= Number(11, 16); - mterm4 *= x_var; - mterm4.last() ^= nr_three; - mterm4 *= madd; - if(!mmul2.isOne()) mterm4 *= mmul2; - mterm4 *= Number(13, 24); - add(mterm2); - add(mterm3); - add(mterm4); - childrenUpdated(true); - return true; - } else if(num.isMinusOne()) { - MathStructure mbak(*this); - CHILD(1).number().set(1, 2, 0, true); - if(!mmul2.isOne()) multiply(mmulsqrt2); - add(x_var); - if(!mmul2.isOne()) LAST.multiply(mmul2); - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - if(!mmul2.isOne()) divide(mmulsqrt2); - return true; - } else if(num == -3) { - CHILD(1).number().set(-1, 2, 0, true); - madd.inverse(); - multiply(madd); - multiply(x_var); - return true; - } - } else if(b_minusone) { - MathStructure m4acmb2(madd); - m4acmb2 *= mmul2; - m4acmb2 *= Number(4, 1); - m4acmb2 += mmul; - m4acmb2.last() ^= nr_two; - m4acmb2.last().negate(); - m4acmb2.calculatesub(eo, eo, true); - if(!m4acmb2.representsNonZero(true)) { - if(m4acmb2.isZero()) { - set(x_var, true); - multiply(mmul2); - multiply(nr_two, true); - add(mmul); - inverse(); - multiply(Number(-2, 1)); - return true; - } else if(!warn_about_denominators_assumed_nonzero(m4acmb2, eo)) { - CANNOT_INTEGRATE - } - } - if(m4acmb2.representsNegative(true)) { - MathStructure mbak(*this); - MathStructure m2axpb(x_var); - m2axpb *= mmul2; - m2axpb *= nr_two; - m2axpb += mmul; - MathStructure mb2m4ac(madd); - mb2m4ac *= mmul2; - mb2m4ac *= Number(-4, 1); - mb2m4ac += mmul; - mb2m4ac.last() ^= nr_two; - mb2m4ac ^= nr_half; - set(m2axpb); - subtract(mb2m4ac); - multiply(m2axpb); - LAST += mb2m4ac; - LAST ^= nr_minus_one; - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - divide(mb2m4ac); - return true; - } - m4acmb2 ^= Number(-1, 2); - set(x_var, true); - multiply(mmul2); - multiply(nr_two, true); - add(mmul); - multiply(m4acmb2); - transform(CALCULATOR->f_atan); - multiply(nr_two); - multiply(m4acmb2, true); - return true; - } else if(CHILD(1).isInteger() && CHILD(1).number().isNegative()) { - MathStructure m2nm3(CHILD(1)); - m2nm3 *= nr_two; - m2nm3 += Number(3, 1); - CHILD(1).number()++; - MathStructure mnp1(CHILD(1)); - mnp1.number().negate(); - mnp1.number().recip(); - MathStructure mthis(*this); - if(integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) CANNOT_INTEGRATE_INTERVAL - MathStructure m4acmb2(madd); - m4acmb2 *= mmul2; - m4acmb2 *= Number(4, 1); - m4acmb2 += mmul; - m4acmb2.last() ^= nr_two; - m4acmb2.last().negate(); - m4acmb2.inverse(); - MathStructure mfac1(mmul2); - mfac1 *= Number(-2, 1); - mfac1 *= m2nm3; - mfac1 *= mnp1; - mfac1 *= m4acmb2; - multiply(mfac1); - MathStructure mterm2(x_var); - mterm2 *= mmul2; - mterm2 *= nr_two; - mterm2 += mmul; - mterm2 *= m4acmb2; - mterm2 *= mthis; - mterm2 *= mnp1; - add(mterm2); - return true; - } - } else if(integrate_info(CHILD(0), x_var, madd, mmul, mexp, false, false)) { - if(madd.isZero() && !b_minusone) { - MathStructure mden(mexp); - mden *= CHILD(1); - mden += m_one; - multiply(x_var); - divide(mden); - return true; - } else if(b_minusone && mexp.isNumber() && mexp.number().isNegative() && mexp.number().isInteger()) { - if(!madd.isZero()) { - Number nexp(mexp.number()); - nexp.negate(); - MathStructure mtest(x_var); - mtest ^= nexp; - mtest *= madd; - mtest += mmul; - mtest.inverse(); - mtest *= x_var; - mtest.last() ^= nexp; - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - set(mtest, true); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - } - } else if(mexp.isNumber() && mexp.number().isRational() && !mexp.number().isInteger()) { - Number num(mexp.number().numerator()); - Number den(mexp.number().denominator()); - MathStructure morig(x_var); - if(num.isNegative()) den.negate(); - Number den_inv(den); - den_inv.recip(); - morig ^= den_inv; - UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(morig) + RIGHT_PARENTHESIS); - Number den_m1(den); - den_m1--; - MathStructure mtest(var); - if(!num.isOne() && !num.isMinusOne()) mtest ^= num; - if(!mmul.isOne()) mtest *= mmul; - if(!madd.isZero()) mtest += madd; - mtest ^= CHILD(1); - mtest *= var; - if(!den_m1.isOne()) { - mtest.last() ^= den_m1; - mtest.childUpdated(mtest.size()); - } - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(morig); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(morig); - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - set(mtest, true); - replace(var, morig); - multiply(den); - var->destroy(); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } - } else if(integrate_info(CHILD(0), x_var, madd, mmul, mexp, false, false, true) && !madd.isZero()) { - if(mexp.isFunction()) { - MathStructure mfunc(mexp); - int bint = integrate_function(mfunc, x_var, eo, CHILD(1), m_one, madd, mmul, use_abs, definite_integral, max_part_depth, parent_parts); - if(bint < 0) CANNOT_INTEGRATE_INTERVAL - if(bint) { - set(mfunc, true); - return true; - } - } else if(mexp.isPower() && mexp[1].containsRepresentativeOf(x_var, true, true) == 0) { - MathStructure mbase(mexp[0]); - if(integrate_info(mbase, x_var, madd, mmul, mexp, false, false) && mexp.isOne() && (!madd.isZero() || !mmul.isOne())) { - MathStructure mtest(*this); - - UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(mbase) + RIGHT_PARENTHESIS); - mtest.replace(mbase, var, mbase.containsInterval()); - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(mbase); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(mbase); - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - set(mtest, true); - replace(var, mbase); - if(!mmul.isOne()) divide(mmul); - var->destroy(); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } - } - } - if(CHILD(0).isAddition()) { - MathStructure mtest(*this); - if(mtest[0].factorize(eo, false, 0, 0, false, false, NULL, x_var)) { - mmul = m_one; - while(mtest[0].isMultiplication() && mtest[0].size() >= 2 && mtest[0][0].containsRepresentativeOf(x_var, true, true) == 0) { - MathStructure *mchild = &mtest[0][0]; - mchild->ref(); - mtest[0].delChild(1, true); - if(mtest[1].representsInteger(true) || COMPARISON_IS_EQUAL_OR_LESS(mchild->compare(m_zero)) || COMPARISON_IS_EQUAL_OR_LESS(mtest[0].compare(m_zero))) { - if(mmul.isOne()) mmul = *mchild; - else mmul *= *mchild; - mchild->unref(); - } else { - mtest[0].multiply_nocopy(mchild, true); - } - } - if(!mmul.isOne()) { - mmul ^= mtest[1]; - } - MathStructure mtest2(mtest); - if(mtest2.decomposeFractions(x_var, eo) && mtest2.isAddition()) { - bool b = true; - CALCULATOR->beginTemporaryStopMessages(); - for(size_t i = 0; i < mtest2.size(); i++) { - if(mtest2[i].integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) <= 0) { - b = false; - break; - } - } - CALCULATOR->endTemporaryStopMessages(b); - if(b) { - set(mtest2, true); - if(!mmul.isOne()) multiply(mmul); - return true; - } - } - MathStructure mmul2(1, 1, 0); - if(mtest[0].isMultiplication() && mtest[0].size() >= 2 && !mtest[0][0].isAddition()) { - MathStructure *mchild = &mtest[0][0]; - mchild->ref(); - mtest[0].delChild(1, true); - if(mtest[1].representsInteger(true) || COMPARISON_IS_EQUAL_OR_LESS(mchild->compare(m_zero)) || COMPARISON_IS_EQUAL_OR_LESS(mtest[0].compare(m_zero))) { - mmul2 = *mchild; - mmul2.calculateRaise(mtest[1], eo2); - mchild->unref(); - } else { - mtest[0].multiply_nocopy(mchild, true); - } - } - if(mtest[0].isPower()) { - if(mtest[1].representsInteger() || mtest[0][1].representsFraction() || COMPARISON_IS_EQUAL_OR_LESS(mtest[0][0].compare(m_zero))) { - mtest[1].calculateMultiply(mtest[0][1], eo2); - mtest[0].setToChild(1); - } else if(mtest[0][1].representsEven()) { - if(COMPARISON_IS_EQUAL_OR_GREATER(mtest[0][0].compare(m_zero))) { - mtest[1].calculateMultiply(mtest[0][1], eo2); - mtest[0].setToChild(1); - mtest[0].calculateNegate(eo2); - } else if(!definite_integral && mtest[0][0].representsReal(true)) { - mtest[1].calculateMultiply(mtest[0][1], eo2); - mtest[0].setToChild(1); - mtest[0].transform(CALCULATOR->f_abs); - } - } - } - mtest[0].evalSort(false); - if(!mmul2.isOne()) { - mtest *= mmul2; - mtest.evalSort(false); - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0) { - CALCULATOR->endTemporaryStopMessages(true); - set(mtest, true); - if(!mmul.isOne()) multiply(mmul); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - } - if(b_minusone) { - MathStructure mmul2; - if(integrate_info(CHILD(0), x_var, madd, mmul, mmul2, false, true) && (!mmul2.isZero() && (!madd.isZero() || !mmul.isZero()))) { - if(mmul.isZero()) { - if(!mmul2.isOne()) { - madd /= mmul2; - } - madd ^= nr_half; - set(x_var); - divide(madd); - transform(STRUCT_FUNCTION); - setFunction(CALCULATOR->f_atan); - divide(madd); - if(!mmul2.isOne()) divide(mmul2); - return true; - } else { - MathStructure acmb2(4, 1, 0); - acmb2 *= mmul2; - acmb2 *= madd; - MathStructure b2(mmul); - b2 ^= nr_two; - acmb2 -= b2; - acmb2 ^= nr_half; - set(2, 1, 0, true); - multiply(mmul2); - multiply(x_var); - add(mmul); - divide(acmb2); - transform(STRUCT_FUNCTION); - setFunction(CALCULATOR->f_atan); - multiply(nr_two); - divide(acmb2); - return true; - } - } - } - } - } else if((CHILD(0).isNumber() && !CHILD(0).number().isOne()) || (!CHILD(0).isNumber() && CHILD(0).containsRepresentativeOf(x_var, true, true) == 0)) { - MathStructure madd, mmul, mexp; - if(integrate_info(CHILD(1), x_var, madd, mmul, mexp)) { - if(mexp.isOne()) { - if(CHILD(0) == CALCULATOR->v_e) { - if(!mmul.isOne()) divide(mmul); - return true; - } else if(CHILD(0).isNumber() || warn_about_assumed_not_value(CHILD(0), m_one, eo)) { - MathStructure mmulfac(CHILD(0)); - mmulfac.transform(CALCULATOR->f_ln); - if(!mmul.isOne()) mmulfac *= mmul; - divide(mmulfac); - return true; - } - } else if(madd.isZero() || COMPARISON_IS_NOT_EQUAL(madd.compare(m_zero))) { - if(mmul.representsPositive(true) && COMPARISON_IS_EQUAL_OR_GREATER(CHILD(0).compare(m_one)) && CHILD(0).compare(m_zero) == COMPARISON_RESULT_LESS) { - madd.negate(); - mmul.negate(); - CHILD(0).inverse(); - } - if(mexp == nr_two) { - if(!madd.isZero()) {madd ^= CHILD(0); madd.swapChildren(1, 2);} - bool mmul_neg = mmul.representsNegative(true); - if(mmul_neg) mmul.negate(); - if(CHILD(0) == CALCULATOR->v_e) { - set(mmul); - if(!mmul.isOne()) raise(nr_half); - multiply(x_var); - if(!mmul_neg) multiply(nr_one_i); - transform(CALCULATOR->f_erf); - if(!mmul.isOne()) { - mmul ^= Number(-1, 2); - multiply(mmul); - } - multiply(CALCULATOR->v_pi); - LAST ^= nr_half; - multiply(nr_half); - if(!mmul_neg) multiply(nr_minus_i); - } else { - MathStructure mlog(CHILD(0)); - mlog.transform(CALCULATOR->f_ln); - mlog ^= nr_half; - set(mmul); - if(!mmul.isOne()) raise(nr_half); - multiply(x_var); - multiply(mlog); - if(!mmul_neg) multiply(nr_one_i); - transform(CALCULATOR->f_erf); - if(!mmul.isOne()) { - mmul ^= Number(-1, 2); - multiply(mmul); - } - multiply(CALCULATOR->v_pi); - LAST ^= nr_half; - multiply(nr_half); - if(!mmul_neg) multiply(nr_minus_i); - divide(mlog); - } - if(!madd.isZero()) multiply(madd); - return true; - } else if(mexp.isNumber() && mexp.number().isRational() && !mexp.isInteger()) { - Number num(mexp.number().numerator()); - Number den(mexp.number().denominator()); - MathStructure morig(x_var); - Number den_inv(den); - den_inv.recip(); - morig ^= den_inv; - - UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(morig) + RIGHT_PARENTHESIS); - MathStructure mvar(var); - if(!num.isOne()) mvar ^= num; - MathStructure mtest(CHILD(0)); - mtest ^= mvar; - if(!mmul.isOne()) mtest.last() *= mmul; - if(!madd.isZero()) mtest.last() += madd; - mtest.childUpdated(mtest.size()); - Number npow(den); - npow--; - mtest *= var; - if(!npow.isOne()) mtest.last() ^= npow; - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(morig); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(morig); - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - set(mtest, true); - replace(var, morig); - multiply(den); - var->destroy(); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } - //integrate(a^(b+cx^d)) = -x*a^b*(-c*x^d*ln(a))^(-1/d)*igamma(1/d, -c*x^d*ln(a))/d - if(definite_integral) CANNOT_INTEGRATE - if(!madd.isZero()) {madd ^= CHILD(0); madd.swapChildren(1, 2);} - MathStructure mexpinv(mexp); - mexpinv.inverse(); - MathStructure marg2(CHILD(0)); - marg2.transform(CALCULATOR->f_ln); - marg2 *= x_var; - marg2.last() ^= mexp; - marg2 *= mmul; - marg2.negate(); - set(CALCULATOR->f_igamma, &mexpinv, &marg2, NULL); - if(!madd.isZero()) multiply(madd); - multiply(x_var); - multiply(mexpinv); - mexpinv.negate(); - multiply(marg2); - LAST ^= mexpinv; - negate(); - return true; - } - } - } - CANNOT_INTEGRATE - } - case STRUCT_FUNCTION: { - MathStructure mfunc(*this); - int bint = integrate_function(mfunc, x_var, eo, m_one, m_one, m_zero, m_one, use_abs, definite_integral, max_part_depth, parent_parts); - if(bint < 0) CANNOT_INTEGRATE_INTERVAL - if(!bint) CANNOT_INTEGRATE - set(mfunc, true); - break; - } - case STRUCT_MULTIPLICATION: { - if(SIZE == 2) { - if(CHILD(0) != x_var && (CHILD(1) == x_var || (CHILD(1).isPower() && CHILD(1)[0] == x_var))) SWAP_CHILDREN(0, 1); - if(CHILD(1).isPower() && CHILD(1)[1].containsRepresentativeOf(x_var, true, true) == 0) { - MathStructure madd, mmul, mmul2; - MathStructure mexp(CHILD(1)[1]); - if(integrate_info(CHILD(1)[0], x_var, madd, mmul, mmul2, false, true)) { - if(mmul2.isZero() && mexp.isNumber()) { - if(CHILD(0) == x_var) { - MathStructure mbak(*this); - SET_CHILD_MAP(1) - SET_CHILD_MAP(0) - if(mexp.number().isMinusOne()) { - MathStructure mterm(x_var); - if(!mmul.isOne()) mterm /= mmul; - if(!madd.isZero()) { - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - multiply(madd); - if(!mmul.isOne()) { - MathStructure a2(mmul); - a2 ^= nr_two; - divide(a2); - } - negate(); - add(mterm); - } else { - set(mterm, true); - } - } else if(mexp.number() == -2) { - MathStructure mterm(*this); - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - MathStructure a2(mmul); - if(!mmul.isOne()) { - a2 ^= nr_two; - divide(a2); - } - if(!madd.isZero()) { - if(!mmul.isOne()) mterm *= a2; - mterm.inverse(); - mterm *= madd; - } - add(mterm); - } else if(mexp.number().isNegative()) { - MathStructure onemn(1, 1, 0); - onemn += mexp; - MathStructure nm1(mexp); - nm1.negate(); - MathStructure nm2(nm1); - nm1 += nr_minus_one; - nm2 += Number(-2, 1); - raise(nm1); - multiply(nm2); - multiply(nm1); - if(!mmul.isOne()) { - MathStructure a2(mmul); - a2 ^= nr_two; - multiply(a2); - } - inverse(); - MathStructure mnum(x_var); - mnum *= onemn; - if(!mmul.isOne()) mnum *= mmul; - if(!madd.isZero()) mnum -= madd; - multiply(mnum); - } else { - MathStructure nm1(mexp); - nm1 += m_one; - raise(nm1); - MathStructure mnum(x_var); - mnum *= nm1; - if(!mmul.isOne()) mnum *= mmul; - mnum -= madd; - MathStructure mden(mexp); - mden += nr_two; - mden *= nm1; - if(!mmul.isOne()) { - mden *= mmul; - mden.last() ^= nr_two; - } - multiply(mnum); - divide(mden); - return true; - } - return true; - } else if(CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1] == nr_two) { - MathStructure mbak(*this); - SET_CHILD_MAP(1) - SET_CHILD_MAP(0) - if(mexp.number().isMinusOne()) { - MathStructure mterm(x_var); - mterm ^= nr_two; - if(!mmul.isOne()) mterm *= mmul; - if(!madd.isZero()) { - MathStructure mtwobx(-2 ,1, 0); - mtwobx *= madd; - mtwobx *= x_var; - mterm += mtwobx; - } - if(!mmul.isOne()) { - MathStructure a2(mmul); - a2 ^= nr_two; - a2 *= nr_two; - mterm /= a2; - } else { - mterm /= nr_two; - } - if(!madd.isZero()) { - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - MathStructure b2(madd); - b2 ^= nr_two; - multiply(b2); - if(!mmul.isOne()) { - MathStructure a3(mmul); - a3 ^= nr_three; - divide(a3); - } - add(mterm); - } else { - set(mterm, true); - } - } else if(mexp.number() == -2) { - MathStructure mterm1(x_var); - if(!mmul.isOne()) mterm1 *= mmul; - if(!madd.isZero()) { - MathStructure mterm2(*this); - if(!transform_absln(mterm2, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - mterm2 *= madd; - mterm2 *= -2; - MathStructure mterm3(*this); - mterm3.inverse(); - madd ^= nr_two; - mterm3 *= madd; - mterm3.negate(); - set(mterm1); - add(mterm2); - add(mterm3); - } else { - set(mterm1); - } - if(!mmul.isOne()) { - MathStructure a3(mmul); - a3 ^= nr_three; - divide(a3); - } - } else if(mexp.number() == -3) { - if(!madd.isZero()) { - MathStructure mterm2(*this); - mterm2.inverse(); - mterm2 *= madd; - mterm2 *= nr_two; - MathStructure mterm3(*this); - mterm3 ^= nr_two; - mterm3 *= nr_two; - mterm3.inverse(); - madd ^= nr_two; - mterm3 *= madd; - mterm3.negate(); - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - add(mterm2); - add(mterm3); - } else { - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - } - if(!mmul.isOne()) { - MathStructure a3(mmul); - a3 ^= nr_three; - divide(a3); - } - } else { - MathStructure mterm2(*this); - MathStructure mterm3(*this); - raise(nr_three); - CHILD(1) += mexp; - MathStructure mden(mexp); - mden += nr_three; - divide(mden); - if(!madd.isZero()) { - mterm2 ^= nr_two; - mterm2[1] += mexp; - mterm2 *= madd; - mterm2 *= -2; - mden = mexp; - mden += nr_two; - mterm2 /= mden; - mterm3 ^= m_one; - mterm3[1] += mexp; - madd ^= nr_two; - mterm3 *= madd; - mden = mexp; - mden += m_one; - mterm3 /= mden; - add(mterm2); - add(mterm3); - } - if(!mmul.isOne()) { - MathStructure a3(mmul); - a3 ^= nr_three; - divide(a3); - } - } - return true; - } else if(CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1] == nr_minus_one && !madd.isZero()) { - if(mexp.number().isMinusOne()) { - MathStructure mbak(*this); - SET_CHILD_MAP(1) - SET_CHILD_MAP(0) - divide(x_var); - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - divide(madd); - negate(); - return true; - } - } else if(CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1] == -2 && !madd.isZero()) { - if(mexp.number().isMinusOne()) { - MathStructure mbak(*this); - SET_CHILD_MAP(1) - SET_CHILD_MAP(0) - divide(x_var); - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - MathStructure madd2(madd); - madd2 ^= nr_two; - divide(madd2); - if(!mmul.isOne()) multiply(mmul); - madd *= x_var; - madd.inverse(); - subtract(madd); - return true; - } else if(mexp.number() == -2) { - MathStructure mbak(*this); - SET_CHILD_MAP(1) - SET_CHILD_MAP(0) - MathStructure mterm2(madd); - mterm2 ^= nr_two; - MathStructure mterm3(mterm2); - mterm2 *= *this; - mterm2.inverse(); - divide(x_var); - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - MathStructure madd3(madd); - madd3 ^= nr_three; - divide(madd3); - multiply(Number(-2, 1, 0)); - mterm3 *= x_var; - if(!mmul.isOne()) mterm3 *= mmul; - mterm3.inverse(); - add(mterm2); - add(mterm3); - mmul.negate(); - multiply(mmul); - return true; - } - } - } else if(mmul.isZero() && !madd.isZero() && mexp.isNumber() && mexp.number().denominatorIsTwo()) { - Number num(mexp.number()); - if(CHILD(0) == x_var) { - num.add(1); - SET_CHILD_MAP(1) - SET_CHILD_MAP(0) - raise(num); - num.multiply(2); - num.recip(); - multiply(num); - if(!mmul2.isOne()) divide(mmul2); - return true; - } else if(CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isInteger()) { - if(CHILD(0)[1].number() == 2) { - if(num == nr_half) { - MathStructure mbak(*this); - SET_CHILD_MAP(1) - MathStructure mterm2(*this); - if(!mmul2.isOne()) { - mterm2 *= mmul2; - mterm2.last() ^= nr_half; - } - mterm2 += x_var; - if(!mmul2.isOne()) mterm2.last() *= mmul2; - if(!transform_absln(mterm2, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - mterm2.multiply(madd); - mterm2.last() ^= nr_two; - multiply(x_var); - if(!mmul2.isOne()) { - multiply(mmul2); - LAST ^= nr_half; - } - multiply(x_var); - LAST ^= nr_two; - if(!mmul2.isOne()) LAST *= mmul2; - LAST *= nr_two; - LAST += madd; - subtract(mterm2); - multiply(Number(1, 8)); - if(!mmul2.isOne()) { - multiply(mmul2); - LAST ^= Number(-3, 2); - } - return true; - } - } else if(CHILD(0)[1].number() == -1) { - if(num == nr_minus_half) { - MathStructure mbak(*this); - SET_CHILD_MAP(1) - SET_CHILD_MAP(0) - raise(nr_half); - multiply(madd); - LAST ^= nr_half; - add(madd); - transform(CALCULATOR->f_ln); - negate(); - add(x_var); - if(!transform_absln(LAST, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - multiply(madd); - LAST ^= nr_minus_half; - return true; - } else if(num == nr_half) { - MathStructure mbak(*this); - SET_CHILD_MAP(1) - MathStructure mterm2(*this); - mterm2 *= madd; - mterm2.last() ^= nr_half; - mterm2 += madd; - mterm2.transform(CALCULATOR->f_ln); - mterm2 *= madd; - mterm2.last() ^= nr_half; - MathStructure mterm3(x_var); - if(!transform_absln(mterm3, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - mterm3 *= madd; - mterm3.last() ^= nr_half; - subtract(mterm2); - add(mterm3); - return true; - } - } - } - } else if(mmul2.isZero()) { - if(CHILD(0) == x_var) { - SET_CHILD_MAP(1) - CHILD(1) += m_one; - MathStructure mnum(x_var); - mnum *= CHILD(1); - if(!mmul.isOne()) mnum *= mmul; - mnum -= madd; - MathStructure mden(CHILD(1)[0]); - mden += nr_two; - mden *= CHILD(1); - if(!mmul.isOne()) { - mden *= mmul; - mden[mden.size() - 1] ^= nr_two; - } - multiply(mnum); - divide(mden); - return true; - } - } else if(mexp.isMinusOne() && CHILD(0) == x_var) { - MathStructure mbak(*this); - SET_CHILD_MAP(1) - MathStructure mterm2(CHILD(0)); - if(integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) CANNOT_INTEGRATE_INTERVAL - multiply(mmul); - divide(mmul2); - multiply(Number(-1, 2)); - if(!transform_absln(mterm2, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - mterm2 /= mmul2; - mterm2 *= nr_half; - add(mterm2); - return true; - } else if(mexp.isMinusOne() && CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1].isMinusOne()) { - MathStructure mbak(*this); - SET_CHILD_MAP(1) - MathStructure mterm2(CHILD(0)); - if(integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) CANNOT_INTEGRATE_INTERVAL - multiply(mmul); - divide(madd); - multiply(Number(-1, 2)); - mterm2.inverse(); - mterm2 *= x_var; - mterm2.last() ^= nr_two; - if(!transform_absln(mterm2, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - mterm2 /= madd; - mterm2 *= nr_half; - add(mterm2); - return true; - } else if(mexp.isInteger() && mexp.number().isNegative() && CHILD(0) == x_var) { - MathStructure mbak(*this); - SET_CHILD_MAP(1) - MathStructure m2nm3(CHILD(1)); - m2nm3 *= nr_two; - m2nm3 += Number(3, 1); - CHILD(1).number()++; - MathStructure mnp1(CHILD(1)); - mnp1.number().negate(); - mnp1.number().recip(); - MathStructure mthis(*this); - if(integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - MathStructure m4acmb2(madd); - m4acmb2 *= mmul2; - m4acmb2 *= Number(4, 1); - m4acmb2 += mmul; - m4acmb2.last() ^= nr_two; - m4acmb2.last().negate(); - m4acmb2.inverse(); - MathStructure mfac1(mmul); - mfac1 *= m2nm3; - mfac1 *= mnp1; - mfac1 *= m4acmb2; - multiply(mfac1); - MathStructure mterm2(x_var); - mterm2 *= mmul; - mterm2 += madd; - mterm2.last() *= nr_two; - mterm2 *= m4acmb2; - mterm2 *= mthis; - mterm2 *= mnp1; - subtract(mterm2); - return true; - } - } - if(CHILD(0) == x_var || (CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isRational())) { - Number nexp(1, 1, 0); - if(CHILD(0).isPower()) nexp = CHILD(0)[1].number(); - MathStructure madd, mmul, mpow; - if(integrate_info(CHILD(1)[0], x_var, madd, mmul, mpow, false, false, true)) { - if(mpow.isPower() && mpow[0] == x_var) { - mpow.setToChild(2); - if(mpow.isNumber() && mpow.number().isRational() & !mpow.number().isOne()) { - if(!nexp.isOne() && mpow.isInteger()) { - if(mexp.isMinusOne() && nexp.isMinusOne()) { - MathStructure mbak(*this); - if(mpow.number().isNegative()) { - set(x_var, true); - mpow.number().negate(); - raise(mpow); - if(!madd.isOne()) multiply(madd); - add(mmul); - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - divide(mpow); - if(!madd.isOne()) divide(madd); - } else { - SET_CHILD_MAP(1) - SET_CHILD_MAP(0) - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - add(x_var); - if(!transform_absln(LAST, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - LAST *= mpow; - LAST.negate(); - negate(); - divide(mpow); - if(!madd.isOne()) divide(madd); - } - return true; - } - Number mpowmexp(mpow.number()); - mpowmexp -= nexp; - if(mpowmexp.isOne()) { - if(mexp.isMinusOne()) { - MathStructure mbak(*this); - if(mpow.number().isNegative()) { - set(x_var, true); - mpow.number().negate(); - raise(mpow); - if(!madd.isOne()) multiply(madd); - add(mmul); - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - divide(mpow); - divide(madd); - add(x_var); - if(!transform_absln(LAST, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - LAST.negate(); - divide(mpow); - divide(madd); - negate(); - } else { - SET_CHILD_MAP(1) - SET_CHILD_MAP(0) - if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} - divide(mpow); - if(!mmul.isOne()) divide(mmul); - } - } else { - SET_CHILD_MAP(1) - MathStructure mden(CHILD(1)); - CHILD(1) += m_one; - mden *= mpow; - if(!mmul.isOne()) mden *= mmul; - mden += mpow; - if(!mmul.isOne()) mden.last() *= mmul; - divide(mden); - } - return true; - } - } - if(x_var.representsNonNegative(true) || mpow.number().isEven() || mpow.number().isFraction()) { - for(int i = 1; i <= 3; i++) { - if(i > 1 && (!mpow.isInteger() || !mpow.number().isIntegerDivisible(i) || mpow.number() == i)) break; - UnknownVariable *var = NULL; - MathStructure m_replace(x_var); - MathStructure mtest(CHILD(1)); - Number new_pow(nexp); - bool b = false; - if(i == 1) { - m_replace ^= mpow; - var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(m_replace) + RIGHT_PARENTHESIS); - mtest.replace(m_replace, var); - new_pow++; - new_pow -= mpow.number(); - new_pow /= mpow.number(); - b = true; - } else if(i == 2) { - new_pow = nexp; - new_pow++; - new_pow -= 2; - new_pow /= 2; - if(new_pow.isInteger()) { - b = true; - m_replace ^= nr_two; - var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(m_replace) + RIGHT_PARENTHESIS); - MathStructure m_prev(x_var), m_new(var); - m_prev ^= mpow; - m_new ^= mpow; - m_new[1].number() /= 2; - mtest.replace(m_prev, m_new); - } - } else if(i == 3) { - new_pow++; - new_pow -= 3; - new_pow /= 3; - if(new_pow.isInteger()) { - b = true; - m_replace ^= nr_three; - var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(m_replace) + RIGHT_PARENTHESIS); - MathStructure m_prev(x_var), m_new(var); - m_prev ^= mpow; - m_new ^= mpow; - m_new[1].number() /= 3; - mtest.replace(m_prev, m_new); - } - } - if(b) { - if(!new_pow.isZero()) { - mtest *= var; - mtest.swapChildren(1, mtest.size()); - if(!new_pow.isOne()) mtest[0] ^= new_pow; - } - CALCULATOR->beginTemporaryStopMessages(); - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(m_replace); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(m_replace); - } - if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0) { - CALCULATOR->endTemporaryStopMessages(true); - mtest.replace(var, m_replace); - set(mtest, true); - divide(m_replace[1]); - var->destroy(); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } - } - } - } - } else if(mpow.isPower() && nexp.isInteger() && !madd.isZero() && mpow[1].containsRepresentativeOf(x_var, true, true) == 0) { - MathStructure mbase(mpow[0]); - if(integrate_info(mbase, x_var, madd, mmul, mpow, false, false) && mpow.isOne() && (!madd.isZero() || !mmul.isOne())) { - MathStructure mtest(CHILD(1)); - - UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(mbase) + RIGHT_PARENTHESIS); - mtest.replace(mbase, var, mbase.containsInterval()); - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(mbase); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(mbase); - } - mtest *= var; - if(!madd.isZero()) { - mtest.last() -= madd; - mtest.childUpdated(mtest.size()); - } - if(!nexp.isOne()) { - mtest.last() ^= nexp; - mtest.childUpdated(mtest.size()); - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - set(mtest, true); - replace(var, mbase); - if(!mmul.isOne()) { - nexp++; - if(!nexp.isOne()) mmul ^= nexp; - divide(mmul); - } - var->destroy(); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } - } /*else if(mpow.isFunction() && mpow.function() == CALCULATOR->f_ln && mpow.size() == 1 && mpow[0] == x_var) { - MathStructure mtest(CHILD(1)); - UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(mpow) + RIGHT_PARENTHESIS); - mtest.replace(mpow, var, mpow.containsInterval()); - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(mpow); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(mpow); - } - nexp++; - mtest *= CALCULATOR->v_e; - mtest.last() ^= nexp; - mtest.last().last() *= var; - mmul = CALCULATOR->v_e; - mmul ^= nexp; - mmul.last() *= Number(-2, 1); - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - set(mtest, true); - replace(var, mpow); - multiply(mmul); - var->destroy(); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - }*/ - } - } - if(CHILD(0).isPower() && (CHILD(0)[1] == x_var || (CHILD(0)[1].isMultiplication() && CHILD(0)[1].size() >= 2 && CHILD(0)[1].last() == x_var)) && CHILD(0)[0].containsRepresentativeOf(x_var, true, true) == 0) { - MathStructure mpow, madd, mmul; - if(integrate_info(CHILD(1)[0], x_var, madd, mmul, mpow, false, false, true) && mpow.isPower() && (mpow[1] == x_var || (mpow[1].isMultiplication() && mpow[1].size() >= 2 && mpow[1].last() == x_var)) && (CHILD(0)[0] == mpow[0] || (CHILD(0)[0].isNumber() && CHILD(0)[0].number().isRational() && mpow[0].isNumber() && mpow[0].number().isRational() && mpow[1] == CHILD(0)[1]))) { - Number pow1(1, 1), pow2; - MathStructure morig(mpow); - bool b = true; - if(CHILD(0)[1].isMultiplication()) { - if(!mpow[1].isMultiplication()) { - if(CHILD(0)[1].size() != 2 || !CHILD(0)[1][0].isNumber()) b = false; - else {pow2 = CHILD(0)[1][0].number(); pow2--;} - } else { - for(size_t i = 0; i < mpow[1].size() - 1; i++) { - if(i == 0 && mpow[1][i].isNumber()) { - pow1 = mpow[1][i].number(); - } else if(CHILD(0)[1][i].containsRepresentativeOf(x_var, true, true) != 0) { - b = false; - break; - } - } - if(b) { - if(mpow[1] == CHILD(0)[1]) { - pow1.set(1, 1); - } else if(CHILD(0)[1].size() - (CHILD(0)[1][0].isNumber() ? 1 : 0) != mpow[1].size() - (mpow[1][0].isNumber() ? 1 : 0)) { - b = false; - } else if(b) { - for(size_t i = 0; i < CHILD(0)[1].size() - 1; i++) { - if(i == 0 && CHILD(0)[1][i].isNumber()) { - pow2 = CHILD(0)[1][i].number(); - pow2--; - } else if(CHILD(0)[1][i] != mpow[1][i + (mpow[1][0].isNumber() ? 1 : 0) - (CHILD(0)[1][0].isNumber() ? 1 : 0)]) { - b = false; - break; - } - } - } - } - } - } else if(mpow[1].isMultiplication()) { - if(mpow[1].size() != 2 || !mpow[1][0].isNumber()) b = false; - else pow1 = mpow[1][0].number(); - } - if(b && !pow1.isOne()) morig[1].delChild(1, true); - if(b && CHILD(0)[0] != mpow[0]) { - bool b1 = CHILD(0)[0].number() < mpow[0].number(); - if(mpow[0].number().isFraction() || CHILD(0)[0].number().isFraction()) b1 = !b1; - Number nlog(b1 ? mpow[0].number() : CHILD(0)[0].number()); - nlog.log(b1 ? CHILD(0)[0].number() : mpow[0].number()); - if(!nlog.isInteger()) { - nlog.round(); - b = nlog.isInteger() && (b1 ? ((CHILD(0)[0].number() ^ nlog) == mpow[0].number()) : ((mpow[0].number() ^ nlog) == CHILD(0)[0].number())); - } - if(b) { - if(b1) { - pow1 = nlog; - morig = CHILD(0); - } else { - pow2 = nlog; - pow2--; - } - } - } - if(b) { - UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(morig) + RIGHT_PARENTHESIS); - MathStructure mtest(var); - if(!pow1.isOne()) mtest ^= pow1; - if(!mmul.isOne()) mtest *= mmul; - if(!madd.isZero()) mtest += madd; - if(!mexp.isOne()) mtest ^= mexp; - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(morig); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(morig); - } - if(!pow2.isZero()) { - mtest *= var; - if(!pow2.isOne()) mtest.last() ^= pow2; - mtest.swapChildren(1, 2); - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - set(mtest, true); - replace(var, morig); - if(morig[0] != CALCULATOR->v_e) divide_nocopy(new MathStructure(CALCULATOR->f_ln, &morig[0], NULL)); - if(morig[1].isMultiplication()) { - morig[1].delChild(morig[1].size(), true); - divide(morig[1]); - } - var->destroy(); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } - } - } - if(CHILD(1)[1].number().isMinusOne() && CHILD(1)[0].isMultiplication() && CHILD(1)[0].size() == 2 && CHILD(1)[0][0].isAddition() && CHILD(1)[0][1].isAddition() && (CHILD(0) == x_var || (CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isTwo()))) { - MathStructure madd1, mmul1, mexp1; - if(integrate_info(CHILD(1)[0][0], x_var, madd1, mmul1, mexp1) && mexp1.isOne()) { - MathStructure madd2, mexp2; - if(integrate_info(CHILD(1)[0][1], x_var, madd2, mmul2, mexp2) && mexp2.isOne()) { - MathStructure mnum1, mnum2, mx1(madd2), mx2(madd1); - mx1.negate(); - if(!mmul2.isOne()) mx1 /= mmul2; - mnum1 = mx1; - if(!mmul1.isOne()) mx1 *= mmul1; - mx1 += madd1; - mnum1 /= mx1; - mx2.negate(); - if(!mmul1.isOne()) mx2 /= mmul1; - mnum2 = mx2; - if(!mmul2.isOne()) mx2 *= mmul2; - mx2 += madd2; - mnum2 /= mx2; - mnum2 /= CHILD(1)[0][0]; - mnum1 /= CHILD(1)[0][1]; - if(CHILD(0) != x_var) { - mnum1 *= x_var; - mnum2 *= x_var; - } - mnum2 += mnum1; - CALCULATOR->beginTemporaryStopMessages(); - if(mnum2.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0) { - CALCULATOR->endTemporaryStopMessages(true); - set(mnum2, true); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - } - } - } - if(CHILD(1)[0].isAddition()) { - bool b_poly = false; - if(CHILD(1)[1].isMinusOne()) { - MathStructure mquo, mrem; - b_poly = polynomial_long_division(CHILD(0), CHILD(1)[0], x_var, mquo, mrem, eo, true); - if(b_poly && !mquo.isZero()) { - MathStructure mtest(mquo); - if(!mrem.isZero()) { - mtest += mrem; - mtest.last() *= CHILD(1); - mtest.childrenUpdated(); - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0) { - CALCULATOR->endTemporaryStopMessages(true); - set(mtest, true); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - } - } - MathStructure mtest(*this); - if(mtest[1][0].factorize(eo, false, 0, 0, false, false, NULL, x_var)) { - mmul = m_one; - while(mtest[1][0].isMultiplication() && mtest[1][0].size() >= 2 && mtest[1][0][0].containsRepresentativeOf(x_var, true, true) == 0) { - MathStructure *mchild = &mtest[1][0][0]; - mchild->ref(); - mtest[1][0].delChild(1, true); - if(CHILD(1)[1].representsInteger(true) || COMPARISON_IS_EQUAL_OR_LESS(mchild->compare(m_zero)) || COMPARISON_IS_EQUAL_OR_LESS(mtest[1][0].compare(m_zero))) { - if(mmul.isOne()) mmul = *mchild; - else mmul *= *mchild; - mchild->unref(); - } else { - mtest[1][0].multiply_nocopy(mchild, true); - } - } - if(!mmul.isOne()) { - mmul ^= CHILD(1)[1]; - } - if(b_poly) { - MathStructure mtest2(mtest); - if(mtest2.decomposeFractions(x_var, eo)) { - if(mtest2.isAddition()) { - bool b = true; - CALCULATOR->beginTemporaryStopMessages(); - for(size_t i = 0; i < mtest2.size(); i++) { - if(mtest2[i].integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) <= 0) { - b = false; - break; - } - } - CALCULATOR->endTemporaryStopMessages(b); - if(b) { - set(mtest2, true); - if(!mmul.isOne()) multiply(mmul); - return true; - } - } - } else { - mtest2 = mtest[1]; - if(mtest2.decomposeFractions(x_var, eo) && mtest2.isAddition()) { - if(mtest2.isAddition()) { - bool b = true; - CALCULATOR->beginTemporaryStopMessages(); - for(size_t i = 0; i < mtest2.size(); i++) { - mtest2[i] *= mtest[0]; - if(mtest2[i].integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) <= 0) { - b = false; - break; - } - } - CALCULATOR->endTemporaryStopMessages(b); - if(b) { - set(mtest2, true); - if(!mmul.isOne()) multiply(mmul); - return true; - } - } - } - } - } - mmul2 = m_one; - if(mtest[1][0].isMultiplication() && mtest[1][0].size() >= 2 && !mtest[1][0][0].isAddition()) { - MathStructure *mchild = &mtest[1][0][0]; - mchild->ref(); - mtest[1][0].delChild(1, true); - if(CHILD(1)[1].representsInteger(true) || COMPARISON_IS_EQUAL_OR_LESS(mchild->compare(m_zero)) || COMPARISON_IS_EQUAL_OR_LESS(mtest[1][0].compare(m_zero))) { - mmul2 = *mchild; - mmul2.calculateRaise(CHILD(1)[1], eo2); - mchild->unref(); - } else { - mtest[1][0].multiply_nocopy(mchild, true); - } - } - if(mtest[1][0].isPower()) { - if(mtest[1][1].representsInteger() || mtest[1][0][1].representsFraction() || COMPARISON_IS_EQUAL_OR_LESS(mtest[1][0][0].compare(m_zero))) { - mtest[1][1].calculateMultiply(mtest[1][0][1], eo2); - mtest[1][0].setToChild(1); - } else if(mtest[1][0][1].representsEven()) { - if(COMPARISON_IS_EQUAL_OR_GREATER(mtest[1][0][0].compare(m_zero))) { - mtest[1][1].calculateMultiply(mtest[1][0][1], eo2); - mtest[1][0].setToChild(1); - mtest[1][0].calculateNegate(eo2); - } else if(!definite_integral && mtest[1][0][0].representsReal(true)) { - mtest[1][1].calculateMultiply(mtest[1][0][1], eo2); - mtest[1][0].setToChild(1); - mtest[1][0].transform(CALCULATOR->f_abs); - } - } - } - mtest[1][0].evalSort(false); - if(!mmul2.isOne()) { - mtest *= mmul2; - mtest.evalSort(false); - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest.integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0) { - CALCULATOR->endTemporaryStopMessages(true); - set(mtest); - if(!mmul.isOne()) multiply(mmul); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - } - if(CHILD(1)[1].number().isMinusOne() && CHILD(0) == x_var) { - if(integrate_info(CHILD(1)[0], x_var, madd, mmul, mmul2, false, true) && !mmul2.isZero() && mmul.isZero() && !madd.isZero()) { - SET_CHILD_MAP(1) - SET_CHILD_MAP(0) - transform(STRUCT_FUNCTION); - setFunction(CALCULATOR->f_ln); - mmul2 *= Number(-2, 1); - multiply(mmul2); - return true; - } - } - } - } else if(CHILD(1).isPower() && ((CHILD(1)[0].isNumber() && !CHILD(1)[0].number().isOne()) || (!CHILD(1)[0].isNumber() && CHILD(1)[0].containsRepresentativeOf(x_var, true, true) == 0))) { - MathStructure mexp(1, 1, 0); - if(CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1].isInteger()) mexp = CHILD(0)[1]; - else if(CHILD(0) != x_var) CANNOT_INTEGRATE; - MathStructure madd, mmul, mpow; - if(mexp.number() < 100 && mexp.number() > -100 && integrate_info(CHILD(1)[1], x_var, madd, mmul, mpow, false, false) && mpow.isInteger()) { - bool b_e = CHILD(1)[0] == CALCULATOR->v_e; - if(b_e || CHILD(1)[0].isNumber() || warn_about_assumed_not_value(CHILD(1)[0], m_one, eo)) { - if(mpow.isOne()) { - SET_CHILD_MAP(1) - if(!b_e) { - if(mmul.isOne()) { - mmul = CHILD(0); - mmul.transform(CALCULATOR->f_ln); - } else { - MathStructure lnbase(CALCULATOR->f_ln, &CHILD(0), NULL); - mmul *= lnbase; - } - } - if(mexp.isOne()) { - MathStructure mmulfac(x_var); - if(!mmul.isOne()) mmulfac *= mmul; - mmulfac += nr_minus_one; - multiply(mmulfac); - if(!mmul.isOne()) { - mmul ^= Number(-2, 1);; - multiply(mmul); - } - } else if(mexp.number().isTwo()) { - MathStructure mmulfac(x_var); - mmulfac ^= nr_two; - if(!mmul.isOne()) mmulfac /= mmul; - mmulfac += x_var; - mmulfac.last() *= Number(-2, 1); - if(!mmul.isOne()) { - mmulfac.last() *= mmul; - mmulfac.last().last() ^= Number(-2, 1); - } - mmulfac += nr_two; - if(!mmul.isOne()) { - mmulfac.last() *= mmul; - mmulfac.last().last() ^= Number(-3, 1); - } - mmulfac.childrenUpdated(true); - multiply(mmulfac); - } else if(mexp.isMinusOne()) { - set(x_var, true); - if(!mmul.isOne()) multiply(mmul); - transform(CALCULATOR->f_Ei); - } else if(mexp.number().isNegative()) { - MathStructure mterm2(*this); - mexp += m_one; - multiply(x_var); - LAST ^= mexp; - CHILDREN_UPDATED - if(integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) CANNOT_INTEGRATE_INTERVAL - if(!mmul.isOne()) multiply(mmul); - mterm2 *= x_var; - mterm2.last() ^= mexp; - mterm2.childrenUpdated(); - subtract(mterm2); - mexp.negate(); - divide(mexp); - } else { - MathStructure mterm2(*this); - multiply(x_var); - LAST ^= mexp; - LAST[1] += nr_minus_one; - LAST.childUpdated(2); - CHILDREN_UPDATED - if(integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) CANNOT_INTEGRATE_INTERVAL - multiply(mexp); - if(!mmul.isOne()) divide(mmul); - negate(); - mterm2 *= x_var; - mterm2.last() ^= mexp; - mterm2.childrenUpdated(); - if(!mmul.isOne()) mterm2.divide(mmul); - add(mterm2); - } - return true; - } else { - Number mpowmexp(mpow.number()); - mpowmexp -= mexp.number(); - if(mpowmexp.isOne()) { - SET_CHILD_MAP(1) - MathStructure malog(CALCULATOR->f_ln, &CHILD(0), NULL); - divide(mpow); - if(!mmul.isOne()) divide(mmul); - if(!b_e) divide(malog); - return true; - } else if(mexp.isMinusOne() && mpow.number().isPositive()) { - MathStructure malog; - if(b_e) { - malog = x_var; - malog ^= mpow; - } else { - malog.set(CALCULATOR->f_ln, &CHILD(1)[0], NULL); - malog *= x_var; - malog.last() ^= mpow; - } - if(!mmul.isOne()) malog *= mmul; - malog.transform(CALCULATOR->f_Ei); - if(madd.isZero()) { - set(malog, true); - } else { - SET_CHILD_MAP(1) - SET_CHILD_MAP(0) - raise(madd); - multiply(malog); - } - divide(mpow); - return true; - } - } - } - } - } - } - if(SIZE >= 2) { - for(size_t i = 0; i < SIZE; i++) { - if((CHILD(i).isFunction() && CHILD(i).function() == CALCULATOR->f_signum) || (CHILD(i).isPower() && CHILD(i)[0].isFunction() && CHILD(i)[0].function() == CALCULATOR->f_signum)) { - MathStructure mfunc(CHILD(i).isPower() ? CHILD(i)[0] : CHILD(i)); - MathStructure mmul(*this); - mmul.delChild(i + 1, true); - CALCULATOR->beginTemporaryStopMessages(); - int bint = integrate_function(mfunc, x_var, eo, CHILD(i).isPower() ? CHILD(i)[1] : m_one, mmul, m_zero, m_one, use_abs, definite_integral, max_part_depth, parent_parts); - CALCULATOR->endTemporaryStopMessages(bint > 0); - if(bint < 0) CANNOT_INTEGRATE_INTERVAL - if(bint) { - set(mfunc, true); - return true; - } - } - } - for(size_t i = 0; i < SIZE; i++) { - if((CHILD(i).isFunction() && CHILD(i).function() != CALCULATOR->f_signum) || (CHILD(i).isPower() && CHILD(i)[0].isFunction() && CHILD(i)[0].function() != CALCULATOR->f_signum)) { - MathStructure mfunc(CHILD(i).isPower() ? CHILD(i)[0] : CHILD(i)); - MathStructure mmul(*this); - mmul.delChild(i + 1, true); - CALCULATOR->beginTemporaryStopMessages(); - int bint = integrate_function(mfunc, x_var, eo, CHILD(i).isPower() ? CHILD(i)[1] : m_one, mmul, m_zero, m_one, use_abs, definite_integral, max_part_depth, parent_parts); - CALCULATOR->endTemporaryStopMessages(bint > 0); - if(bint < 0) CANNOT_INTEGRATE_INTERVAL - if(bint) { - set(mfunc, true); - return true; - } - } - } - MathStructure mbak(*this); - if(CHILD(0) == x_var || (CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isRational())) { - Number nexp(1, 1, 0); - if(CHILD(0).isPower()) nexp = CHILD(0)[1].number(); - MathStructure mpow(1, 1, 0); - bool b = true; - MathStructure madd, mmul, mpown; - for(size_t i = 1; i < SIZE; i++) { - if(CHILD(i).isFunction() && CHILD(i).size() >= 1) { - if(!integrate_info(CHILD(i)[0], x_var, madd, mmul, mpown, false, false) || !mpown.isNumber() || !mpown.number().isRational() || mpown.number().isOne() || (!mpow.isOne() && mpow != mpown)) { - b = false; - break; - } - mpow = mpown; - } else if(CHILD(i).isPower() && CHILD(i)[1].containsRepresentativeOf(x_var, true, true) == 0) { - if((CHILD(i)[0].isFunction() && CHILD(i)[0].size() == 1)) { - if(!integrate_info(CHILD(i)[0][0], x_var, madd, mmul, mpown, false, false)) {b = false; break;} - } else if(integrate_info(CHILD(i)[0], x_var, madd, mmul, mpown, false, false, true)) { - if(mpown.isPower() && mpown[0] == x_var) { - mpown.setToChild(2); - if(SIZE == 2 && mpown.isInteger()) {b = false; break;} - } else if(mpown.isFunction() && mpown.size() >= 1) { - MathStructure marg(mpown[0]); - if(!integrate_info(marg, x_var, madd, mmul, mpown, false, false)) {b = false; break; } - } else { - b = false; break; - } - } else { - b = false; break; - } - if(!mpown.isNumber() || !mpown.number().isRational() || mpown.number().isOne() || (!mpow.isOne() && mpow != mpown)) { - b = false; - break; - } - mpow = mpown; - } else if(CHILD(i).isPower() && CHILD(i)[0].containsRepresentativeOf(x_var, true, true) == 0) { - if(!integrate_info(CHILD(i)[1], x_var, madd, mmul, mpown, false, false) || !mpown.isNumber() || !mpown.number().isRational() || mpown.number().isOne() || (!mpow.isOne() && mpow != mpown)) { - b = false; - break; - } - mpow = mpown; - } else { - b = false; - break; - } - } - if(b && (x_var.representsNonNegative(true) || mpow.number().isEven() || mpow.number().isFraction())) { - for(int i = 1; i <= 3; i++) { - if(!mpow.isInteger()) { - if(i > 2) break; - } else if(i > 1 && (!mpow.number().isIntegerDivisible(i) || mpow.number() == i)) { - break; - } - if(CALCULATOR->aborted()) CANNOT_INTEGRATE - UnknownVariable *var = NULL; - MathStructure m_replace(x_var); - MathStructure mtest(*this); - mtest.delChild(1, true); - Number new_pow(nexp); - b = false; - if(i == 1) { - m_replace ^= mpow; - var = new UnknownVariable("", ""); - mtest.replace(m_replace, var); - new_pow++; - new_pow -= mpow.number(); - new_pow /= mpow.number(); - b = true; - } else if(i == 2) { - if(!mpow.number().isInteger()) { - Number nden = mpow.number().denominator(); - nden.recip(); - nden--; - nden.negate(); - new_pow = nexp; - new_pow += nden; - new_pow *= mpow.number().denominator(); - if(new_pow.isInteger()) { - b = true; - m_replace ^= mpow.number().denominator(); - m_replace[1].number().recip(); - var = new UnknownVariable("", ""); - MathStructure m_prev(x_var), m_new(var); - m_prev ^= mpow; - if(!mpow.number().numeratorIsOne()) m_new ^= mpow.number().numerator(); - mtest.replace(m_prev, m_new); - } - } else if((mpow.number() / 2).isEven()) { - new_pow = nexp; - new_pow++; - new_pow -= 2; - new_pow /= 2; - if(new_pow.isInteger()) { - b = true; - m_replace ^= nr_two; - var = new UnknownVariable("", ""); - MathStructure m_prev(x_var), m_new(var); - m_prev ^= mpow; - m_new ^= mpow; - m_new[1].number() /= 2; - mtest.replace(m_prev, m_new); - } - } - } else if(i == 3) { - new_pow++; - new_pow -= 3; - new_pow /= 3; - if(new_pow.isInteger()) { - b = true; - m_replace ^= nr_three; - var = new UnknownVariable("", ""); - MathStructure m_prev(x_var), m_new(var); - m_prev ^= mpow; - m_new ^= mpow; - m_new[1].number() /= 3; - mtest.replace(m_prev, m_new); - } - } - if(b) { - if(!new_pow.isZero()) { - mtest *= var; - mtest.swapChildren(1, mtest.size()); - if(!new_pow.isOne()) mtest[0] ^= new_pow; - } - CALCULATOR->beginTemporaryStopMessages(); - var->setName(string(LEFT_PARENTHESIS) + format_and_print(m_replace) + RIGHT_PARENTHESIS); - if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { - MathStructure m_interval(m_replace); - m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - var->setInterval(m_interval); - } else { - var->setInterval(m_replace); - } - if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunction(CALCULATOR->f_integrate) <= 0) { - CALCULATOR->endTemporaryStopMessages(true); - mtest.replace(var, m_replace); - set(mtest, true); - if(m_replace.isPower()) divide(m_replace[1]); - var->destroy(); - return true; - } - CALCULATOR->endTemporaryStopMessages(); - var->destroy(); - } - } - } - } - vector parent_parts_pre; - if(parent_parts) { - for(size_t i = 0; i < parent_parts->size(); i++) { - if(equals(*(*parent_parts)[i], true)) CANNOT_INTEGRATE - } - } else { - parent_parts = &parent_parts_pre; - } - size_t pp_size = parent_parts->size(); - bool b = false; - for(size_t i = 0; !b && max_part_depth > 0 && (i < SIZE || (SIZE == 3 && i < SIZE * 2)) && SIZE < 10; i++) { - if(CALCULATOR->aborted()) CANNOT_INTEGRATE - CALCULATOR->beginTemporaryStopMessages(); - // integration by parts - MathStructure mstruct_u; - MathStructure mstruct_v; - MathStructure minteg_v; - if(SIZE == 3 && i >= 3) { - mstruct_v = CHILD(i - 3); - mstruct_u = *this; - mstruct_u.delChild(i - 2); - } else { - mstruct_u = CHILD(i); - if(SIZE == 2 && i == 0) mstruct_v = CHILD(1); - else if(SIZE == 2 && i == 1) mstruct_v = CHILD(0); - else {mstruct_v = *this; mstruct_v.delChild(i + 1);} - } - MathStructure mdiff_u(mstruct_u); - if(mdiff_u.differentiate(x_var, eo2) && mdiff_u.containsFunction(CALCULATOR->f_diff, true) <= 0 && (!definite_integral || check_zero_div(mdiff_u, x_var, eo))) { - minteg_v = mstruct_v; - if(minteg_v.integrate(x_var, eo, false, use_abs, definite_integral, true, 0, parent_parts) > 0) { - parent_parts->push_back(this); - MathStructure minteg_2(minteg_v); - if(!mdiff_u.isOne()) minteg_2 *= mdiff_u; - if(minteg_2.countTotalChildren() < 1000) { - minteg_2.evalSort(true); - minteg_2.calculateFunctions(eo2); - minteg_2.calculatesub(eo2, eo2, true); - do_simplification(minteg_2, eo, true, false, false, true, true); - } - if(minteg_2.countTotalChildren() < 100 && minteg_2.integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth - 1, parent_parts) > 0) { - int cui = contains_unsolved_integrate(minteg_2, this, parent_parts); - if(cui == 3) { - MathStructure mfunc(CALCULATOR->f_integrate, this, &m_undefined, &m_undefined, &x_var, &m_zero, NULL); - UnknownVariable *var = new UnknownVariable("", format_and_print(mfunc)); - var->setAssumptions(mfunc); - MathStructure mvar(var); - minteg_2.replace(mfunc, mvar); - MathStructure msolve(mstruct_u); - msolve.multiply(minteg_v); - msolve.evalSort(false); - msolve.calculatesub(eo2, eo2, true); - msolve.subtract(minteg_2); - msolve.evalSort(false); - msolve.calculatesub(eo2, eo2, true); - MathStructure msolve_d(msolve); - if(msolve_d.differentiate(mvar, eo2) && COMPARISON_IS_NOT_EQUAL(msolve_d.compareApproximately(m_one, eo2))) { - msolve.transform(COMPARISON_EQUALS, mvar); - msolve.isolate_x(eo2, mvar); - if(msolve.isComparison() && msolve.comparisonType() == COMPARISON_EQUALS && msolve[0] == mvar && msolve[1].contains(mvar, true) <= 0) { - b = true; - set(msolve[1], true); - } - } - var->destroy(); - } else if(cui != 1) { - set(mstruct_u); - multiply(minteg_v); - subtract(minteg_2); - b = true; - } - } - parent_parts->pop_back(); - } - } - CALCULATOR->endTemporaryStopMessages(b); - } - while(parent_parts->size() > pp_size) parent_parts->pop_back(); - if(b) return true; - } - CANNOT_INTEGRATE - break; - } - case STRUCT_SYMBOLIC: { - if(representsNumber(true)) { - multiply(x_var); - } else { - CANNOT_INTEGRATE - } - break; - } - case STRUCT_VARIABLE: { - if(eo.calculate_variables && o_variable->isKnown()) { - if(eo.approximation != APPROXIMATION_EXACT || !o_variable->isApproximate()) { - set(((KnownVariable*) o_variable)->get(), true); - unformat(eo); - return integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts); - } else if(containsRepresentativeOf(x_var, true, true) != 0) { - CANNOT_INTEGRATE - } - } - if(representsNumber(true)) { - multiply(x_var); - break; - } - } - default: { - CANNOT_INTEGRATE - } - } - return true; -} - - -const MathStructure &MathStructure::find_x_var() const { - if(isSymbolic()) { - return *this; - } else if(isVariable()) { - if(o_variable->isKnown()) return m_undefined; - return *this; - } - const MathStructure *mstruct; - const MathStructure *x_mstruct = &m_undefined; - for(size_t i = 0; i < SIZE; i++) { - mstruct = &CHILD(i).find_x_var(); - if(mstruct->isVariable()) { - if(!((UnknownVariable*) mstruct->variable())->interval().isUndefined()) { - if(x_mstruct->isUndefined()) x_mstruct = mstruct; - } else if(mstruct->variable() == CALCULATOR->v_x) { - return *mstruct; - } else if(!x_mstruct->isVariable()) { - x_mstruct = mstruct; - } else if(mstruct->variable() == CALCULATOR->v_y) { - x_mstruct = mstruct; - } else if(mstruct->variable() == CALCULATOR->v_z && x_mstruct->variable() != CALCULATOR->v_y) { - x_mstruct = mstruct; - } - } else if(mstruct->isSymbolic()) { - if(!x_mstruct->isVariable() && (!x_mstruct->isSymbolic() || x_mstruct->symbol() > mstruct->symbol())) { - x_mstruct = mstruct; - } - } - } - return *x_mstruct; -} - -bool isUnit_multi(const MathStructure &mstruct) { - if(!mstruct.isMultiplication() || mstruct.size() == 0) return false; - for(size_t i = 0; i < mstruct.size(); i++) { - if((i > 0 || !mstruct[i].isNumber()) && !mstruct[i].isUnit_exp()) return false; - } - return true; -} - -int test_comparisons(const MathStructure &msave, MathStructure &mthis, const MathStructure &x_var, const EvaluationOptions &eo, bool sub, int alt) { - if(mthis.isComparison() && mthis[0] == x_var) { - if(mthis.comparisonType() != COMPARISON_EQUALS && mthis.comparisonType() != COMPARISON_NOT_EQUALS) return 1; - MathStructure mtest; - EvaluationOptions eo2 = eo; - eo2.calculate_functions = false; - eo2.isolate_x = false; - eo2.test_comparisons = true; - eo2.warn_about_denominators_assumed_nonzero = false; - eo2.assume_denominators_nonzero = false; - eo2.approximation = APPROXIMATION_APPROXIMATE; - mtest = mthis; - mtest.eval(eo2); - if(mtest.isComparison()) { - mtest = msave; - mtest.replace(x_var, mthis[1]); - if(CALCULATOR->usesIntervalArithmetic()) { - MathStructure mtest2(mtest[0]); - if(!mtest[1].isZero()) { - mtest2.subtract(mtest[1]); - } - CALCULATOR->beginTemporaryStopMessages(); - mtest2.eval(eo2); - if(CALCULATOR->endTemporaryStopMessages() > 0) { - if(!sub) mthis = msave; - return -1; - } - if(mtest2.isNumber()) { - if(mtest.comparisonType() == COMPARISON_LESS || mtest.comparisonType() == COMPARISON_EQUALS_LESS) { - if(!mtest2.number().hasImaginaryPart() && mtest2.number().lowerEndPoint().isNonPositive()) return 1; - } else if(mtest.comparisonType() == COMPARISON_GREATER || mtest.comparisonType() == COMPARISON_EQUALS_GREATER) { - if(!mtest2.number().hasImaginaryPart() && mtest2.number().upperEndPoint().isNonNegative()) return 1; - } else if(mtest.comparisonType() == COMPARISON_NOT_EQUALS) { - if(!mtest2.number().isNonZero()) return 1; - else if(mtest2.number().isInterval() || mtest2[0].number().isRational()) {mthis = m_one; return 0;} - } else { - if(!mtest2.number().isNonZero()) return 1; - else if(mtest2.number().isInterval() || mtest2.number().isRational()) {mthis.clear(); return 0;} - } - } else if(mtest2.isUnit_exp()) { - if(mtest.comparisonType() == COMPARISON_GREATER || mtest.comparisonType() == COMPARISON_EQUALS_GREATER) return 1; - else if(mtest.comparisonType() == COMPARISON_EQUALS) {mthis.clear(); return 0;} - else if(mtest.comparisonType() == COMPARISON_NOT_EQUALS) {mthis = m_one; return 0;} - } else if(isUnit_multi(mtest2)) { - if(mtest.comparisonType() == COMPARISON_LESS || mtest.comparisonType() == COMPARISON_EQUALS_LESS) { - if(mtest2[0].isNumber() && !mtest2[0].number().hasImaginaryPart() && mtest2[0].number().lowerEndPoint().isNonPositive()) return 1; - } else if(mtest.comparisonType() == COMPARISON_GREATER || mtest.comparisonType() == COMPARISON_EQUALS_GREATER) { - if(!mtest2[0].isNumber() || (!mtest2[0].number().hasImaginaryPart() && mtest2.number().upperEndPoint().isNonNegative())) return 1; - - } else if(mtest.comparisonType() == COMPARISON_NOT_EQUALS) { - if(!mtest2[0].isNumber()) {mthis = m_one; return 0;} - if(!mtest2[0].number().isNonZero()) return 1; - else if(mtest2[0].number().isInterval() || mtest2[0].number().isRational()) {mthis = m_one; return 0;} - } else { - if(!mtest2[0].isNumber()) {mthis.clear(); return 0;} - if(!mtest2[0].number().isNonZero()) return 1; - else if(mtest2[0].number().isInterval() || mtest2[0].number().isRational()) {mthis.clear(); return 0;} - } - } - - } - CALCULATOR->beginTemporaryStopMessages(); - if(mtest[1].isZero() && mtest[0].isAddition() && mtest[0].size() > 1) { - mtest[1].subtract(mtest[0][0]); - mtest[0].delChild(1, true); - } - mtest.eval(eo2); - if(CALCULATOR->endTemporaryStopMessages() > 0) { - if(!sub) mthis = msave; - return -1; - } - if(mtest.isNumber()) { - if(mtest.number().getBoolean() == 1) { - return 1; - } else if(mtest.number().getBoolean() == 0) { - if(mtest.isApproximate() && mtest.comparisonType() != COMPARISON_EQUALS && mtest.comparisonType() != COMPARISON_NOT_EQUALS) return -1; - if(mtest.comparisonType() == COMPARISON_EQUALS) mthis.clear(); - else if(mtest.comparisonType() == COMPARISON_NOT_EQUALS) mthis = m_one; - return 0; - } - } - } else { - mthis = mtest; - if(mtest.isNumber()) { - if(mtest.number().getBoolean() == 0) { - return 0; - } - } - return 1; - } - if(!sub) mthis = msave; - return -1; - } - if(alt && mthis.isComparison()) { - if(!sub && alt != 1) mthis = msave; - return -1; - } - if(mthis.isLogicalOr() || mthis.isLogicalAnd()) { - int i_ret = 1; - for(size_t i = 0; i < mthis.size(); i++) { - if(test_comparisons(msave, mthis[i], x_var, eo, true, alt) < 0) { - if(alt != 1) { - mthis = msave; - return -1; - } - i_ret = -1; - } - } - return i_ret; - } - if(sub) return 1; - else return -1; -} - -bool isx_deabsify(MathStructure &mstruct); -bool isx_deabsify(MathStructure &mstruct) { - switch(mstruct.type()) { - case STRUCT_FUNCTION: { - if(mstruct.function() == CALCULATOR->f_abs && mstruct.size() == 1 && mstruct[0].representsNonComplex(true)) { - mstruct.setToChild(1, true); - return true; - } - break; - } - case STRUCT_POWER: { - if(mstruct[1].isMinusOne()) { - return isx_deabsify(mstruct[0]); - } - break; - } - case STRUCT_MULTIPLICATION: { - bool b = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(isx_deabsify(mstruct[i])) b = true; - } - return b; - } - default: {} - } - return false; -} - -int newton_raphson(const MathStructure &mstruct, MathStructure &x_value, const MathStructure &x_var, const EvaluationOptions &eo) { - if(mstruct == x_var) { - x_value = m_zero; - return 1; - } - - if(!mstruct.isAddition()) return -1; - if(mstruct.size() == 2) { - if(mstruct[1] == x_var && mstruct[0].isNumber() && mstruct[0].number().isReal()) { - x_value = mstruct[0]; - x_value.number().negate(); - return 1; - } - if(mstruct[0] == x_var && mstruct[1].isNumber() && mstruct[1].number().isReal()) { - x_value = mstruct[1]; - x_value.number().negate(); - return 1; - } - } - - Number nr; - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i] != x_var) { - switch(mstruct[i].type()) { - case STRUCT_NUMBER: {nr = mstruct[i].number(); break;} - case STRUCT_MULTIPLICATION: { - if(mstruct[i].size() == 2 && mstruct[i][0].isNumber() && (mstruct[i][1] == x_var || (mstruct[i][1].isPower() && mstruct[i][1][0] == x_var && mstruct[i][1][1].isNumber() && mstruct[i][1][1].number().isInteger() && mstruct[i][1][1].number().isPositive()))) { - break; - } - return -1; - } - case STRUCT_POWER: { - if(mstruct[i][0] == x_var && mstruct[i][1].isNumber() && mstruct[i][1].number().isInteger() && mstruct[i][1].number().isPositive()) { - break; - } - } - default: {return -1;} - } - } - } - - MathStructure mdiff(mstruct); - if(!mdiff.differentiate(x_var, eo)) return -1; - MathStructure minit(mstruct); - minit.divide(mdiff); - minit.negate(); - minit.add(x_var); - minit.eval(eo); - - Number nr_target_high(1, 1, -(PRECISION) - 10); - Number nr_target_low(1, 1, 0); - nr_target_low -= nr_target_high; - nr_target_high++; - MathStructure mguess(2, 1, 0); - Number ndeg(mstruct.degree(x_var)); - bool overflow = false; - int ideg = ndeg.intValue(&overflow); - if(overflow || ideg > 100) return -1; - nr.negate(); - if(!nr.isZero()) { - bool b_neg = nr.isNegative(); - if(b_neg) nr.negate(); - if(nr.root(ndeg)) { - if(ndeg.isOdd() && b_neg) nr.negate(); - mguess = nr; - } else { - nr = mguess.number(); - } - } else { - nr = mguess.number(); - } - - for(int i = 0; i < 100 + PRECISION + ideg * 2; i++) { - - mguess.number().setToFloatingPoint(); - if(mguess.number().hasImaginaryPart()) mguess.number().internalImaginary()->setToFloatingPoint(); - - if(CALCULATOR->aborted()) return -1; - - MathStructure mtest(minit); - mtest.replace(x_var, mguess); - mtest.eval(eo); - - Number nrdiv(mguess.number()); - if(!mtest.isNumber() || !nrdiv.divide(mtest.number())) { - return -1; - } - - if(nrdiv.isLessThan(nr_target_high) && nrdiv.isGreaterThan(nr_target_low)) { - if(CALCULATOR->usesIntervalArithmetic()) { - if(!x_value.number().setInterval(mguess.number(), mtest.number())) return -1; - } else { - x_value = mtest; - if(x_value.number().precision() < 0 || x_value.number().precision() > PRECISION + 10) x_value.number().setPrecision(PRECISION + 10); - } - x_value.numberUpdated(); - return 1; - } - mguess = mtest; - } - - nr.negate(); - mguess = nr; - for(int i = 0; i < 100 + PRECISION + ideg * 2; i++) { - - mguess.number().setToFloatingPoint(); - if(mguess.number().hasImaginaryPart()) mguess.number().internalImaginary()->setToFloatingPoint(); - - if(CALCULATOR->aborted()) return -1; - - MathStructure mtest(minit); - mtest.replace(x_var, mguess); - mtest.eval(eo); - - Number nrdiv(mguess.number()); - if(!mtest.isNumber() || !nrdiv.divide(mtest.number())) { - return -1; - } - if(nrdiv.isLessThan(nr_target_high) && nrdiv.isGreaterThan(nr_target_low)) { - if(CALCULATOR->usesIntervalArithmetic()) { - if(!x_value.number().setInterval(mguess.number(), mtest.number())) return -1; - } else { - x_value = mtest; - if(x_value.number().precision() < 0 || x_value.number().precision() > PRECISION + 10) x_value.number().setPrecision(PRECISION + 10); - } - x_value.numberUpdated(); - return 1; - } - mguess = mtest; - } - - return 0; - -} - -int find_interval_precision(const MathStructure &mstruct); - -int find_interval_precision(const MathStructure &mstruct) { - if(mstruct.isNumber()) { - return mstruct.number().precision(1); - } - int iv_prec = -1; - for(size_t i = 0; i < mstruct.size(); i++) { - if(iv_prec > -1) { - if(find_interval_precision(mstruct[i]) > -1) return 0; - } else { - iv_prec = find_interval_precision(mstruct[i]); - } - } - return iv_prec; -} - -MathStructure *find_abs_sgn(MathStructure &mstruct, const MathStructure &x_var); -MathStructure *find_abs_sgn(MathStructure &mstruct, const MathStructure &x_var) { - switch(mstruct.type()) { - case STRUCT_FUNCTION: { - if(((mstruct.function() == CALCULATOR->f_abs && mstruct.size() == 1) || (mstruct.function() == CALCULATOR->f_signum && mstruct.size() == 2)) && mstruct[0].contains(x_var, false) && mstruct[0].representsNonComplex()) { - return &mstruct; - } - break; - } - case STRUCT_POWER: { - return find_abs_sgn(mstruct[0], x_var); - } - case STRUCT_ADDITION: {} - case STRUCT_MULTIPLICATION: { - for(size_t i = 0; i < mstruct.size(); i++) { - MathStructure *m = find_abs_sgn(mstruct[i], x_var); - if(m) return m; - } - break; - } - default: {break;} - } - return NULL; -} - -bool is_units_with_multiplier(const MathStructure &mstruct) { - if(!mstruct.isMultiplication() || mstruct.size() == 0 || !mstruct[0].isNumber()) return false; - for(size_t i = 1; i < mstruct.size(); i++) { - if(!mstruct[i].isUnit_exp()) return false; - } - return true; -} - -bool fix_n_multiple(MathStructure &mstruct, const EvaluationOptions &eo, const EvaluationOptions &feo, const MathStructure &x_var) { - bool b_ret = false; - if(mstruct.isComparison()) { - if(mstruct.comparisonType() == COMPARISON_EQUALS && x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined() && mstruct[1].contains(CALCULATOR->v_n)) { - MathStructure mtest(mstruct); - mtest.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); - EvaluationOptions eo2 = eo; - EvaluationOptions feo2 = feo; - if(eo.approximation == APPROXIMATION_EXACT) { - eo2.approximation = APPROXIMATION_TRY_EXACT; - feo2.approximation = APPROXIMATION_TRY_EXACT; - } - CALCULATOR->beginTemporaryEnableIntervalArithmetic(); - CALCULATOR->beginTemporaryStopMessages(); - mtest.calculateFunctions(feo2); - if(mtest.isolate_x(eo2, feo2, CALCULATOR->v_n)) { - if(CALCULATOR->endTemporaryStopMessages() == 0) { - if(mtest.isZero()) { - mstruct.clear(true); - b_ret = true; - } else if(mtest.isComparison() && mtest.comparisonType() == COMPARISON_EQUALS && mtest[0] == CALCULATOR->v_n && mtest[1].isNumber()) { - if(mtest[1].number().isInteger()) { - mstruct.calculateReplace(CALCULATOR->v_n, mtest[1], eo); - b_ret = true; - } else if(mtest[1].number().isInterval()) { - Number nr_int; bool b_multiple = false; - if(mtest[1].number().getCentralInteger(nr_int, &b_multiple)) { - mstruct.calculateReplace(CALCULATOR->v_n, nr_int, eo); - b_ret = true; - } else if(!b_multiple) { - mstruct.clear(true); - b_ret = true; - } - } else { - mstruct.clear(true); - b_ret = true; - } - } - } - } else { - CALCULATOR->endTemporaryStopMessages(); - } - CALCULATOR->endTemporaryEnableIntervalArithmetic(); - } - } else { - for(size_t i = 0; i < mstruct.size(); i++) { - if(fix_n_multiple(mstruct[i], eo, feo, x_var)) { - mstruct.childUpdated(i + 1); - b_ret = true; - } - } - if(b_ret) mstruct.calculatesub(eo, feo, false); - } - return b_ret; -} - -bool MathStructure::isolate_x_sub(const EvaluationOptions &eo, EvaluationOptions &eo2, const MathStructure &x_var, MathStructure *morig) { - if(!isComparison()) { - cout << "isolate_x_sub: " << *this << " is not a comparison." << endl; - return false; - } - - if(CHILD(0) == x_var) return false; - if(contains(x_var, true) <= 0) return false; - - if(CALCULATOR->aborted()) return false; - - switch(CHILD(0).type()) { - case STRUCT_ADDITION: { - bool b = false; - // x+y=z => x=z-y - for(size_t i = 0; i < CHILD(0).size();) { - if(!CHILD(0)[i].contains(x_var)) { - CHILD(0)[i].calculateNegate(eo2); - CHILD(0)[i].ref(); - CHILD(1).add_nocopy(&CHILD(0)[i], true); - CHILD(1).calculateAddLast(eo2); - CHILD(0).delChild(i + 1); - b = true; - } else { - i++; - } - } - if(b) { - CHILD_UPDATED(0); - CHILD_UPDATED(1); - if(CHILD(0).size() == 1) { - CHILD(0).setToChild(1, true); - } else if(CHILD(0).size() == 0) { - CHILD(0).clear(true); - } - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } - if(CALCULATOR->aborted()) return false; - - // ax^(2n)+bx^n=c - if(CHILD(0).size() >= 2 && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { - bool sqpow = false, nopow = false; - MathStructure mstruct_a, mstruct_b, mpow_a, mpow_b; - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CHILD(0)[i] == x_var || (CHILD(0)[i].isPower() && CHILD(0)[i][0] == x_var)) { - b = false; - const MathStructure *mexp = &m_one; - if(CHILD(0)[i] != x_var) mexp = &CHILD(0)[i][1]; - if(nopow) { - if(*mexp == mpow_b) { - mstruct_b.add(m_one, true); - b = true; - } else if(!sqpow) { - MathStructure mtest(*mexp); - mtest.calculateMultiply(nr_half, eo); - if(mtest == mpow_b) { - mpow_a = *mexp; - mstruct_a.set(m_one, true); - b = true; - } else { - mtest = *mexp; - mtest.calculateMultiply(nr_two, eo); - if(mtest == mpow_b) { - mpow_a = mpow_b; - mpow_b = *mexp; - mstruct_a = mstruct_b; - mstruct_b.set(m_one, true); - b = true; - } - } - if(b) sqpow = true; - } else if(*mexp == mpow_a) { - mstruct_a.add(m_one, true); - b = true; - } - } else if(sqpow) { - if(*mexp == mpow_a) { - mstruct_a.add(m_one, true); - b = true; - } else { - MathStructure mtest(*mexp); - mtest.calculateMultiply(nr_two, eo); - if(mtest == mpow_a) { - mpow_b = *mexp; - mstruct_b.set(m_one, true); - b = true; - } else { - mtest = *mexp; - mtest.calculateMultiply(nr_half, eo); - if(mtest == mpow_a) { - mpow_b = mpow_a; - mpow_a = *mexp; - mstruct_b = mstruct_a; - mstruct_a.set(m_one, true); - b = true; - } - } - if(b) nopow = true; - } - } else { - if(mexp->isOne()) { - mpow_b = *mexp; - nopow = true; - mstruct_b.set(m_one); - } else { - mpow_a = *mexp; - sqpow = true; - mstruct_a.set(m_one); - } - b = true; - } - if(!b) { - sqpow = false; - nopow = false; - break; - } - } else if(CHILD(0)[i].isMultiplication()) { - for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { - if(CHILD(0)[i][i2] == x_var || (CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][0] == x_var)) { - b = false; - const MathStructure *mexp = &m_one; - if(CHILD(0)[i][i2] != x_var) mexp = &CHILD(0)[i][i2][1]; - if(nopow) { - if(*mexp == mpow_b) { - MathStructure *madd = new MathStructure(CHILD(0)[i]); - madd->delChild(i2 + 1, true); - mstruct_b.add_nocopy(madd, true); - b = true; - } else if(!sqpow) { - MathStructure mtest(*mexp); - mtest.calculateMultiply(nr_half, eo); - if(mtest == mpow_b) { - mpow_a = *mexp; - mstruct_a = CHILD(0)[i]; - mstruct_a.delChild(i2 + 1, true); - b = true; - } else { - mtest = *mexp; - mtest.calculateMultiply(nr_two, eo); - if(mtest == mpow_b) { - mpow_a = mpow_b; - mpow_b = *mexp; - mstruct_a = mstruct_b; - mstruct_b = CHILD(0)[i]; - mstruct_b.delChild(i2 + 1, true); - b = true; - } - } - if(b) sqpow = true; - } else if(*mexp == mpow_a) { - MathStructure *madd = new MathStructure(CHILD(0)[i]); - madd->delChild(i2 + 1, true); - mstruct_a.add_nocopy(madd, true); - b = true; - } - } else if(sqpow) { - if(*mexp == mpow_a) { - MathStructure *madd = new MathStructure(CHILD(0)[i]); - madd->delChild(i2 + 1, true); - mstruct_a.add_nocopy(madd, true); - b = true; - } else { - MathStructure mtest(*mexp); - mtest.calculateMultiply(nr_two, eo); - if(mtest == mpow_a) { - mpow_b = *mexp; - mstruct_b.add(m_one, true); - mstruct_b = CHILD(0)[i]; - mstruct_b.delChild(i2 + 1, true); - b = true; - } else { - mtest = *mexp; - mtest.calculateMultiply(nr_half, eo); - if(mtest == mpow_a) { - mpow_b = mpow_a; - mpow_a = *mexp; - mstruct_b = mstruct_a; - mstruct_a = CHILD(0)[i]; - mstruct_a.delChild(i2 + 1, true); - b = true; - } - } - if(b) nopow = true; - } - } else { - if(mexp->isOne()) { - mpow_b = *mexp; - nopow = true; - mstruct_b = CHILD(0)[i]; - mstruct_b.delChild(i2 + 1, true); - } else { - mpow_a = *mexp; - sqpow = true; - mstruct_a = CHILD(0)[i]; - mstruct_a.delChild(i2 + 1, true); - } - b = true; - } - if(!b) { - sqpow = false; - nopow = false; - break; - } - } else if(CHILD(0)[i][i2].contains(x_var)) { - sqpow = false; - nopow = false; - break; - } - } - if(!sqpow && !nopow) break; - } else { - sqpow = false; - nopow = false; - break; - } - } - b = false; - if(sqpow && nopow && !mstruct_a.representsZero(true)) { - b = mstruct_a.representsNonZero(true); - if(!b && eo2.approximation == APPROXIMATION_EXACT) { - MathStructure mtest(mstruct_a); - mtest.add(m_zero, OPERATION_NOT_EQUALS); - EvaluationOptions eo3 = eo2; - eo3.test_comparisons = true; - mtest.calculatesub(eo3, eo, false); - b = mtest.isOne(); - } - } - if(b) { - int a_iv = find_interval_precision(mstruct_a); - int b_iv = find_interval_precision(mstruct_b); - int c_iv = find_interval_precision(CHILD(1)); - if(a_iv >= 0 && (c_iv < 0 || c_iv > a_iv) && CHILD(1).representsNonZero()) { - //x=(-2c)/(b+/-sqrt(b^2-4ac)) - MathStructure mbak(*this); - bool stop_iv = false; - if(c_iv >= 0 && c_iv <= PRECISION) { - stop_iv = true; - } else if(b_iv >= 0) { - MathStructure mstruct_bl; - MathStructure mstruct_bu; - stop_iv = true; - if(mstruct_b.isNumber() && mstruct_b.number().isNonZero() && !mstruct_b.number().hasImaginaryPart()) { - mstruct_bl = mstruct_b.number().lowerEndPoint(); - mstruct_bu = mstruct_b.number().upperEndPoint(); - stop_iv = false; - } else if(is_units_with_multiplier(mstruct_b) && mstruct_b[0].number().isNonZero() && !mstruct_b[0].number().hasImaginaryPart()) { - mstruct_bl = mstruct_b; - mstruct_bl[0].number() = mstruct_b[0].number().lowerEndPoint(); - mstruct_bu = mstruct_b; - mstruct_bu[0].number() = mstruct_b[0].number().upperEndPoint(); - stop_iv = false; - } - if(!stop_iv) { - // Lower b+sqrt(b^2-4ac) - MathStructure b2l(mstruct_bl); - b2l.calculateRaise(nr_two, eo2); - MathStructure ac(4, 1); - ac.calculateMultiply(mstruct_a, eo2); - ac.calculateMultiply(CHILD(1), eo2); - b2l.calculateAdd(ac, eo2); - - b2l.calculateRaise(nr_half, eo2); - MathStructure mstruct_1l(mstruct_bl); - mstruct_1l.calculateAdd(b2l, eo2); - - // Upper -b+sqrt(b^2-4ac) - MathStructure b2u(mstruct_bu); - b2u.calculateRaise(nr_two, eo2); - b2u.calculateAdd(ac, eo2); - - b2u.calculateRaise(nr_half, eo2); - MathStructure mstruct_1u(mstruct_bu); - mstruct_1u.calculateAdd(b2u, eo2); - - MathStructure mstruct_1(mstruct_1l); - mstruct_1.transform(STRUCT_FUNCTION, mstruct_1u); - mstruct_1.setFunction(CALCULATOR->f_interval); - mstruct_1.calculateFunctions(eo, false); - - // Lower -b-sqrt(b^2-4ac) - MathStructure mstruct_2l(mstruct_bl); - mstruct_2l.calculateSubtract(b2l, eo2); - - // Upper -b-sqrt(b^2-4ac) - MathStructure mstruct_2u(mstruct_bu); - mstruct_2u.calculateSubtract(b2u, eo2); - - MathStructure mstruct_2(mstruct_2l); - mstruct_2.transform(STRUCT_FUNCTION, mstruct_2u); - mstruct_2.setFunction(CALCULATOR->f_interval); - mstruct_2.calculateFunctions(eo, false); - - MathStructure mstruct_c(CHILD(1)); - mstruct_c.calculateMultiply(nr_two, eo2); - - mstruct_1.calculateInverse(eo2); - mstruct_2.calculateInverse(eo2); - mstruct_1.calculateMultiply(mstruct_c, eo2); - mstruct_2.calculateMultiply(mstruct_c, eo2); - - CHILD(0) = x_var; - if(!mpow_b.isOne()) {CHILD(0) ^= mpow_b; CHILD_UPDATED(0);} - if(mstruct_1 == mstruct_2) { - CHILD(1) = mstruct_1; - isolate_x_sub(eo, eo2, x_var, morig); - } else { - CHILD(1) = mstruct_1; - MathStructure *mchild2 = new MathStructure(CHILD(0)); - isolate_x_sub(eo, eo2, x_var, morig); - mchild2->transform(STRUCT_COMPARISON, mstruct_2); - mchild2->setComparisonType(ct_comp); - mchild2->isolate_x_sub(eo, eo2, x_var, morig); - if(ct_comp == COMPARISON_NOT_EQUALS) { - transform_nocopy(STRUCT_LOGICAL_AND, mchild2); - } else { - transform_nocopy(STRUCT_LOGICAL_OR, mchild2); - } - calculatesub(eo2, eo, false); - } - CHILDREN_UPDATED - return true; - } - } - EvaluationOptions eo3 = eo2; - if(b && stop_iv) { - CALCULATOR->beginTemporaryStopIntervalArithmetic(); - eo3.interval_calculation = INTERVAL_CALCULATION_NONE; - bool failed = false; - fix_intervals(*this, eo3, &failed); - if(failed) { - set(mbak); - CALCULATOR->endTemporaryStopIntervalArithmetic(); - b = false; - } - } - if(b) { - MathStructure b2(mstruct_b); - b2.calculateRaise(nr_two, eo3); - MathStructure ac(4, 1); - ac.calculateMultiply(mstruct_a, eo3); - ac.calculateMultiply(CHILD(1), eo3); - b2.calculateAdd(ac, eo3); - - b2.calculateRaise(nr_half, eo3); - MathStructure mstruct_1(mstruct_b); - mstruct_1.calculateAdd(b2, eo3); - MathStructure mstruct_2(mstruct_b); - mstruct_2.calculateSubtract(b2, eo3); - - MathStructure mstruct_c(CHILD(1)); - mstruct_c.calculateMultiply(nr_two, eo3); - - mstruct_1.calculateInverse(eo3); - mstruct_2.calculateInverse(eo3); - mstruct_1.calculateMultiply(mstruct_c, eo3); - mstruct_2.calculateMultiply(mstruct_c, eo3); - - CHILD(0) = x_var; - if(!mpow_b.isOne()) {CHILD(0) ^= mpow_b; CHILD_UPDATED(0);} - if(mstruct_1 == mstruct_2) { - CHILD(1) = mstruct_1; - isolate_x_sub(eo, eo3, x_var, morig); - } else { - CHILD(1) = mstruct_1; - MathStructure *mchild2 = new MathStructure(CHILD(0)); - isolate_x_sub(eo, eo3, x_var, morig); - mchild2->transform(STRUCT_COMPARISON, mstruct_2); - mchild2->setComparisonType(ct_comp); - mchild2->isolate_x_sub(eo, eo3, x_var, morig); - if(ct_comp == COMPARISON_NOT_EQUALS) { - transform_nocopy(STRUCT_LOGICAL_AND, mchild2); - } else { - transform_nocopy(STRUCT_LOGICAL_OR, mchild2); - } - calculatesub(eo3, eo, false); - } - CHILDREN_UPDATED; - if(stop_iv) { - CALCULATOR->endTemporaryStopIntervalArithmetic(); - CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); - fix_intervals(*this, eo2); - } - return true; - } - } else if(CHILD(1).isZero()) { - // x=0 || x=-a/b || (a=0 && b=0) - ComparisonType ct = ct_comp; - CHILD(0) = x_var; - if(!mpow_b.isOne()) {CHILD(0) ^= mpow_b; CHILD_UPDATED(0);} - MathStructure *mchild2 = new MathStructure(CHILD(0)); - CHILD(1) = mstruct_b; - CHILD(1).calculateDivide(mstruct_a, eo2); - CHILD(1).calculateNegate(eo2); - isolate_x_sub(eo, eo2, x_var, morig); - if(!mstruct_a.representsNonZero()) { - MathStructure *mtest = new MathStructure(mstruct_a); - mtest->transform(ct == COMPARISON_NOT_EQUALS ? COMPARISON_EQUALS : COMPARISON_NOT_EQUALS, m_zero); - mtest->calculatesub(eo2, eo, false); - transform_nocopy(ct == COMPARISON_NOT_EQUALS ? STRUCT_LOGICAL_OR : STRUCT_LOGICAL_AND, mtest); - calculatesub(eo2, eo, false); - } - mchild2->transform(ct, m_zero); - mchild2->isolate_x_sub(eo, eo2, x_var, morig); - transform_nocopy(ct == COMPARISON_NOT_EQUALS ? STRUCT_LOGICAL_AND : STRUCT_LOGICAL_OR, mchild2); - if(!mstruct_b.representsNonZero() && !mstruct_a.representsNonZero()) { - MathStructure *mchild3a = new MathStructure(mstruct_a); - mchild3a->transform(ct, m_zero); - MathStructure *mchild3b = new MathStructure(mstruct_b); - mchild3b->transform(ct, m_zero); - mchild3a->transform_nocopy(ct == COMPARISON_NOT_EQUALS ? STRUCT_LOGICAL_OR : STRUCT_LOGICAL_AND, mchild3b); - mchild3a->calculatesub(eo2, eo, false); - add_nocopy(mchild3a, ct == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); - } - calculatesub(eo2, eo, false); - return true; - } else { - // x=(-b+/-sqrt(b^2-4ac))/(2a) - MathStructure mbak(*this); - bool stop_iv = false; - if(a_iv >= 0 && a_iv <= PRECISION) { - stop_iv = true; - } else if(b_iv >= 0) { - MathStructure mstruct_bl; - MathStructure mstruct_bu; - stop_iv = true; - if(mstruct_b.isNumber() && mstruct_b.number().isNonZero() && !mstruct_b.number().hasImaginaryPart()) { - mstruct_bl = mstruct_b.number().lowerEndPoint(); - mstruct_bu = mstruct_b.number().upperEndPoint(); - stop_iv = false; - } else if(is_units_with_multiplier(mstruct_b) && mstruct_b[0].number().isNonZero() && !mstruct_b[0].number().hasImaginaryPart()) { - mstruct_bl = mstruct_b; - mstruct_bl[0].number() = mstruct_b[0].number().lowerEndPoint(); - mstruct_bu = mstruct_b; - mstruct_bu[0].number() = mstruct_b[0].number().upperEndPoint(); - stop_iv = false; - } - if(!stop_iv) { - // Lower -b+sqrt(b^2-4ac) - MathStructure b2l(mstruct_bl); - b2l.calculateRaise(nr_two, eo2); - MathStructure ac(4, 1); - ac.calculateMultiply(mstruct_a, eo2); - ac.calculateMultiply(CHILD(1), eo2); - b2l.calculateAdd(ac, eo2); - - b2l.calculateRaise(nr_half, eo2); - mstruct_bl.calculateNegate(eo2); - MathStructure mstruct_1l(mstruct_bl); - mstruct_1l.calculateAdd(b2l, eo2); - - // Upper -b+sqrt(b^2-4ac) - MathStructure b2u(mstruct_bu); - b2u.calculateRaise(nr_two, eo2); - b2u.calculateAdd(ac, eo2); - - b2u.calculateRaise(nr_half, eo2); - mstruct_bu.calculateNegate(eo2); - MathStructure mstruct_1u(mstruct_bu); - mstruct_1u.calculateAdd(b2u, eo2); - - MathStructure mstruct_1(mstruct_1l); - mstruct_1.transform(STRUCT_FUNCTION, mstruct_1u); - mstruct_1.setFunction(CALCULATOR->f_interval); - mstruct_1.calculateFunctions(eo, false); - - // Lower -b-sqrt(b^2-4ac) - MathStructure mstruct_2l(mstruct_bl); - mstruct_2l.calculateSubtract(b2l, eo2); - - // Upper -b-sqrt(b^2-4ac) - MathStructure mstruct_2u(mstruct_bu); - mstruct_2u.calculateSubtract(b2u, eo2); - - MathStructure mstruct_2(mstruct_2l); - mstruct_2.transform(STRUCT_FUNCTION, mstruct_2u); - mstruct_2.setFunction(CALCULATOR->f_interval); - mstruct_2.calculateFunctions(eo, false); - - mstruct_a.calculateMultiply(nr_two, eo2); - mstruct_a.calculateInverse(eo2); - mstruct_1.calculateMultiply(mstruct_a, eo2); - mstruct_2.calculateMultiply(mstruct_a, eo2); - CHILD(0) = x_var; - if(!mpow_b.isOne()) {CHILD(0) ^= mpow_b; CHILD_UPDATED(0);} - if(mstruct_1 == mstruct_2) { - CHILD(1) = mstruct_1; - isolate_x_sub(eo, eo2, x_var, morig); - } else { - CHILD(1) = mstruct_1; - MathStructure *mchild2 = new MathStructure(CHILD(0)); - isolate_x_sub(eo, eo2, x_var, morig); - mchild2->transform(STRUCT_COMPARISON, mstruct_2); - mchild2->setComparisonType(ct_comp); - mchild2->isolate_x_sub(eo, eo2, x_var, morig); - if(ct_comp == COMPARISON_NOT_EQUALS) { - transform_nocopy(STRUCT_LOGICAL_AND, mchild2); - } else { - transform_nocopy(STRUCT_LOGICAL_OR, mchild2); - } - calculatesub(eo2, eo, false); - } - CHILDREN_UPDATED - return true; - } - } - EvaluationOptions eo3 = eo2; - if(b && stop_iv) { - CALCULATOR->beginTemporaryStopIntervalArithmetic(); - eo3.interval_calculation = INTERVAL_CALCULATION_NONE; - bool failed = false; - fix_intervals(*this, eo3, &failed); - if(failed) { - set(mbak); - CALCULATOR->endTemporaryStopIntervalArithmetic(); - b = false; - } - } - if(b) { - MathStructure b2(mstruct_b); - b2.calculateRaise(nr_two, eo3); - MathStructure ac(4, 1); - ac.calculateMultiply(mstruct_a, eo3); - ac.calculateMultiply(CHILD(1), eo3); - b2.calculateAdd(ac, eo3); - - b2.calculateRaise(nr_half, eo3); - mstruct_b.calculateNegate(eo3); - MathStructure mstruct_1(mstruct_b); - mstruct_1.calculateAdd(b2, eo3); - MathStructure mstruct_2(mstruct_b); - mstruct_2.calculateSubtract(b2, eo3); - mstruct_a.calculateMultiply(nr_two, eo3); - mstruct_a.calculateInverse(eo3); - mstruct_1.calculateMultiply(mstruct_a, eo3); - mstruct_2.calculateMultiply(mstruct_a, eo3); - CHILD(0) = x_var; - if(!mpow_b.isOne()) {CHILD(0) ^= mpow_b; CHILD_UPDATED(0);} - if(mstruct_1 == mstruct_2) { - CHILD(1) = mstruct_1; - isolate_x_sub(eo, eo3, x_var, morig); - } else { - CHILD(1) = mstruct_1; - MathStructure *mchild2 = new MathStructure(CHILD(0)); - isolate_x_sub(eo, eo3, x_var, morig); - mchild2->transform(STRUCT_COMPARISON, mstruct_2); - mchild2->setComparisonType(ct_comp); - mchild2->isolate_x_sub(eo, eo3, x_var, morig); - if(ct_comp == COMPARISON_NOT_EQUALS) { - transform_nocopy(STRUCT_LOGICAL_AND, mchild2); - } else { - transform_nocopy(STRUCT_LOGICAL_OR, mchild2); - } - calculatesub(eo3, eo, false); - } - CHILDREN_UPDATED; - if(stop_iv) { - CALCULATOR->endTemporaryStopIntervalArithmetic(); - CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); - fix_intervals(*this, eo2); - } - return true; - } - } - } - } - if(CALCULATOR->aborted()) return false; - - // a*b^x+cx=0 => -lambertw(a*log(b)/c)/log(b) - // a*b^x+cx=d => (d*log(b)-c*lambertw(a*b^(d/c)*log(b)/c))/(c*log(b)) - if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && CHILD(0).size() > 1) { - size_t i_px = 0, i_mpx = 0; - MathStructure mbak(*this); - MathStructure *mvar = NULL, *m_b_p; - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CHILD(0)[i].isMultiplication()) { - for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { - if(CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][1].contains(x_var) && !CHILD(0)[i][i2][0].contains(x_var)) { - mvar = &CHILD(0)[i][i2][1]; - m_b_p = &CHILD(0)[i][i2][0]; - i_px = i; - i_mpx = i2; - break; - } - } - if(mvar) break; - } else if(CHILD(0)[i].isPower() && CHILD(0)[i][1].contains(x_var) && !CHILD(0)[i][0].contains(x_var)) { - mvar = &CHILD(0)[i][1]; - m_b_p = &CHILD(0)[i][0]; - i_px = i; - break; - } - } - if(mvar) { - MathStructure m_b(*m_b_p); - if((mvar->isAddition() || mvar->isMultiplication()) && m_b.representsPositive()) { - MathStructure *mvar2 = NULL; - if(mvar->isMultiplication()) { - for(size_t i = 0; i < mvar->size(); i++) { - if((*mvar)[i].contains(x_var)) {mvar2 = &(*mvar)[i]; break;} - } - } else if(mvar->isAddition()) { - for(size_t i = 0; i < mvar->size(); i++) { - if((*mvar)[i].contains(x_var)) { - mvar2 = &(*mvar)[i]; - if(mvar2->isMultiplication()) { - for(size_t i2 = 0; i2 < mvar2->size(); i2++) { - if((*mvar2)[i2].contains(x_var)) {mvar2 = &(*mvar2)[i2]; break;} - } - } - break; - } - } - } - if(mvar2) { - MathStructure m_b_exp; - if(get_multiplier(*mvar, *mvar2, m_b_exp) && m_b.representsReal() && !m_b.contains(x_var)) { - m_b ^= m_b_exp; - mvar = mvar2; - } else { - mvar = NULL; - } - } - } - MathStructure m_c; - if(mvar && get_multiplier(CHILD(0), *mvar, m_c, i_px) && m_c.representsNonZero() && m_c.contains(x_var) == 0) { - MathStructure mlogb(CALCULATOR->f_ln, &m_b, NULL); - if(mlogb.calculateFunctions(eo)) mlogb.calculatesub(eo2, eo, true); - MathStructure *marg = NULL; - if(mlogb.representsNonZero()) { - marg = new MathStructure(mlogb); - if(CHILD(0)[i_px].isMultiplication()) { - marg->multiply(CHILD(0)[i_px]); - marg->last().delChild(i_mpx + 1, true); - if(!marg->last().representsNonZero()) {marg->unref(); marg = NULL;} - else marg->calculateMultiplyLast(eo2); - } - } - if(marg) { - if(!CHILD(1).isZero()) { - marg->multiply(m_b); - marg->last().raise(CHILD(1)); - if(!m_c.isOne()) marg->last().last().calculateDivide(m_c, eo2); - marg->last().calculateRaiseExponent(eo2); - marg->calculateMultiplyLast(eo2); - } - if(!m_c.isOne()) marg->calculateDivide(m_c, eo2); - } - if(marg && mvar->representsNonComplex() && m_b.representsPositive()) { - if(marg->representsComplex()) { - marg->unref(); - if(ct_comp == COMPARISON_EQUALS) clear(true); - else set(1, 1, 0, true); - return true; - } - MathStructure *mreq1 = NULL; - MathStructure *marg2 = NULL; - MathStructure *mreq2 = NULL; - if(!marg->representsNonNegative()) { - mreq1 = new MathStructure(*marg); - mreq2 = new MathStructure(*marg); - marg2 = new MathStructure(*marg); - marg2->transform(CALCULATOR->f_lambert_w); - marg2->addChild(m_minus_one); - if(marg2->calculateFunctions(eo)) marg2->calculatesub(eo2, eo, true); - marg2->calculateNegate(eo2); - if(CHILD(1).isZero()) { - marg2->calculateDivide(mlogb, eo2); - } else { - if(!m_c.isOne()) marg->calculateMultiply(m_c, eo2); - marg2->add(CHILD(1)); - marg2->last().calculateMultiply(mlogb, eo); - marg2->calculateAddLast(eo2); - marg2->calculateDivide(mlogb, eo2); - if(!m_c.isOne()) marg->calculateDivide(m_c, eo2); - } - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->v_e); - mreq1->last().calculateRaise(m_minus_one, eo2); - mreq1->last().calculateNegate(eo2); - mreq1->childUpdated(2); - mreq1->isolate_x(eo2, eo); - mreq2->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, m_zero); - mreq2->isolate_x(eo2, eo); - marg2->transform(ct_comp, *mvar); - marg2->swapChildren(1, 2); - marg2->isolate_x_sub(eo, eo2, x_var, morig); - marg2->add(*mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - marg2->add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - marg2->calculatesub(eo2, eo, false); - } - marg->transform(CALCULATOR->f_lambert_w); - marg->addChild(m_zero); - if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); - marg->calculateNegate(eo2); - if(CHILD(1).isZero()) { - marg->calculateDivide(mlogb, eo2); - } else { - if(!m_c.isOne()) marg->calculateMultiply(m_c, eo2); - marg->add(CHILD(1)); - marg->last().calculateMultiply(mlogb, eo); - marg->calculateAddLast(eo2); - marg->calculateDivide(mlogb, eo2); - if(!m_c.isOne()) marg->calculateDivide(m_c, eo2); - } - setChild_nocopy(marg, 2, true); - mvar->ref(); - CHILD(0).clear(true); - setChild_nocopy(mvar, 1, true); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - if(mreq1) { - add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - if(marg2) { - add_nocopy(marg2, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - return true; - } else if(marg) { - marg->transform(CALCULATOR->f_lambert_w); - marg->addChild(CALCULATOR->v_n); - if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); - marg->calculateNegate(eo2); - if(CHILD(1).isZero()) { - marg->calculateDivide(mlogb, eo2); - } else { - if(!m_c.isOne()) marg->calculateMultiply(m_c, eo2); - marg->add(CHILD(1)); - marg->last().calculateMultiply(mlogb, eo); - marg->calculateAddLast(eo2); - marg->calculateDivide(mlogb, eo2); - if(!m_c.isOne()) marg->calculateDivide(m_c, eo2); - } - setChild_nocopy(marg, 2, true); - mvar->ref(); - CHILD(0).clear(true); - setChild_nocopy(mvar, 1, true); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } - } - } - if(i_px == 0) { - // a^(2x)+a^x, a^(-x)+a^x - MathStructure *mvar1 = NULL, *mvar2 = NULL; - b = true; - for(size_t i = 0; i < CHILD(0).size() && b; i++) { - b = false; - if(CHILD(0)[i].isMultiplication()) { - for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { - if(!b && CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][1].contains(x_var) && !CHILD(0)[i][i2][0].contains(x_var)) { - if(mvar2) { - if(mvar1->equals(CHILD(0)[i][i2]) || mvar2->equals(CHILD(0)[i][i2])) { - b = true; - } - } else if(mvar1) { - if(!mvar1->equals(CHILD(0)[i][i2])) { - mvar2 = &CHILD(0)[i][i2]; - } - b = true; - } else { - mvar1 = &CHILD(0)[i][i2]; - b = true; - } - if(!b) break; - } else if(CHILD(0)[i][i2].contains(x_var)) { - b = false; - break; - } - } - } else if(CHILD(0)[i].isPower() && CHILD(0)[i][1].contains(x_var) && !CHILD(0)[i][0].contains(x_var)) { - if(mvar2) { - if(mvar1->equals(CHILD(0)[i]) || mvar2->equals(CHILD(0)[i])) { - b = true; - } - } else if(mvar1) { - if(!mvar1->equals(CHILD(0)[i])) { - mvar2 = &CHILD(0)[i]; - } - b = true; - } else { - mvar1 = &CHILD(0)[i]; - b = true; - } - } - } - if(b && mvar2 && mvar1->base()->representsPositive()) { - bool b_two = false, b_m_one = false; - if(mvar1->base()->equals(*mvar2->base())) { - MathStructure m1m2((*mvar1)[1]); - m1m2.calculateMultiply(nr_two, eo2); - if(m1m2.equals((*mvar2)[1])) { - b_two = true; - MathStructure *mtmp = mvar2; - mvar2 = mvar1; - mvar1 = mtmp; - } - if(!b_two && !b_m_one) { - MathStructure m1mm1((*mvar1)[1]); - m1mm1.calculateMultiply(nr_minus_one, eo2); - if(m1mm1.equals((*mvar2)[1])) { - b_m_one = true; - MathStructure *mtmp = mvar2; - mvar2 = mvar1; - mvar1 = mtmp; - } - } - if(!b_two && !b_m_one) { - MathStructure m2m2((*mvar2)[1]); - m2m2.calculateMultiply(nr_two, eo2); - if(m2m2.equals((*mvar1)[1])) { - b_two = true; - } - } - if(!b_two && !b_m_one) { - MathStructure m2mm1((*mvar2)[1]); - m2mm1.calculateMultiply(nr_minus_one, eo2); - if(m2mm1.equals((*mvar1)[1])) { - b_m_one = true; - } - } - } else if(mvar1->base()->isNumber() && mvar2->base()->isNumber() && !mvar1->base()->number().isInterval() && !mvar2->base()->number().isInterval()) { - if(mvar1->base()->number() < mvar2->base()->number()) { - if(mvar2->base()->number() == (mvar1->base()->number() ^ 2)) { - b_two = true; - } else if(mvar1->base()->number() == (mvar2->base()->number() ^ -1)) { - b_m_one = true; - MathStructure *mtmp = mvar2; - mvar2 = mvar1; - mvar1 = mtmp; - } - } else { - if(mvar1->base()->number() == (mvar2->base()->number() ^ 2)) { - b_two = true; - MathStructure *mtmp = mvar2; - mvar2 = mvar1; - mvar1 = mtmp; - } else if(mvar2->base()->number() == (mvar1->base()->number() ^ -1)) { - b_m_one = true; - } - } - } - if(b_two || b_m_one) { - MathStructure mv(*mvar1); - MathStructure mv2(*mvar2); - UnknownVariable *var = new UnknownVariable("", format_and_print(mv)); - var->setInterval(mv); - MathStructure u_var(var); - replace(mv, u_var); - MathStructure u_var2(var); - u_var2.raise(b_two ? nr_two : nr_minus_one); - replace(mv2, u_var2); - b = isolate_x_sub(eo, eo2, u_var); - calculateReplace(u_var, mv, eo2); - var->destroy(); - if(b) isolate_x(eo, eo2, x_var); - return b; - } - } - } - if(CHILD(0).containsFunction(CALCULATOR->f_ln)) { - // x+ln(x)=lambertw(x) - MathStructure *mln = NULL; - mvar = NULL; - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CHILD(0)[i].isMultiplication()) { - MathStructure *mln2 = NULL; - for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { - if(CHILD(0)[i][i2].contains(x_var)) { - if(!mln2 && CHILD(0)[i][i2].isFunction() && CHILD(0)[i][i2].function() == CALCULATOR->f_ln && CHILD(0)[i][i2].size() == 1) { - mln2 = &CHILD(0)[i][i2]; - } else { - mln2 = NULL; - break; - } - } - } - if(mln2) { - if(mln) { - if(*mln2 != *mln) { - if(!mvar) mvar = &CHILD(0)[i]; - } - } else { - mln = mln2; - } - } else if(!mvar) { - mvar = &CHILD(0)[i]; - } - } else if(!mln && CHILD(0)[i].isFunction() && CHILD(0)[i].function() == CALCULATOR->f_ln && CHILD(0)[i].size() == 1) { - mln = &CHILD(0)[i]; - } else if(!mvar) { - mvar = &CHILD(0)[i]; - } - } - if(mvar && mln) { - MathStructure mx(1, 1, 0); - MathStructure mmul2; - if(mvar->isMultiplication()) { - for(size_t i = 0; i < mvar->size(); i++) { - if((*mvar)[i].contains(x_var)) { - if(mx.isOne()) mx = (*mvar)[i]; - else mx.multiply((*mvar)[i], true); - } - } - } else { - mx = *mvar; - } - if(!mx.isOne() && !get_multiplier((*mln)[0], mx, mmul2)) { - mx = m_one; - } - if(!mx.isOne()) { - MathStructure mbak(*this); - MathStructure mlns; - MathStructure mmul1; - mlns.setType(STRUCT_ADDITION); - bool b_mul = false; - for(size_t i = 0; i < CHILD(0).size();) { - if(&CHILD(0)[i] == mln || CHILD(0)[i] == *mln) { - if(&CHILD(0)[i] != mln) b_mul = true; - CHILD(0)[i].ref(); - mlns.addChild_nocopy(&CHILD(0)[i]); - CHILD(0).delChild(i + 1); - } else if(CHILD(0)[i].isMultiplication()) { - b = false; - for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { - if(CHILD(0)[i][i2] == *mln) { - CHILD(0)[i].ref(); - mlns.addChild_nocopy(&CHILD(0)[i]); - CHILD(0).delChild(i + 1); - b = true; - b_mul = true; - break; - } - } - if(!b) i++; - } else { - i++; - } - } - if(CHILD(0).size() == 1) CHILD(0).setToChild(1, true); - if(!get_multiplier(CHILD(0), mx, mmul1)) { - mx = m_one; - } - if(!mx.isOne()) { - if(mlns.size() == 0) { - mx = m_one; - } else if(b_mul) { - MathStructure mmul3; - MathStructure mln2(*mln); - if(!get_multiplier(mlns, mln2, mmul3)) { - mx = m_one; - } else if(!mmul3.isOne()) { - mmul1.calculateDivide(mmul3, eo2); - CHILD(1).calculateDivide(mmul3, eo2); - } - } - } - if(!mx.isOne() && mmul1.representsNonZero() && mmul2.representsNonZero() && !mmul2.contains(x_var)) { - MathStructure *marg; - if(!CHILD(1).isZero()) { - marg = new MathStructure(CALCULATOR->v_e); - marg->calculateRaise(CHILD(1), eo2); - if(!mmul1.isOne()) marg->calculateMultiply(mmul1, eo2); - } else { - marg = new MathStructure(mmul1); - } - if(!mmul2.isOne()) marg->calculateDivide(mmul2, eo2); - MathStructure *mreq1 = NULL; - if(mx.representsNonComplex() && !marg->representsNonNegative()) { - mreq1 = new MathStructure(*marg); - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->v_e); - mreq1->last().calculateRaise(m_minus_one, eo2); - mreq1->last().calculateNegate(eo2); - mreq1->childUpdated(2); - mreq1->isolate_x(eo2, eo); - } - marg->transform(CALCULATOR->f_lambert_w); - marg->addChild(m_zero); - if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); - CHILD(0).set(mx, true); - setChild_nocopy(marg, 2); - if(!mmul1.isOne()) CHILD(1).calculateDivide(mmul1, eo2); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - if(mreq1) { - add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - return true; - } - set(mbak); - } - } - } - if(CHILD(0).containsFunction(CALCULATOR->f_cosh) && CHILD(0).containsFunction(CALCULATOR->f_sinh)) { - // a*cosh(x) + b*cosh(x) - MathStructure *marg = NULL, *m_cosh = NULL, *m_sinh = NULL; - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CHILD(0)[i].isMultiplication()) { - bool b_found = false; - for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { - if(CHILD(0)[i][i2].contains(x_var)) { - if(!b_found && CHILD(0)[i][i2].isFunction() && (CHILD(0)[i][i2].function() == CALCULATOR->f_cosh || CHILD(0)[i][i2].function() == CALCULATOR->f_sinh) && CHILD(0)[i][i2].size() == 1 && (!marg || marg->equals(CHILD(0)[i][i2][0]))) { - if(!marg) marg = &CHILD(0)[i][i2][0]; - if(CHILD(0)[i][i2].function() == CALCULATOR->f_cosh) m_cosh = &CHILD(0)[i][i2]; - else m_sinh = &CHILD(0)[i][i2]; - b_found = true; - } else { - b_found = false; - break; - } - } - } - if(!b_found) { - marg = NULL; - break; - } - } else if(CHILD(0)[i].isFunction() && (CHILD(0)[i].function() == CALCULATOR->f_cosh || CHILD(0)[i].function() == CALCULATOR->f_sinh) && CHILD(0)[i].size() == 1 && (!marg || marg->equals(CHILD(0)[i][0]))) { - if(!marg) marg = &CHILD(0)[i][0]; - if(CHILD(0)[i].function() == CALCULATOR->f_cosh) m_cosh = &CHILD(0)[i]; - else m_sinh = &CHILD(0)[i]; - } else { - marg = NULL; - break; - } - } - if(marg && m_cosh && m_sinh) { - MathStructure mtest(*this); - EvaluationOptions eo3 = eo; - eo3.approximation = APPROXIMATION_EXACT; - MathStructure m_ex(CALCULATOR->v_e); - m_ex.raise(*marg); - MathStructure m_emx(m_ex); - m_emx.last().calculateMultiply(nr_minus_one, eo2); - m_ex *= nr_half; - m_emx *= nr_half; - m_ex.swapChildren(1, 2); - m_emx.swapChildren(1, 2); - MathStructure mr_sinh(m_ex); - mr_sinh.calculateSubtract(m_emx, eo3); - MathStructure mr_cosh(m_ex); - mr_cosh.calculateAdd(m_emx, eo3); - mtest[0].calculateReplace(*m_sinh, mr_sinh, eo3); - mtest[0].calculateReplace(*m_cosh, mr_cosh, eo3); - if(mtest.isolate_x_sub(eo, eo3, x_var, morig)) { - if(eo2.approximation != APPROXIMATION_EXACT) mtest.calculatesub(eo2, eo, true); - set(mtest); - return true; - } - } - } - } - - // x+x^(1/a)=b => x=(b-x)^a - if(eo2.expand && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && CHILD(0).size() <= 10 && CHILD(0).size() > 1) { - int i_root = 0; - size_t root_index = 0; - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CALCULATOR->aborted()) return false; - if(CHILD(0)[i].isPower()) { - if(CHILD(0)[i][1].isNumber() && !CHILD(0)[i][1].isInteger() && CHILD(0)[i][1].number().numeratorIsOne() && CHILD(0)[i][1].number().denominatorIsLessThan(10)) { - if(i_root) { - if(i_root != CHILD(0)[i][1].number().denominator().intValue()) { - i_root = 0; - break; - } - } else { - i_root = CHILD(0)[i][1].number().denominator().intValue(); - root_index = i; - } - } else if(!CHILD(0)[i][1].isNumber() || !CHILD(0)[i][1].number().isInteger()) { - i_root = 0; - break; - } - } else if(CHILD(0)[i].isFunction() && CHILD(0)[i].function() == CALCULATOR->f_root) { - if(VALID_ROOT(CHILD(0)[i]) && CHILD(0)[i][1].number().isLessThan(10)) { - if(i_root) { - if(i_root != CHILD(0)[i][1].number().intValue()) { - i_root = 0; - break; - } - } else { - i_root = CHILD(0)[i][1].number().intValue(); - root_index = i; - } - } else { - i_root = 0; - break; - } - } else if(CHILD(0)[i].isMultiplication()) { - bool b_break = false; - for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { - if(CHILD(0)[i][i2].contains(x_var)) { - if(CHILD(0)[i][i2].isPower()) { - if(CHILD(0)[i][i2][1].isNumber() && !CHILD(0)[i][i2][1].number().isInteger() && CHILD(0)[i][i2][1].number().numeratorIsOne() && CHILD(0)[i][i2][1].number().denominatorIsLessThan(10)) { - if(i_root) { - if(i_root != CHILD(0)[i][i2][1].number().denominator().intValue()) { - i_root = 0; - b_break = true; - break; - } - } else { - i_root = CHILD(0)[i][i2][1].number().denominator().intValue(); - root_index = i; - } - } else if(!CHILD(0)[i][i2][1].isNumber() || !CHILD(0)[i][i2][1].number().isInteger()) { - i_root = 0; - b_break = true; - break; - } - } else if(CHILD(0)[i][i2].isFunction() && CHILD(0)[i][i2].function() == CALCULATOR->f_root) { - if(VALID_ROOT(CHILD(0)[i][i2]) && CHILD(0)[i][i2][1].number().isLessThan(10)) { - if(i_root) { - if(i_root != CHILD(0)[i][i2][1].number().intValue()) { - i_root = 0; - b_break = true; - break; - } - } else { - i_root = CHILD(0)[i][i2][1].number().intValue(); - root_index = i; - } - } else { - i_root = 0; - b_break = true; - break; - } - } - } - } - if(b_break) break; - } - } - if(i_root) { - MathStructure mtest(*this); - MathStructure msub; - if(mtest[0].size() == 2) { - msub = mtest[0][root_index == 0 ? 1 : 0]; - } else { - msub = mtest[0]; - msub.delChild(root_index + 1); - } - mtest[0].setToChild(root_index + 1); - mtest[1].calculateSubtract(msub, eo2); - if(mtest[0].calculateRaise(i_root, eo2) && mtest[1].calculateRaise(i_root, eo2)) { - mtest.childrenUpdated(); - if(mtest.isolate_x(eo2, eo, x_var)) { - if((mtest.isLogicalAnd() || mtest.isLogicalOr() || mtest.isComparison()) && test_comparisons(*this, mtest, x_var, eo, false, eo2.expand ? 1 : 2) < 0) { - if(eo2.expand) { - add(mtest, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); - calculatesub(eo2, eo, false); - return true; - } - } else { - set(mtest); - return true; - } - } - } - - } - } - - // x+y/x=z => x*x+y=z*x - MathStructure mdiv; - mdiv.setUndefined(); - MathStructure mdiv_inv; - bool b_multiple_div = false; - for(size_t i = 0; i < CHILD(0).size() && !b_multiple_div; i++) { - if(CALCULATOR->aborted()) return false; - if(CHILD(0)[i].isMultiplication()) { - for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { - if(CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][1].isNumber() && CHILD(0)[i][i2][1].number().isReal() && CHILD(0)[i][i2][1].number().isNegative()) { - if(!mdiv.isUndefined()) b_multiple_div = true; - else mdiv = CHILD(0)[i][i2]; - break; - } - } - } else if(CHILD(0)[i].isPower() && CHILD(0)[i][1].isNumber() && CHILD(0)[i][1].number().isReal() && CHILD(0)[i][1].number().isNegative()) { - if(!mdiv.isUndefined()) b_multiple_div = true; - else mdiv = CHILD(0)[i]; - } - } - if(!mdiv.isUndefined() && countTotalChildren() > 200) mdiv.setUndefined(); - if(!mdiv.isUndefined() && b_multiple_div && mdiv.containsInterval()) { - MathStructure mbak(*this); - CALCULATOR->beginTemporaryStopIntervalArithmetic(); - bool failed = false; - EvaluationOptions eo3 = eo2; - eo3.interval_calculation = INTERVAL_CALCULATION_NONE; - fix_intervals(*this, eo3, &failed); - if(!failed && isolate_x_sub(eo, eo3, x_var, morig)) { - CALCULATOR->endTemporaryStopIntervalArithmetic(); - if((CALCULATOR->usesIntervalArithmetic() && eo.approximation != APPROXIMATION_EXACT) || mbak.containsInterval()) CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); - fix_intervals(*this, eo2); - return true; - } - CALCULATOR->endTemporaryStopIntervalArithmetic(); - set(mbak); - } else if(!mdiv.isUndefined()) { - if(mdiv[1].isMinusOne()) { - mdiv_inv = mdiv[0]; - } else { - mdiv_inv = mdiv; - mdiv_inv[1].number().negate(); - } - EvaluationOptions eo3 = eo2; - eo3.expand = true; - bool b2 = false; - for(size_t i3 = 0; i3 < CHILD(0).size(); i3++) { - bool b = false; - if(!b2 || !mdiv.containsInterval()) { - if(CHILD(0)[i3].isPower() && CHILD(0)[i3].equals(mdiv, true)) { - CHILD(0)[i3].set(1, 1, 0, true); - b = true; - } else if(CHILD(0)[i3].isMultiplication()) { - for(size_t i4 = 0; i4 < CHILD(0)[i3].size(); i4++) { - if(CHILD(0)[i3][i4].isPower() && CHILD(0)[i3][i4].equals(mdiv, true)) { - b = true; - CHILD(0)[i3].delChild(i4 + 1); - if(CHILD(0)[i3].size() == 0) CHILD(0)[i3].set(1, 1, 0, true); - else if(CHILD(0)[i3].size() == 1) CHILD(0)[i3].setToChild(1, true); - break; - } - } - } - } - if(!b) { - CHILD(0)[i3].calculateMultiply(mdiv_inv, eo3); - } else { - b2 = true; - } - } - CHILD(0).childrenUpdated(); - CHILD(0).evalSort(); - CHILD(0).calculatesub(eo2, eo, false); - CHILD(1).calculateMultiply(mdiv_inv, eo3); - CHILDREN_UPDATED - if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { - bool not_equals = ct_comp == COMPARISON_NOT_EQUALS; - isolate_x(eo, eo2, x_var, morig); - if(!mdiv[0].representsNonZero(true)) { - MathStructure *mtest = new MathStructure(mdiv[0]); - mtest->add(m_zero, not_equals ? OPERATION_EQUALS : OPERATION_NOT_EQUALS); - mtest->isolate_x_sub(eo, eo2, x_var); - add_nocopy(mtest, not_equals ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - } else { - MathStructure *malt = new MathStructure(*this); - if(ct_comp == COMPARISON_EQUALS_GREATER) { - ct_comp = COMPARISON_EQUALS_LESS; - } else if(ct_comp == COMPARISON_GREATER) { - ct_comp = COMPARISON_LESS; - } else if(ct_comp == COMPARISON_EQUALS_LESS) { - ct_comp = COMPARISON_EQUALS_GREATER; - } else if(ct_comp == COMPARISON_LESS) { - ct_comp = COMPARISON_GREATER; - } - isolate_x(eo, eo2, x_var, morig); - MathStructure *mtest = new MathStructure(mdiv); - mtest->add(m_zero, OPERATION_LESS); - MathStructure *mtest_alt = new MathStructure(*mtest); - mtest_alt->setComparisonType(COMPARISON_GREATER); - mtest->isolate_x_sub(eo, eo2, x_var); - add_nocopy(mtest, OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - malt->isolate_x(eo, eo2, x_var, morig); - mtest_alt->isolate_x_sub(eo, eo2, x_var); - malt->add_nocopy(mtest_alt, OPERATION_LOGICAL_AND); - malt->calculatesub(eo2, eo, false); - add_nocopy(malt, OPERATION_LOGICAL_OR); - calculatesub(eo2, eo, false); - return true; - } - return true; - } - - // x^a+x^(b/c)=d => x^(1/c)^(a*c)+x^(1/c)^b=d; f(x)^a+f(x)^b=c => u^a+u^b=c - MathStructure mbase; - b = true; - Number nr_root; - bool b_f_root = false; - - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CALCULATOR->aborted()) return false; - if(!mbase.isZero() && CHILD(0)[i] == mbase) { - } else if(CHILD(0)[i].isPower() && CHILD(0)[i][1].isNumber() && CHILD(0)[i][1].number().isPositive() && CHILD(0)[i][1].number().isRational()) { - if(CHILD(0)[i][0].isFunction() && CHILD(0)[i][0].function() == CALCULATOR->f_root && VALID_ROOT(CHILD(0)[i][0])) { - if(mbase.isZero()) mbase = CHILD(0)[i][0][0]; - else if(mbase != CHILD(0)[i][0][0]) {b = false; break;} - if(!nr_root.isZero()) { - if(!b_f_root) {b = false; break;} - nr_root.lcm(CHILD(0)[i][0][1].number()); - } else { - nr_root = CHILD(0)[i][0][1].number(); - } - b_f_root = true; - } else { - if(mbase.isZero()) mbase = CHILD(0)[i][0]; - else if(mbase != CHILD(0)[i][0]) {b = false; break;} - if(!CHILD(0)[i][1].number().isInteger()) { - if(b_f_root) {b = false; break;} - if(!nr_root.isZero()) { - nr_root.lcm(CHILD(0)[i][1].number().denominator()); - } else { - nr_root = CHILD(0)[i][1].number().denominator(); - } - } - } - } else if(CHILD(0)[i].isMultiplication()) { - for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { - if(!mbase.isZero() && CHILD(0)[i][i2] == mbase) { - } else if(CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][1].isNumber() && CHILD(0)[i][i2][1].number().isPositive() && CHILD(0)[i][i2][1].number().isRational()) { - if(CHILD(0)[i][i2][0].isFunction() && CHILD(0)[i][i2][0].function() == CALCULATOR->f_root && VALID_ROOT(CHILD(0)[i][i2][0])) { - if(mbase.isZero()) mbase = CHILD(0)[i][i2][0][0]; - else if(mbase != CHILD(0)[i][i2][0][0]) {b = false; break;} - if(!nr_root.isZero()) { - if(!b_f_root) {b = false; break;} - nr_root.lcm(CHILD(0)[i][i2][0][1].number()); - } else { - nr_root = CHILD(0)[i][i2][0][1].number(); - } - b_f_root = true; - } else { - if(mbase.isZero()) mbase = CHILD(0)[i][i2][0]; - else if(mbase != CHILD(0)[i][i2][0]) {b = false; break;} - if(!CHILD(0)[i][i2][1].number().isInteger()) { - if(b_f_root) {b = false; break;} - if(!nr_root.isZero()) { - nr_root.lcm(CHILD(0)[i][i2][1].number().denominator()); - } else { - nr_root = CHILD(0)[i][i2][1].number().denominator(); - } - } - } - } else if(CHILD(0)[i][i2].isFunction() && CHILD(0)[i][i2].function() == CALCULATOR->f_root && VALID_ROOT(CHILD(0)[i][i2])) { - if(mbase.isZero()) mbase = CHILD(0)[i][i2][0]; - else if(mbase != CHILD(0)[i][i2][0]) {b = false; break;} - if(!nr_root.isZero()) { - if(!b_f_root) {b = false; break;} - nr_root.lcm(CHILD(0)[i][i2][1].number()); - } else { - nr_root = CHILD(0)[i][i2][1].number(); - } - b_f_root = true; - } else if(CHILD(0)[i][i2].isNumber() && !CHILD(0)[i][i2].number().isZero()) { - } else if(mbase.isZero()) { - mbase = CHILD(0)[i][i2]; - } else { - b = false; break; - } - } - if(!b) break; - } else if(CHILD(0)[i].isFunction() && CHILD(0)[i].function() == CALCULATOR->f_root && VALID_ROOT(CHILD(0)[i])) { - if(mbase.isZero()) mbase = CHILD(0)[i][0]; - else if(mbase != CHILD(0)[i][0]) {b = false; break;} - if(!nr_root.isZero()) { - if(!b_f_root) {b = false; break;} - nr_root.lcm(CHILD(0)[i][1].number()); - } else { - nr_root = CHILD(0)[i][1].number(); - } - b_f_root = true; - } else if(mbase.isZero()) { - mbase = CHILD(0)[i]; - } else { - b = false; break; - } - } - if(b && !mbase.isZero() && nr_root.isLessThan(100)) { - MathStructure mvar(mbase); - if(!nr_root.isZero()) { - if(b_f_root) { - MathStructure mroot(nr_root); - mvar.set(CALCULATOR->f_root, &mbase, &mroot, NULL); - } else { - Number nr_pow(nr_root); - nr_pow.recip(); - mvar.raise(nr_pow); - } - } - UnknownVariable *var = NULL; - if(mvar != x_var) { - var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(mvar) + RIGHT_PARENTHESIS); - var->setInterval(mvar); - } - if(!nr_root.isZero()) { - MathStructure mbak(*this); - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CALCULATOR->aborted()) {set(mbak); return false;} - if(CHILD(0)[i] == mbase) { - CHILD(0)[i] = var; - CHILD(0)[i].raise(nr_root); - } else if(CHILD(0)[i].isPower() && CHILD(0)[i][1].isNumber()) { - if(CHILD(0)[i][0].isFunction() && CHILD(0)[i][0].function() == CALCULATOR->f_root && CHILD(0)[i][0] != mbase) { - CHILD(0)[i][1].number().multiply(nr_root); - CHILD(0)[i][1].number().divide(CHILD(0)[i][0][1].number()); - if(CHILD(0)[i][1].isOne()) CHILD(0)[i] = var; - else CHILD(0)[i][0] = var; - } else if(CHILD(0)[i][0] == mbase) { - CHILD(0)[i][1].number().multiply(nr_root); - if(CHILD(0)[i][1].isOne()) CHILD(0)[i] = var; - else CHILD(0)[i][0] = var; - } else { - // should not happen - } - } else if(CHILD(0)[i].isMultiplication()) { - for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { - if(CHILD(0)[i][i2] == mbase) { - CHILD(0)[i][i2] = var; - CHILD(0)[i][i2].raise(nr_root); - } else if(CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][1].isNumber()) { - if(CHILD(0)[i][i2][0].isFunction() && CHILD(0)[i][i2][0].function() == CALCULATOR->f_root && CHILD(0)[i][i2][0] != mbase) { - CHILD(0)[i][i2][1].number().multiply(nr_root); - CHILD(0)[i][i2][1].number().divide(CHILD(0)[i][i2][0][1].number()); - if(CHILD(0)[i][i2][1].isOne()) CHILD(0)[i][i2] = var; - else CHILD(0)[i][i2][0] = var; - } else if(CHILD(0)[i][i2][0] == mbase) { - CHILD(0)[i][i2][1].number().multiply(nr_root); - if(CHILD(0)[i][i2][1].isOne()) CHILD(0)[i][i2] = var; - else CHILD(0)[i][i2][0] = var; - } else { - // should not happen - } - } else if(CHILD(0)[i][i2].isFunction() && CHILD(0)[i][i2].function() == CALCULATOR->f_root) { - Number nr_pow(nr_root); - nr_pow.divide(CHILD(0)[i][i2][1].number()); - CHILD(0)[i][i2][1] = nr_pow; - CHILD(0)[i][i2][0] = var; - CHILD(0)[i][i2].setType(STRUCT_POWER); - } else if(CHILD(0)[i][i2].isNumber() && !CHILD(0)[i][i2].number().isZero()) { - } else { - // should not happen - } - } - } else if(CHILD(0)[i].isFunction() && CHILD(0)[i].function() == CALCULATOR->f_root) { - Number nr_pow(nr_root); - nr_pow.divide(CHILD(0)[i][1].number()); - CHILD(0)[i][1] = nr_pow; - CHILD(0)[i][0] = var; - CHILD(0)[i].setType(STRUCT_POWER); - } else { - // should not happen - } - } - MathStructure u_var(var); - replace(mvar, u_var); - CHILD(0).calculatesub(eo2, eo2, true); - CHILD_UPDATED(0) - b = isolate_x_sub(eo, eo2, u_var); - calculateReplace(u_var, mvar, eo2); - var->destroy(); - if(b) isolate_x(eo, eo2, x_var); - return b; - } else if(mvar != x_var) { - MathStructure u_var(var); - replace(mvar, u_var); - CHILD(0).calculatesub(eo2, eo2, true); - CHILD_UPDATED(0) - b = isolate_x_sub(eo, eo2, u_var); - calculateReplace(u_var, mvar, eo2); - var->destroy(); - if(b) isolate_x(eo, eo2, x_var); - return b; - } - } - - if(!eo2.expand) break; - - // Try factorization - if(!morig || !equals(*morig)) { - MathStructure mtest(*this); - if(!mtest[1].isZero()) { - mtest[0].calculateSubtract(CHILD(1), eo2); - mtest[1].clear(); - mtest.childrenUpdated(); - } - b = eo2.do_polynomial_division && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && do_simplification(mtest[0], eo, true, true, false, false, true); - if(b && mtest[0].isMultiplication() && mtest[0].size() == 2 && mtest[0][1].isPower() && mtest[0][1][1].representsNegative()) { - MathStructure mreq(mtest); - mtest[0].setToChild(1, true); - mtest.childUpdated(1); - eo2.do_polynomial_division = false; - if(mtest.isolate_x_sub(eo, eo2, x_var, this)) { - mreq.setComparisonType(ct_comp == COMPARISON_EQUALS ? COMPARISON_NOT_EQUALS : COMPARISON_EQUALS); - mreq[0].setToChild(2, true); - mreq[0][1].calculateNegate(eo2); - mreq[0].calculateRaiseExponent(eo2); - mreq.childUpdated(1); - mreq.isolate_x_sub(eo, eo2, x_var, this); - mtest.add(mreq, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); - mtest.calculatesub(eo2, eo, false); - set_nocopy(mtest); - return true; - } - } else { - if(b) { - mtest = *this; - if(!mtest[1].isZero()) { - mtest[0].calculateSubtract(CHILD(1), eo2); - mtest[1].clear(); - mtest.childrenUpdated(); - } - } - if(mtest[0].factorize(eo2, false, false, 0, false, false, NULL, m_undefined, false, false, 3) && !(mtest[0].isMultiplication() && mtest[0].size() == 2 && ((mtest[0][0].isNumber() && mtest[0][1].isAddition()) || mtest[0][0] == CHILD(1) || mtest[0][1] == CHILD(1)))) { - mtest.childUpdated(1); - if(mtest.isolate_x_sub(eo, eo2, x_var, this)) { - set_nocopy(mtest); - return true; - } - } - } - } - - // ax^3+bx^2+cx=d - if(CHILD(0).size() >= 2 && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { - bool cbpow = false, sqpow = false, nopow = false; - MathStructure mstruct_a, mstruct_b, mstruct_c; - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CALCULATOR->aborted()) return false; - if(CHILD(0)[i].isPower() && CHILD(0)[i][0] == x_var && CHILD(0)[i][1].isNumber() && CHILD(0)[i][1].number() == 3) { - if(cbpow) mstruct_a.add(m_one, true); - else {cbpow = true; mstruct_a.set(m_one);} - } else if(CHILD(0)[i].isPower() && CHILD(0)[i][0] == x_var && CHILD(0)[i][1].isNumber() && CHILD(0)[i][1].number() == 2) { - if(sqpow) mstruct_b.add(m_one, true); - else {sqpow = true; mstruct_b.set(m_one);} - } else if(CHILD(0)[i] == x_var) { - if(nopow) mstruct_c.add(m_one, true); - else {nopow = true; mstruct_c.set(m_one);} - } else if(CHILD(0)[i].isMultiplication()) { - for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { - if(CHILD(0)[i][i2] == x_var) { - if(nopow) { - MathStructure *madd = new MathStructure(CHILD(0)[i]); - madd->delChild(i2 + 1, true); - mstruct_c.add_nocopy(madd, true); - } else { - nopow = true; - mstruct_c = CHILD(0)[i]; - mstruct_c.delChild(i2 + 1, true); - } - } else if(CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][0] == x_var && CHILD(0)[i][i2][1].isNumber() && CHILD(0)[i][i2][1].number() == 2) { - if(sqpow) { - MathStructure *madd = new MathStructure(CHILD(0)[i]); - madd->delChild(i2 + 1, true); - mstruct_b.add_nocopy(madd, true); - } else { - sqpow = true; - mstruct_b = CHILD(0)[i]; - mstruct_b.delChild(i2 + 1, true); - } - } else if(CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][0] == x_var && CHILD(0)[i][i2][1].isNumber() && CHILD(0)[i][i2][1].number() == 3) { - if(cbpow) { - MathStructure *madd = new MathStructure(CHILD(0)[i]); - madd->delChild(i2 + 1, true); - mstruct_a.add_nocopy(madd, true); - } else { - cbpow = true; - mstruct_a = CHILD(0)[i]; - mstruct_a.delChild(i2 + 1, true); - } - } else if(CHILD(0)[i][i2].contains(x_var)) { - cbpow = false; - sqpow = false; - nopow = false; - break; - } - } - if(!cbpow && !sqpow && !nopow) break; - } else { - cbpow = false; - sqpow = false; - nopow = false; - break; - } - } - bool b = false; - if(cbpow && (nopow || sqpow) && !mstruct_a.representsZero(true)) { - b = mstruct_a.representsNonZero(true); - if(!b && eo2.approximation == APPROXIMATION_EXACT) { - MathStructure mtest(mstruct_a); - mtest.add(m_zero, OPERATION_NOT_EQUALS); - EvaluationOptions eo3 = eo2; - eo3.test_comparisons = true; - mtest.calculatesub(eo3, eo, false); - b = mtest.isOne(); - } - } - if(b) { - - MathStructure mbak(*this); - - bool stop_iv = containsInterval(true, false, false, -2, false); - - cube_eq_stop_iv: - - CALCULATOR->beginTemporaryStopMessages(); - - EvaluationOptions eo3 = eo2; - bool failed = false; - if(stop_iv) { - CALCULATOR->beginTemporaryStopIntervalArithmetic(); - eo3.interval_calculation = INTERVAL_CALCULATION_NONE; - fix_intervals(*this, eo3, &failed); - } - if(failed) { - set(mbak); - CALCULATOR->endTemporaryStopIntervalArithmetic(); - CALCULATOR->endTemporaryStopMessages(); - } else { - eo3.keep_zero_units = false; - - MathStructure mstruct_d(CHILD(1)); - mstruct_d.calculateNegate(eo3); - - // 18abcd - 4b^3*d + b^2*c^2 - 4a*c^3 - 27a^2*d^2 - MathStructure mdelta(18, 1, 0); - mdelta.multiply(mstruct_a); - mdelta.multiply(mstruct_b, true); - mdelta.multiply(mstruct_c, true); - mdelta.multiply(mstruct_d, true); - MathStructure *mdelta_b = new MathStructure(mstruct_b); - mdelta_b->raise(nr_three); - mdelta_b->multiply(Number(-4, 1, 0)); - mdelta_b->multiply(mstruct_d); - MathStructure *mdelta_c = new MathStructure(mstruct_b); - mdelta_c->raise(nr_two); - MathStructure *mdelta_c2 = new MathStructure(mstruct_c); - mdelta_c2->raise(nr_two); - mdelta_c->multiply_nocopy(mdelta_c2); - MathStructure *mdelta_d = new MathStructure(mstruct_c); - mdelta_d->raise(nr_three); - mdelta_d->multiply(Number(-4, 1, 0)); - mdelta_d->multiply(mstruct_a, true); - MathStructure *mdelta_e = new MathStructure(mstruct_a); - mdelta_e->raise(nr_two); - MathStructure *mdelta_e2 = new MathStructure(mstruct_d); - mdelta_e2->raise(nr_two); - mdelta_e->multiply_nocopy(mdelta_e2); - mdelta_e->multiply(Number(-27, 1, 0)); - mdelta.add_nocopy(mdelta_b); - mdelta.add_nocopy(mdelta_c, true); - mdelta.add_nocopy(mdelta_d, true); - mdelta.add_nocopy(mdelta_e, true); - mdelta.calculatesub(eo3, eo); - - if(CALCULATOR->aborted()) {CALCULATOR->endTemporaryStopMessages(); if(stop_iv) CALCULATOR->endTemporaryStopIntervalArithmetic(); set(mbak); return false;} - - int b_zero = -1; - int b_real = -1; - if(mdelta.representsNonZero(true)) b_zero = 0; - else if(mdelta.representsZero(true)) b_zero = 1; - - if(b_zero == 0) { - if(mdelta.representsPositive(true)) { - b_real = 1; - } else if(mdelta.representsNegative(true)) { - b_real = 0; - } - } else if(b_zero < 0) { - ComparisonResult cr = mdelta.compareApproximately(m_zero, eo); - if(cr == COMPARISON_RESULT_EQUAL) { - b_zero = 1; - } else if(COMPARISON_IS_NOT_EQUAL(cr)) { - if(cr == COMPARISON_RESULT_GREATER) b_real = 0; - else if(cr == COMPARISON_RESULT_LESS) b_real = 1; - b_zero = 0; - } - } - if(b_real < 0 && mdelta.representsComplex(true)) b_real = -2; - if(b_real == -1) b_zero = -1; - - if(b_real > 0 && (!mstruct_a.representsNonComplex() || !mstruct_b.representsNonComplex() || !mstruct_c.representsNonComplex() || !mstruct_d.representsNonComplex())) b_real = -2; - - MathStructure mdelta0; - int b0_zero = -1; - - if(CALCULATOR->aborted()) {CALCULATOR->endTemporaryStopMessages(); if(stop_iv) CALCULATOR->endTemporaryStopIntervalArithmetic(); set(mbak); return false;} - - if(b_zero >= 0) { - // b^2 - 3ac - mdelta0 = mstruct_b; - mdelta0.raise(nr_two); - MathStructure *mdelta0_b = new MathStructure(-3, 1, 0); - mdelta0_b->multiply(mstruct_a); - mdelta0_b->multiply(mstruct_c, true); - mdelta0.add_nocopy(mdelta0_b); - mdelta0.calculatesub(eo3, eo, true); - if(mdelta0.representsNonZero(true)) b0_zero = 0; - else if(mdelta0.representsZero(true)) b0_zero = 1; - else { - ComparisonResult cr = mdelta0.compareApproximately(m_zero, eo); - if(cr == COMPARISON_RESULT_EQUAL) { - b0_zero = 1; - } else if(COMPARISON_IS_NOT_EQUAL(cr)) { - b0_zero = 0; - } - } - } - - if(CALCULATOR->aborted()) {CALCULATOR->endTemporaryStopMessages(); if(stop_iv) CALCULATOR->endTemporaryStopIntervalArithmetic(); set(mbak); return false;} - - if(b_zero == 1) { - if(b0_zero == 1) { - // -b/(3a) - CHILD(0) = x_var; - CHILD(1).set(-1, 3); - CHILD(1).calculateMultiply(mstruct_b, eo3); - CHILD(1).calculateDivide(mstruct_a, eo3); - CHILDREN_UPDATED; - if(stop_iv) { - CALCULATOR->endTemporaryStopIntervalArithmetic(); - CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); - fix_intervals(*this, eo2); - } else if(containsInterval(true, false, false, -2, false)) { - set(mbak); - stop_iv = true; - CALCULATOR->endTemporaryStopMessages(); - goto cube_eq_stop_iv; - } - CALCULATOR->endTemporaryStopMessages(true); - return true; - } else if(b0_zero == 0) { - - MathStructure *malt1 = new MathStructure(x_var); - malt1->transform(STRUCT_COMPARISON, m_zero); - malt1->setComparisonType(comparisonType()); - MathStructure *malt2 = new MathStructure(*malt1); - - // (9ad - bc) / (2*delta0) - (*malt1)[1].set(9, 1, 0); - (*malt1)[1].calculateMultiply(mstruct_a, eo3); - (*malt1)[1].calculateMultiply(mstruct_d, eo3); - MathStructure *malt1_2b = new MathStructure(-1, 1, 0); - malt1_2b->calculateMultiply(mstruct_b, eo3); - malt1_2b->calculateMultiply(mstruct_c, eo3); - (*malt1)[1].add_nocopy(malt1_2b); - (*malt1)[1].calculateAddLast(eo3); - (*malt1)[1].calculateDivide(nr_two, eo3); - (*malt1)[1].calculateDivide(mdelta0, eo3); - - // (4abc - 9a^2*d - b^3) / (a*delta0) - (*malt2)[1].set(4, 1, 0); - (*malt2)[1].calculateMultiply(mstruct_a, eo3); - (*malt2)[1].calculateMultiply(mstruct_b, eo3); - (*malt2)[1].calculateMultiply(mstruct_c, eo3); - MathStructure *malt2_2b = new MathStructure(mstruct_a); - malt2_2b->calculateRaise(nr_two, eo3); - malt2_2b->calculateMultiply(Number(-9, 1, 0), eo3); - malt2_2b->calculateMultiply(mstruct_d, eo3); - (*malt2)[1].add_nocopy(malt2_2b); - (*malt2)[1].calculateAddLast(eo3); - MathStructure *malt2_2c = new MathStructure(mstruct_b); - malt2_2c->calculateRaise(nr_three, eo3); - malt2_2c->calculateNegate(eo3); - (*malt2)[1].add_nocopy(malt2_2c); - (*malt2)[1].calculateAddLast(eo3); - (*malt2)[1].calculateDivide(mstruct_a, eo3); - (*malt2)[1].calculateDivide(mdelta0, eo3); - - if(ct_comp == COMPARISON_NOT_EQUALS) { - clear(true); - setType(STRUCT_LOGICAL_AND); - } else { - clear(true); - setType(STRUCT_LOGICAL_OR); - } - - malt1->childUpdated(2); - malt2->childUpdated(2); - - addChild_nocopy(malt1); - addChild_nocopy(malt2); - - calculatesub(eo3, eo, false); - - if(stop_iv) { - CALCULATOR->endTemporaryStopIntervalArithmetic(); - CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); - fix_intervals(*this, eo2); - } else if(containsInterval(true, false, false, -2, false)) { - set(mbak); - stop_iv = true; - CALCULATOR->endTemporaryStopMessages(); - goto cube_eq_stop_iv; - } - CALCULATOR->endTemporaryStopMessages(true); - return true; - } - } - - if(CALCULATOR->aborted()) {CALCULATOR->endTemporaryStopMessages(); if(stop_iv) CALCULATOR->endTemporaryStopIntervalArithmetic(); return false;} - - MathStructure mdelta1; - bool b_neg = false; - - if(b_zero == 0 && b0_zero >= 0) { - - // 2b^3 - 9abc + 27a^2*d - mdelta1 = mstruct_b; - mdelta1.raise(nr_three); - mdelta1.multiply(nr_two); - MathStructure *mdelta1_b = new MathStructure(-9, 1, 0); - mdelta1_b->multiply(mstruct_a); - mdelta1_b->multiply(mstruct_b, true); - mdelta1_b->multiply(mstruct_c, true); - MathStructure *mdelta1_c = new MathStructure(mstruct_a); - mdelta1_c->raise(nr_two); - mdelta1_c->multiply(Number(27, 1, 0)); - mdelta1_c->multiply(mstruct_d, true); - mdelta1.add_nocopy(mdelta1_b); - mdelta1.add_nocopy(mdelta1_c, true); - mdelta1.calculatesub(eo3, eo, true); - - if(b0_zero == 1) { - - if(mdelta1.representsNegative(true)) { - b_neg = true; - } else if(!mdelta1.representsPositive(true)) { - if(mdelta1.representsZero(true)) { - // -b/(3a) - CHILD(0) = x_var; - CHILD(1).set(-1, 3); - CHILD(1).calculateMultiply(mstruct_b, eo3); - CHILD(1).calculateDivide(mstruct_a, eo3); - CHILDREN_UPDATED; - if(stop_iv) { - CALCULATOR->endTemporaryStopIntervalArithmetic(); - CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); - fix_intervals(*this, eo2); - } else if(containsInterval(true, false, false, -2, false)) { - set(mbak); - stop_iv = true; - CALCULATOR->endTemporaryStopMessages(); - goto cube_eq_stop_iv; - } - CALCULATOR->endTemporaryStopMessages(true); - return true; - } - ComparisonResult cr = mdelta1.compareApproximately(m_zero, eo); - if(cr == COMPARISON_RESULT_EQUAL) { - // -b/(3a) - CHILD(0) = x_var; - CHILD(1).set(-1, 3); - CHILD(1).calculateMultiply(mstruct_b, eo3); - CHILD(1).calculateDivide(mstruct_a, eo3); - CHILDREN_UPDATED; - if(stop_iv) { - CALCULATOR->endTemporaryStopIntervalArithmetic(); - CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); - fix_intervals(*this, eo2); - } else if(containsInterval(true, false, false, -2, false)) { - set(mbak); - stop_iv = true; - CALCULATOR->endTemporaryStopMessages(); - goto cube_eq_stop_iv; - } - CALCULATOR->endTemporaryStopMessages(true); - return true; - } else if(cr == COMPARISON_RESULT_GREATER) { - b_neg = true; - } else if(cr != COMPARISON_RESULT_LESS) { - b_zero = -1; - } - } - } - } - - if(b_zero == 0 && b0_zero == 0) { - - // ((delta1 +-sqrt(delta1^2-4*delta0^3))/2)^(1/3) - MathStructure mC; - MathStructure *md0_43 = new MathStructure(mdelta0); - md0_43->raise(nr_three); - md0_43->multiply(Number(-4, 1, 0)); - MathStructure *md1_2 = new MathStructure(mdelta1); - md1_2->raise(nr_two); - md1_2->add_nocopy(md0_43); - md1_2->raise(nr_half); - if(b_neg) md1_2->calculateNegate(eo3); - md1_2->calculatesub(eo3, eo, true); - - if(CALCULATOR->aborted()) {CALCULATOR->endTemporaryStopMessages(); if(stop_iv) CALCULATOR->endTemporaryStopIntervalArithmetic(); set(mbak); return false;} - - mC = mdelta1; - mC.add_nocopy(md1_2); - mC.calculateAddLast(eo3); - mC.calculateDivide(nr_two, eo3); - if(b_real == 0 && x_var.representsReal(true)) { - if(!mC.representsComplex(true)) { - mC.transform(STRUCT_FUNCTION); - mC.addChild(nr_three); - mC.setFunction(CALCULATOR->f_root); - if(mC.calculateFunctions(eo)) mC.calculatesub(eo3, eo, true); - // x = -1/(3a)*(b + C + delta0/C) - CHILD(0) = x_var; - CHILD(1).set(-1, 3, 0); - CHILD(1).calculateDivide(mstruct_a, eo3); - MathStructure *malt1_2b = new MathStructure(mdelta0); - malt1_2b->calculateDivide(mC, eo3); - malt1_2b->calculateAdd(mC, eo3); - malt1_2b->calculateAdd(mstruct_b, eo3); - CHILD(1).multiply_nocopy(malt1_2b); - CHILD(1).calculateMultiplyLast(eo3); - CHILDREN_UPDATED; - if(stop_iv) { - CALCULATOR->endTemporaryStopIntervalArithmetic(); - CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); - fix_intervals(*this, eo2); - } else if(containsInterval(true, false, false, -2, false)) { - set(mbak); - stop_iv = true; - CALCULATOR->endTemporaryStopMessages(); - goto cube_eq_stop_iv; - } - CALCULATOR->endTemporaryStopMessages(true); - return true; - } - } else if(eo3.allow_complex) { - - if(mC.representsNegative(true)) { - mC.calculateNegate(eo3); - mC.calculateRaise(Number(1, 3, 0), eo3); - mC.calculateNegate(eo3); - } else { - mC.calculateRaise(Number(1, 3, 0), eo3); - } - - // x = -1/(3a)*(b + C + delta0/C) - - MathStructure *malt1 = new MathStructure(x_var); - malt1->transform(STRUCT_COMPARISON, Number(-1, 3, 0)); - malt1->setComparisonType(comparisonType()); - (*malt1)[1].calculateDivide(mstruct_a, eo3); - - MathStructure *malt2 = new MathStructure(*malt1); - MathStructure *malt3 = new MathStructure(*malt1); - - MathStructure *malt1_2b = new MathStructure(mdelta0); - malt1_2b->calculateDivide(mC, eo3); - malt1_2b->calculateAdd(mC, eo3); - malt1_2b->calculateAdd(mstruct_b, eo3); - (*malt1)[1].multiply_nocopy(malt1_2b); - (*malt1)[1].calculateMultiplyLast(eo3); - - MathStructure cbrt_mul(nr_three); - cbrt_mul.calculateRaise(nr_half, eo3); - cbrt_mul.calculateMultiply(nr_one_i, eo3); - MathStructure cbrt_mul2(cbrt_mul); - cbrt_mul.calculateMultiply(nr_half, eo3); - cbrt_mul.calculateAdd(Number(-1, 2, 0), eo3); - cbrt_mul2.calculateMultiply(Number(-1, 2, 0), eo3); - cbrt_mul2.calculateAdd(Number(-1, 2, 0), eo3); - - MathStructure mC2(mC); - mC2.calculateMultiply(cbrt_mul, eo3); - MathStructure mC3(mC); - mC3.calculateMultiply(cbrt_mul2, eo3); - - MathStructure *malt2_2b = new MathStructure(mdelta0); - malt2_2b->calculateDivide(mC2, eo3); - malt2_2b->calculateAdd(mC2, eo3); - malt2_2b->calculateAdd(mstruct_b, eo3); - (*malt2)[1].multiply_nocopy(malt2_2b); - (*malt2)[1].calculateMultiplyLast(eo3); - - MathStructure *malt3_2b = new MathStructure(mdelta0); - malt3_2b->calculateDivide(mC3, eo3); - malt3_2b->calculateAdd(mC3, eo3); - malt3_2b->calculateAdd(mstruct_b, eo3); - (*malt3)[1].multiply_nocopy(malt3_2b); - (*malt3)[1].calculateMultiplyLast(eo3); - - if(b_real == 1) { - if((*malt1)[1].isNumber()) { - (*malt1)[1].number().clearImaginary(); - } else if((*malt1)[1].isMultiplication() && (*malt1)[1][0].isNumber()) { - bool b = true; - for(size_t i = 1; i < (*malt1)[1].size(); i++) { - if(!(*malt1)[1][i].representsReal(true)) { - b = false; - break; - } - } - if(b) (*malt1)[1][0].number().clearImaginary(); - } - if((*malt2)[1].isNumber()) { - (*malt2)[1].number().clearImaginary(); - } else if((*malt2)[1].isMultiplication() && (*malt2)[1][0].isNumber()) { - bool b = true; - for(size_t i = 1; i < (*malt2)[1].size(); i++) { - if(!(*malt2)[1][i].representsReal(true)) { - b = false; - break; - } - } - if(b) (*malt2)[1][0].number().clearImaginary(); - } - if((*malt3)[1].isNumber()) { - (*malt3)[1].number().clearImaginary(); - } else if((*malt3)[1].isMultiplication() && (*malt3)[1][0].isNumber()) { - bool b = true; - for(size_t i = 1; i < (*malt3)[1].size(); i++) { - if(!(*malt3)[1][i].representsReal(true)) { - b = false; - break; - } - } - if(b) (*malt3)[1][0].number().clearImaginary(); - } - } - - if(b_real < 1 || !x_var.representsReal(true) || (!(*malt1)[1].representsComplex(true) && !(*malt2)[1].representsComplex(true) && !(*malt3)[1].representsComplex(true))) { - - if(ct_comp == COMPARISON_NOT_EQUALS) { - clear(true); - setType(STRUCT_LOGICAL_AND); - } else { - clear(true); - setType(STRUCT_LOGICAL_OR); - } - - malt1->childUpdated(2); - malt2->childUpdated(2); - malt3->childUpdated(2); - - addChild_nocopy(malt1); - addChild_nocopy(malt2); - addChild_nocopy(malt3); - - calculatesub(eo3, eo, false); - if(stop_iv) { - CALCULATOR->endTemporaryStopIntervalArithmetic(); - CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); - fix_intervals(*this, eo2); - } else if(containsInterval(true, false, false, -2, false)) { - set(mbak); - stop_iv = true; - goto cube_eq_stop_iv; - CALCULATOR->endTemporaryStopMessages(); - } - CALCULATOR->endTemporaryStopMessages(true); - return true; - } - } - } - CALCULATOR->endTemporaryStopMessages(); - if(stop_iv) CALCULATOR->endTemporaryStopIntervalArithmetic(); - } - } - } - - - // abs(x)+x=a => -x+x=a || x+x=a; sgn(x)+x=a => -1+x=a || 0+x=a || 1+x=a - if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { - MathStructure *m = find_abs_sgn(CHILD(0), x_var); - if(m && m->function() == CALCULATOR->f_abs) { - - MathStructure mabs(*m); - - ComparisonType cmp_type = ct_comp; - MathStructure *malt = new MathStructure(*this); - MathStructure mabs_minus(mabs[0]); - mabs_minus.calculateNegate(eo2); - (*malt)[0].replace(mabs, mabs_minus, mabs.containsInterval()); - (*malt)[0].calculatesub(eo2, eo, true); - malt->childUpdated(1); - MathStructure *mcheck = new MathStructure(mabs[0]); - mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_EQUALS_GREATER : OPERATION_LESS); - mcheck->isolate_x_sub(eo, eo2, x_var); - malt->isolate_x_sub(eo, eo2, x_var); - malt->add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - malt->calculatesub(eo2, eo, false); - - mcheck = new MathStructure(mabs[0]); - CHILD(0).replace(mabs, mabs[0], mabs.containsInterval()); - CHILD(0).calculatesub(eo2, eo, true); - CHILD_UPDATED(0) - mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LESS : OPERATION_EQUALS_GREATER); - mcheck->isolate_x_sub(eo, eo2, x_var); - isolate_x_sub(eo, eo2, x_var); - add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - calculatesub(eo2, eo, false); - add_nocopy(malt, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); - calculatesub(eo2, eo, false); - - return true; - } else if(m && m->function() == CALCULATOR->f_signum) { - MathStructure mabs(*m); - - ComparisonType cmp_type = ct_comp; - MathStructure *malt = new MathStructure(*this); - (*malt)[0].replace(mabs, m_minus_one, mabs.containsInterval()); - (*malt)[0].calculatesub(eo2, eo, true); - malt->childUpdated(1); - MathStructure *mcheck = new MathStructure(mabs[0]); - mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? ((*m)[1].isMinusOne() ? OPERATION_GREATER : OPERATION_EQUALS_GREATER) : ((*m)[1].isMinusOne() ? OPERATION_EQUALS_LESS : OPERATION_LESS)); - mcheck->isolate_x_sub(eo, eo2, x_var); - malt->isolate_x_sub(eo, eo2, x_var); - malt->add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - malt->calculatesub(eo2, eo, false); - - MathStructure *malt0 = NULL; - if(!(*m)[1].isOne() && !(*m)[1].isMinusOne()) { - malt0 = new MathStructure(*this); - (*malt0)[0].replace(mabs, (*m)[1], mabs.containsInterval()); - (*malt0)[0].calculatesub(eo2, eo, true); - malt0->childUpdated(1); - mcheck = new MathStructure(mabs[0]); - mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_NOT_EQUALS : OPERATION_EQUALS); - mcheck->isolate_x_sub(eo, eo2, x_var); - malt0->isolate_x_sub(eo, eo2, x_var); - malt0->add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - malt0->calculatesub(eo2, eo, false); - } - - mcheck = new MathStructure(mabs[0]); - CHILD(0).replace(mabs, m_one, mabs.containsInterval()); - CHILD(0).calculatesub(eo2, eo, true); - CHILD_UPDATED(0) - mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? ((*m)[1].isOne() ? OPERATION_LESS : OPERATION_EQUALS_LESS) : ((*m)[1].isOne() ? OPERATION_EQUALS_GREATER : OPERATION_GREATER)); - mcheck->isolate_x_sub(eo, eo2, x_var); - isolate_x_sub(eo, eo2, x_var); - add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - calculatesub(eo2, eo, false); - add_nocopy(malt, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); - if(malt0) add_nocopy(malt0, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); - calculatesub(eo2, eo, false); - return true; - } - } - - // Use newton raphson to calculate approximate solution for polynomial - MathStructure x_value; - if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && CHILD(1).isNumber() && eo.approximation != APPROXIMATION_EXACT && !x_var.representsComplex(true)) { - MathStructure mtest(CHILD(0)); - if(!CHILD(0).isZero()) mtest.calculateSubtract(CHILD(1), eo2); - CALCULATOR->beginTemporaryStopIntervalArithmetic(); - EvaluationOptions eo3 = eo2; - eo3.interval_calculation = INTERVAL_CALCULATION_NONE; - bool failed = false; - fix_intervals(mtest, eo3, &failed); - if(failed) { - CALCULATOR->endTemporaryStopIntervalArithmetic(); - } else { - MathStructure mbak(*this); - int ret = -1; - eo3.approximation = APPROXIMATION_APPROXIMATE; - if(ct_comp == COMPARISON_EQUALS) clear(true); - else set(1, 1, 0, true); - while((ret = newton_raphson(mtest, x_value, x_var, eo3)) > 0) { - if(isNumber()) { - set(x_var, true); - transform(STRUCT_COMPARISON, x_value); - setComparisonType(mbak.comparisonType()); - } else { - if(isComparison()) transform(mbak.comparisonType() == COMPARISON_NOT_EQUALS ? STRUCT_LOGICAL_AND : STRUCT_LOGICAL_OR); - MathStructure *mnew = new MathStructure(x_var); - mnew->transform(STRUCT_COMPARISON, x_value); - mnew->setComparisonType(mbak.comparisonType()); - addChild_nocopy(mnew); - } - MathStructure mdiv(x_var); - mdiv.calculateSubtract(x_value, eo3); - MathStructure mtestcopy(mtest); - MathStructure mrem; - if(!polynomial_long_division(mtestcopy, mdiv, x_var, mtest, mrem, eo3, false, true) || !mrem.isNumber()) { - ret = -1; - break; - } - if(!mtest.contains(x_var)) break; - } - CALCULATOR->endTemporaryStopIntervalArithmetic(); - if(ret < 0) { - set(mbak); - } else { - if(!x_var.representsReal()) CALCULATOR->error(false, _("Not all complex roots were calculated for %s."), format_and_print(mbak).c_str(), NULL); - if((CALCULATOR->usesIntervalArithmetic() && eo.approximation != APPROXIMATION_EXACT) || mbak.containsInterval()) CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); - fix_intervals(*this, eo2); - return true; - } - } - } - - // Try factorization - if((!morig || !equals(*morig)) && !CHILD(1).isZero()) { - MathStructure mtest(*this); - if(mtest[0].factorize(eo2, false, false, 0, false, false, NULL, m_undefined, false, false, 3) && !(mtest[0].isMultiplication() && mtest[0].size() == 2 && (mtest[0][0].isNumber() || mtest[0][0] == CHILD(1) || mtest[0][1] == CHILD(1)))) { - mtest.childUpdated(1); - if(mtest.isolate_x_sub(eo, eo2, x_var, this)) { - set_nocopy(mtest); - return true; - } - } - } - - break; - } - case STRUCT_MULTIPLICATION: { - if(!representsNonMatrix()) return false; - //x*y=0 => x=0 || y=0 - if(CHILD(1).isZero()) { - if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { - vector checktype; - bool bdoit = false; - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CALCULATOR->aborted()) return false; - if(CHILD(0)[i].isPower() && !CHILD(0)[i][1].representsNonNegative()) { - if(CHILD(0)[i][1].representsNegative()) { - checktype.push_back(1); - } else { - checktype.push_back(2); - bdoit = true; - } - } else { - checktype.push_back(0); - bdoit = true; - } - } - if(!bdoit) break; - MathStructure *mcheckpowers = NULL; - ComparisonType ct = ct_comp; - setToChild(1); - if(ct == COMPARISON_NOT_EQUALS) { - setType(STRUCT_LOGICAL_AND); - } else { - setType(STRUCT_LOGICAL_OR); - } - MathStructure mbak(*this); - for(size_t i = 0; i < SIZE;) { - if(CALCULATOR->aborted()) { - set(mbak); - if(mcheckpowers) mcheckpowers->unref(); - return false; - } - if(checktype[i] > 0) { - MathStructure *mcheck = new MathStructure(CHILD(i)[0]); - if(ct_comp == COMPARISON_NOT_EQUALS) mcheck->add(m_zero, OPERATION_EQUALS); - else mcheck->add(m_zero, OPERATION_NOT_EQUALS); - mcheck->isolate_x_sub(eo, eo2, x_var); - if(checktype[i] == 2) { - MathStructure *mexpcheck = new MathStructure(CHILD(i)[1]); - if(ct_comp == COMPARISON_NOT_EQUALS) mexpcheck->add(m_zero, OPERATION_LESS); - else mexpcheck->add(m_zero, OPERATION_EQUALS_GREATER); - mexpcheck->isolate_x_sub(eo, eo2, x_var); - if(ct_comp == COMPARISON_NOT_EQUALS) mexpcheck->add_nocopy(mcheck, OPERATION_LOGICAL_AND, true); - else mexpcheck->add_nocopy(mcheck, OPERATION_LOGICAL_OR, true); - mexpcheck->calculatesub(eo2, eo, false); - mcheck = mexpcheck; - } - if(mcheckpowers) { - if(ct_comp == COMPARISON_NOT_EQUALS) mcheckpowers->add_nocopy(mcheck, OPERATION_LOGICAL_OR, true); - else mcheckpowers->add_nocopy(mcheck, OPERATION_LOGICAL_AND, true); - } else { - mcheckpowers = mcheck; - } - } - if(checktype[i] == 1) { - ERASE(i) - checktype.erase(checktype.begin() + i); - } else { - CHILD(i).transform(STRUCT_COMPARISON, m_zero); - CHILD(i).setComparisonType(ct); - CHILD(i).isolate_x_sub(eo, eo2, x_var); - CHILD_UPDATED(i) - i++; - } - } - if(SIZE == 1) setToChild(1); - else if(SIZE == 0) clear(true); - else calculatesub(eo2, eo, false); - if(mcheckpowers) { - mcheckpowers->calculatesub(eo2, eo, false); - if(ct_comp == COMPARISON_NOT_EQUALS) add_nocopy(mcheckpowers, OPERATION_LOGICAL_OR, true); - else add_nocopy(mcheckpowers, OPERATION_LOGICAL_AND, true); - SWAP_CHILDREN(0, SIZE - 1) - calculatesub(eo2, eo, false); - } - return true; - } else if(CHILD(0).size() >= 2) { - MathStructure mless1(CHILD(0)[0]); - MathStructure mless2; - if(CHILD(0).size() == 2) { - mless2 = CHILD(0)[1]; - } else { - mless2 = CHILD(0); - mless2.delChild(1); - } - - int checktype1 = 0, checktype2 = 0; - MathStructure *mcheck1 = NULL, *mcheck2 = NULL; - if(mless1.isPower() && !mless1[1].representsNonNegative()) { - if(mless1[1].representsNegative()) { - checktype1 = 1; - } else if(ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER) { - checktype1 = 2; - mcheck1 = new MathStructure(mless1[1]); - mcheck1->add(m_zero, OPERATION_EQUALS_GREATER); - mcheck1->isolate_x_sub(eo, eo2, x_var); - MathStructure *mcheck = new MathStructure(mless1[0]); - mcheck->add(m_zero, OPERATION_NOT_EQUALS); - mcheck->isolate_x_sub(eo, eo2, x_var); - mcheck1->add_nocopy(mcheck, OPERATION_LOGICAL_OR); - mcheck1->calculatesub(eo2, eo, false); - } - } - if(mless2.isPower() && !mless2[1].representsNonNegative()) { - if(mless2[1].representsNegative()) { - checktype2 = 1; - } else if(ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER) { - checktype2 = 2; - mcheck2 = new MathStructure(mless2[1]); - mcheck2->add(m_zero, OPERATION_EQUALS_GREATER); - mcheck2->isolate_x_sub(eo, eo2, x_var); - MathStructure *mcheck = new MathStructure(mless2[0]); - mcheck->add(m_zero, OPERATION_NOT_EQUALS); - mcheck->isolate_x_sub(eo, eo2, x_var); - mcheck2->add_nocopy(mcheck, OPERATION_LOGICAL_OR); - mcheck2->calculatesub(eo2, eo, false); - } - } - - mless1.transform(STRUCT_COMPARISON, m_zero); - if(checktype1 != 1 && (ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER)) { - mless1.setComparisonType(COMPARISON_EQUALS_LESS); - } else { - mless1.setComparisonType(COMPARISON_LESS); - } - mless1.isolate_x_sub(eo, eo2, x_var); - mless2.transform(STRUCT_COMPARISON, m_zero); - mless2.setComparisonType(COMPARISON_LESS); - if(checktype2 != 1 && (ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER)) { - mless2.setComparisonType(COMPARISON_EQUALS_LESS); - } else { - mless2.setComparisonType(COMPARISON_LESS); - } - mless2.isolate_x_sub(eo, eo2, x_var); - MathStructure mgreater1(CHILD(0)[0]); - mgreater1.transform(STRUCT_COMPARISON, m_zero); - if(checktype1 != 1 && (ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER)) { - mgreater1.setComparisonType(COMPARISON_EQUALS_GREATER); - } else { - mgreater1.setComparisonType(COMPARISON_GREATER); - } - mgreater1.isolate_x_sub(eo, eo2, x_var); - MathStructure mgreater2; - if(CHILD(0).size() == 2) { - mgreater2 = CHILD(0)[1]; - } else { - mgreater2 = CHILD(0); - mgreater2.delChild(1); - } - mgreater2.transform(STRUCT_COMPARISON, m_zero); - if(checktype2 != 1 && (ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER)) { - mgreater2.setComparisonType(COMPARISON_EQUALS_GREATER); - } else { - mgreater2.setComparisonType(COMPARISON_GREATER); - } - mgreater2.isolate_x_sub(eo, eo2, x_var); - clear(); - - if(ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) { - set(mless1); - transform(STRUCT_LOGICAL_AND, mgreater2); - calculatesub(eo2, eo, false); - transform(STRUCT_LOGICAL_OR, mless2); - CHILD(1).transform(STRUCT_LOGICAL_AND, mgreater1); - CHILD(1).calculatesub(eo2, eo, false); - CHILD_UPDATED(1) - calculatesub(eo2, eo, false); - } else { - set(mless1); - transform(STRUCT_LOGICAL_AND, mless2); - calculatesub(eo2, eo, false); - transform(STRUCT_LOGICAL_OR, mgreater1); - CHILD(1).transform(STRUCT_LOGICAL_AND, mgreater2); - CHILD(1).calculatesub(eo2, eo, false); - CHILD_UPDATED(1) - calculatesub(eo2, eo, false); - } - if(checktype1 == 2) { - add_nocopy(mcheck1, OPERATION_LOGICAL_AND, true); - calculatesub(eo2, eo, false); - } - if(checktype2 == 2) { - add_nocopy(mcheck2, OPERATION_LOGICAL_AND, true); - calculatesub(eo2, eo, false); - } - return true; - - } - } - // x/(x+a)=b => x=b(x+a) - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CALCULATOR->aborted()) return false; - if(CHILD(0)[i].isPower() && CHILD(0)[i][1].isNumber() && CHILD(0)[i][1].number().isNegative() && CHILD(0)[i][1].number().isReal()) { - MathStructure *mtest; - if(CHILD(0)[i][1].number().isMinusOne()) { - CHILD(1).multiply(CHILD(0)[i][0]); - mtest = new MathStructure(CHILD(0)[i][0]); - } else { - CHILD(0)[i][1].number().negate(); - CHILD(1).multiply(CHILD(0)[i]); - mtest = new MathStructure(CHILD(0)[i]); - } - CHILD(0).delChild(i + 1); - if(CHILD(0).size() == 1) CHILD(0).setToChild(1); - CHILD(0).calculateSubtract(CHILD(1), eo); - ComparisonType cmp_type = ct_comp; - CHILD(1).clear(); - CHILDREN_UPDATED - if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { - isolate_x_sub(eo, eo2, x_var, morig); - mtest->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_EQUALS : OPERATION_NOT_EQUALS); - mtest->isolate_x_sub(eo, eo2, x_var); - add_nocopy(mtest, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - calculatesub(eo2, eo, false); - return true; - } else { - MathStructure *malt = new MathStructure(*this); - if(ct_comp == COMPARISON_EQUALS_GREATER) { - ct_comp = COMPARISON_EQUALS_LESS; - } else if(ct_comp == COMPARISON_GREATER) { - ct_comp = COMPARISON_LESS; - } else if(ct_comp == COMPARISON_EQUALS_LESS) { - ct_comp = COMPARISON_EQUALS_GREATER; - } else if(ct_comp == COMPARISON_LESS) { - ct_comp = COMPARISON_GREATER; - } - isolate_x_sub(eo, eo2, x_var, morig); - mtest->add(m_zero, OPERATION_LESS); - MathStructure *mtest_alt = new MathStructure(*mtest); - mtest_alt->setComparisonType(COMPARISON_GREATER); - mtest->isolate_x_sub(eo, eo2, x_var); - add_nocopy(mtest, OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - malt->isolate_x_sub(eo, eo2, x_var, morig); - mtest_alt->isolate_x_sub(eo, eo2, x_var); - malt->add_nocopy(mtest_alt, OPERATION_LOGICAL_AND); - malt->calculatesub(eo2, eo, false); - add_nocopy(malt, OPERATION_LOGICAL_OR); - calculatesub(eo2, eo, false); - return true; - } - } - } - bool b = false; - int zero1; - if(CHILD(1).isZero()) zero1 = 1; - else if(CHILD(1).representsNonZero(true)) zero1 = 0; - else zero1 = 2; - MathStructure *mcheckmulti = NULL, *mtryzero = NULL, *mchecknegative = NULL, *mchecknonzeropow = NULL; - MathStructure mchild2(CHILD(1)); - MathStructure mbak(*this); - ComparisonType ct_orig = ct_comp; - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CALCULATOR->aborted()) { - set(mbak); - if(mcheckmulti) mcheckmulti->unref(); - if(mtryzero) mcheckmulti->unref(); - if(mchecknegative) mcheckmulti->unref(); - if(mchecknonzeropow) mcheckmulti->unref(); - return false; - } - if(!CHILD(0)[i].contains(x_var)) { - bool nonzero = false; - if(CHILD(0)[i].isPower() && !CHILD(0)[i][1].representsNonNegative(true) && !CHILD(0)[i][0].representsNonZero(true)) { - MathStructure *mcheck = new MathStructure(CHILD(0)[i][0]); - if(ct_comp == COMPARISON_NOT_EQUALS) mcheck->add(m_zero, OPERATION_EQUALS); - else mcheck->add(m_zero, OPERATION_NOT_EQUALS); - mcheck->isolate_x(eo2, eo); - if(CHILD(0)[i][1].representsNegative(true)) { - nonzero = true; - } else { - MathStructure *mcheckor = new MathStructure(CHILD(0)[i][1]); - if(ct_comp == COMPARISON_NOT_EQUALS) mcheckor->add(m_zero, OPERATION_EQUALS_LESS); - else mcheckor->add(m_zero, OPERATION_EQUALS_GREATER); - mcheckor->isolate_x(eo2, eo); - if(ct_comp == COMPARISON_NOT_EQUALS) mcheck->add_nocopy(mcheckor, OPERATION_LOGICAL_AND); - else mcheck->add_nocopy(mcheckor, OPERATION_LOGICAL_OR); - mcheck->calculatesub(eo2, eo, false); - } - if(mchecknonzeropow) { - if(ct_comp == COMPARISON_NOT_EQUALS) mchecknonzeropow->add_nocopy(mcheck, OPERATION_LOGICAL_OR); - else mchecknonzeropow->add_nocopy(mcheck, OPERATION_LOGICAL_AND); - } else { - mchecknonzeropow = mcheck; - } - } - if(!nonzero && !CHILD(0)[i].representsNonZero(true)) { - if(zero1 != 1 && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { - MathStructure *mcheck = new MathStructure(CHILD(0)[i]); - if(ct_comp == COMPARISON_NOT_EQUALS) mcheck->add(m_zero, OPERATION_EQUALS); - else mcheck->add(m_zero, OPERATION_NOT_EQUALS); - mcheck->isolate_x(eo2, eo); - if(mcheckmulti) { - if(ct_comp == COMPARISON_NOT_EQUALS) mcheckmulti->add_nocopy(mcheck, OPERATION_LOGICAL_OR); - else mcheckmulti->add_nocopy(mcheck, OPERATION_LOGICAL_AND); - } else { - mcheckmulti = mcheck; - } - } - if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { - if(!mtryzero) { - mtryzero = new MathStructure(CHILD(0)[i]); - mtryzero->add(m_zero, OPERATION_EQUALS); - mtryzero->isolate_x(eo2, eo); - MathStructure *mcheck = new MathStructure(mchild2); - switch(ct_orig) { - case COMPARISON_LESS: {mcheck->add(m_zero, OPERATION_GREATER); break;} - case COMPARISON_GREATER: {mcheck->add(m_zero, OPERATION_LESS); break;} - case COMPARISON_EQUALS_LESS: {mcheck->add(m_zero, OPERATION_EQUALS_GREATER); break;} - case COMPARISON_EQUALS_GREATER: {mcheck->add(m_zero, OPERATION_EQUALS_LESS); break;} - default: {} - } - mcheck->isolate_x(eo2, eo); - mtryzero->add_nocopy(mcheck, OPERATION_LOGICAL_AND); - } else { - MathStructure *mcheck = new MathStructure(CHILD(0)[i]); - mcheck->add(m_zero, OPERATION_EQUALS); - mcheck->isolate_x(eo2, eo); - (*mtryzero)[0].add_nocopy(mcheck, OPERATION_LOGICAL_OR); - mtryzero[0].calculateLogicalOrLast(eo2); - } - } else if(zero1 > 0) { - MathStructure *mcheck = new MathStructure(CHILD(0)[i]); - if(ct_comp == COMPARISON_NOT_EQUALS) mcheck->add(m_zero, OPERATION_NOT_EQUALS); - else mcheck->add(m_zero, OPERATION_EQUALS); - mcheck->isolate_x(eo2, eo); - if(zero1 == 2) { - MathStructure *mcheck2 = new MathStructure(mchild2); - if(ct_comp == COMPARISON_NOT_EQUALS) mcheck2->add(m_zero, OPERATION_NOT_EQUALS); - else mcheck2->add(m_zero, OPERATION_EQUALS); - mcheck2->isolate_x(eo2, eo); - if(ct_comp == COMPARISON_NOT_EQUALS) mcheck2->add_nocopy(mcheck, OPERATION_LOGICAL_OR); - else mcheck2->add_nocopy(mcheck, OPERATION_LOGICAL_AND); - mcheck2->calculatesub(eo2, eo, false); - mcheck = mcheck2; - } - if(mtryzero) { - if(ct_comp == COMPARISON_NOT_EQUALS) mtryzero->add_nocopy(mcheck, OPERATION_LOGICAL_AND); - else mtryzero->add_nocopy(mcheck, OPERATION_LOGICAL_OR); - } else { - mtryzero = mcheck; - } - } - } - if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { - if(CHILD(0)[i].representsNegative()) { - switch(ct_comp) { - case COMPARISON_LESS: {ct_comp = COMPARISON_GREATER; break;} - case COMPARISON_GREATER: {ct_comp = COMPARISON_LESS; break;} - case COMPARISON_EQUALS_LESS: {ct_comp = COMPARISON_EQUALS_GREATER; break;} - case COMPARISON_EQUALS_GREATER: {ct_comp = COMPARISON_EQUALS_LESS; break;} - default: {} - } - } else if(!CHILD(0)[i].representsNonNegative()) { - if(mchecknegative) { - mchecknegative->multiply(CHILD(0)[i]); - } else { - mchecknegative = new MathStructure(CHILD(0)[i]); - } - } - } - if(zero1 != 1) { - CHILD(1).calculateDivide(CHILD(0)[i], eo2); - CHILD_UPDATED(1); - } - CHILD(0).delChild(i + 1); - b = true; - } - } - if(!b && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && CHILD(0).size() >= 2) { - // (x+a)*b^(c*x)=d => x=(lambertw(b^(a*c)*c*d*ln(b))-a*c*ln(b)))/(c*ln(b)) - if(CALCULATOR->aborted()) { - set(mbak); - if(mcheckmulti) mcheckmulti->unref(); - if(mtryzero) mcheckmulti->unref(); - if(mchecknegative) mcheckmulti->unref(); - if(mchecknonzeropow) mcheckmulti->unref(); - return false; - } - size_t i_px = 0, i_mpx = 0; - MathStructure *mvar = NULL; - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CHILD(0)[i].isPower() && CHILD(0)[i][1].contains(x_var) && !CHILD(0)[i][0].contains(x_var)) { - if(CHILD(0)[i][1].isMultiplication()) { - for(size_t i2 = 0; i2 < CHILD(0)[i][1].size(); i2++) { - if(CHILD(0)[i][1][i2].contains(x_var)) { - if(mvar) { - mvar = NULL; - break; - } else { - mvar = &CHILD(0)[i][1][i2]; - i_mpx = i2; - i_px = i; - } - } - } - } else { - mvar = &CHILD(0)[i][1]; - i_px = i; - } - break; - } - } - if(mvar) { - size_t i_x = 0; - bool found_mvar = false; - MathStructure mmul(1, 1, 0), m_a; - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(i != i_px) { - if(CHILD(0)[i].contains(x_var)) { - if(!found_mvar && CHILD(0)[i].equals(*mvar)) { - found_mvar = true; - i_x = i; - } else if(!found_mvar && CHILD(0)[i].isAddition()) { - i_x = i; - for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { - if(CHILD(0)[i][i2].contains(*mvar)) { - if(!found_mvar && CHILD(0)[i][i2].equals(*mvar)) { - found_mvar = true; - } else if(!found_mvar && CHILD(0)[i][i2].isMultiplication()) { - for(size_t i3 = 0; i3 < CHILD(0)[i][i2].size(); i3++) { - if(CHILD(0)[i][i2][i3].equals(*mvar)) { - mmul = CHILD(0)[i][i2]; - mmul.delChild(i3 + 1, true); - break; - } - } - if(mmul.contains(*mvar)) { - found_mvar = false; - break; - } - } else { - found_mvar = false; - break; - } - m_a = CHILD(0)[i]; - m_a.delChild(i2 + 1, true); - if(!mmul.isOne()) m_a.calculateDivide(mmul, eo2); - } - } - if(!found_mvar) break; - } else { - found_mvar = false; - break; - } - } - } - } - if(found_mvar) { - MathStructure mln(CALCULATOR->f_ln, &CHILD(0)[i_px][0], NULL); - if(mln.calculateFunctions(eo)) mln.calculatesub(eo2, eo, true); - MathStructure *marg = NULL; - MathStructure m_c(1, 1, 0); - if(mln.representsNonZero()) { - marg = new MathStructure(mln); - if(CHILD(0)[i_px][1].isMultiplication()) { - m_c = CHILD(0)[i_px][1]; - m_c.delChild(i_mpx + 1, true); - } - if(!m_c.representsNonZero()) {marg->unref(); marg = NULL;} - else if(!m_c.isOne()) marg->calculateMultiply(m_c, eo2); - } - if(marg) { - marg->calculateMultiply(CHILD(1), eo2); - if(CHILD(0).size() > 2) { - marg->multiply(CHILD(0)); - marg->last().delChild(i_x + 1); - marg->last().delChild(i_px + (i_px < i_x ? 1 : 0), true); - if(!marg->last().representsNonZero()) { - marg->unref(); marg = NULL; - } else { - marg->last().calculateRaise(nr_minus_one, eo2); - marg->calculateMultiplyLast(eo2); - } - } - if(!mmul.isOne()) marg->calculateDivide(mmul, eo2); - - } - if(marg && !m_a.isZero()) { - marg->multiply(CHILD(0)[i_px][0]); - marg->last().raise(m_a); - if(!m_c.isOne()) marg->last().last().calculateMultiply(m_c, eo2); - marg->last().calculateRaiseExponent(eo2); - marg->calculateMultiplyLast(eo2); - } - if(marg && mvar->representsNonComplex() && CHILD(0)[i_px][0].representsPositive()) { - if(mcheckmulti) mcheckmulti->unref(); - if(mtryzero) mcheckmulti->unref(); - if(mchecknegative) mcheckmulti->unref(); - if(mchecknonzeropow) mcheckmulti->unref(); - if(marg->representsComplex()) { - marg->unref(); - if(ct_comp == COMPARISON_EQUALS) clear(true); - else set(1, 1, 0, true); - return 1; - } - MathStructure *mreq1 = NULL; - MathStructure *marg2 = NULL; - MathStructure *mreq2 = NULL; - - if(m_a == CHILD(1)) { - marg2 = new MathStructure(*mvar); - marg2->transform(ct_comp, m_zero); - marg2->calculatesub(eo2, eo, false); - } - if(!m_a.isZero()) { - if(!m_c.isOne()) m_a.calculateMultiply(m_c, eo2); - m_a.calculateMultiply(mln, eo2); - } - if(!marg2 && !marg->representsNonNegative()) { - mreq1 = new MathStructure(*marg); - mreq2 = new MathStructure(*marg); - marg2 = new MathStructure(*marg); - marg2->transform(CALCULATOR->f_lambert_w); - marg2->addChild(m_minus_one); - if(marg2->calculateFunctions(eo)) marg2->calculatesub(eo2, eo, true); - if(!m_a.isZero()) marg2->calculateSubtract(m_a, eo2); - if(!m_c.isOne()) marg2->calculateDivide(m_c, eo2); - marg2->calculateDivide(mln, eo2); - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->v_e); - mreq1->last().calculateRaise(m_minus_one, eo2); - mreq1->last().calculateNegate(eo2); - mreq1->childUpdated(2); - mreq1->isolate_x(eo2, eo); - mreq2->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_EQUALS_LESS : COMPARISON_GREATER, m_zero); - mreq2->isolate_x(eo2, eo); - marg2->transform(ct_comp, *mvar); - marg2->swapChildren(1, 2); - marg2->isolate_x_sub(eo, eo2, x_var, morig); - marg2->add(*mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - marg2->add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - marg2->calculatesub(eo2, eo, false); - } - marg->transform(CALCULATOR->f_lambert_w); - marg->addChild(m_zero); - if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); - if(!m_a.isZero()) marg->calculateSubtract(m_a, eo2); - if(!m_c.isOne()) marg->calculateDivide(m_c, eo2); - marg->calculateDivide(mln, eo2); - setChild_nocopy(marg, 2, true); - mvar->ref(); - CHILD(0).clear(true); - setChild_nocopy(mvar, 1, true); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - if(mreq1) { - add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - if(marg2) { - add_nocopy(marg2, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - return true; - } else if(marg) { - if(mcheckmulti) mcheckmulti->unref(); - if(mtryzero) mcheckmulti->unref(); - if(mchecknegative) mcheckmulti->unref(); - if(mchecknonzeropow) mcheckmulti->unref(); - marg->transform(CALCULATOR->f_lambert_w); - marg->addChild(CALCULATOR->v_n); - if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); - if(!m_a.isZero()) { - m_a.calculateMultiply(mln, eo2); - marg->calculateSubtract(m_a, eo2); - } - if(!m_c.isOne()) marg->calculateDivide(m_c, eo2); - marg->calculateDivide(mln, eo2); - setChild_nocopy(marg, 2, true); - mvar->ref(); - CHILD(0).clear(true); - setChild_nocopy(mvar, 1, true); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } - } - } - - if(CHILD(0).size() == 2) { - // x*ln(x)=a => e^lambertw(a) - bool b_swap = false; - if(CHILD(0)[0].isFunction() && CHILD(0)[0].function() == CALCULATOR->f_ln && CHILD(0)[0].size() == 1) { - CHILD(0).swapChildren(1, 2); - b_swap = true; - } - if(CHILD(0)[1].isFunction() && CHILD(0)[1].function() == CALCULATOR->f_ln && CHILD(0)[1].size() == 1) { - MathStructure mmul(1, 1, 0), mexp(1, 1, 0); - mvar = NULL; - if(CHILD(0)[0] == CHILD(0)[1][0]) { - mvar = &CHILD(0)[0]; - } else if(CHILD(0)[0].isPower() && CHILD(0)[0][0] == CHILD(0)[1][0]) { - mexp = CHILD(0)[0][1]; - mvar = &CHILD(0)[0][0]; - } else { - if(get_multiplier(CHILD(0)[1][0], CHILD(0)[0], mmul)) { - mvar = &CHILD(0)[0]; - } else if(CHILD(0)[0].isPower() && get_multiplier(CHILD(0)[1][0], CHILD(0)[0][0], mmul)) { - mexp = CHILD(0)[0][1]; - mvar = &CHILD(0)[0][0]; - } - - } - if(mvar && mexp.isInteger() && (mexp.number().isOne() || mexp.number().isTwo()) && mmul.representsNonZero() && !mmul.contains(x_var)) { - if(mcheckmulti) mcheckmulti->unref(); - if(mtryzero) mcheckmulti->unref(); - if(mchecknegative) mcheckmulti->unref(); - if(mchecknonzeropow) mcheckmulti->unref(); - MathStructure *marg; - if(mexp.isOne() || mmul.isOne()) { - marg = new MathStructure(CHILD(1)); - if(!mmul.isOne()) marg->calculateMultiply(mmul, eo2); - else if(!mexp.isOne()) marg->calculateMultiply(mexp, eo2); - } else { - marg = new MathStructure(mmul); - marg->calculateRaise(mexp, eo2); - marg->calculateMultiply(CHILD(1), eo2); - marg->calculateMultiply(mexp, eo2); - } - if(mvar->representsNonComplex()) { - MathStructure *mreq1 = NULL; - MathStructure *marg2 = NULL; - MathStructure *mreq2 = NULL; - if(!marg->representsPositive()) { - mreq1 = new MathStructure(*marg); - mreq2 = new MathStructure(*marg); - marg2 = new MathStructure(*marg); - marg2->transform(CALCULATOR->f_lambert_w); - marg2->addChild(m_minus_one); - if(marg2->calculateFunctions(eo)) marg2->calculatesub(eo2, eo, true); - if(!mexp.isOne()) marg2->calculateDivide(mexp, eo2); - marg2->transform(STRUCT_POWER); - marg2->insertChild(CALCULATOR->v_e, 1); - (*marg2)[0].calculatesub(eo2, eo, true); - marg2->calculateRaiseExponent(eo2); - if(!mmul.isOne()) marg2->calculateDivide(mmul, eo2); - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->v_e); - mreq1->last().calculateRaise(m_minus_one, eo2); - mreq1->last().calculateNegate(eo2); - mreq1->childUpdated(2); - mreq1->isolate_x(eo2, eo); - mreq2->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_EQUALS_LESS : COMPARISON_GREATER, m_zero); - mreq2->isolate_x(eo2, eo); - marg2->transform(ct_comp, *mvar); - marg2->swapChildren(1, 2); - marg2->isolate_x_sub(eo, eo2, x_var, morig); - marg2->add(*mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - marg2->add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - marg2->calculatesub(eo2, eo, false); - } - marg->transform(CALCULATOR->f_lambert_w); - marg->addChild(m_zero); - if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); - if(!mexp.isOne()) marg->calculateDivide(mexp, eo2); - CHILD(0).setToChild(1, true); - if(!mexp.isOne()) CHILD(0).setToChild(1, true); - CHILD(1).set(CALCULATOR->v_e); - CHILD(1).raise_nocopy(marg); - CHILD(1).calculateRaiseExponent(eo2); - if(!mmul.isOne()) CHILD(1).calculateDivide(mmul, eo2); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - if(mreq1) { - add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - if(marg2) { - add_nocopy(marg2, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - } else { - if(!mexp.isOne()) marg->calculateMultiply(mexp, eo2); - if(!mmul.isOne()) marg->calculateDivide(mmul, eo2); - MathStructure *marg2 = new MathStructure(*marg); - MathStructure *marg3 = new MathStructure(*marg); - marg2->transform(CALCULATOR->f_lambert_w); - marg2->addChild(m_minus_one); - if(marg2->calculateFunctions(eo)) marg2->calculatesub(eo2, eo, true); - if(!mexp.isOne()) marg2->calculateDivide(mexp, eo2); - marg2->transform(STRUCT_POWER); - marg2->insertChild(CALCULATOR->v_e, 1); - (*marg2)[0].calculatesub(eo2, eo, true); - marg2->calculateRaiseExponent(eo2); - if(!mmul.isOne()) marg2->calculateDivide(mmul, eo2); - marg3->transform(CALCULATOR->f_lambert_w); - marg3->addChild(m_one); - if(marg3->calculateFunctions(eo)) marg3->calculatesub(eo2, eo, true); - if(!mexp.isOne()) marg3->calculateDivide(mexp, eo2); - marg3->transform(STRUCT_POWER); - marg3->insertChild(CALCULATOR->v_e, 1); - (*marg3)[0].calculatesub(eo2, eo, true); - marg3->calculateRaiseExponent(eo2); - if(!mmul.isOne()) marg3->calculateDivide(mmul, eo2); - marg2->transform(ct_comp, *mvar); - marg2->swapChildren(1, 2); - marg2->isolate_x_sub(eo, eo2, x_var, morig); - marg3->transform(ct_comp, *mvar); - marg3->swapChildren(1, 2); - marg3->isolate_x_sub(eo, eo2, x_var, morig); - marg->transform(CALCULATOR->f_lambert_w); - marg->addChild(m_zero); - if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); - if(!mexp.isOne()) marg->calculateDivide(mexp, eo2); - CHILD(0).setToChild(1, true); - if(!mexp.isOne()) CHILD(0).setToChild(1, true); - CHILD(1).set(CALCULATOR->v_e); - CHILD(1).raise_nocopy(marg); - CHILD(1).calculateRaiseExponent(eo2); - if(!mmul.isOne()) CHILD(1).calculateDivide(mmul, eo2); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - add_nocopy(marg2, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - add_nocopy(marg3, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - calculatesub(eo2, eo, false); - } - return true; - } - } - if(b_swap) CHILD(0).swapChildren(1, 2); - } - } - if(b) { - if(CHILD(0).size() == 1) { - CHILD(0).setToChild(1); - } - if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && CHILD(1).contains(x_var)) { - CHILD(0).calculateSubtract(CHILD(1), eo2); - CHILD(1).clear(); - } - if(mchecknegative) { - MathStructure *mneg = new MathStructure(*this); - switch(ct_comp) { - case COMPARISON_LESS: {mneg->setComparisonType(COMPARISON_GREATER); break;} - case COMPARISON_GREATER: {mneg->setComparisonType(COMPARISON_LESS); break;} - case COMPARISON_EQUALS_LESS: {mneg->setComparisonType(COMPARISON_EQUALS_GREATER); break;} - case COMPARISON_EQUALS_GREATER: {mneg->setComparisonType(COMPARISON_EQUALS_LESS); break;} - default: {} - } - isolate_x_sub(eo, eo2, x_var, morig); - //mneg->isolate_x_sub(eo, eo2, x_var); - mchecknegative->add(m_zero, OPERATION_GREATER); - add(*mchecknegative, OPERATION_LOGICAL_AND, true); - SWAP_CHILDREN(0, SIZE - 1) - calculatesub(eo2, eo, false); - //LAST.isolate_x(eo2, eo); - mchecknegative->setComparisonType(COMPARISON_LESS); - mchecknegative->isolate_x(eo2, eo); - mneg->add_nocopy(mchecknegative, OPERATION_LOGICAL_AND, true); - mneg->calculatesub(eo2, eo, false); - add_nocopy(mneg, OPERATION_LOGICAL_OR, true); - calculatesub(eo2, eo, false); - } else { - isolate_x_sub(eo, eo2, x_var, morig); - } - if(mcheckmulti) { - mcheckmulti->calculatesub(eo2, eo, false); - if(ct_comp == COMPARISON_NOT_EQUALS) { - add_nocopy(mcheckmulti, OPERATION_LOGICAL_OR, true); - } else { - add_nocopy(mcheckmulti, OPERATION_LOGICAL_AND, true); - SWAP_CHILDREN(0, SIZE - 1) - } - calculatesub(eo2, eo, false); - } - if(mchecknonzeropow) { - mchecknonzeropow->calculatesub(eo2, eo, false); - if(ct_comp == COMPARISON_NOT_EQUALS) { - add_nocopy(mchecknonzeropow, OPERATION_LOGICAL_OR, true); - } else { - add_nocopy(mchecknonzeropow, OPERATION_LOGICAL_AND, true); - SWAP_CHILDREN(0, SIZE - 1) - } - calculatesub(eo2, eo, false); - } - if(mtryzero) { - mtryzero->calculatesub(eo2, eo, false); - if(ct_comp == COMPARISON_NOT_EQUALS) { - add_nocopy(mtryzero, OPERATION_LOGICAL_AND, true); - SWAP_CHILDREN(0, SIZE - 1) - } else { - add_nocopy(mtryzero, OPERATION_LOGICAL_OR, true); - } - calculatesub(eo2, eo, false); - } - return true; - } - - if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { - // x*(x+a)^(1/b)=c => (x*(x+a)^(1/b))^b=c^b - Number nrexp; - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CALCULATOR->aborted()) return false; - if(CHILD(0)[i].isPower() && CHILD(0)[i][1].isNumber() && CHILD(0)[i][1].number().isRational()) { - if(!CHILD(0)[i][1].number().isInteger()) { - if(nrexp.isZero()) nrexp = CHILD(0)[i][1].number().denominator(); - else nrexp.lcm(CHILD(0)[i][1].number().denominator()); - } - } else if(CHILD(0)[i].isFunction() && CHILD(0)[i].function() == CALCULATOR->f_root && VALID_ROOT(CHILD(0)[i])) { - if(nrexp.isZero()) nrexp = CHILD(0)[i][1].number(); - else nrexp.lcm(CHILD(0)[i][1].number()); - } else if(CHILD(0)[i] != x_var && !(CHILD(0)[i].isFunction() && CHILD(0)[i].function() == CALCULATOR->f_abs && CHILD(0)[i].size() == 1 && CHILD(0)[i][0].representsReal(true))) { - nrexp.clear(); - break; - } - } - if(!nrexp.isZero()) { - MathStructure mtest(*this); - if(mtest[0].calculateRaise(nrexp, eo2)) { - mtest[1].calculateRaise(nrexp, eo2); - mtest.childrenUpdated(); - if(mtest.isolate_x(eo2, eo, x_var)) { - if((mtest.isLogicalAnd() || mtest.isLogicalOr() || mtest.isComparison()) && test_comparisons(*this, mtest, x_var, eo, false, eo.expand ? 1 : 2) < 0) { - if(eo.expand) { - add(mtest, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); - calculatesub(eo2, eo, false); - return true; - } - } else { - set(mtest); - return true; - } - } - } - } - } - if(!eo2.expand) break; - // abs(x)*x=a => -x*x=a || x*x=a; sgn(x)*x=a => -1*x=a || 0*x=a || 1*x=a - if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { - MathStructure *m = find_abs_sgn(CHILD(0), x_var); - if(m && m->function() == CALCULATOR->f_abs) { - - MathStructure mabs(*m); - - ComparisonType cmp_type = ct_comp; - MathStructure *malt = new MathStructure(*this); - MathStructure mabs_minus(mabs[0]); - mabs_minus.calculateNegate(eo2); - (*malt)[0].replace(mabs, mabs_minus, mabs.containsInterval()); - (*malt)[0].calculatesub(eo2, eo, true); - MathStructure *mcheck = new MathStructure(mabs[0]); - mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_EQUALS_GREATER : OPERATION_LESS); - mcheck->isolate_x_sub(eo, eo2, x_var); - malt->isolate_x_sub(eo, eo2, x_var); - malt->add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - malt->calculatesub(eo2, eo, false); - - mcheck = new MathStructure(mabs[0]); - CHILD(0).replace(mabs, mabs[0], mabs.containsInterval()); - CHILD(0).calculatesub(eo2, eo, true); - mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LESS : OPERATION_EQUALS_GREATER); - mcheck->isolate_x_sub(eo, eo2, x_var); - isolate_x_sub(eo, eo2, x_var); - add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - calculatesub(eo2, eo, false); - add_nocopy(malt, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); - calculatesub(eo2, eo, false); - return true; - } else if(m && m->function() == CALCULATOR->f_signum) { - MathStructure mabs(*m); - - ComparisonType cmp_type = ct_comp; - MathStructure *malt = new MathStructure(*this); - (*malt)[0].replace(mabs, m_minus_one, mabs.containsInterval()); - (*malt)[0].calculatesub(eo2, eo, true); - MathStructure *mcheck = new MathStructure(mabs[0]); - mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_EQUALS_GREATER : OPERATION_LESS); - mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? ((*m)[1].isMinusOne() ? OPERATION_GREATER : OPERATION_EQUALS_GREATER) : ((*m)[1].isMinusOne() ? OPERATION_EQUALS_LESS : OPERATION_LESS)); - mcheck->isolate_x_sub(eo, eo2, x_var); - malt->isolate_x_sub(eo, eo2, x_var); - malt->add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - malt->calculatesub(eo2, eo, false); - - MathStructure *malt0 = NULL; - if(!(*m)[1].isOne() && !(*m)[1].isMinusOne()) { - malt0 = new MathStructure(*this); - (*malt0)[0].replace(mabs, (*m)[1], mabs.containsInterval()); - (*malt0)[0].calculatesub(eo2, eo, true); - mcheck = new MathStructure(mabs[0]); - mcheck->add((*m)[1], cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_NOT_EQUALS : OPERATION_EQUALS); - mcheck->isolate_x_sub(eo, eo2, x_var); - malt0->isolate_x_sub(eo, eo2, x_var); - malt0->add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - malt0->calculatesub(eo2, eo, false); - } - - mcheck = new MathStructure(mabs[0]); - CHILD(0).replace(mabs, m_one, mabs.containsInterval()); - CHILD(0).calculatesub(eo2, eo, true); - mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? ((*m)[1].isOne() ? OPERATION_LESS : OPERATION_EQUALS_LESS) : ((*m)[1].isOne() ? OPERATION_EQUALS_GREATER : OPERATION_GREATER)); - mcheck->isolate_x_sub(eo, eo2, x_var); - isolate_x_sub(eo, eo2, x_var); - add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - calculatesub(eo2, eo, false); - add_nocopy(malt, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); - if(malt0) add_nocopy(malt0, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); - calculatesub(eo2, eo, false); - return true; - } - } - // Try factorization - if(!CHILD(1).isZero() && (!morig || !equals(*morig))) { - MathStructure mtest(*this); - mtest[0].calculateSubtract(CHILD(1), eo2); - mtest[1].clear(); - mtest.childrenUpdated(); - if(mtest[0].factorize(eo2, false, false, 0, false, false, NULL, m_undefined, false, false, 3) && !(mtest[0].isMultiplication() && mtest[0].size() == 2 && (mtest[0][0].isNumber() || mtest[0][0] == CHILD(1) || mtest[0][1] == CHILD(1)))) { - mtest.childUpdated(1); - if(mtest.isolate_x_sub(eo, eo2, x_var, this)) { - set_nocopy(mtest); - return true; - } - } - } - break; - } - case STRUCT_POWER: { - if(CHILD(0)[0].contains(x_var)) { - if(CHILD(0)[1].contains(x_var)) { - if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && CHILD(1).representsNonZero()) { - // x^(a*x)=b => x=e^(lambertw(ln(x)/a)) - MathStructure mmul(1, 1, 0); - const MathStructure *mvar = get_power_term(CHILD(0)[1], CHILD(0)[0]); - if(!mvar || !get_multiplier(CHILD(0)[1], *mvar, mmul) || mmul.contains(x_var) || !mmul.representsNonZero()) return false; - MathStructure mexp(1, 1, 0); - if(mvar->isPower() && *mvar != CHILD(0)[0]) mexp = (*mvar)[1]; - if(!mexp.representsPositive()) return false; - if(mmul.isOne() && mexp.isOne() && CHILD(0)[0].representsNonComplex()) { - if(CHILD(1).number().isInteger()) { - if(CHILD(1).number().isOne()) { - CHILD(0).setToChild(1, true); - return true; - } else if(CHILD(1).number().isMinusOne()) { - CHILD(0).setToChild(1, true); - return true; - } else if(CHILD(1).number() == 4) { - CHILD(1).set(2, 1, 0, true); - CHILD(0).setToChild(1, true); - return true; - } else if(CHILD(1).number() == 27) { - CHILD(1).set(3, 1, 0, true); - CHILD(0).setToChild(1, true); - return true; - } else if(CHILD(1).number() == 256) { - CHILD(1).set(4, 1, 0, true); - CHILD(0).setToChild(1, true); - return true; - } else if(CHILD(1).number() == 3125) { - CHILD(1).set(5, 1, 0, true); - CHILD(0).setToChild(1, true); - return true; - } else if(CHILD(1).number() == 46656) { - CHILD(1).set(6, 1, 0, true); - CHILD(0).setToChild(1, true); - return true; - } else if(CHILD(1).number() == 823543) { - CHILD(1).set(7, 1, 0, true); - CHILD(0).setToChild(1, true); - return true; - } - } else if(CHILD(1).number().numeratorIsOne()) { - Number nr_den = CHILD(1).number().denominator(); - if(nr_den == 4) { - CHILD(1).set(-2, 1, 0, true); - CHILD(0).setToChild(1, true); - return true; - } else if(nr_den == 256) { - CHILD(1).set(-4, 1, 0, true); - CHILD(0).setToChild(1, true); - return true; - } else if(nr_den == 46656) { - CHILD(1).set(-6, 1, 0, true); - CHILD(0).setToChild(1, true); - return true; - } - } else if(CHILD(1).number().numeratorIsMinusOne()) { - Number nr_den = CHILD(1).number().denominator(); - if(nr_den == 27) { - CHILD(1).set(-3, 1, 0, true); - CHILD(0).setToChild(1, true); - return true; - } else if(nr_den == 3125) { - CHILD(1).set(-5, 1, 0, true); - CHILD(0).setToChild(1, true); - return true; - } else if(nr_den == 823543) { - CHILD(1).set(-7, 1, 0, true); - CHILD(0).setToChild(1, true); - return true; - } - } - } - MathStructure *marg = new MathStructure(CALCULATOR->f_ln, &CHILD(1), NULL); - if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); - if(CHILD(1).representsPositive() && CHILD(0)[0].representsNonComplex()) { - if(!mexp.isOne()) marg->calculateMultiply(mexp, eo2); - if(!mmul.isOne()) marg->calculateDivide(mmul, eo2); - MathStructure *mreq1 = NULL; - MathStructure *marg2 = NULL; - MathStructure *mreq2 = NULL; - if(!marg->representsNonNegative()) { - mreq1 = new MathStructure(*marg); - mreq2 = new MathStructure(*marg); - marg2 = new MathStructure(*marg); - marg2->transform(CALCULATOR->f_lambert_w); - marg2->addChild(m_minus_one); - if(marg2->calculateFunctions(eo)) marg2->calculatesub(eo2, eo, true); - if(!mexp.isOne()) marg2->calculateDivide(mexp, eo2); - marg2->transform(STRUCT_POWER); - marg2->insertChild(CALCULATOR->v_e, 1); - (*marg2)[0].calculatesub(eo2, eo, true); - marg2->calculateRaiseExponent(eo2); - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->v_e); - mreq1->last().calculateRaise(m_minus_one, eo2); - mreq1->last().calculateNegate(eo2); - mreq1->childUpdated(2); - mreq1->isolate_x(eo2, eo); - mreq2->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, m_zero); - mreq2->isolate_x(eo2, eo); - marg2->transform(ct_comp, CHILD(0)[0]); - marg2->swapChildren(1, 2); - marg2->isolate_x_sub(eo, eo2, x_var, morig); - marg2->add(*mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - marg2->add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - marg2->calculatesub(eo2, eo, false); - } - marg->transform(CALCULATOR->f_lambert_w); - marg->addChild(m_zero); - if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); - if(!mexp.isOne()) marg->calculateDivide(mexp, eo2); - CHILD(0).setToChild(1, true); - CHILD(1).set(CALCULATOR->v_e); - CHILD(1).raise_nocopy(marg); - CHILD(1).calculateRaiseExponent(eo2); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - if(mreq1) { - add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - if(marg2) { - add_nocopy(marg2, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - } else { - marg->add(nr_one_i); - marg->last().multiply(nr_two); - marg->last().multiply(CALCULATOR->v_pi, true); - marg->last().multiply(CALCULATOR->v_n, true); - marg->evalSort(true); - MathStructure *mreq1 = new MathStructure(*marg); - if(!mexp.isOne()) marg->calculateMultiply(mexp, eo2); - if(!mmul.isOne()) marg->calculateDivide(mmul, eo2); - MathStructure *marg2 = new MathStructure(*marg); - MathStructure *marg3 = new MathStructure(*marg); - marg2->transform(CALCULATOR->f_lambert_w); - marg2->addChild(m_minus_one); - if(marg2->calculateFunctions(eo)) marg2->calculatesub(eo2, eo, true); - if(!mexp.isOne()) marg2->calculateDivide(mexp, eo2); - marg2->transform(STRUCT_POWER); - marg2->insertChild(CALCULATOR->v_e, 1); - (*marg2)[0].calculatesub(eo2, eo, true); - marg2->calculateRaiseExponent(eo2); - marg3->transform(CALCULATOR->f_lambert_w); - marg3->addChild(m_one); - if(marg3->calculateFunctions(eo)) marg3->calculatesub(eo2, eo, true); - if(!mexp.isOne()) marg3->calculateDivide(mexp, eo2); - marg3->transform(STRUCT_POWER); - marg3->insertChild(CALCULATOR->v_e, 1); - (*marg3)[0].calculatesub(eo2, eo, true); - marg3->calculateRaiseExponent(eo2); - mreq1->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_NOT_EQUALS : COMPARISON_EQUALS, m_zero); - mreq1->isolate_x(eo2, eo); - MathStructure *mreq2 = new MathStructure(*mreq1); - marg2->transform(ct_comp, CHILD(0)[0]); - marg2->swapChildren(1, 2); - marg2->isolate_x_sub(eo, eo2, x_var, morig); - marg2->add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - marg2->calculatesub(eo2, eo, false); - marg3->transform(ct_comp, CHILD(0)[0]); - marg3->swapChildren(1, 2); - marg3->isolate_x_sub(eo, eo2, x_var, morig); - marg3->add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - marg3->calculatesub(eo2, eo, false); - marg->transform(CALCULATOR->f_lambert_w); - marg->addChild(m_zero); - if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); - if(!mexp.isOne()) marg->calculateDivide(mexp, eo2); - CHILD(0).setToChild(1, true); - CHILD(1).set(CALCULATOR->v_e); - CHILD(1).raise_nocopy(marg); - CHILD(1).calculateRaiseExponent(eo2); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - add_nocopy(marg2, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - add_nocopy(marg3, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - calculatesub(eo2, eo, false); - } - return true; - } - } else if(CHILD(0)[1].isNumber() && CHILD(0)[1].number().isRational()) { - // x^a=b - if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && !CHILD(0)[1].number().isInteger() && !CHILD(0)[1].number().isFraction() && !CHILD(0).representsNonComplex(true)) { - MathStructure mvar(CHILD(0)[0]); - mvar.raise(CHILD(0)[1].number().numerator()); - - UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(mvar) + RIGHT_PARENTHESIS); - var->setInterval(mvar); - MathStructure mu(var); - MathStructure mtest(mu); - mtest.raise(CHILD(0)[1]); - mtest[1].number().divide(CHILD(0)[1].number().numerator()); - mtest.transform(ct_comp, CHILD(1)); - if(mtest.isolate_x_sub(eo, eo2, mu)) { - mtest.replace(mu, mvar); - if((mtest.isLogicalAnd() || mtest.isLogicalOr() || mtest.isComparison()) && test_comparisons(*this, mtest, x_var, eo, false, eo.expand ? 1 : 2) < 0) { - if(eo.expand) { - add(mtest, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); - calculatesub(eo2, eo, false); - var->destroy(); - return true; - } - } else { - set(mtest); - var->destroy(); - return true; - } - } - var->destroy(); - return false; - } - bool b_neg = CHILD(0)[1].number().isNegative(); - bool b_nonzero = !CHILD(1).isZero() && CHILD(1).representsNonZero(true); - if(b_neg && CHILD(1).isZero()) { - if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { - CHILD(0).setToChild(1); - CHILD(1) = nr_plus_inf; - CHILDREN_UPDATED - MathStructure *malt = new MathStructure(*this); - (*malt)[1] = nr_minus_inf; - isolate_x_sub(eo, eo2, x_var, morig); - malt->isolate_x_sub(eo, eo2, x_var, morig); - add_nocopy(malt, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); - calculatesub(eo, eo2, false); - return true; - } - if(CHILD(0)[1].number().isInteger() && CHILD(0)[1].number().isEven()) { - if(ct_comp == COMPARISON_EQUALS_LESS) { - clear(true); - return true; - } - ct_comp = COMPARISON_NOT_EQUALS; - CHILD(1).clear(true); - CHILD(0).setToChild(1); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } - if(ct_comp == COMPARISON_EQUALS_GREATER) { - ct_comp = COMPARISON_GREATER; - } else if(ct_comp == COMPARISON_EQUALS_LESS) { - ct_comp = COMPARISON_LESS; - } - CHILD(1).clear(true); - CHILD(0).setToChild(1); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } else if(CHILD(1).isZero()) { - if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS && CHILD(0)[1].number().isInteger() && CHILD(0)[1].number().isEven()) { - if(ct_comp == COMPARISON_LESS) { - clear(true); - return true; - } - if(ct_comp == COMPARISON_EQUALS_LESS) { - ct_comp = COMPARISON_EQUALS; - CHILD(0).setToChild(1); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } - if(ct_comp == COMPARISON_EQUALS_GREATER) { - set(1, 1, 0, true); - return true; - } - CHILD(0).setToChild(1); - MathStructure *mneg = new MathStructure(*this); - if(ct_comp == COMPARISON_GREATER) mneg->setComparisonType(COMPARISON_LESS); - mneg->isolate_x_sub(eo, eo2, x_var, morig); - add_nocopy(mneg, OPERATION_LOGICAL_OR); - calculatesub(eo2, eo, false); - } else { - if(!CHILD(0)[1].number().isInteger()) { - if(ct_comp == COMPARISON_LESS) { - clear(true); - return true; - } - if(ct_comp == COMPARISON_EQUALS_LESS) { - ct_comp = COMPARISON_EQUALS; - CHILD(0).setToChild(1); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } - } - CHILD(0).setToChild(1); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - } - return true; - } else if(b_neg && ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { - if(CHILD(0)[1].number().isMinusOne()) { - CHILD(0).setToChild(1); - } else { - CHILD(0)[1].number().negate(); - - } - MathStructure *mtest = new MathStructure(CHILD(0)); - CHILD(1).set(1, 1, 0); - CHILDREN_UPDATED - MathStructure *malt = new MathStructure(*this); - if(ct_comp == COMPARISON_EQUALS_GREATER) { - ct_comp = COMPARISON_EQUALS_LESS; - } else if(ct_comp == COMPARISON_GREATER) { - ct_comp = COMPARISON_LESS; - } else if(ct_comp == COMPARISON_EQUALS_LESS) { - ct_comp = COMPARISON_EQUALS_GREATER; - } else if(ct_comp == COMPARISON_LESS) { - ct_comp = COMPARISON_GREATER; - } - isolate_x_sub(eo, eo2, x_var, morig); - mtest->add(m_zero, OPERATION_GREATER); - MathStructure *mtest_alt = new MathStructure(*mtest); - mtest_alt->setComparisonType(COMPARISON_LESS); - mtest->isolate_x_sub(eo, eo2, x_var); - add_nocopy(mtest, OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - malt->isolate_x_sub(eo, eo2, x_var, morig); - mtest_alt->isolate_x_sub(eo, eo2, x_var); - malt->add_nocopy(mtest_alt, OPERATION_LOGICAL_AND); - malt->calculatesub(eo2, eo, false); - add_nocopy(malt, OPERATION_LOGICAL_OR); - calculatesub(eo2, eo, false); - return true; - } - MathStructure mbak(*this); - if(CHILD(0)[1].number().isMinusOne()) { - CHILD(0).setToChild(1, true); - CHILD(1).calculateRaise(m_minus_one, eo2); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - } else if(CHILD(0)[1].number().isInteger()) { - bool b_real = CHILD(0)[0].representsNonComplex(true); - bool b_complex = !b_real && CHILD(0)[0].representsComplex(true); - bool warn_complex = false; - bool check_complex = false; - if(CHILD(0)[1].number().isEven()) { - if(!CHILD(1).representsNonNegative(true)) { - if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { - if(CHILD(1).representsNegative(true)) { - if(ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_LESS) clear(true); - else set(1, 1, 0, true); - return true; - } - return false; - } - if(b_real && (CHILD(1).representsNegative(true) || CHILD(1).representsComplex(true))) { - if(ct_comp == COMPARISON_EQUALS) { - clear(true); - } else if(ct_comp == COMPARISON_NOT_EQUALS) { - set(1, 1, 0, true); - } - return true; - } - } - } - bool b_set = false; - if(b_neg) CHILD(0)[1].number().negate(); - if(CHILD(0)[1].number().isTwo()) { - CHILD(1).raise(CHILD(0)[1].number()); - CHILD(1)[1].number().recip(); - if(b_neg) CHILD(1)[1].number().negate(); - CHILD(1).calculateRaiseExponent(eo2); - CHILDREN_UPDATED - } else if(!b_real && CHILD(0)[1].number() == 4 && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { - CHILD(1).raise(CHILD(0)[1].number()); - CHILD(1)[1].number().recip(); - if(b_neg) CHILD(1)[1].number().negate(); - CHILD(1).calculateRaiseExponent(eo2); - CHILD(0).setToChild(1); - CHILDREN_UPDATED - MathStructure *malt1 = new MathStructure(*this); - MathStructure *malt2 = new MathStructure(*this); - MathStructure *malt3 = new MathStructure(*this); - (*malt1)[1].calculateNegate(eo2); - (*malt2)[1].calculateMultiply(m_one_i, eo2); - (*malt3)[1].calculateMultiply(nr_minus_i, eo2); - malt1->childUpdated(2); - malt2->childUpdated(2); - malt3->childUpdated(2); - malt1->isolate_x_sub(eo, eo2, x_var, morig); - malt2->isolate_x_sub(eo, eo2, x_var, morig); - malt3->isolate_x_sub(eo, eo2, x_var, morig); - isolate_x_sub(eo, eo2, x_var, morig); - add_nocopy(malt1, ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); - add_nocopy(malt2, ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); - add_nocopy(malt3, ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); - calculatesub(eo2, eo, false); - b_set = true; - } else if(!b_real && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { - if(CHILD(0)[1].number() > 20) return false; - MathStructure mdeg(CHILD(0)[1]); - Number marg_pi; - MathStructure marg; - if(CHILD(1).representsNegative(true)) { - marg_pi.set(1, 1, 0); - } else if(!CHILD(1).representsNegative(true)) { - if(CHILD(1).isNumber() && !CHILD(1).number().hasRealPart()) { - if(CHILD(1).number().imaginaryPartIsNegative()) marg_pi.set(-1, 2, 0); - else marg_pi.set(1, 2, 0); - } else { - marg.set(CALCULATOR->f_arg, &CHILD(1), NULL); - marg.calculateFunctions(eo); - switch(eo2.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {marg.multiply(Number(1, 180, 0)); marg.multiply(CALCULATOR->v_pi); break;} - case ANGLE_UNIT_GRADIANS: {marg.multiply(Number(1, 200, 0)); marg.multiply(CALCULATOR->v_pi); break;} - case ANGLE_UNIT_RADIANS: {break;} - default: {if(CALCULATOR->getRadUnit()) marg /= CALCULATOR->getRadUnit();} - } - marg.calculatesub(eo2, eo, true); - } - } - MathStructure minv(mdeg); - minv.number().recip(); - MathStructure mmul(CALCULATOR->f_abs, &CHILD(1), NULL); - mmul.calculateFunctions(eo); - mmul.calculateRaise(minv, eo2); - Number nr_i; - while(nr_i.isLessThan(mdeg.number())) { - MathStructure mroot; - if(CALCULATOR->aborted()) {set(mbak); return false;} - MathStructure mexp; - Number nexp; - if(!nr_i.isZero()) { - nexp.set(2, 1, 0); - if(!nexp.multiply(nr_i)) {set(mbak); return false;} - } - b_set = false; - if(!marg_pi.isZero()) { - if(nexp.isZero()) nexp = marg_pi; - else if(!nexp.add(marg_pi)) {set(mbak); return false;} - if(!nexp.divide(mdeg.number())) {set(mbak); return false;} - if(nexp.isInteger()) { - mroot.set(mmul); - if(nexp.isOdd()) { - mroot.calculateNegate(eo2); - } - b_set = true; - } else if(nexp.isRational() && nexp.denominatorIsTwo()) { - if(!nexp.floor()) {set(mbak); return false;} - mroot.set(mmul); - if(nexp.isEven()) { - mroot.calculateMultiply(nr_one_i, eo2); - } else { - mroot.calculateMultiply(nr_minus_i, eo2); - } - b_set = true; - } - if(!b_set) { - mexp.set(nexp); - mexp.multiply(CALCULATOR->v_pi); - } - } else { - if(nexp.isZero()) { - if(!marg.isZero()) { - mexp.set(marg); - mexp.multiply(minv); - } - } else { - mexp.set(nexp); - mexp.multiply(CALCULATOR->v_pi); - if(!marg.isZero()) mexp.add(marg); - mexp.multiply(minv); - } - } - if(!b_set) { - if(mexp.isZero()) { - mroot.set(mmul); - } else { - mexp.multiply(m_one_i); - mroot.set(CALCULATOR->v_e); - mroot.raise(mexp); - mroot.calculatesub(eo2, eo, true); - mroot.calculateMultiply(mmul, eo2); - } - } - if(b_neg) mroot.calculateRaise(m_minus_one, eo2); - if(nr_i.isZero()) { - CHILD(0).setToChild(1); - CHILD(1) = mroot; - isolate_x_sub(eo, eo2, x_var, morig); - } else { - MathStructure *malt = new MathStructure(mbak[0][0]); - malt->add(mroot, mbak.comparisonType() == COMPARISON_NOT_EQUALS ? OPERATION_NOT_EQUALS : OPERATION_EQUALS); - malt->isolate_x_sub(eo, eo2, x_var, morig); - add_nocopy(malt, mbak.comparisonType() == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); - } - nr_i++; - } - calculatesub(eo2, eo, false); - b_set = true; - } else { - if(b_complex) { - warn_complex = true; - } else if(!b_real) { - check_complex = true; - } - CHILD(1).transform(STRUCT_FUNCTION, CHILD(0)[1]); - CHILD(1).setFunction(CALCULATOR->f_root); - if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); - if(b_neg) CHILD(1).calculateRaise(m_minus_one, eo2); - childUpdated(2); - } - if(!b_set) { - if(CHILD(0)[1].number().isEven()) { - CHILD(0).setToChild(1); - MathStructure *mneg = new MathStructure(*this); - (*mneg)[1].calculateNegate(eo2); - mneg->childUpdated(2); - if(ct_comp == COMPARISON_LESS) mneg->setComparisonType(COMPARISON_GREATER); - else if(ct_comp == COMPARISON_GREATER) mneg->setComparisonType(COMPARISON_LESS); - else if(ct_comp == COMPARISON_EQUALS_LESS) mneg->setComparisonType(COMPARISON_EQUALS_GREATER); - else if(ct_comp == COMPARISON_EQUALS_GREATER) mneg->setComparisonType(COMPARISON_EQUALS_LESS); - mneg->isolate_x_sub(eo, eo2, x_var, morig); - isolate_x_sub(eo, eo2, x_var, morig); - add_nocopy(mneg, ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); - calculatesub(eo2, eo, false); - } else { - CHILD(0).setToChild(1); - isolate_x_sub(eo, eo2, x_var, morig); - } - } - if(check_complex) { - if(!isComparison() || CHILD(0) != x_var) { - warn_complex = true; - } - MathStructure mtest(mbak[0][0]); - if(!warn_complex && check_complex) { - mtest.replace(x_var, CHILD(1)); - if(mtest.representsNonComplex(true)) check_complex = false; - if(mtest.representsComplex(true)) { - warn_complex = true; - } - } - if(!warn_complex && check_complex) { - CALCULATOR->beginTemporaryStopMessages(); - EvaluationOptions eo3 = eo; - eo3.approximation = APPROXIMATION_APPROXIMATE; - mtest.eval(eo3); - if(CALCULATOR->endTemporaryStopMessages() || !mtest.representsReal(true)) { - warn_complex = true; - } - } - } - if(warn_complex) CALCULATOR->error(false, _("Only one or two of the roots where calculated for %s."), format_and_print(mbak).c_str(), NULL); - } else { - MathStructure *mposcheck = NULL; - bool b_test = false; - if(!CHILD(1).representsNonNegative(true)) { - if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { - if(CHILD(1).representsNegative(true)) { - if(ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_LESS) clear(true); - else {CHILD(0).setToChild(1, true); CHILD(1).clear(true); CHILDREN_UPDATED} - return true; - } - if(ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_GREATER) { - mposcheck = new MathStructure(CHILD(0)[0]); - mposcheck->add(m_zero, OPERATION_EQUALS_GREATER); - mposcheck->isolate_x_sub(eo, eo2, x_var); - } - } else { - if(CHILD(1).representsNegative(true)) { - if(ct_comp == COMPARISON_EQUALS) { - clear(true); - } else if(ct_comp == COMPARISON_NOT_EQUALS) { - set(1, 1, 0, true); - } - return true; - } - if(CHILD(1).representsNonComplex(true)) { - mposcheck = new MathStructure(CHILD(1)); - mposcheck->add(m_zero, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LESS : OPERATION_EQUALS_GREATER); - mposcheck->isolate_x_sub(eo, eo2, x_var); - } else { - b_test = true; - mposcheck = new MathStructure(*this); - } - } - } - if(ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_LESS) { - mposcheck = new MathStructure(CHILD(0)[0]); - mposcheck->add(m_zero, OPERATION_EQUALS_GREATER); - mposcheck->isolate_x_sub(eo, eo2, x_var); - } - CHILD(0)[1].number().recip(); - CHILD(1).calculateRaise(CHILD(0)[1], eo); - CHILD(0).setToChild(1); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - if(b_test) { - if(test_comparisons(*mposcheck, *this, x_var, eo) < 0) { - mposcheck->unref(); - return false; - } - mposcheck->unref(); - } else if(mposcheck) { - add_nocopy(mposcheck, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - } - if(b_neg && !b_nonzero) { - MathStructure *mtest = new MathStructure(mbak[1]); - mtest->add(m_zero, (mbak.comparisonType() == COMPARISON_NOT_EQUALS) ? OPERATION_EQUALS : OPERATION_NOT_EQUALS); - mtest->isolate_x_sub(eo, eo2, x_var); - add_nocopy(mtest, (mbak.comparisonType() == COMPARISON_NOT_EQUALS) ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - if(mbak.comparisonType() != COMPARISON_NOT_EQUALS && mbak.comparisonType() != COMPARISON_EQUALS) { - MathStructure *malt = new MathStructure(mbak[0]); - if(mbak[0][1].representsInteger() && mbak[0][1].representsEven()) { - malt->add(m_zero, OPERATION_NOT_EQUALS); - } else { - malt->add(m_zero, (ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_GREATER) ? OPERATION_LESS : OPERATION_GREATER); - } - malt->isolate_x_sub(eo, eo2, x_var, morig); - MathStructure *mtest2 = new MathStructure(mbak[1]); - mtest2->add(m_zero, OPERATION_EQUALS); - mtest2->isolate_x_sub(eo, eo2, x_var); - malt->add_nocopy(mtest2, (mbak.comparisonType() == COMPARISON_NOT_EQUALS) ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - malt->calculatesub(eo2, eo, false); - add_nocopy(malt, OPERATION_LOGICAL_OR); - calculatesub(eo2, eo, false); - } - } - return true; - } - } else if(CHILD(0)[1].contains(x_var) && CHILD(0)[0].representsNumber() && (!CHILD(0)[1].representsNonComplex() || (CHILD(0)[0].representsNonNegative() || (CHILD(0)[0].isNumber() && CHILD(0)[0].number().isNegative() && CHILD(1).isNumber())))) { - // a^x=b => x=log(b, a) - MathStructure *mtest = NULL, *m0 = NULL, *m1 = NULL; - if(CHILD(0)[0].isOne()) return false; - if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && !CHILD(0)[0].representsNonZero()) { - if(!CHILD(1).representsNonZero()) { - MathStructure *mtest2 = NULL; - if(!CHILD(1).isZero()) { - mtest2 = new MathStructure(CHILD(1)); - mtest2->transform(ct_comp, m_zero); - mtest2->isolate_x(eo2, eo); - } - m0 = new MathStructure(CHILD(0)[1]); - if(!m0->representsNonComplex(true)) { - m0->transform(CALCULATOR->f_re); - if(m0->calculateFunctions(eo)) m0->calculatesub(eo2, eo, true); - } - m0->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, m_zero); - m0->isolate_x_sub(eo, eo2, x_var, morig); - if(mtest2) { - m0->add_nocopy(mtest2, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); - m0->calculatesub(eo2, eo, false); - } - if(CHILD(0)[0].isZero()) { - set_nocopy(*m0, true); - m0->unref(); - return true; - } - MathStructure *mtest3 = new MathStructure(CHILD(0)[0]); - mtest3->transform(ct_comp, m_zero); - mtest3->isolate_x(eo2, eo); - m0->add_nocopy(mtest3, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); - m0->calculatesub(eo2, eo, false); - } - mtest = new MathStructure(CHILD(0)[1]); - mtest->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_NOT_EQUALS : COMPARISON_EQUALS, m_zero); - mtest->isolate_x_sub(eo, eo2, x_var, morig); - if(!CHILD(0)[0].isZero()) { - MathStructure *mtest_b = new MathStructure(CHILD(0)[0]); - mtest_b->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_NOT_EQUALS : COMPARISON_EQUALS, m_zero); - mtest_b->isolate_x_sub(eo, eo2, x_var, morig); - mtest->add_nocopy(mtest_b, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - mtest->calculatesub(eo2, eo, false); - } - } - ComparisonResult cr1 = COMPARISON_RESULT_NOT_EQUAL; - if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { - cr1 = CHILD(0)[0].compare(m_one); - if(cr1 == COMPARISON_RESULT_EQUAL) { - ComparisonResult cr2 = CHILD(1).compare(m_one); - if(cr2 == COMPARISON_RESULT_EQUAL) { - if(ct_comp == COMPARISON_EQUALS) set(1, 1, 0, true); - else clear(true); - return true; - } else if(COMPARISON_MIGHT_BE_EQUAL(cr2)) { - m1 = new MathStructure(); - m1->setType(STRUCT_COMPARISON); - m1->setComparisonType(ct_comp); - m1->addChild(CHILD(1)); - m1->addChild(m_one); - m1->isolate_x(eo2, eo); - } - } else if(COMPARISON_MIGHT_BE_EQUAL(cr1)) { - ComparisonResult cr2 = CHILD(1).compare(m_one); - if(cr2 == COMPARISON_RESULT_EQUAL) { - m1 = new MathStructure(); - m1->setType(STRUCT_COMPARISON); - m1->setComparisonType(ct_comp); - m1->addChild(CHILD(0)[0]); - m1->addChild(m_one); - m1->isolate_x(eo2, eo); - } else if(COMPARISON_MIGHT_BE_EQUAL(cr2)) { - m1 = new MathStructure(); - m1->setType(STRUCT_COMPARISON); - m1->setComparisonType(ct_comp); - m1->addChild(CHILD(1)); - m1->addChild(m_one); - m1->isolate_x(eo2, eo); - MathStructure *m1b = new MathStructure(); - m1b->setType(STRUCT_COMPARISON); - m1b->setComparisonType(ct_comp); - m1b->addChild(CHILD(0)[0]); - m1b->addChild(m_one); - m1b->isolate_x(eo2, eo); - m1->add_nocopy(m1b, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - m1->calculatesub(eo2, eo, false); - } - } - } - ComparisonType ct = ct_comp; - - if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { - if(CHILD(0)[0].isMinusOne()) { - if(CHILD(1).isOne() || CHILD(1).isMinusOne()) { - bool b_m1 = CHILD(1).isMinusOne(); - CHILD(0).setToChild(2, true); - CHILD(1).set(2, 1, 0, true); - CHILD(1) *= CALCULATOR->v_n; - if(b_m1) CHILD(1) += m_one; - CHILD(1).evalSort(false); - fix_n_multiple(*this, eo2, eo, x_var); - CHILDREN_UPDATED; - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } - } else if(CHILD(1).isOne() && CHILD(0)[1].representsNonComplex()) { - CHILD(0).setToChild(2, true); - CHILD(1).clear(true); - isolate_x_sub(eo, eo2, x_var, morig); - if(m1) { - add_nocopy(m1, ct == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - if(mtest) { - add_nocopy(mtest, ct == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - return true; - } - } - if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { - if(CHILD(0)[0].isNumber() && CHILD(0)[0].number().isReal() && CHILD(0)[0].number().isPositive()) { - if(CHILD(1).representsNegative()) { - if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) { - set(1, 1, 0, true); - } else { - clear(true); - } - return true; - } - if(CHILD(0)[0].number().isFraction()) { - switch(ct_comp) { - case COMPARISON_LESS: {ct_comp = COMPARISON_GREATER; break;} - case COMPARISON_GREATER: {ct_comp = COMPARISON_LESS; break;} - case COMPARISON_EQUALS_LESS: {ct_comp = COMPARISON_EQUALS_GREATER; break;} - case COMPARISON_EQUALS_GREATER: {ct_comp = COMPARISON_EQUALS_LESS; break;} - default: {} - } - } - } else if(CHILD(0)[0].isZero()) { - bool b_clear = false, b_gz = false; - switch(ct_comp) { - case COMPARISON_LESS: {b_gz = CHILD(1).representsPositive(); b_clear = !b_gz && CHILD(1).representsNonPositive(); break;} - case COMPARISON_GREATER: {b_gz = CHILD(1).representsNegative(); b_clear = !b_gz && CHILD(1).representsNonNegative(); break;} - case COMPARISON_EQUALS_LESS: {b_gz = CHILD(1).representsNonNegative(); b_clear = !b_gz && CHILD(1).representsNegative(); break;} - case COMPARISON_EQUALS_GREATER: {b_gz = CHILD(1).representsNonPositive(); b_clear = !b_gz && CHILD(1).representsPositive(); break;} - default: {} - } - if(b_clear) { - clear(true); - return true; - } else if(b_gz) { - ct_comp = COMPARISON_GREATER; - CHILD(1).clear(true); - CHILD(0).setToChild(2, true); - if(!CHILD(0).representsNonComplex(true)) { - CHILD(0).transform(CALCULATOR->f_re); - if(CHILD(0).calculateFunctions(eo)) CHILD(0).calculatesub(eo2, eo, true); - } - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } else { - return false; - } - } else { - return false; - } - } - MathStructure msave(CHILD(1)); - if(CHILD(0)[1].representsNonComplex()) { - if(CHILD(0)[0].representsNegative()) { - MathStructure mtest2(CALCULATOR->f_logn, &msave, &CHILD(0)[0], NULL); - mtest2[1].calculateNegate(eo2); - mtest2.childUpdated(2); - if(mtest2.calculateFunctions(eo)) mtest2.calculatesub(eo2, eo, true); - if(mtest) mtest->unref(); - if(m0) m0->unref(); - mtest = NULL; - if(!mtest2.isInteger()) return false; - if(mtest2.number().isOdd()) { - if(ct_comp == COMPARISON_NOT_EQUALS) set(1, 1, 0, true); - else clear(true); - return true; - } - CHILD(1).set(mtest2, true); - } else { - CHILD(1).set(CALCULATOR->f_logn, &msave, &CHILD(0)[0], NULL); - bool b = CHILD(1).calculateFunctions(eo); - if(b) CHILD(1).calculatesub(eo2, eo, true); - } - } else { - CHILD(1).set(CALCULATOR->f_ln, &msave, NULL); - CHILD(1) += nr_one_i; - CHILD(1)[1] *= nr_two; - CHILD(1)[1].multiply(CALCULATOR->v_pi, true); - CHILD(1)[1].multiply(CALCULATOR->v_n, true); - CHILD(1).divide_nocopy(new MathStructure(CALCULATOR->f_ln, &CHILD(0)[0], NULL)); - CHILD(1).evalSort(true); - bool b = CHILD(1).calculateFunctions(eo); - if(b) CHILD(1).calculatesub(eo2, eo, true); - } - MathStructure *mn1 = NULL; - if(COMPARISON_MIGHT_BE_EQUAL(cr1)) { - mn1 = new MathStructure(); - mn1->setType(STRUCT_COMPARISON); - mn1->setComparisonType(ct == COMPARISON_EQUALS ? COMPARISON_NOT_EQUALS : COMPARISON_EQUALS); - mn1->addChild(CHILD(0)[0]); - mn1->addChild(m_one); - mn1->isolate_x(eo2, eo); - } - CHILD(0).setToChild(2, true); - CHILDREN_UPDATED; - isolate_x_sub(eo, eo2, x_var, morig); - if(mn1) { - add_nocopy(mn1, ct == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - if(m1) { - add_nocopy(m1, ct == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - if(mtest) { - add_nocopy(mtest, ct == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - if(m0) { - add_nocopy(m0, ct == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - } - fix_n_multiple(*this, eo2, eo, x_var); - return true; - } - break; - } - case STRUCT_FUNCTION: { - if(CHILD(0).function() == CALCULATOR->f_root && VALID_ROOT(CHILD(0))) { - if(CHILD(0)[0].contains(x_var)) { - MathStructure *mposcheck = NULL; - bool b_test = false; - if(CHILD(0)[1].number().numeratorIsEven() && !CHILD(1).representsNonNegative(true)) { - if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { - if(CHILD(1).representsNegative(true)) { - if(ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_LESS) clear(true); - else {CHILD(0).setToChild(1, true); CHILD(1).clear(true); CHILDREN_UPDATED} - return true; - } - if(ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_GREATER) { - mposcheck = new MathStructure(CHILD(0)[0]); - mposcheck->add(m_zero, OPERATION_EQUALS_GREATER); - mposcheck->isolate_x_sub(eo, eo2, x_var); - } - } else { - if(CHILD(1).representsNegative(true)) { - if(ct_comp == COMPARISON_EQUALS) { - clear(true); - } else if(ct_comp == COMPARISON_NOT_EQUALS) { - set(1, 1, 0, true); - } - return true; - } - if(CHILD(1).representsNonComplex(true)) { - mposcheck = new MathStructure(CHILD(1)); - mposcheck->add(m_zero, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LESS : OPERATION_EQUALS_GREATER); - mposcheck->isolate_x_sub(eo, eo2, x_var); - } else { - b_test = true; - mposcheck = new MathStructure(*this); - } - } - } - if((ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_LESS) && CHILD(0)[1].number().numeratorIsEven()) { - mposcheck = new MathStructure(CHILD(0)[0]); - mposcheck->add(m_zero, OPERATION_EQUALS_GREATER); - mposcheck->isolate_x_sub(eo, eo2, x_var); - } - CHILD(1).calculateRaise(CHILD(0)[1], eo); - CHILD(0).setToChild(1); - CHILDREN_UPDATED - isolate_x_sub(eo, eo2, x_var, morig); - if(b_test) { - if(test_comparisons(*mposcheck, *this, x_var, eo) < 0) { - mposcheck->unref(); - return false; - } - mposcheck->unref(); - } else if(mposcheck) { - add_nocopy(mposcheck, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - calculatesub(eo2, eo, false); - } - return true; - } - } else if(CHILD(0).function() == CALCULATOR->f_ln && CHILD(0).size() == 1) { - if(CHILD(0)[0].contains(x_var)) { - if(!CHILD(1).representsNonComplex()) { - if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) return false; - MathStructure mtest(CALCULATOR->v_e); - mtest.raise(CHILD(1)); - mtest.transform(CALCULATOR->f_ln); - ComparisonResult cr = mtest.compareApproximately(CHILD(1), eo); - if(cr != COMPARISON_RESULT_EQUAL) { - if(COMPARISON_IS_NOT_EQUAL(cr)) { - if(ct_comp == COMPARISON_EQUALS) clear(true); - else set(1, 1, 0, true); - return true; - } - return false; - } - } - MathStructure msave(CHILD(1)); - CHILD(1).set(CALCULATOR->v_e); - CHILD(1).calculateRaise(msave, eo2); - CHILD(0).setToChild(1, true); - CHILDREN_UPDATED; - if(ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) { - MathStructure *mand = new MathStructure(CHILD(0)); - mand->add(m_zero, OPERATION_GREATER); - mand->isolate_x_sub(eo, eo2, x_var); - isolate_x_sub(eo, eo2, x_var, morig); - add_nocopy(mand, OPERATION_LOGICAL_AND); - SWAP_CHILDREN(0, 1); - calculatesub(eo2, eo, false); - } else { - isolate_x_sub(eo, eo2, x_var, morig); - } - return true; - } - } else if(CHILD(0).function() == CALCULATOR->f_lambert_w && (CHILD(0).size() == 1 || (CHILD(0).size() == 2 && CHILD(0)[1].isZero())) && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { - if(CHILD(0)[0].contains(x_var)) { - MathStructure msave(CHILD(1)); - CHILD(1).set(CALCULATOR->v_e); - CHILD(1).calculateRaise(msave, eo2); - CHILD(1).calculateMultiply(msave, eo2); - CHILD(0).setToChild(1, true); - CHILDREN_UPDATED; - if(ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) { - MathStructure *mand = new MathStructure(CHILD(0)); - mand->add(m_zero, OPERATION_GREATER); - mand->isolate_x_sub(eo, eo2, x_var); - isolate_x_sub(eo, eo2, x_var, morig); - add_nocopy(mand, OPERATION_LOGICAL_AND); - SWAP_CHILDREN(0, 1); - calculatesub(eo2, eo, false); - } else { - isolate_x_sub(eo, eo2, x_var, morig); - } - return true; - } - } else if(CHILD(0).function() == CALCULATOR->f_logn && CHILD(0).size() == 2) { - if(CHILD(0)[0].contains(x_var)) { - MathStructure msave(CHILD(1)); - CHILD(1) = CHILD(0)[1]; - CHILD(1).calculateRaise(msave, eo2); - CHILD(0).setToChild(1, true); - CHILDREN_UPDATED; - if(ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) { - MathStructure *mand = new MathStructure(CHILD(0)); - mand->add(m_zero, OPERATION_GREATER); - mand->isolate_x_sub(eo, eo2, x_var); - isolate_x_sub(eo, eo2, x_var, morig); - add_nocopy(mand, OPERATION_LOGICAL_AND); - SWAP_CHILDREN(0, 1); - calculatesub(eo2, eo, false); - } else { - isolate_x_sub(eo, eo2, x_var, morig); - } - return true; - } - } else if((CHILD(0).function() == CALCULATOR->f_tan || CHILD(0).function() == CALCULATOR->f_sin || CHILD(0).function() == CALCULATOR->f_cos) && CHILD(0).size() == 1 && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { - MathFunction *f = CHILD(0).function(); - CHILD(0).setToChild(1, true); - if(f == CALCULATOR->f_sin) CHILD(1).transform(CALCULATOR->f_asin); - else if(f == CALCULATOR->f_cos) CHILD(1).transform(CALCULATOR->f_acos); - else CHILD(1).transform(CALCULATOR->f_atan); - CHILD(1).calculateFunctions(eo); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - EvaluationOptions eo3 = eo2; - eo3.sync_units = true; - CHILD(0) /= CALCULATOR->getDegUnit(); - CHILD(0).calculatesub(eo3, eo, true); - CHILD(1) += Number(180, 1); - break; - } - case ANGLE_UNIT_GRADIANS: { - EvaluationOptions eo3 = eo2; - eo3.sync_units = true; - CHILD(0) /= CALCULATOR->getGraUnit(); - CHILD(0).calculatesub(eo3, eo, true); - CHILD(1) += Number(200, 1); - break; - } - case ANGLE_UNIT_RADIANS: { - CHILD(0).calculateDivide(CALCULATOR->getRadUnit(), eo2); - CHILD(1) += CALCULATOR->v_pi; - break; - } - default: { - CHILD(1) += CALCULATOR->v_pi; - CHILD(1)[1] *= CALCULATOR->getRadUnit(); - } - } - CHILD(1)[1] *= CALCULATOR->v_n; - if(f == CALCULATOR->f_sin || f == CALCULATOR->f_cos) { - CHILD(1)[1] *= 2; - MathStructure *malt = new MathStructure(*this); - (*malt)[1][0].negate(); - if(f == CALCULATOR->f_sin) { - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {(*malt)[1].add(Number(180, 1), true); break;} - case ANGLE_UNIT_GRADIANS: {(*malt)[1].add(Number(200, 1), true); break;} - case ANGLE_UNIT_RADIANS: {(*malt)[1].add(CALCULATOR->v_pi, true); break;} - default: {(*malt)[1].add(CALCULATOR->v_pi, true); (*malt)[1].last() *= CALCULATOR->getRadUnit();} - } - } - CHILD(1).calculatesub(eo2, eo, true); - (*malt)[1].calculatesub(eo2, eo, true); - CHILDREN_UPDATED; - malt->childrenUpdated(); - isolate_x_sub(eo, eo2, x_var, morig); - malt->isolate_x_sub(eo, eo2, x_var, morig); - if(ct_comp == COMPARISON_NOT_EQUALS) add_nocopy(malt, OPERATION_LOGICAL_AND); - else add_nocopy(malt, OPERATION_LOGICAL_OR); - calculatesub(eo2, eo, false); - } else { - CHILD(1).calculatesub(eo2, eo, true); - CHILDREN_UPDATED; - isolate_x_sub(eo, eo2, x_var, morig); - } - fix_n_multiple(*this, eo2, eo, x_var); - return true; - } else if(CHILD(0).function() == CALCULATOR->f_sinh && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { - CHILD(0).setToChild(1, true); - CHILD(1).transform(CALCULATOR->f_asinh); - if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); - if(CHILD(0).representsNonComplex()) { - CHILDREN_UPDATED; - isolate_x_sub(eo, eo2, x_var, morig); - } else { - MathStructure *malt = new MathStructure(*this); - CHILD(1) *= nr_one_i; - (*malt)[1] *= nr_minus_i; - CHILD(1) += CALCULATOR->v_pi; - CHILD(1) += CALCULATOR->v_n; CHILD(1).last() *= CALCULATOR->v_pi; CHILD(1).last() *= nr_two; - (*malt)[1] += CALCULATOR->v_n; (*malt)[1].last() *= CALCULATOR->v_pi; (*malt)[1].last() *= nr_two; - CHILD(1) *= nr_one_i; - (*malt)[1] *= nr_one_i; - CHILD(1).calculatesub(eo2, eo, true); - (*malt)[1].calculatesub(eo2, eo, true); - CHILDREN_UPDATED; - malt->childrenUpdated(); - isolate_x_sub(eo, eo2, x_var, morig); - malt->isolate_x_sub(eo, eo2, x_var, morig); - if(ct_comp == COMPARISON_NOT_EQUALS) add_nocopy(malt, OPERATION_LOGICAL_AND); - else add_nocopy(malt, OPERATION_LOGICAL_OR); - calculatesub(eo2, eo, false); - fix_n_multiple(*this, eo2, eo, x_var); - } - return true; - } else if(CHILD(0).function() == CALCULATOR->f_cosh && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { - CHILD(0).setToChild(1, true); - CHILD(1).transform(CALCULATOR->f_acosh); - if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); - if(CHILD(0).representsNonComplex()) { - MathStructure *malt = new MathStructure(*this); - (*malt)[1].calculateNegate(eo2); - CHILDREN_UPDATED; - malt->childrenUpdated(); - isolate_x_sub(eo, eo2, x_var, morig); - malt->isolate_x_sub(eo, eo2, x_var, morig); - if(ct_comp == COMPARISON_NOT_EQUALS) add_nocopy(malt, OPERATION_LOGICAL_AND); - else add_nocopy(malt, OPERATION_LOGICAL_OR); - calculatesub(eo2, eo, false); - } else { - MathStructure *malt = new MathStructure(*this); - CHILD(1) *= nr_one_i; - (*malt)[1] *= nr_minus_i; - CHILD(1) += CALCULATOR->v_n; CHILD(1).last() *= CALCULATOR->v_pi; CHILD(1).last() *= nr_two; - (*malt)[1] += CALCULATOR->v_n; (*malt)[1].last() *= CALCULATOR->v_pi; (*malt)[1].last() *= nr_two; - CHILD(1) *= nr_one_i; - (*malt)[1] *= nr_one_i; - CHILD(1).calculatesub(eo2, eo, true); - (*malt)[1].calculatesub(eo2, eo, true); - CHILDREN_UPDATED; - malt->childrenUpdated(); - isolate_x_sub(eo, eo2, x_var, morig); - malt->isolate_x_sub(eo, eo2, x_var, morig); - if(ct_comp == COMPARISON_NOT_EQUALS) add_nocopy(malt, OPERATION_LOGICAL_AND); - else add_nocopy(malt, OPERATION_LOGICAL_OR); - calculatesub(eo2, eo, false); - fix_n_multiple(*this, eo2, eo, x_var); - } - return true; - } else if(CHILD(0).function() == CALCULATOR->f_tanh && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { - CHILD(0).setToChild(1, true); - CHILD(1).transform(CALCULATOR->f_atanh); - if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); - if(CHILD(0).representsNonComplex()) { - CHILDREN_UPDATED; - isolate_x_sub(eo, eo2, x_var, morig); - } else { - CHILD(1) *= nr_minus_i; - CHILD(1) += CALCULATOR->v_n; CHILD(1).last() *= CALCULATOR->v_pi; - CHILD(1) *= nr_one_i; - CHILD(1).calculatesub(eo2, eo, true); - CHILDREN_UPDATED; - isolate_x_sub(eo, eo2, x_var, morig); - fix_n_multiple(*this, eo2, eo, x_var); - } - return true; - } else if(CHILD(0).function() == CALCULATOR->f_asin && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { - MathStructure m1(CHILD(1)); - CHILD(0).setToChild(1, true); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {CHILD(1) *= CALCULATOR->getDegUnit(); break;} - case ANGLE_UNIT_GRADIANS: {CHILD(1) *= CALCULATOR->getGraUnit(); break;} - case ANGLE_UNIT_RADIANS: {CHILD(1) *= CALCULATOR->getRadUnit(); break;} - default: {} - } - CHILD(1).transform(CALCULATOR->f_sin); - if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); - CHILDREN_UPDATED; - isolate_x_sub(eo, eo2, x_var, morig); - if(eo.parse_options.angle_unit == ANGLE_UNIT_NONE) { - m1 /= CALCULATOR->getRadUnit(); - m1.convert(CALCULATOR->getRadUnit()); - } - m1.transform(CALCULATOR->f_re); - if(m1.calculateFunctions(eo)) m1.calculatesub(eo2, eo, true); - MathStructure *mreq1 = new MathStructure(m1); - MathStructure *mreq2 = new MathStructure(m1); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, Number(90, 1)); - mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, Number(-90, 1)); - break; - } - case ANGLE_UNIT_GRADIANS: { - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, Number(100, 1)); - mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, Number(-100, 1)); - break; - } - default: { - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, CALCULATOR->v_pi); - mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->v_pi); - mreq1->last() *= nr_half; - mreq2->last() *= nr_minus_half; - } - } - mreq1->isolate_x(eo2, eo); - mreq2->isolate_x(eo2, eo); - add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - if(eo.parse_options.angle_unit == ANGLE_UNIT_NONE) convert(CALCULATOR->getRadUnit()); - calculatesub(eo2, eo, false); - return true; - } else if(CHILD(0).function() == CALCULATOR->f_acos && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { - MathStructure m1(CHILD(1)), m2(CHILD(1)); - CHILD(0).setToChild(1, true); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {CHILD(1) *= CALCULATOR->getDegUnit(); break;} - case ANGLE_UNIT_GRADIANS: {CHILD(1) *= CALCULATOR->getGraUnit(); break;} - case ANGLE_UNIT_RADIANS: {CHILD(1) *= CALCULATOR->getRadUnit();} - default: {} - } - CHILD(1).transform(CALCULATOR->f_cos); - if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); - CHILDREN_UPDATED; - isolate_x_sub(eo, eo2, x_var, morig); - if(eo.parse_options.angle_unit == ANGLE_UNIT_NONE) { - m1 /= CALCULATOR->getRadUnit(); - m1.convert(CALCULATOR->getRadUnit()); - m2 /= CALCULATOR->getRadUnit(); - m2.convert(CALCULATOR->getRadUnit()); - } - m2.transform(CALCULATOR->f_im); - m1.transform(CALCULATOR->f_re); - if(m1.calculateFunctions(eo)) m1.calculatesub(eo2, eo, true); - MathStructure *mreq1 = new MathStructure(m1); - MathStructure *mreq2 = new MathStructure(m1); - MathStructure *mreq3 = new MathStructure(m1); - MathStructure *mreq4 = new MathStructure(m2); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, Number(180, 1)); - break; - } - case ANGLE_UNIT_GRADIANS: { - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, Number(200, 1)); - break; - } - default: { - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, CALCULATOR->v_pi); - } - } - mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, m_zero); - mreq3->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_EQUALS : COMPARISON_NOT_EQUALS, m_zero); - mreq4->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, m_zero); - mreq1->isolate_x(eo2, eo); - mreq2->isolate_x(eo2, eo); - mreq3->isolate_x(eo2, eo); - mreq4->isolate_x(eo2, eo); - add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - mreq3->add_nocopy(mreq4, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); - mreq3->calculatesub(eo2, eo, false); - add_nocopy(mreq3, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - if(eo.parse_options.angle_unit == ANGLE_UNIT_NONE) convert(CALCULATOR->getRadUnit()); - calculatesub(eo2, eo, false); - return true; - } else if(CHILD(0).function() == CALCULATOR->f_atan && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { - MathStructure m1(CHILD(1)); - CHILD(0).setToChild(1, true); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: {CHILD(1) *= CALCULATOR->getDegUnit(); break;} - case ANGLE_UNIT_GRADIANS: {CHILD(1) *= CALCULATOR->getGraUnit(); break;} - case ANGLE_UNIT_RADIANS: {CHILD(1) *= CALCULATOR->getRadUnit();} - default: {} - } - CHILD(1).transform(CALCULATOR->f_tan); - if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); - CHILDREN_UPDATED; - isolate_x_sub(eo, eo2, x_var, morig); - if(eo.parse_options.angle_unit == ANGLE_UNIT_NONE) { - m1 /= CALCULATOR->getRadUnit(); - m1.convert(CALCULATOR->getRadUnit()); - } - m1.transform(CALCULATOR->f_re); - if(m1.calculateFunctions(eo)) m1.calculatesub(eo2, eo, true); - MathStructure *mreq1 = new MathStructure(m1); - MathStructure *mreq2 = new MathStructure(m1); - switch(eo.parse_options.angle_unit) { - case ANGLE_UNIT_DEGREES: { - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, Number(90, 1)); - mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, Number(-90, 1)); - break; - } - case ANGLE_UNIT_GRADIANS: { - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, Number(100, 1)); - mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, Number(-100, 1)); - break; - } - default: { - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, CALCULATOR->v_pi); - mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->v_pi); - mreq1->last() *= nr_half; - mreq2->last() *= nr_minus_half; - } - } - mreq1->isolate_x(eo2, eo); - mreq2->isolate_x(eo2, eo); - add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - if(eo.parse_options.angle_unit == ANGLE_UNIT_NONE) convert(CALCULATOR->getRadUnit()); - calculatesub(eo2, eo, false); - return true; - } else if(CHILD(0).function() == CALCULATOR->f_asinh && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { - MathStructure m1(CHILD(1)); - CHILD(0).setToChild(1, true); - CHILD(1).transform(CALCULATOR->f_sinh); - if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); - CHILDREN_UPDATED; - isolate_x_sub(eo, eo2, x_var, morig); - m1.transform(CALCULATOR->f_im); - if(m1.calculateFunctions(eo)) m1.calculatesub(eo2, eo, true); - MathStructure *mreq1 = new MathStructure(m1); - MathStructure *mreq2 = new MathStructure(m1); - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, CALCULATOR->v_pi); - mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->v_pi); - mreq1->last() *= nr_half; - mreq2->last() *= nr_minus_half; - mreq1->isolate_x(eo2, eo); - mreq2->isolate_x(eo2, eo); - add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - calculatesub(eo2, eo, false); - return true; - } else if(CHILD(0).function() == CALCULATOR->f_acosh && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { - MathStructure m1(CHILD(1)); - CHILD(0).setToChild(1, true); - CHILD(1).transform(CALCULATOR->f_cosh); - if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); - CHILDREN_UPDATED; - isolate_x_sub(eo, eo2, x_var, morig); - MathStructure m1im(m1); - m1.transform(CALCULATOR->f_re); - m1im.transform(CALCULATOR->f_im); - if(m1.calculateFunctions(eo)) m1.calculatesub(eo2, eo, true); - if(m1im.calculateFunctions(eo)) m1im.calculatesub(eo2, eo, true); - MathStructure *mreq1 = new MathStructure(m1); - MathStructure *mreq2 = new MathStructure(m1im); - MathStructure *mreq3 = new MathStructure(m1im); - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, m_zero); - mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, CALCULATOR->v_pi); - mreq3->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, m_zero); - mreq3->last().negate(); - mreq1->isolate_x(eo2, eo); - mreq2->isolate_x(eo2, eo); - mreq3->isolate_x(eo2, eo); - add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - add_nocopy(mreq3, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - calculatesub(eo2, eo, false); - return true; - } else if(CHILD(0).function() == CALCULATOR->f_atanh && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { - MathStructure m1(CHILD(1)); - CHILD(0).setToChild(1, true); - CHILD(1).transform(CALCULATOR->f_tanh); - if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); - CHILDREN_UPDATED; - isolate_x_sub(eo, eo2, x_var, morig); - m1.transform(CALCULATOR->f_im); - if(m1.calculateFunctions(eo)) m1.calculatesub(eo2, eo, true); - MathStructure *mreq1 = new MathStructure(m1); - MathStructure *mreq2 = new MathStructure(m1); - mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, CALCULATOR->v_pi); - mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->v_pi); - mreq1->last() *= nr_half; - mreq2->last() *= nr_minus_half; - mreq1->isolate_x(eo2, eo); - mreq2->isolate_x(eo2, eo); - add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); - add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); - calculatesub(eo2, eo, false); - return true; - } else if(CHILD(0).function() == CALCULATOR->f_abs && CHILD(0).size() == 1) { - if(CHILD(0)[0].contains(x_var)) { - if(CHILD(1).representsComplex() || CHILD(1).representsNegative()) { - clear(true); - return true; - } else if(CHILD(1).representsReal(true)) { - if(CHILD(0)[0].representsReal(true)) { - CHILD(0).setToChild(1); - CHILD_UPDATED(0) - CHILD(0) ^= nr_two; - CHILD(0) ^= nr_half; - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } else if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && CHILD(1).representsNonNegative(true)) { - CHILD(0).setToChild(1); - CHILD_UPDATED(0) - CHILD(1) *= CALCULATOR->v_e; - CHILD(1).last() ^= CALCULATOR->v_n; - CHILD(1).last().last() *= nr_one_i; - CHILD(1).calculatesub(eo2, eo); - isolate_x_sub(eo, eo2, x_var, morig); - fix_n_multiple(*this, eo2, eo, x_var); - return true; - } - } - } - } else if(CHILD(0).function() == CALCULATOR->f_signum && CHILD(0).size() == 2) { - if(CHILD(0)[0].contains(x_var) && CHILD(0)[0].representsNonComplex(true)) { - if(CHILD(1).isZero() && CHILD(0)[1].isZero()) { - CHILD(0).setToChild(1, true, this, 1); - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } - if(CHILD(1).isNumber() && !CHILD(1).number().isInterval(false)) { - if(CHILD(1).number().isOne()) { - if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_EQUALS_GREATER) ct_comp = (CHILD(0)[1].isOne() ? COMPARISON_EQUALS_GREATER : COMPARISON_GREATER); - else if(ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_LESS) ct_comp = (CHILD(0)[1].isOne() ? COMPARISON_LESS : COMPARISON_EQUALS_LESS); - else if(ct_comp == COMPARISON_GREATER) {clear(true); return 1;} - else {set(1, 1, 0, true); return 1;} - CHILD(0).setToChild(1, true, this, 1); - CHILD(1).clear(true); - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } else if(CHILD(1).number().isMinusOne()) { - if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_EQUALS_LESS) ct_comp = (CHILD(0)[1].isMinusOne() ?COMPARISON_EQUALS_LESS : COMPARISON_LESS); - else if(ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_GREATER) ct_comp = (CHILD(0)[1].isMinusOne() ? COMPARISON_GREATER : COMPARISON_EQUALS_GREATER); - else if(ct_comp == COMPARISON_LESS) {clear(true); return 1;} - else {set(1, 1, 0, true); return 1;} - CHILD(0).setToChild(1, true, this, 1); - CHILD(1).clear(true); - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } - if(ct_comp == COMPARISON_EQUALS) { - clear(true); - return true; - } else if(ct_comp == COMPARISON_NOT_EQUALS) { - set(1, 1, 0, true); - return true; - } - if(CHILD(0)[1].isZero() || CHILD(0)[1].isOne() || CHILD(0)[1].isMinusOne()) { - if(CHILD(1).number().isPositive()) { - if(CHILD(1).number().isGreaterThan(1)) { - if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) clear(true); - else set(1, 1, 0, true); - return 1; - } - if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) ct_comp = (CHILD(0)[1].isOne() ? COMPARISON_EQUALS_GREATER : COMPARISON_GREATER); - else ct_comp = (CHILD(0)[1].isOne() ? COMPARISON_LESS : COMPARISON_EQUALS_LESS); - CHILD(0).setToChild(1, true, this, 1); - CHILD(1).clear(true); - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } else if(CHILD(1).number().isNegative()) { - if(CHILD(1).number().isLessThan(-1)) { - if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) set(1, 1, 0, true); - else clear(true); - return 1; - } - if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) ct_comp = (CHILD(0)[1].isMinusOne() ? COMPARISON_GREATER : COMPARISON_EQUALS_GREATER); - else ct_comp = (CHILD(0)[1].isMinusOne() ? COMPARISON_EQUALS_LESS : COMPARISON_LESS); - CHILD(0).setToChild(1, true, this, 1); - CHILD(1).clear(true); - isolate_x_sub(eo, eo2, x_var, morig); - return true; - } - } - } - } - } - break; - } - default: {} - } - return false; -} - -bool contains_unsolved_equals(const MathStructure &mstruct, const MathStructure &x_var) { - if(mstruct.isComparison()) { - return mstruct.comparisonType() == COMPARISON_EQUALS && mstruct[0] != x_var && mstruct[1] != x_var && mstruct.contains(x_var); - } - for(size_t i = 0; i < mstruct.size(); i++) { - if(contains_unsolved_equals(mstruct[i], x_var)) return true; - } - return false; -} - -bool sync_sine(MathStructure &mstruct, const EvaluationOptions &eo, const MathStructure &x_var, bool use_cos, bool b_hyp = false, const MathStructure &mstruct_parent = m_undefined) { - if(!mstruct_parent.isUndefined() && mstruct.isFunction() && mstruct.function() == (b_hyp ? CALCULATOR->f_sinh : CALCULATOR->f_sin) && mstruct[0].contains(x_var)) { - MathStructure m_half(mstruct); - m_half[0].calculateDivide(nr_two, eo); - bool b = mstruct_parent.contains(m_half); - if(!b) { - m_half.setFunction(b_hyp ? CALCULATOR->f_cosh : CALCULATOR->f_cos); - b = mstruct_parent.contains(m_half); - m_half.setFunction(b_hyp ? CALCULATOR->f_sinh : CALCULATOR->f_sin); - } - if(b) { - mstruct = m_half; - MathStructure *m_cos = new MathStructure(mstruct); - (*m_cos).setFunction(b_hyp ? CALCULATOR->f_cosh : CALCULATOR->f_cos); - mstruct.multiply_nocopy(m_cos); - mstruct.multiply(nr_two); - return true; - } - } else if(mstruct.isPower() && mstruct[0].isFunction() && mstruct[1].isNumber() && mstruct[1].number().isEven() && mstruct[0].size() == 1) { - if(!mstruct_parent.isUndefined() && mstruct[0].function() == (b_hyp ? CALCULATOR->f_sinh : CALCULATOR->f_sin) && mstruct[0][0].contains(x_var)) { - MathStructure m_half(mstruct[0]); - m_half[0].calculateDivide(nr_two, eo); - bool b = mstruct_parent.contains(m_half); - if(!b) { - m_half.setFunction(b_hyp ? CALCULATOR->f_cosh : CALCULATOR->f_cos); - b = mstruct_parent.contains(m_half); - m_half.setFunction(b_hyp ? CALCULATOR->f_sinh : CALCULATOR->f_sin); - } - if(b) { - MathStructure *mmul = new MathStructure(2, 1, 0); - mmul->raise(mstruct[1]); - mstruct[0] = m_half; - MathStructure *m_cos = new MathStructure(mstruct); - (*m_cos)[0].setFunction(b_hyp ? CALCULATOR->f_cosh : CALCULATOR->f_cos); - mstruct.multiply_nocopy(m_cos); - mstruct.multiply_nocopy(mmul); - sync_sine(mstruct, eo, x_var, use_cos, b_hyp, mstruct_parent); - return true; +bool MathStructure::replace(const MathStructure &mfrom, const MathStructure &mto, bool once_only, bool exclude_function_arguments) { + if(b_protected) b_protected = false; + if(equals(mfrom, true, true)) { + set(mto); + return true; + } + if(mfrom.size() > 0 && mfrom.type() == m_type && SIZE > mfrom.size() && (mfrom.isAddition() || mfrom.isMultiplication() || mfrom.isLogicalAnd() || mfrom.isLogicalOr())) { + bool b = true; + size_t i2 = 0; + for(size_t i = 0; i < mfrom.size(); i++) { + b = false; + for(; i2 < SIZE; i2++) { + if(CHILD(i2).equals(mfrom[i], true, true)) {b = true; break;} } + if(!b) break; } - if(mstruct[0].function() == (b_hyp ? CALCULATOR->f_tanh : CALCULATOR->f_tan) && mstruct[0][0].contains(x_var)) { - mstruct[0].setFunction(CALCULATOR->f_sin); - MathStructure *m_cos = new MathStructure(mstruct); - (*m_cos)[0].setFunction(CALCULATOR->f_cos); - (*m_cos)[1].number().negate(); - mstruct.multiply_nocopy(m_cos); - sync_sine(mstruct, eo, x_var, use_cos, b_hyp, mstruct_parent); - return true; - } - if(mstruct[0].function() == (use_cos ? (b_hyp ? CALCULATOR->f_sinh : CALCULATOR->f_sin) : (b_hyp ? CALCULATOR->f_cosh : CALCULATOR->f_cos)) && mstruct[0][0].contains(x_var)) { - mstruct[0].setFunction(use_cos ? (b_hyp ? CALCULATOR->f_cosh : CALCULATOR->f_cos) : (b_hyp ? CALCULATOR->f_sinh : CALCULATOR->f_sin)); - Number nr_pow = mstruct[1].number(); - nr_pow /= 2; - mstruct[1].set(nr_two, true); - if(b_hyp) { - if(use_cos) mstruct += m_minus_one; - else mstruct += m_one; - } else { - mstruct.negate(); - mstruct += m_one; - } - if(!nr_pow.isOne()) { - mstruct ^= nr_pow; + if(b) { + i2 = 0; + for(size_t i = 0; i < mfrom.size(); i++) { + for(; i2 < SIZE; i2++) { + if(CHILD(i2).equals(mfrom[i], true, true)) {ERASE(i2); break;} + } } + if(SIZE == 1) setToChild(1); + else if(SIZE == 0) clear(); + else if(!once_only) replace(mfrom, mto, once_only, exclude_function_arguments); + if(mfrom.isAddition()) add(mto); + else if(mfrom.isMultiplication()) multiply(mto); + else if(mfrom.isLogicalAnd()) transform(STRUCT_LOGICAL_AND, mto); + else if(mfrom.isLogicalOr()) transform(STRUCT_LOGICAL_OR, mto); return true; } } + if(exclude_function_arguments && m_type == STRUCT_FUNCTION) return false; bool b = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(CALCULATOR->aborted()) return false; - if(sync_sine(mstruct[i], eo, x_var, use_cos, b_hyp, mstruct_parent.isUndefined() ? mstruct : mstruct_parent)) b = true; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).replace(mfrom, mto, once_only, exclude_function_arguments)) { + b = true; + CHILD_UPDATED(i); + if(once_only) return true; + } } return b; } -void sync_find_cos_sin(const MathStructure &mstruct, const MathStructure &x_var, bool &b_sin, bool &b_cos, bool b_hyp = false) { - if(mstruct.isFunction() && mstruct.size() == 1) { - if(!b_sin && mstruct.function() == (b_hyp ? CALCULATOR->f_sinh : CALCULATOR->f_sin) && mstruct[0].contains(x_var)) { - b_sin = true; - } else if(!b_cos && mstruct.function() == (b_hyp ? CALCULATOR->f_cosh : CALCULATOR->f_cos) && mstruct[0].contains(x_var)) { - b_cos = true; - } - if(b_sin && b_cos) return; - } - for(size_t i = 0; i < mstruct.size(); i++) { - sync_find_cos_sin(mstruct[i], x_var, b_sin, b_cos, b_hyp); - if(b_sin && b_cos) return; - } -} -bool sync_trigonometric_functions(MathStructure &mstruct, const EvaluationOptions &eo, const MathStructure &x_var, bool use_cos = false) { - bool b_ret = false; - if(sync_sine(mstruct, eo, x_var, use_cos)) b_ret = true; - if(sync_sine(mstruct, eo, x_var, use_cos, true)) b_ret = true; - return b_ret; +bool MathStructure::replace(Variable *v, const MathStructure &mto) { + if(b_protected) b_protected = false; + if(m_type == STRUCT_VARIABLE && o_variable == v) { + set(mto); + return true; + } + bool b = false; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).replace(v, mto)) { + b = true; + CHILD_UPDATED(i); + } + } + return b; } - -bool simplify_functions(MathStructure &mstruct, const EvaluationOptions &eo, const EvaluationOptions &feo, const MathStructure &x_var) { - if(!mstruct.isAddition()) { - bool b = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(CALCULATOR->aborted()) break; - if(simplify_functions(mstruct[i], eo, feo, x_var)) {b = true; mstruct.childUpdated(i + 1);} - } - return b; - } - if(mstruct.containsFunction(CALCULATOR->f_sin, false, false, false) > 0 && mstruct.containsFunction(CALCULATOR->f_cos, false, false, false)) { - if(x_var.isUndefined()) { - // a*(sin(x)+cos(x))=a*sqrt(2)*sin(x+pi/4) - bool b_ret = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isFunction() && mstruct[i].size() == 1 && mstruct[i].function() == CALCULATOR->f_sin) { - for(size_t i2 = 0; i2 < mstruct.size(); i2++) { - if(i != i2 && mstruct[i2].isFunction() && mstruct[i2].size() == 1 && mstruct[i2].function() == CALCULATOR->f_cos && mstruct[i][0] == mstruct[i2][0]) { - MathStructure madd(CALCULATOR->v_pi); - madd /= Number(4, 1); - madd *= CALCULATOR->getRadUnit(); - madd.calculatesub(eo, feo, true); - mstruct[i][0].calculateAdd(madd, eo); - mstruct[i].childUpdated(1); - mstruct.childUpdated(i + 1); - MathStructure mmul(nr_two); - mmul.calculateRaise(nr_half, eo); - mstruct[i].calculateMultiply(mmul, eo); - mstruct.delChild(i2 + 1); - b_ret = true; - break; - } - } - } else if(mstruct[i].isMultiplication()) { - for(size_t i3 = 0; i3 < mstruct[i].size(); i3++) { - if(mstruct[i][i3].isFunction() && mstruct[i][i3].size() == 1 && mstruct[i][i3].function() == CALCULATOR->f_sin) { - mstruct[i][i3].setFunction(CALCULATOR->f_cos); - bool b = false; - for(size_t i2 = 0; i2 < mstruct.size(); i2++) { - if(i != i2 && mstruct[i2] == mstruct[i]) { - MathStructure madd(CALCULATOR->v_pi); - madd /= Number(4, 1); - madd *= CALCULATOR->getRadUnit(); - madd.calculatesub(eo, feo, true); - mstruct[i][i3].setFunction(CALCULATOR->f_sin); - mstruct[i][i3][0].calculateAdd(madd, eo); - mstruct[i][i3].childUpdated(1); - mstruct[i].childUpdated(i3 + 1); - mstruct.childUpdated(i + 1); - MathStructure mmul(nr_two); - mmul.calculateRaise(nr_half, eo); - mstruct[i].calculateMultiply(mmul, eo); - mstruct.delChild(i2 + 1); - b = true; - break; - } - } - if(b) { - b_ret = true; - break; - } else { - mstruct[i][i3].setFunction(CALCULATOR->f_sin); - } - } - } - } +bool MathStructure::calculateReplace(const MathStructure &mfrom, const MathStructure &mto, const EvaluationOptions &eo, bool exclude_function_arguments) { + if(equals(mfrom, true, true)) { + set(mto); + return true; + } + if(mfrom.size() > 0 && mfrom.type() == m_type && SIZE > mfrom.size() && (mfrom.isAddition() || mfrom.isMultiplication() || mfrom.isLogicalAnd() || mfrom.isLogicalOr())) { + bool b = true; + size_t i2 = 0; + for(size_t i = 0; i < mfrom.size(); i++) { + b = false; + for(; i2 < SIZE; i2++) { + if(CHILD(i2).equals(mfrom[i], true, true)) {b = true; break;} } - if(mstruct.size() == 1) mstruct.setToChild(1, true); - return b_ret; - } else { - // a*sin(x)+b*cos(x)=a*sqrt((b/a)^2+1)*sin(x+atan(b/a)) - MathStructure *marg = NULL; - bool b_cos = false; - for(size_t i = 0; i < mstruct.size(); i++) { - if(mstruct[i].isFunction() && mstruct[i].size() == 1 && (mstruct[i].function() == CALCULATOR->f_sin || mstruct[i].function() == CALCULATOR->f_cos) && mstruct[i][0].contains(x_var)) { - marg = &mstruct[i][0]; - b_cos = mstruct[i].function() == CALCULATOR->f_cos; - } else if(mstruct[i].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { - if(!marg && mstruct[i][i2].isFunction() && mstruct[i][i2].size() == 1 && (mstruct[i][i2].function() == CALCULATOR->f_sin || mstruct[i][i2].function() == CALCULATOR->f_cos) && mstruct[i][i2][0].contains(x_var)) { - marg = &mstruct[i][i2][0]; - b_cos = mstruct[i][i2].function() == CALCULATOR->f_cos; - } else if(mstruct[i][i2].contains(x_var)) { - marg = NULL; - break; - } - } - } - if(marg) { - bool b = false; - for(size_t i3 = i + 1; i3 < mstruct.size(); i3++) { - if(mstruct[i3].isFunction() && mstruct[i3].size() == 1 && mstruct[i3].function() == (b_cos ? CALCULATOR->f_sin : CALCULATOR->f_cos) && mstruct[i3][0] == *marg) { - b = true; - } else if(mstruct[i3].isMultiplication()) { - bool b2 = false; - for(size_t i2 = 0; i2 < mstruct[i3].size(); i2++) { - if(!b2 && mstruct[i3][i2].isFunction() && mstruct[i3][i2].size() == 1 && (mstruct[i3][i2].function() == CALCULATOR->f_sin || mstruct[i3][i2].function() == CALCULATOR->f_cos) && mstruct[i3][i2][0] == *marg) { - if((mstruct[i3][i2].function() == CALCULATOR->f_sin) == b_cos) b = true; - b2 = true; - } else if(mstruct[i3][i2].contains(x_var)) { - marg = NULL; - break; - } - } - if(!marg) break; - } - } - if(!b) marg = NULL; - } - if(marg) { - marg->ref(); - MathStructure m_a, m_b; - for(size_t i3 = i; i3 < mstruct.size();) { - bool b = false; - if(mstruct[i3].isFunction() && mstruct[i3].size() == 1 && mstruct[i3].function() == CALCULATOR->f_sin && mstruct[i3][0] == *marg) { - if(m_a.isZero()) m_a = m_one; - else m_a.add(m_one, true); - b = true; - } else if(mstruct[i3].isFunction() && mstruct[i3].size() == 1 && mstruct[i3].function() == CALCULATOR->f_cos && mstruct[i3][0] == *marg) { - if(m_b.isZero()) m_a = m_one; - else m_b.add(m_one, true); - b = true; - } else if(mstruct[i3].isMultiplication()) { - for(size_t i2 = 0; i2 < mstruct[i3].size(); i2++) { - if(mstruct[i3][i2].isFunction() && mstruct[i3][i2].size() == 1 && mstruct[i3][i2].function() == CALCULATOR->f_sin && mstruct[i3][i2][0] == *marg) { - mstruct[i3].delChild(i2 + 1, true); - if(m_a.isZero()) m_a.set_nocopy(mstruct[i3]); - else {mstruct[i3].ref(); m_a.add_nocopy(&mstruct[i3], true);} - b = true; - break; - } else if(mstruct[i3][i2].isFunction() && mstruct[i3][i2].size() == 1 && mstruct[i3][i2].function() == CALCULATOR->f_cos && mstruct[i3][i2][0] == *marg) { - mstruct[i3].delChild(i2 + 1, true); - if(m_b.isZero()) m_b.set_nocopy(mstruct[i3]); - else {mstruct[i3].ref(); m_b.add_nocopy(&mstruct[i3], true);} - b = true; - break; - } - } - } - if(b) { - mstruct.delChild(i3 + 1); - } else { - i3++; - } - } - MathStructure *m_sin = new MathStructure(CALCULATOR->f_sin, NULL); - m_sin->addChild_nocopy(marg); - m_b.calculateDivide(m_a, eo); - MathStructure *m_atan = new MathStructure(CALCULATOR->f_atan, &m_b, NULL); - if(m_atan->calculateFunctions(feo)) m_atan->calculatesub(eo, feo, true); - if(eo.parse_options.angle_unit != ANGLE_UNIT_NONE) m_atan->calculateMultiply(CALCULATOR->getRadUnit(), eo); - (*m_sin)[0].add_nocopy(m_atan); - (*m_sin)[0].calculateAddLast(eo); - m_sin->childUpdated(1); - m_b.calculateRaise(nr_two, eo); - m_b.calculateAdd(m_one, eo); - m_b.calculateRaise(nr_half, eo); - m_sin->calculateMultiply(m_b, eo); - m_sin->calculateMultiply(m_a, eo); - if(mstruct.size() == 0) {mstruct.set_nocopy(*m_sin); m_sin->unref();} - else mstruct.insertChild_nocopy(m_sin, i + 1); - simplify_functions(mstruct, eo, feo, x_var); - return true; + if(!b) break; + } + if(b) { + i2 = 0; + for(size_t i = 0; i < mfrom.size(); i++) { + for(; i2 < SIZE; i2++) { + if(CHILD(i2).equals(mfrom[i], true, true)) {ERASE(i2); break;} } } + if(SIZE == 1) setToChild(1); + else if(SIZE == 0) clear(); + else calculateReplace(mfrom, mto, eo, exclude_function_arguments); + if(mfrom.isAddition()) add(mto); + else if(mfrom.isMultiplication()) multiply(mto); + else if(mfrom.isLogicalAnd()) transform(STRUCT_LOGICAL_AND, mto); + else if(mfrom.isLogicalOr()) transform(STRUCT_LOGICAL_OR, mto); + calculatesub(eo, eo, false); + return true; } } - return false; -} - -bool MathStructure::isolate_x(const EvaluationOptions &eo, const MathStructure &x_varp, bool check_result) { - return isolate_x(eo, eo, x_varp, check_result); -} -bool MathStructure::isolate_x(const EvaluationOptions &eo, const EvaluationOptions &feo, const MathStructure &x_varp, bool check_result) { - if(isProtected()) return false; - if(!isComparison()) { - bool b = false; - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isolate_x(eo, feo, x_varp, check_result)) { - CHILD_UPDATED(i); - b = true; - } + if(exclude_function_arguments && m_type == STRUCT_FUNCTION) return false; + bool b = false; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).calculateReplace(mfrom, mto, eo, exclude_function_arguments)) { + b = true; + CHILD_UPDATED(i); } - return b; } - MathStructure x_var(x_varp); - if(x_var.isUndefined()) { - const MathStructure *x_var2; - if(eo.isolate_var && contains(*eo.isolate_var)) x_var2 = eo.isolate_var; - else x_var2 = &find_x_var(); - if(x_var2->isUndefined()) return false; - x_var = *x_var2; + if(b) { + calculatesub(eo, eo, false); } + return b; +} - if(CHILD(0) == x_var && !CHILD(1).contains(x_var)) return true; - if(!CHILD(1).isZero()) { - CHILD(0).calculateSubtract(CHILD(1), eo); - CHILD(1).clear(true); - CHILDREN_UPDATED +bool MathStructure::replace(const MathStructure &mfrom1, const MathStructure &mto1, const MathStructure &mfrom2, const MathStructure &mto2) { + if(equals(mfrom1, true, true)) { + set(mto1); + return true; } - - if(eo.expand > 0) simplify_functions(*this, eo, feo, x_var); - - EvaluationOptions eo2 = eo; - eo2.calculate_functions = false; - eo2.test_comparisons = false; - eo2.isolate_x = false; - - if(check_result && CHILD(1).isZero() && CHILD(0).isAddition()) { - bool found_1x = false; - for(size_t i = 0; i < CHILD(0).size(); i++) { - if(CHILD(0)[i] == x_var) { - found_1x = true; - } else if(CHILD(0)[i].contains(x_var)) { - found_1x = false; - break; - } - } - if(found_1x) check_result = false; + if(equals(mfrom2, true, true)) { + set(mto2); + return true; } - - MathStructure msave(*this); - - bool b = isolate_x_sub(feo, eo2, x_var); - - if(CALCULATOR->aborted()) return !check_result && b; - - if(eo.expand > 0 && contains_unsolved_equals(*this, x_var)) { - MathStructure mtest(msave); - EvaluationOptions eo3 = eo; - eo3.transform_trigonometric_functions = false; - eo2.transform_trigonometric_functions = false; - bool do_cos = true; - if(sync_trigonometric_functions(mtest, eo3, x_var, false)) { - mtest.calculatesub(eo3, feo); - if(CALCULATOR->aborted()) return !check_result && b; - if(eo.do_polynomial_division) do_simplification(mtest, eo3, true, eo.structuring == STRUCTURING_NONE || eo.structuring == STRUCTURING_FACTORIZE, false, true, true); - if(CALCULATOR->aborted()) return !check_result && b; - if(mtest.isComparison() && mtest.isolate_x_sub(feo, eo2, x_var) && !contains_unsolved_equals(mtest, x_var)) { - set(mtest); - b = true; - do_cos = false; - } else if(CALCULATOR->aborted()) { - return !check_result && b; - } - } - if(do_cos) { - mtest = msave; - if(sync_trigonometric_functions(mtest, eo3, x_var, true)) { - mtest.calculatesub(eo3, feo); - if(CALCULATOR->aborted()) return !check_result && b; - if(eo.do_polynomial_division) do_simplification(mtest, eo3, true, eo.structuring == STRUCTURING_NONE || eo.structuring == STRUCTURING_FACTORIZE, false, true, true); - if(CALCULATOR->aborted()) return !check_result && b; - if(mtest.isComparison() && mtest.isolate_x_sub(feo, eo2, x_var) && !contains_unsolved_equals(mtest, x_var)) { - b = true; - set(mtest); - } - } + bool b = false; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).replace(mfrom1, mto1, mfrom2, mto2)) { + b = true; + CHILD_UPDATED(i); } } - fix_n_multiple(*this, eo, feo, x_var); - if(check_result && b) { - b = test_comparisons(msave, *this, x_var, eo) >= 0; - } - return b; - } - -bool MathStructure::isRationalPolynomial(bool allow_non_rational_coefficient, bool allow_interval_coefficient) const { - switch(m_type) { - case STRUCT_NUMBER: { - if(allow_interval_coefficient) return o_number.isReal() && o_number.isNonZero(); - if(allow_non_rational_coefficient) return o_number.isReal() && !o_number.isInterval() && o_number.isNonZero(); - return o_number.isRational() && !o_number.isZero(); - } - case STRUCT_MULTIPLICATION: { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isAddition() || CHILD(i).isMultiplication() || !CHILD(i).isRationalPolynomial(allow_non_rational_coefficient, allow_interval_coefficient)) { - return false; - } - } - return true; - } - case STRUCT_ADDITION: { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isAddition() || !CHILD(i).isRationalPolynomial(allow_non_rational_coefficient, allow_interval_coefficient)) { - return false; +bool MathStructure::removeType(StructureType mtype) { + if(m_type == mtype || (m_type == STRUCT_POWER && CHILD(0).type() == mtype)) { + set(1); + return true; + } + bool b = false; + if(m_type == STRUCT_MULTIPLICATION) { + for(long int i = 0; i < (long int) SIZE; i++) { + if(CHILD(i).removeType(mtype)) { + if(CHILD(i).isOne()) { + ERASE(i); + i--; + } else { + CHILD_UPDATED(i); } + b = true; } - return true; } - case STRUCT_POWER: { - return CHILD(1).isInteger() && CHILD(1).number().isNonNegative() && !CHILD(1).number().isOne() && CHILD(1).number() < 1000 && !CHILD(0).isNumber() && !CHILD(0).isMultiplication() && !CHILD(0).isAddition() && !CHILD(0).isPower() && CHILD(0).isRationalPolynomial(allow_non_rational_coefficient, allow_interval_coefficient); + if(SIZE == 0) { + set(1); + } else if(SIZE == 1) { + setToChild(1, true); } - case STRUCT_FUNCTION: { - if(o_function == CALCULATOR->f_uncertainty || o_function == CALCULATOR->f_interval || containsInterval() || containsInfinity()) return false; + } else { + if(m_type == STRUCT_FUNCTION) { + if(mtype != STRUCT_UNIT || (o_function->id() != FUNCTION_ID_SQRT && o_function->id() != FUNCTION_ID_ROOT && o_function->id() != FUNCTION_ID_CBRT)) return b; } - case STRUCT_UNIT: {} - case STRUCT_VARIABLE: {} - case STRUCT_SYMBOLIC: { - return representsNonMatrix() && !representsUndefined(true, true); + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).removeType(mtype)) { + b = true; + CHILD_UPDATED(i); + } } - default: {} } - return false; + return b; } -const Number &MathStructure::overallCoefficient() const { - switch(m_type) { - case STRUCT_NUMBER: { - return o_number; - } - case STRUCT_MULTIPLICATION: { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isNumber()) { - return CHILD(i).number(); - } + +const MathStructure &MathStructure::find_x_var() const { + if(isSymbolic()) { + return *this; + } else if(isVariable()) { + if(o_variable->isKnown()) return m_undefined; + return *this; + } + const MathStructure *mstruct; + const MathStructure *x_mstruct = &m_undefined; + for(size_t i = 0; i < SIZE; i++) { + mstruct = &CHILD(i).find_x_var(); + if(mstruct->isVariable()) { + if(!((UnknownVariable*) mstruct->variable())->interval().isUndefined()) { + if(x_mstruct->isUndefined()) x_mstruct = mstruct; + } else if(mstruct->variable() == CALCULATOR->getVariableById(VARIABLE_ID_X)) { + return *mstruct; + } else if(!x_mstruct->isVariable()) { + x_mstruct = mstruct; + } else if(mstruct->variable() == CALCULATOR->getVariableById(VARIABLE_ID_Y)) { + x_mstruct = mstruct; + } else if(mstruct->variable() == CALCULATOR->getVariableById(VARIABLE_ID_Z) && x_mstruct->variable() != CALCULATOR->getVariableById(VARIABLE_ID_Y)) { + x_mstruct = mstruct; } - return nr_one; - } - case STRUCT_ADDITION: { - for(size_t i = 0; i < SIZE; i++) { - if(CHILD(i).isNumber()) { - return CHILD(i).number(); - } + } else if(mstruct->isSymbolic()) { + if(!x_mstruct->isVariable() && (!x_mstruct->isSymbolic() || x_mstruct->symbol() > mstruct->symbol())) { + x_mstruct = mstruct; } - return nr_zero; } - case STRUCT_POWER: { - return nr_zero; - } - default: {} } - return nr_zero; + return *x_mstruct; } bool MathStructure::inParentheses() const {return b_parentheses;} void MathStructure::setInParentheses(bool b) {b_parentheses = b;} +bool flattenMultiplication(MathStructure &mstruct) { + bool retval = false; + for(size_t i = 0; i < mstruct.size();) { + if(mstruct[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { + mstruct[i][i2].ref(); + mstruct.insertChild_nocopy(&mstruct[i][i2], i + i2 + 2); + } + mstruct.delChild(i + 1); + retval = true; + } else { + i++; + } + } + return retval; +} diff -Nru libqalculate-3.6.0/libqalculate/MathStructure-convert.cc libqalculate-3.7.0/libqalculate/MathStructure-convert.cc --- libqalculate-3.6.0/libqalculate/MathStructure-convert.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure-convert.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,1016 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "MathStructure.h" +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "Number.h" +#include "Function.h" +#include "Variable.h" +#include "Unit.h" +#include "Prefix.h" +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +void gatherInformation(const MathStructure &mstruct, vector &base_units, vector &alias_units, bool check_variables = false) { + switch(mstruct.type()) { + case STRUCT_UNIT: { + switch(mstruct.unit()->subtype()) { + case SUBTYPE_BASE_UNIT: { + for(size_t i = 0; i < base_units.size(); i++) { + if(base_units[i] == mstruct.unit()) { + return; + } + } + base_units.push_back(mstruct.unit()); + break; + } + case SUBTYPE_ALIAS_UNIT: { + for(size_t i = 0; i < alias_units.size(); i++) { + if(alias_units[i] == mstruct.unit()) { + return; + } + } + alias_units.push_back((AliasUnit*) (mstruct.unit())); + break; + } + case SUBTYPE_COMPOSITE_UNIT: { + gatherInformation(((CompositeUnit*) (mstruct.unit()))->generateMathStructure(), base_units, alias_units, check_variables); + break; + } + } + break; + } + case STRUCT_VARIABLE: { + if(check_variables && mstruct.variable()->isKnown()) gatherInformation(((KnownVariable*) mstruct.variable())->get(), base_units, alias_units, check_variables); + break; + } + case STRUCT_FUNCTION: { + if(mstruct.function()->id() == FUNCTION_ID_STRIP_UNITS) break; + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct.function()->getArgumentDefinition(i + 1) || mstruct.function()->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) { + gatherInformation(mstruct[i], base_units, alias_units, check_variables); + } + } + break; + } + default: { + for(size_t i = 0; i < mstruct.size(); i++) { + gatherInformation(mstruct[i], base_units, alias_units, check_variables); + } + break; + } + } + +} + +int MathStructure::isUnitCompatible(const MathStructure &mstruct) const { + if(!isMultiplication() && mstruct.isMultiplication()) return mstruct.isUnitCompatible(*this); + int b1 = mstruct.containsRepresentativeOfType(STRUCT_UNIT, true, true); + int b2 = containsRepresentativeOfType(STRUCT_UNIT, true, true); + if(b1 < 0 || b2 < 0) return -1; + if(b1 != b2) return false; + if(!b1) return true; + if(isMultiplication()) { + size_t unit_count1 = 0, unit_count2 = 0; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isUnit_exp()) unit_count1++; + else if(CHILD(i).containsRepresentativeOfType(STRUCT_UNIT, true, true) != 0) return -1; + } + if(mstruct.isMultiplication()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isUnit_exp()) unit_count2++; + else if(mstruct[i].containsRepresentativeOfType(STRUCT_UNIT, true, true) != 0) return -1; + } + } else if(mstruct.isUnit_exp()) { + if(unit_count1 > 1) return false; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isUnit_exp()) return CHILD(1) == mstruct; + } + } else { + return -1; + } + if(unit_count1 != unit_count2) return false; + size_t i2 = 0; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isUnit_exp()) { + for(; i2 < mstruct.size(); i2++) { + if(mstruct[i2].isUnit_exp()) { + if(CHILD(i) != mstruct[i2]) return false; + i2++; + break; + } + } + } + } + } else if(isUnit_exp()) { + if(mstruct.isUnit_exp()) return equals(mstruct); + } + return -1; +} + +bool MathStructure::syncUnits(bool sync_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo) { + if(SIZE == 0) return false; + vector base_units; + vector alias_units; + vector composite_units; + gatherInformation(*this, base_units, alias_units); + if(alias_units.empty() || base_units.size() + alias_units.size() == 1) return false; + CompositeUnit *cu; + bool b = false, do_erase = false; + for(size_t i = 0; i < alias_units.size(); ) { + do_erase = false; + if(alias_units[i]->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { + b = false; + cu = (CompositeUnit*) alias_units[i]->baseUnit(); + for(size_t i2 = 0; i2 < base_units.size(); i2++) { + if(cu->containsRelativeTo(base_units[i2])) { + for(size_t i3 = 0; i3 < composite_units.size(); i3++) { + if(composite_units[i3] == cu) { + b = true; + break; + } + } + if(!b) composite_units.push_back(cu); + do_erase = true; + break; + } + } + for(size_t i2 = 0; !do_erase && i2 < alias_units.size(); i2++) { + if(i != i2 && alias_units[i2]->baseUnit() != cu && cu->containsRelativeTo(alias_units[i2])) { + for(size_t i3 = 0; i3 < composite_units.size(); i3++) { + if(composite_units[i3] == cu) { + b = true; + break; + } + } + if(!b) composite_units.push_back(cu); + do_erase = true; + break; + } + } + } + if(do_erase) { + alias_units.erase(alias_units.begin() + i); + for(int i2 = 1; i2 <= (int) cu->countUnits(); i2++) { + b = false; + Unit *cub = cu->get(i2); + switch(cub->subtype()) { + case SUBTYPE_BASE_UNIT: { + for(size_t i3 = 0; i3 < base_units.size(); i3++) { + if(base_units[i3] == cub) { + b = true; + break; + } + } + if(!b) base_units.push_back(cub); + break; + } + case SUBTYPE_ALIAS_UNIT: { + for(size_t i3 = 0; i3 < alias_units.size(); i3++) { + if(alias_units[i3] == cub) { + b = true; + break; + } + } + if(!b) alias_units.push_back((AliasUnit*) cub); + break; + } + case SUBTYPE_COMPOSITE_UNIT: { + gatherInformation(((CompositeUnit*) cub)->generateMathStructure(), base_units, alias_units); + break; + } + } + } + i = 0; + } else { + i++; + } + } + + for(size_t i = 0; i < alias_units.size();) { + do_erase = false; + for(size_t i2 = 0; i2 < alias_units.size(); i2++) { + if(i != i2 && alias_units[i]->baseUnit() == alias_units[i2]->baseUnit()) { + if(alias_units[i2]->isParentOf(alias_units[i])) { + do_erase = true; + break; + } else if(!alias_units[i]->isParentOf(alias_units[i2])) { + b = false; + for(size_t i3 = 0; i3 < base_units.size(); i3++) { + if(base_units[i3] == alias_units[i2]->firstBaseUnit()) { + b = true; + break; + } + } + if(!b) base_units.push_back((Unit*) alias_units[i]->baseUnit()); + do_erase = true; + break; + } + } + } + if(do_erase) { + alias_units.erase(alias_units.begin() + i); + i = 0; + } else { + i++; + } + } + for(size_t i = 0; i < alias_units.size();) { + do_erase = false; + if(alias_units[i]->baseUnit()->subtype() == SUBTYPE_BASE_UNIT) { + for(size_t i2 = 0; i2 < base_units.size(); i2++) { + if(alias_units[i]->baseUnit() == base_units[i2]) { + do_erase = true; + break; + } + } + } + if(do_erase) { + alias_units.erase(alias_units.begin() + i); + i = 0; + } else { + i++; + } + } + b = false; + bool fcr = false; + for(size_t i = 0; i < composite_units.size(); i++) { + if(convert(composite_units[i], sync_nonlinear_relations, (found_nonlinear_relations || sync_nonlinear_relations) ? &fcr : NULL, calculate_new_functions, feo)) b = true; + } + if(dissolveAllCompositeUnits()) b = true; + for(size_t i = 0; i < base_units.size(); i++) { + if(convert(base_units[i], sync_nonlinear_relations, (found_nonlinear_relations || sync_nonlinear_relations) ? &fcr : NULL, calculate_new_functions, feo)) b = true; + } + for(size_t i = 0; i < alias_units.size(); i++) { + if(convert(alias_units[i], sync_nonlinear_relations, (found_nonlinear_relations || sync_nonlinear_relations) ? &fcr : NULL, calculate_new_functions, feo)) b = true; + } + if(b && sync_nonlinear_relations && fcr) CALCULATOR->error(false, _("Calculations involving conversion of units without proportional linear relationship (e.g. with multiple temperature units), might give unexpected results and is not recommended."), NULL); + if(fcr && found_nonlinear_relations) *found_nonlinear_relations = fcr; + return b; +} + +bool has_approximate_relation_to_base(Unit *u, bool do_intervals) { + if(u->subtype() == SUBTYPE_ALIAS_UNIT) { + if(((AliasUnit*) u)->isApproximate()) return do_intervals; + if(((AliasUnit*) u)->expression().find_first_not_of(NUMBER_ELEMENTS EXPS) != string::npos && !((AliasUnit*) u)->hasNonlinearExpression()) return true; + return has_approximate_relation_to_base(((AliasUnit*) u)->firstBaseUnit()); + } else if(u->subtype() == SUBTYPE_COMPOSITE_UNIT) { + for(size_t i = 1; i <= ((CompositeUnit*) u)->countUnits(); i++) { + if(has_approximate_relation_to_base(((CompositeUnit*) u)->get(i))) return true; + } + } + return false; +} + +bool MathStructure::testDissolveCompositeUnit(Unit *u) { + if(m_type == STRUCT_UNIT) { + if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) { + if(((CompositeUnit*) o_unit)->containsRelativeTo(u)) { + set(((CompositeUnit*) o_unit)->generateMathStructure()); + return true; + } + } else if(o_unit->subtype() == SUBTYPE_ALIAS_UNIT && o_unit->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { + if(((CompositeUnit*) (o_unit->baseUnit()))->containsRelativeTo(u)) { + if(convert(o_unit->baseUnit())) { + convert(u); + return true; + } + } + } + } + return false; +} +bool test_dissolve_cu(MathStructure &mstruct, Unit *u, bool convert_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo, Prefix *new_prefix = NULL) { + if(mstruct.isUnit()) { + if(mstruct.unit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { + if(((CompositeUnit*) mstruct.unit())->containsRelativeTo(u)) { + mstruct.set(((CompositeUnit*) mstruct.unit())->generateMathStructure()); + return true; + } + } else if(mstruct.unit()->subtype() == SUBTYPE_ALIAS_UNIT && mstruct.unit()->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { + if(((CompositeUnit*) (mstruct.unit()->baseUnit()))->containsRelativeTo(u)) { + if(mstruct.convert(mstruct.unit()->baseUnit(), convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo)) { + mstruct.convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); + return true; + } + } + } + } + return false; +} +bool MathStructure::testCompositeUnit(Unit *u) { + if(m_type == STRUCT_UNIT) { + if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) { + if(((CompositeUnit*) o_unit)->containsRelativeTo(u)) { + return true; + } + } else if(o_unit->subtype() == SUBTYPE_ALIAS_UNIT && o_unit->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { + if(((CompositeUnit*) (o_unit->baseUnit()))->containsRelativeTo(u)) { + return true; + } + } + } + return false; +} +bool MathStructure::dissolveAllCompositeUnits() { + switch(m_type) { + case STRUCT_UNIT: { + if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) { + set(((CompositeUnit*) o_unit)->generateMathStructure()); + return true; + } + break; + } + default: { + bool b = false; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).dissolveAllCompositeUnits()) { + CHILD_UPDATED(i); + b = true; + } + } + return b; + } + } + return false; +} +bool MathStructure::setPrefixForUnit(Unit *u, Prefix *new_prefix) { + if(m_type == STRUCT_UNIT && o_unit == u) { + if(o_prefix != new_prefix) { + Number new_value(1, 1); + if(o_prefix) new_value = o_prefix->value(); + if(new_prefix) new_value.divide(new_prefix->value()); + o_prefix = new_prefix; + multiply(new_value); + return true; + } + return false; + } + bool b = false; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).setPrefixForUnit(u, new_prefix)) { + CHILD_UPDATED(i); + b = true; + } + } + return b; +} + +bool searchSubMultiplicationsForComplexRelations(Unit *u, const MathStructure &mstruct) { + int b_c = -1; + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isUnit_exp()) { + if((mstruct[i].isUnit() && u->hasNonlinearRelationTo(mstruct[i].unit())) || (mstruct[i].isPower() && u->hasNonlinearRelationTo(mstruct[i][0].unit()))) { + return true; + } + } else if(b_c == -1 && mstruct[i].isMultiplication()) { + b_c = -3; + } + } + if(b_c == -3) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isMultiplication() && searchSubMultiplicationsForComplexRelations(u, mstruct[i])) return true; + } + } + return false; +} +bool MathStructure::convertToBaseUnits(bool convert_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo, bool avoid_approximate_variables) { + if(m_type == STRUCT_UNIT) { + if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) { + set(((CompositeUnit*) o_unit)->generateMathStructure()); + convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables); + return true; + } else if(o_unit->subtype() == SUBTYPE_ALIAS_UNIT) { + AliasUnit *au = (AliasUnit*) o_unit; + if(au->hasNonlinearRelationTo(au->baseUnit())) { + if(found_nonlinear_relations) *found_nonlinear_relations = true; + if(!convert_nonlinear_relations) { + if(!au->hasNonlinearExpression() && ((feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES) || !au->hasApproximateExpression(avoid_approximate_variables, false))) { + MathStructure mstruct_old(*this); + if(convert(au->firstBaseUnit(), false, NULL, calculate_new_functions, feo) && !equals(mstruct_old)) { + convertToBaseUnits(false, NULL, calculate_new_functions, feo, avoid_approximate_variables); + return true; + } + } + return false; + } + } + if((feo.approximation == APPROXIMATION_EXACT || feo.approximation == APPROXIMATION_EXACT_VARIABLES) && au->hasApproximateRelationTo(au->baseUnit(), avoid_approximate_variables, false)) { + MathStructure mstruct_old(*this); + if(convert(au->firstBaseUnit(), false, NULL, calculate_new_functions, feo) && !equals(mstruct_old)) { + convertToBaseUnits(false, NULL, calculate_new_functions, feo, avoid_approximate_variables); + return true; + } + return false; + } + if(convert(au->baseUnit(), convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo)) { + convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables); + return true; + } + } + return false; + } else if(m_type == STRUCT_MULTIPLICATION && (convert_nonlinear_relations || found_nonlinear_relations)) { + AliasUnit *complex_au = NULL; + if(convert_nonlinear_relations && convertToBaseUnits(false, NULL, calculate_new_functions, feo, avoid_approximate_variables)) { + convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables); + return true; + } + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return false; + if(CHILD(i).isUnit_exp() && CHILD(i).unit_exp_unit()->subtype() == SUBTYPE_ALIAS_UNIT) { + AliasUnit *au = (AliasUnit*) CHILD(i).unit_exp_unit(); + if(au && au->hasNonlinearRelationTo(au->baseUnit())) { + if(found_nonlinear_relations) { + *found_nonlinear_relations = true; + } + if(convert_nonlinear_relations) { + if(complex_au) { + complex_au = NULL; + convert_nonlinear_relations = false; + break; + } else { + complex_au = au; + } + } else { + break; + } + } + } + } + if(convert_nonlinear_relations && complex_au && ((feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES) || !complex_au->hasApproximateExpression(avoid_approximate_variables, false))) { + MathStructure mstruct_old(*this); + if(convert(complex_au->firstBaseUnit(), true, NULL, calculate_new_functions, feo) && !equals(mstruct_old)) { + convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables); + return true; + } + } + } else if(m_type == STRUCT_FUNCTION) { + if(o_function->id() == FUNCTION_ID_STRIP_UNITS) return false; + bool b = false; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return b; + if((!o_function->getArgumentDefinition(i + 1) || o_function->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) && CHILD(i).convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables)) { + CHILD_UPDATED(i); + b = true; + } + } + return b; + } + bool b = false; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return b; + if(CHILD(i).convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, avoid_approximate_variables)) { + CHILD_UPDATED(i); + b = true; + } + } + return b; +} +bool convert_approximate(MathStructure &m, Unit *u, const EvaluationOptions &feo, vector *vars, vector *uncs, vector *units, bool do_intervals); +bool convert_approximate(MathStructure &m, const MathStructure unit_mstruct, const EvaluationOptions &feo, vector *vars, vector *uncs, vector *units, bool do_intervals) { + bool b = false; + if(unit_mstruct.type() == STRUCT_UNIT) { + if(convert_approximate(m, unit_mstruct.unit(), feo, vars, uncs, units, do_intervals)) b = true; + } else { + for(size_t i = 0; i < unit_mstruct.size(); i++) { + if(convert_approximate(m, unit_mstruct[i], feo, vars, uncs, units, do_intervals)) b = true; + } + } + return b; +} +bool test_dissolve_cu_approximate(MathStructure &mstruct, Unit *u, const EvaluationOptions &feo, vector *vars, vector *uncs, vector *units, bool do_intervals) { + if(mstruct.isUnit()) { + if(mstruct.unit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { + if(((CompositeUnit*) mstruct.unit())->containsRelativeTo(u)) { + mstruct.set(((CompositeUnit*) mstruct.unit())->generateMathStructure()); + return true; + } + } else if(mstruct.unit()->subtype() == SUBTYPE_ALIAS_UNIT && mstruct.unit()->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { + if(((CompositeUnit*) (mstruct.unit()->baseUnit()))->containsRelativeTo(u)) { + if(convert_approximate(mstruct, mstruct.unit()->baseUnit(), feo, vars, uncs, units, do_intervals)) { + convert_approximate(mstruct, u, feo, vars, uncs, units, do_intervals); + return true; + } + } + } + } + return false; +} +bool convert_approximate(MathStructure &m, Unit *u, const EvaluationOptions &feo, vector *vars, vector *uncs, vector *units, bool do_intervals) { + bool b = false; + if(m.type() == STRUCT_UNIT && (m.unit() == u || m.prefix())) { + return false; + } + if(u->subtype() == SUBTYPE_COMPOSITE_UNIT && !(m.type() == STRUCT_UNIT && m.unit()->baseUnit() == u)) { + return convert_approximate(m, ((CompositeUnit*) u)->generateMathStructure(false, true), feo, vars, uncs, units, do_intervals); + } + if(m.type() == STRUCT_UNIT) { + if(u->hasApproximateRelationTo(m.unit(), feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES, true) || u->hasNonlinearRelationTo(m.unit())) { + return false; + } + if(!vars) return true; + if(m.unit()->baseUnit() != u->baseUnit() && test_dissolve_cu_approximate(m, u, feo, vars, uncs, units, do_intervals)) { + convert_approximate(m, u, feo, vars, uncs, units, do_intervals); + return true; + } + MathStructure *exp = new MathStructure(1, 1, 0); + MathStructure *mstruct = new MathStructure(1, 1, 0); + Unit *u_m = m.unit(); + if(u_m->subtype() == SUBTYPE_ALIAS_UNIT && do_intervals) { + for(size_t i = 0; i < units->size(); i++) { + if((*units)[i] == u_m) { + mstruct->set((*vars)[i]); + u_m = ((AliasUnit*) u_m)->firstBaseUnit(); + } + } + if(u_m == m.unit()) { + ((AliasUnit*) u_m)->convertToFirstBaseUnit(*mstruct, *exp); + if(mstruct->isNumber() && mstruct->number().isInterval()) { + uncs->push_back(mstruct->number().uncertainty()); + units->push_back(u_m); + Number nmid(mstruct->number()); + nmid.intervalToMidValue(); + nmid.setApproximate(false); + KnownVariable *v = new KnownVariable("", string("(") + format_and_print(nmid) + ")", nmid); + mstruct->set(v); + vars->push_back(v); + v->destroy(); + u_m = ((AliasUnit*) u_m)->firstBaseUnit(); + } else { + mstruct->set(1, 1, 0); + exp->set(1, 1, 0); + } + } + } + if(u->convert(u_m, *mstruct, *exp) && (do_intervals || (!mstruct->containsInterval(true, false, false, 1, true) && !exp->containsInterval(true, false, false, 1, true)))) { + m.setUnit(u); + if(!exp->isOne()) { + if(feo.calculate_functions) { + calculate_nondifferentiable_functions(*exp, feo, true, true, feo.interval_calculation != INTERVAL_CALCULATION_VARIANCE_FORMULA ? 0 : ((feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES) ? 2 : 1)); + } + if(do_intervals) exp->calculatesub(feo, feo, true); + m.raise_nocopy(exp); + } else { + exp->unref(); + } + if(!mstruct->isOne()) { + if(feo.calculate_functions) { + calculate_nondifferentiable_functions(*mstruct, feo, true, true, feo.interval_calculation != INTERVAL_CALCULATION_VARIANCE_FORMULA ? 0 : ((feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES) ? 2 : 1)); + } + if(do_intervals) mstruct->calculatesub(feo, feo, true); + m.multiply_nocopy(mstruct); + } else { + mstruct->unref(); + } + return true; + } else { + exp->unref(); + mstruct->unref(); + return false; + } + } else { + if(m.type() == STRUCT_FUNCTION) { + if(m.function()->id() == FUNCTION_ID_STRIP_UNITS) return b; + for(size_t i = 0; i < m.size(); i++) { + if(m.size() > 100 && CALCULATOR->aborted()) return b; + if((!m.function()->getArgumentDefinition(i + 1) || m.function()->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) && convert_approximate(m[i], u, feo, vars, uncs, units, do_intervals)) { + m.childUpdated(i + 1); + b = true; + } + } + return b; + } + for(size_t i = 0; i < m.size(); i++) { + if(m.size() > 100 && CALCULATOR->aborted()) return b; + if(convert_approximate(m[i], u, feo, vars, uncs, units, do_intervals)) { + m.childUpdated(i + 1); + b = true; + } + } + return b; + } + return b; +} + +bool contains_approximate_relation_to_base(const MathStructure &m, bool do_intervals) { + if(m.isUnit()) { + return has_approximate_relation_to_base(m.unit(), do_intervals); + } else if(m.isFunction() && m.function()->id() == FUNCTION_ID_STRIP_UNITS) { + return false; + } + for(size_t i = 0; i < m.size(); i++) { + if(contains_approximate_relation_to_base(m[i], do_intervals)) return true; + } + return false; +} + +bool sync_approximate_units(MathStructure &m, const EvaluationOptions &feo, vector *vars, vector *uncs, bool do_intervals) { + if(m.size() == 0) return false; + if(!contains_approximate_relation_to_base(m, do_intervals)) return false; + bool check_variables = (feo.approximation != APPROXIMATION_EXACT && feo.approximation != APPROXIMATION_EXACT_VARIABLES); + vector base_units; + vector alias_units; + vector composite_units; + gatherInformation(m, base_units, alias_units, check_variables); + if(alias_units.empty() || base_units.size() + alias_units.size() == 1) return false; + CompositeUnit *cu; + bool b = false, do_erase = false; + for(size_t i = 0; i < alias_units.size(); ) { + do_erase = false; + if(alias_units[i]->baseUnit()->subtype() == SUBTYPE_COMPOSITE_UNIT) { + b = false; + cu = (CompositeUnit*) alias_units[i]->baseUnit(); + for(size_t i2 = 0; i2 < base_units.size(); i2++) { + if(cu->containsRelativeTo(base_units[i2])) { + for(size_t i3 = 0; i3 < composite_units.size(); i3++) { + if(composite_units[i3] == cu) { + b = true; + break; + } + } + if(!b) composite_units.push_back(cu); + do_erase = true; + break; + } + } + for(size_t i2 = 0; !do_erase && i2 < alias_units.size(); i2++) { + if(i != i2 && alias_units[i2]->baseUnit() != cu && cu->containsRelativeTo(alias_units[i2])) { + for(size_t i3 = 0; i3 < composite_units.size(); i3++) { + if(composite_units[i3] == cu) { + b = true; + break; + } + } + if(!b) composite_units.push_back(cu); + do_erase = true; + break; + } + } + } + if(do_erase) { + alias_units.erase(alias_units.begin() + i); + for(int i2 = 1; i2 <= (int) cu->countUnits(); i2++) { + b = false; + Unit *cub = cu->get(i2); + switch(cub->subtype()) { + case SUBTYPE_BASE_UNIT: { + for(size_t i3 = 0; i3 < base_units.size(); i3++) { + if(base_units[i3] == cub) { + b = true; + break; + } + } + if(!b) base_units.push_back(cub); + break; + } + case SUBTYPE_ALIAS_UNIT: { + for(size_t i3 = 0; i3 < alias_units.size(); i3++) { + if(alias_units[i3] == cub) { + b = true; + break; + } + } + if(!b) alias_units.push_back((AliasUnit*) cub); + break; + } + case SUBTYPE_COMPOSITE_UNIT: { + gatherInformation(((CompositeUnit*) cub)->generateMathStructure(), base_units, alias_units, check_variables); + break; + } + } + } + i = 0; + } else { + i++; + } + } + + for(size_t i = 0; i < alias_units.size();) { + do_erase = false; + for(size_t i2 = 0; i2 < alias_units.size(); i2++) { + if(i != i2 && alias_units[i]->baseUnit() == alias_units[i2]->baseUnit()) { + if(alias_units[i2]->isParentOf(alias_units[i])) { + do_erase = true; + break; + } else if(!alias_units[i]->isParentOf(alias_units[i2])) { + b = false; + for(size_t i3 = 0; i3 < base_units.size(); i3++) { + if(base_units[i3] == alias_units[i2]->firstBaseUnit()) { + b = true; + break; + } + } + if(!b) base_units.push_back((Unit*) alias_units[i]->baseUnit()); + do_erase = true; + break; + } + } + } + if(do_erase) { + alias_units.erase(alias_units.begin() + i); + i = 0; + } else { + i++; + } + } + for(size_t i = 0; i < alias_units.size();) { + do_erase = false; + if(alias_units[i]->baseUnit()->subtype() == SUBTYPE_BASE_UNIT) { + for(size_t i2 = 0; i2 < base_units.size(); i2++) { + if(alias_units[i]->baseUnit() == base_units[i2]) { + do_erase = true; + break; + } + } + } + if(do_erase) { + alias_units.erase(alias_units.begin() + i); + i = 0; + } else { + i++; + } + } + b = false; + vector units; + for(size_t i = 0; i < composite_units.size(); i++) { + if(convert_approximate(m, composite_units[i], feo, vars, uncs, &units, do_intervals)) b = true; + } + if(m.dissolveAllCompositeUnits()) b = true; + for(size_t i = 0; i < base_units.size(); i++) { + if(convert_approximate(m, base_units[i], feo, vars, uncs, &units, do_intervals)) b = true; + } + for(size_t i = 0; i < alias_units.size(); i++) { + if(convert_approximate(m, alias_units[i], feo, vars, uncs, &units, do_intervals)) b = true; + } + return b; +} + + +bool MathStructure::convert(Unit *u, bool convert_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo, Prefix *new_prefix) { + if(m_type == STRUCT_ADDITION && containsType(STRUCT_DATETIME, false, true, false) > 0) return false; + bool b = false; + if(m_type == STRUCT_UNIT && o_unit == u) { + if((new_prefix || o_prefix) && o_prefix != new_prefix) { + Number new_value(1, 1); + if(o_prefix) new_value = o_prefix->value(); + if(new_prefix) new_value.divide(new_prefix->value()); + o_prefix = new_prefix; + multiply(new_value); + return true; + } + return false; + } + if(u->subtype() == SUBTYPE_COMPOSITE_UNIT && !(m_type == STRUCT_UNIT && o_unit->baseUnit() == u)) { + return convert(((CompositeUnit*) u)->generateMathStructure(false, true), convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo); + } + if(m_type == STRUCT_UNIT) { + if(u->hasNonlinearRelationTo(o_unit)) { + if(found_nonlinear_relations) *found_nonlinear_relations = true; + if(!convert_nonlinear_relations) return false; + } + if(o_unit->baseUnit() != u->baseUnit() && test_dissolve_cu(*this, u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix)) { + convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); + return true; + } + MathStructure *exp = new MathStructure(1, 1, 0); + MathStructure *mstruct = new MathStructure(1, 1, 0); + if(o_prefix) { + mstruct->set(o_prefix->value()); + } + if(u->convert(o_unit, *mstruct, *exp) && (feo.approximation != APPROXIMATION_EXACT || (!mstruct->isApproximate() && !exp->isApproximate()))) { + setUnit(u); + o_prefix = new_prefix; + if(new_prefix) { + divide(new_prefix->value()); + } + if(!exp->isOne()) { + if(calculate_new_functions) exp->calculateFunctions(feo, true, false); + raise_nocopy(exp); + } else { + exp->unref(); + } + if(!mstruct->isOne()) { + if(calculate_new_functions) mstruct->calculateFunctions(feo, true, false); + multiply_nocopy(mstruct); + } else { + mstruct->unref(); + } + return true; + } else { + exp->unref(); + mstruct->unref(); + return false; + } + } else { + if(convert_nonlinear_relations || found_nonlinear_relations) { + if(m_type == STRUCT_MULTIPLICATION) { + long int b_c = -1; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isUnit_exp()) { + Unit *u2 = CHILD(i).isPower() ? CHILD(i)[0].unit() : CHILD(i).unit(); + if(u->hasNonlinearRelationTo(u2)) { + if(found_nonlinear_relations) *found_nonlinear_relations = true; + + b_c = i; + break; + } + } else if(CHILD(i).isMultiplication()) { + b_c = -3; + } + } + if(b_c == -3) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isMultiplication()) { + if(searchSubMultiplicationsForComplexRelations(u, CHILD(i))) { + if(!convert_nonlinear_relations) { + *found_nonlinear_relations = true; + break; + } + flattenMultiplication(*this); + return convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); + } + } + } + } + if(convert_nonlinear_relations && b_c >= 0) { + if(flattenMultiplication(*this)) return convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); + MathStructure mstruct(1, 1); + MathStructure mstruct2(1, 1); + if(SIZE == 2) { + if(b_c == 0) mstruct = CHILD(1); + else mstruct = CHILD(0); + if(mstruct.isUnit_exp()) { + mstruct2 = mstruct; + mstruct.set(1, 1, 0); + } + } else if(SIZE > 2) { + mstruct = *this; + size_t nr_of_del = 0; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isUnit_exp()) { + mstruct.delChild(i + 1 - nr_of_del); + nr_of_del++; + if((long int) i != b_c) { + if(mstruct2.isOne()) mstruct2 = CHILD(i); + else mstruct2.multiply(CHILD(i), true); + } + } + } + if(mstruct.size() == 1) mstruct.setToChild(1); + else if(mstruct.size() == 0) mstruct.set(1, 1, 0); + } + MathStructure exp(1, 1); + Unit *u2; + bool b_p = false; + if(CHILD(b_c).isPower()) { + if(CHILD(b_c)[0].unit()->baseUnit() != u->baseUnit()) { + if(CHILD(b_c)[0].unit()->subtype() != SUBTYPE_BASE_UNIT && (CHILD(b_c)[0].unit()->subtype() != SUBTYPE_ALIAS_UNIT || ((AliasUnit*) CHILD(b_c)[0].unit())->firstBaseUnit()->subtype() != SUBTYPE_COMPOSITE_UNIT)) { + convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo); + } else { + return false; + } + convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); + return true; + } + exp = CHILD(b_c)[1]; + u2 = CHILD(b_c)[0].unit(); + if(CHILD(b_c)[0].prefix()) b_p = true; + } else { + if(CHILD(b_c).unit()->baseUnit() != u->baseUnit()) { + if(CHILD(b_c).unit()->subtype() != SUBTYPE_BASE_UNIT && (CHILD(b_c).unit()->subtype() != SUBTYPE_ALIAS_UNIT || ((AliasUnit*) CHILD(b_c).unit())->firstBaseUnit()->subtype() != SUBTYPE_COMPOSITE_UNIT)) { + convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo); + } else { + return false; + } + convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); + return true; + } + u2 = CHILD(b_c).unit(); + if(CHILD(b_c).prefix()) b_p = true; + } + size_t efc = 0, mfc = 0; + if(calculate_new_functions) { + efc = exp.countFunctions(); + mfc = mstruct.countFunctions(); + } + if(u->convert(u2, mstruct, exp)) { + if(feo.approximation == APPROXIMATION_EXACT && !isApproximate() && (mstruct.isApproximate() || exp.isApproximate())) return false; + if(b_p) { + unformat(feo); + return convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); + } + set(u); + if(!exp.isOne()) { + if(calculate_new_functions && exp.countFunctions() > efc) exp.calculateFunctions(feo, true, false); + raise(exp); + } + if(!mstruct2.isOne()) { + multiply(mstruct2); + } + if(!mstruct.isOne()) { + if(calculate_new_functions && mstruct.countFunctions() > mfc) mstruct.calculateFunctions(feo, true, false); + multiply(mstruct); + } + return true; + } + return false; + } + } else if(m_type == STRUCT_POWER) { + if(CHILD(0).isUnit() && u->hasNonlinearRelationTo(CHILD(0).unit())) { + if(found_nonlinear_relations) *found_nonlinear_relations = true; + if(convert_nonlinear_relations) { + if(CHILD(0).unit()->baseUnit() != u->baseUnit()) { + if(CHILD(0).unit()->subtype() != SUBTYPE_BASE_UNIT && (CHILD(0).unit()->subtype() != SUBTYPE_ALIAS_UNIT || ((AliasUnit*) CHILD(0).unit())->firstBaseUnit()->subtype() != SUBTYPE_COMPOSITE_UNIT)) { + convertToBaseUnits(convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo); + } else { + return false; + } + convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix); + return true; + } + MathStructure exp(CHILD(1)); + MathStructure mstruct(1, 1); + if(CHILD(0).prefix()) { + mstruct.set(CHILD(0).prefix()->value()); + mstruct.raise(exp); + } + size_t efc = 0; + if(calculate_new_functions) { + efc = exp.countFunctions(); + } + if(u->convert(CHILD(0).unit(), mstruct, exp)) { + if(feo.approximation == APPROXIMATION_EXACT && !isApproximate() && (mstruct.isApproximate() || exp.isApproximate())) return false; + set(u); + if(!exp.isOne()) { + if(calculate_new_functions && exp.countFunctions() > efc) exp.calculateFunctions(feo, true, false); + raise(exp); + } + if(!mstruct.isOne()) { + if(calculate_new_functions) mstruct.calculateFunctions(feo, true, false); + multiply(mstruct); + } + return true; + } + return false; + } + } + } + /*if(m_type == STRUCT_MULTIPLICATION || m_type == STRUCT_POWER) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).convert(u, false, found_nonlinear_relations, calculate_new_functions, feo, new_prefix)) { + CHILD_UPDATED(i); + b = true; + } + } + return b; + }*/ + } + if(m_type == STRUCT_FUNCTION) { + if(o_function->id() == FUNCTION_ID_STRIP_UNITS) return b; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return b; + if((!o_function->getArgumentDefinition(i + 1) || o_function->getArgumentDefinition(i + 1)->type() != ARGUMENT_TYPE_ANGLE) && CHILD(i).convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix)) { + CHILD_UPDATED(i); + b = true; + } + } + return b; + } + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return b; + if(CHILD(i).convert(u, convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, new_prefix)) { + CHILD_UPDATED(i); + b = true; + } + } + return b; + } + return b; +} +bool MathStructure::convert(const MathStructure unit_mstruct, bool convert_nonlinear_relations, bool *found_nonlinear_relations, bool calculate_new_functions, const EvaluationOptions &feo) { + bool b = false; + if(unit_mstruct.type() == STRUCT_UNIT) { + if(convert(unit_mstruct.unit(), convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo, feo.keep_prefixes ? unit_mstruct.prefix() : NULL)) b = true; + } else { + for(size_t i = 0; i < unit_mstruct.size(); i++) { + if(convert(unit_mstruct[i], convert_nonlinear_relations, found_nonlinear_relations, calculate_new_functions, feo)) b = true; + } + } + return b; +} + diff -Nru libqalculate-3.6.0/libqalculate/MathStructure-decompose.cc libqalculate-3.7.0/libqalculate/MathStructure-decompose.cc --- libqalculate-3.6.0/libqalculate/MathStructure-decompose.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure-decompose.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,465 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "MathStructure.h" +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "Number.h" +#include "Function.h" +#include "Variable.h" +#include "Unit.h" +#include "Prefix.h" +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +bool MathStructure::decomposeFractions(const MathStructure &x_var, const EvaluationOptions &eo) { + MathStructure mtest2; + bool b = false; + int mmul_i = 0; + if(isPower()) { + if(CHILD(1).isMinusOne() && CHILD(0).isMultiplication() && CHILD(0).size() >= 2) { + mtest2 = CHILD(0); + b = true; + } + } else if(isMultiplication() && SIZE == 2) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isPower() && CHILD(i)[1].isMinusOne() && (CHILD(i)[0].isPower() || CHILD(i)[0].isMultiplication())) { + mtest2 = CHILD(i)[0]; + b = true; + } else if(CHILD(i) == x_var) { + mmul_i = 1; + } else if(CHILD(i).isPower() && CHILD(i)[0] == x_var && CHILD(i)[1].isInteger() && CHILD(i)[1].number().isPositive() && CHILD(i)[1].number().isLessThan(100)) { + mmul_i = CHILD(i)[1].number().intValue(); + } + } + if(mmul_i == 0) b = false; + } + if(b) { + if(!mtest2.isMultiplication()) mtest2.transform(STRUCT_MULTIPLICATION); + MathStructure mfacs, mnew; + mnew.setType(STRUCT_ADDITION); + mfacs.setType(STRUCT_ADDITION); + vector i_degrees; + i_degrees.resize(mtest2.size(), 1); + for(size_t i = 0; i < mtest2.size() && b; i++) { + if(CALCULATOR->aborted()) return false; + MathStructure mfactor = mtest2[i]; + if(mtest2[i].isPower()) { + if(!mtest2[i][1].isInteger() || !mtest2[i][1].number().isPositive() || mtest2[i][1].isOne() || mtest2[i][1].number().isGreaterThan(100)) { + b = false; + break; + } + mfactor = mtest2[i][0]; + } + if(mfactor.isAddition()) { + bool b2 = false; + for(size_t i2 = 0; i2 < mfactor.size() && b; i2++) { + if(mfactor[i2].isMultiplication()) { + bool b_x = false; + for(size_t i3 = 0; i3 < mfactor[i2].size() && b; i3++) { + if(!b_x && mfactor[i2][i3].isPower() && mfactor[i2][i3][0] == x_var) { + if(!mfactor[i2][i3][1].isInteger() || !mfactor[i2][i3][1].number().isPositive() || mfactor[i2][i3][1].isOne() || mfactor[i2][i3][1].number().isGreaterThan(100)) { + b = false; + } else if(mfactor[i2][i3][1].number().intValue() > i_degrees[i]) { + i_degrees[i] = mfactor[i2][i3][1].number().intValue(); + } + b_x = true; + } else if(!b_x && mfactor[i2][i3] == x_var) { + b_x = true; + } else if(mfactor[i2][i3].containsRepresentativeOf(x_var, true, true) != 0) { + b = false; + } + } + if(!b_x) b2 = true; + } else if(mfactor[i2].isPower() && mfactor[i2][0] == x_var) { + if(!mfactor[i2][1].isInteger() || !mfactor[i2][1].number().isPositive() || mfactor[i2][1].isOne() || mfactor[i2][1].number().isGreaterThan(100)) { + b = false; + } else if(mfactor[i2][1].number().intValue() > i_degrees[i]) { + i_degrees[i] = mfactor[i2][1].number().intValue(); + } + } else if(mfactor[i2] == x_var) { + } else if(mfactor[i2].containsRepresentativeOf(x_var, true, true) != 0) { + b = false; + } else { + b2 = true; + } + } + if(!b2) b = false; + } else if(mfactor != x_var) { + b = false; + } + } + MathStructure mtest3, mnums3; + mnums3.clearVector(); + mtest3.clearVector(); + if(b) { + UnknownVariable *var = new UnknownVariable("", string("a")); + var->setAssumptions(new Assumptions()); + MathStructure mvar(var); + for(size_t i = 0; i < mtest2.size(); i++) { + if(CALCULATOR->aborted()) return false; + if(i_degrees[i] == 1) { + MathStructure mnum(1, 1, 0); + if(mtest2.size() != 1) { + mnum = mtest2; + mnum.delChild(i + 1, true); + } + MathStructure mx(mtest2[i]); + mx.transform(COMPARISON_EQUALS, m_zero); + mx.replace(x_var, mvar); + mx.isolate_x(eo, mvar); + mx.calculatesub(eo, eo, true); + if(mx.isLogicalOr()) mx.setToChild(1); + if(!mx.isComparison() || mx.comparisonType() != COMPARISON_EQUALS || mx[0] != var) {b = false; break;} + mx.setToChild(2); + if(mtest2.size() != 1) { + mfacs.addChild(mnum); + mnum.replace(x_var, mx); + mnum.inverse(); + } + if(mmul_i > 0) { + mx ^= Number(mmul_i, 1); + if(mtest2.size() == 1) mnum = mx; + else mnum *= mx; + } + mnum.calculatesub(eo, eo, true); + if(mtest2.size() == 1) mfacs.addChild(mnum); + else mfacs.last() *= mnum; + mnums3.addChild(mnum); + mtest3.addChild(mtest2[i]); + } + } + var->destroy(); + } + if(b) { + vector vars; + bool b_solve = false; + for(size_t i = 0; i < mtest2.size(); i++) { + if(CALCULATOR->aborted()) return false; + if(mtest2[i].isPower()) { + int i_exp = mtest2[i][1].number().intValue(); + for(int i_exp_n = mtest2[i][1].number().intValue() - (i_degrees[i] == 1 ? 1 : 0); i_exp_n > 0; i_exp_n--) { + if(i_exp_n == 1) { + mtest3.addChild(mtest2[i][0]); + } else { + mtest3.addChild(mtest2[i]); + if(i_exp_n != i_exp) mtest3.last()[1].number() = i_exp_n; + } + if(i_exp == i_exp_n) { + if(mtest2.size() > 1) { + mfacs.addChild(mtest2); + mfacs.last().delChild(i + 1, true); + } + } else { + mfacs.addChild(mtest2); + if(i_exp - i_exp_n == 1) mfacs.last()[i].setToChild(1); + else mfacs.last()[i][1].number() = i_exp - i_exp_n; + } + if(i_degrees[i] == 1) { + UnknownVariable *var = new UnknownVariable("", string("a") + i2s(mtest3.size())); + var->setAssumptions(new Assumptions()); + mnums3.addChild_nocopy(new MathStructure(var)); + vars.push_back(var); + } else { + mnums3.addChild_nocopy(new MathStructure()); + mnums3.last().setType(STRUCT_ADDITION); + for(int i2 = 1; i2 <= i_degrees[i]; i2++) { + UnknownVariable *var = new UnknownVariable("", string("a") + i2s(mtest3.size()) + i2s(i2)); + var->setAssumptions(new Assumptions()); + if(i2 == 1) { + mnums3.last().addChild_nocopy(new MathStructure(var)); + } else { + mnums3.last().addChild_nocopy(new MathStructure(var)); + mnums3.last().last() *= x_var; + if(i2 > 2) mnums3.last().last().last() ^= Number(i2 - 1, 1); + } + vars.push_back(var); + } + } + if(i_exp != i_exp_n || mtest2.size() > 1) mfacs.last() *= mnums3.last(); + else mfacs.addChild(mnums3.last()); + b_solve = true; + } + } else if(i_degrees[i] > 1) { + mtest3.addChild(mtest2[i]); + if(mtest2.size() > 1) { + mfacs.addChild(mtest2); + mfacs.last().delChild(i + 1, true); + } + mnums3.addChild_nocopy(new MathStructure()); + mnums3.last().setType(STRUCT_ADDITION); + for(int i2 = 1; i2 <= i_degrees[i]; i2++) { + UnknownVariable *var = new UnknownVariable("", string("a") + i2s(mtest3.size()) + i2s(i2)); + var->setAssumptions(new Assumptions()); + if(i2 == 1) { + mnums3.last().addChild_nocopy(new MathStructure(var)); + } else { + mnums3.last().addChild_nocopy(new MathStructure(var)); + mnums3.last().last() *= x_var; + if(i2 > 2) mnums3.last().last().last() ^= Number(i2 - 1, 1); + } + vars.push_back(var); + } + if(mtest2.size() > 1) mfacs.last() *= mnums3.last(); + else mfacs.addChild(mnums3.last()); + b_solve = true; + } + } + if(b_solve) { + mfacs.childrenUpdated(true); + MathStructure mfac_expand(mfacs); + mfac_expand.calculatesub(eo, eo, true); + size_t i_degree = 0; + if(mfac_expand.isAddition()) { + i_degree = mfac_expand.degree(x_var).uintValue(); + if(i_degree >= 100 || i_degree <= 0) b = false; + } + if(i_degree == 0) b = false; + if(b) { + MathStructure m_eqs; + m_eqs.resizeVector(i_degree + 1, m_zero); + for(size_t i = 0; i < m_eqs.size(); i++) { + for(size_t i2 = 0; i2 < mfac_expand.size();) { + if(CALCULATOR->aborted()) return false; + bool b_add = false; + if(i == 0) { + if(!mfac_expand[i2].contains(x_var)) b_add = true; + } else { + if(mfac_expand[i2].isMultiplication() && mfac_expand[i2].size() >= 2) { + for(size_t i3 = 0; i3 < mfac_expand[i2].size(); i3++) { + if(i == 1 && mfac_expand[i2][i3] == x_var) b_add = true; + else if(i > 1 && mfac_expand[i2][i3].isPower() && mfac_expand[i2][i3][0] == x_var && mfac_expand[i2][i3][1] == i) b_add = true; + if(b_add) { + mfac_expand[i2].delChild(i3 + 1, true); + break; + } + } + + } else { + if(i == 1 && mfac_expand[i2] == x_var) b_add = true; + else if(i > 1 && mfac_expand[i2].isPower() && mfac_expand[i2][0] == x_var && mfac_expand[i2][1] == i) b_add = true; + if(b_add) mfac_expand[i2].set(1, 1, 0); + } + } + if(b_add) { + if(m_eqs[i].isZero()) m_eqs[i] = mfac_expand[i2]; + else m_eqs[i].add(mfac_expand[i2], true); + mfac_expand.delChild(i2 + 1); + } else { + i2++; + } + } + } + if(mfac_expand.size() == 0 && m_eqs.size() >= vars.size()) { + for(size_t i = 0; i < m_eqs.size(); i++) { + if(!m_eqs[i].isZero()) { + m_eqs[i].transform(COMPARISON_EQUALS, i == (size_t) mmul_i ? m_one : m_zero); + } + } + for(size_t i = 0; i < m_eqs.size();) { + if(m_eqs[i].isZero()) { + m_eqs.delChild(i + 1); + if(i == (size_t) mmul_i) b = false; + } else { + i++; + } + } + if(b) { + MathStructure vars_m; + vars_m.clearVector(); + for(size_t i = 0; i < vars.size(); i++) { + vars_m.addChild_nocopy(new MathStructure(vars[i])); + } + for(size_t i = 0; i < m_eqs.size() && b; i++) { + for(size_t i2 = 0; i2 < vars_m.size(); i2++) { + if(m_eqs[i].isComparison() && m_eqs[i][0].contains(vars_m[i2], true)) { + if(CALCULATOR->aborted() || m_eqs[i].countTotalChildren() > 1000) return false; + m_eqs[i].isolate_x(eo, vars_m[i2]); + if(CALCULATOR->aborted() || m_eqs[i].countTotalChildren() > 10000) return false; + m_eqs[i].calculatesub(eo, eo, true); + if(m_eqs[i].isLogicalOr()) m_eqs[i].setToChild(1); + if(m_eqs[i].isComparison() && m_eqs[i].comparisonType() == COMPARISON_EQUALS && m_eqs[i][0] == vars_m[i2]) { + for(size_t i3 = 0; i3 < m_eqs.size(); i3++) { + if(i3 != i) { + if(CALCULATOR->aborted()) return false; + m_eqs[i3][0].calculateReplace(vars_m[i2], m_eqs[i][1], eo); + if(CALCULATOR->aborted()) return false; + m_eqs[i3][1].calculateReplace(vars_m[i2], m_eqs[i][1], eo); + } + } + vars_m.delChild(i2 + 1); + } else { + b = false; + } + break; + } + } + } + for(size_t i = 0; i < m_eqs.size();) { + if(CALCULATOR->aborted()) return false; + m_eqs[i].calculatesub(eo, eo); + if(m_eqs[i].isZero()) {b = false; break;} + if(m_eqs[i].isOne()) m_eqs.delChild(i + 1); + else i++; + } + if(b && vars_m.size() == 0) { + for(size_t i = 0; i < vars.size(); i++) { + for(size_t i2 = 0; i2 < m_eqs.size(); i2++) { + if(m_eqs[i2][0] == vars[i]) { + mnums3.replace(vars[i], m_eqs[i2][1]); + break; + } + } + } + } else { + b = false; + } + } + } else { + b = false; + } + } + } + for(size_t i = 0; i < vars.size(); i++) { + vars[i]->destroy(); + } + if(b) { + for(size_t i = 0; i < mnums3.size(); i++) { + mnums3.calculatesub(eo, eo, true); + if(!mnums3[i].isZero()) { + if(mnums3[i].isOne()) { + mnew.addChild(mtest3[i]); + mnew.last().inverse(); + } else { + mnew.addChild(mnums3[i]); + mnew.last() /= mtest3[i]; + } + } + } + } + if(b) { + if(mnew.size() == 0) mnew.clear(); + else if(mnew.size() == 1) mnew.setToChild(1); + mnew.childrenUpdated(); + if(equals(mnew, true)) return false; + set(mnew, true); + return true; + } + } + } + return false; +} + +bool expand_partial_fractions(MathStructure &m, const EvaluationOptions &eo, bool do_simplify = true) { + MathStructure mtest(m); + if(do_simplify) { + mtest.simplify(eo); + mtest.calculatesub(eo, eo, true); + } + if(mtest.isPower() && mtest[1].representsNegative()) { + MathStructure x_var = mtest[0].find_x_var(); + if(!x_var.isUndefined() && mtest[0].factorize(eo, false, 0, 0, false, false, NULL, x_var)) { + if(mtest.decomposeFractions(x_var, eo) && mtest.isAddition()) { + m = mtest; + return true; + } + } + } else if(mtest.isMultiplication()) { + for(size_t i = 0; i < mtest.size(); i++) { + if(mtest[i].isPower() && mtest[i][1].isMinusOne() && mtest[i][0].isAddition()) { + MathStructure x_var = mtest[i][0].find_x_var(); + if(!x_var.isUndefined()) { + MathStructure mfac(mtest); + mfac.delChild(i + 1, true); + bool b_poly = true; + if(mfac.contains(x_var, true)) { + MathStructure mquo, mrem; + b_poly = polynomial_long_division(mfac, mtest[i][0], x_var, mquo, mrem, eo, true); + if(b_poly && !mquo.isZero()) { + m = mquo; + if(!mrem.isZero()) { + m += mrem; + m.last() *= mtest[i]; + m.childrenUpdated(); + } + expand_partial_fractions(m, eo, false); + return true; + } + } + if(b_poly && mtest[i][0].factorize(eo, false, 0, 0, false, false, NULL, x_var)) { + MathStructure mmul(1, 1, 0); + while(mtest[i][0].isMultiplication() && mtest[i][0].size() >= 2 && !mtest[i][0][0].containsRepresentativeOf(x_var, true)) { + if(mmul.isOne()) { + mmul = mtest[i][0][0]; + mmul.calculateInverse(eo); + } else { + mmul *= mtest[i][0][0]; + mmul.last().calculateInverse(eo); + mmul.calculateMultiplyLast(eo); + } + mtest[i][0].delChild(1, true); + } + for(size_t i2 = 0; i2 < mtest.size();) { + if(i2 != i && !mtest[i2].containsRepresentativeOf(x_var, true)) { + if(mmul.isOne()) { + mmul = mtest[i2]; + } else { + mmul.calculateMultiply(mtest[i2], eo); + } + if(mtest.size() == 2) { + mtest.setToChild(i + 1, true); + break; + } else { + mtest.delChild(i2 + 1); + if(i2 < i) i--; + } + } else { + i2++; + } + } + if(mtest.decomposeFractions(x_var, eo) && mtest.isAddition()) { + m = mtest; + if(!mmul.isOne()) { + for(size_t i2 = 0; i2 < m.size(); i2++) { + m[i2].calculateMultiply(mmul, eo); + } + } + return true; + } + } + } + } + } + } else { + bool b = false; + for(size_t i = 0; i < mtest.size(); i++) { + if(expand_partial_fractions(mtest[i], eo, false)) { + b = true; + } + } + if(b) { + m = mtest; + m.calculatesub(eo, eo, false); + return true; + } + } + return false; +} +bool MathStructure::expandPartialFractions(const EvaluationOptions &eo) { + return expand_partial_fractions(*this, eo, true); +} + diff -Nru libqalculate-3.6.0/libqalculate/MathStructure-differentiate.cc libqalculate-3.7.0/libqalculate/MathStructure-differentiate.cc --- libqalculate-3.6.0/libqalculate/MathStructure-differentiate.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure-differentiate.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,726 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "MathStructure.h" +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "Number.h" +#include "Function.h" +#include "Variable.h" +#include "Unit.h" +#include "Prefix.h" +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +bool function_differentiable(MathFunction *o_function) { + return (o_function->id() == FUNCTION_ID_SQRT || o_function->id() == FUNCTION_ID_ROOT || o_function->id() == FUNCTION_ID_CBRT || o_function->id() == FUNCTION_ID_LOG || o_function->id() == FUNCTION_ID_LOGN || o_function->id() == FUNCTION_ID_ARG || o_function->id() == FUNCTION_ID_GAMMA || o_function->id() == FUNCTION_ID_BETA || o_function->id() == FUNCTION_ID_ABS || o_function->id() == FUNCTION_ID_FACTORIAL || o_function->id() == FUNCTION_ID_BESSELJ || o_function->id() == FUNCTION_ID_BESSELY || o_function->id() == FUNCTION_ID_ERF || o_function->id() == FUNCTION_ID_ERFI || o_function->id() == FUNCTION_ID_ERFC || o_function->id() == FUNCTION_ID_LOGINT || o_function->id() == FUNCTION_ID_POLYLOG || o_function->id() == FUNCTION_ID_EXPINT || o_function->id() == FUNCTION_ID_SININT || o_function->id() == FUNCTION_ID_COSINT || o_function->id() == FUNCTION_ID_SINHINT || o_function->id() == FUNCTION_ID_COSHINT || o_function->id() == FUNCTION_ID_FRESNEL_C || o_function->id() == FUNCTION_ID_FRESNEL_S || o_function->id() == FUNCTION_ID_ABS || o_function->id() == FUNCTION_ID_SIGNUM || o_function->id() == FUNCTION_ID_HEAVISIDE || o_function->id() == FUNCTION_ID_LAMBERT_W || o_function->id() == FUNCTION_ID_SINC || o_function->id() == FUNCTION_ID_SIN || o_function->id() == FUNCTION_ID_COS || o_function->id() == FUNCTION_ID_TAN || o_function->id() == FUNCTION_ID_ASIN || o_function->id() == FUNCTION_ID_ACOS || o_function->id() == FUNCTION_ID_ATAN || o_function->id() == FUNCTION_ID_SINH || o_function->id() == FUNCTION_ID_COSH || o_function->id() == FUNCTION_ID_TANH || o_function->id() == FUNCTION_ID_ASINH || o_function->id() == FUNCTION_ID_ACOSH || o_function->id() == FUNCTION_ID_ATANH || o_function->id() == FUNCTION_ID_STRIP_UNITS); +} + +bool is_differentiable(const MathStructure &m) { + if(m.isFunction() && !function_differentiable(m.function())) return false; + for(size_t i = 0; i < m.size(); i++) { + if(!is_differentiable(m[i])) return false; + } + return true; +} + +void remove_zero_mul(MathStructure &m) { + if(m.isMultiplication()) { + for(size_t i = 0; i < m.size(); i++) { + if(m[i].isZero()) { + m.clear(true); + return; + } + } + } + for(size_t i = 0; i < m.size(); i++) { + remove_zero_mul(m[i]); + } +} +bool MathStructure::differentiate(const MathStructure &x_var, const EvaluationOptions &eo) { + if(CALCULATOR->aborted()) { + transformById(FUNCTION_ID_DIFFERENTIATE); + addChild(x_var); + addChild(m_one); + addChild(m_undefined); + return false; + } + if(equals(x_var)) { + // x'=1 + set(m_one); + return true; + } + if(containsRepresentativeOf(x_var, true, true) == 0) { + // f(a)'=0 + clear(true); + return true; + } + switch(m_type) { + case STRUCT_ADDITION: { + // sum rule: (f(x)+g(x))'=f'+g' + for(size_t i = 0; i < SIZE;) { + if(CHILD(i).differentiate(x_var, eo)) { + CHILD_UPDATED(i); + if(SIZE > 1 && CHILD(i).isZero()) {ERASE(i);} + else i++; + } else i++; + } + if(SIZE == 1) SET_CHILD_MAP(0) + break; + } + case STRUCT_LOGICAL_AND: { + bool b = true; + for(size_t i = 0; i < SIZE; i++) { + if(!CHILD(i).isComparison()) {b = false; break;} + } + if(b) { + // a&&b=a*b + MathStructure mtest(*this); + mtest.setType(STRUCT_MULTIPLICATION); + if(mtest.differentiate(x_var, eo) && mtest.containsFunctionId(FUNCTION_ID_DIFFERENTIATE, true) <= 0) { + set(mtest); + break; + } + } + } + case STRUCT_COMPARISON: { + if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) { + // f(x)>=0 = sgn(heaviside(f)) : sgn(heaviside(f))'=f'*2*dirac(f)*dirac(heaviside(f)) + // f(x)<0 = sgn(-heaviside(f)) : sgn(heaviside(-f))'=f'*-2*dirac(f)*dirac(heaviside(-f)) + // f(x)<=0 = sgn(heaviside(-f)) : sgn(-heaviside(f))'=f'*-2*dirac(f)*dirac(heaviside(f)) + // f(x)>0 = sgn(-heaviside(-f)) : sgn(-heaviside(-f))'=f'*2*dirac(f)*dirac(heaviside(-f)) + ComparisonType ct = ct_comp; + if(!CHILD(1).isZero()) CHILD(0) -= CHILD(1); + SET_CHILD_MAP(0) + MathStructure mstruct2(*this); + MathStructure mstruct(*this); + if(ct == COMPARISON_EQUALS_LESS || ct == COMPARISON_GREATER) negate(); + transformById(FUNCTION_ID_HEAVISIDE); + transformById(FUNCTION_ID_DIRAC); + mstruct2.transformById(FUNCTION_ID_DIRAC); + multiply(mstruct2); + if(ct == COMPARISON_EQUALS_GREATER || ct == COMPARISON_LESS) multiply_nocopy(new MathStructure(2, 1, 0)); + else multiply_nocopy(new MathStructure(-2, 1, 0)); + mstruct.differentiate(x_var, eo); + multiply(mstruct); + break; + } + transformById(FUNCTION_ID_DIFFERENTIATE); + addChild(x_var); + addChild(m_one); + addChild(m_undefined); + return false; + } + case STRUCT_UNIT: {} + case STRUCT_NUMBER: { + // a'=0 + clear(true); + break; + } + case STRUCT_POWER: { + if(SIZE < 1) { + clear(true); + break; + } else if(SIZE < 2) { + setToChild(1, true); + return differentiate(x_var, eo); + } + bool x_in_base = CHILD(0).containsRepresentativeOf(x_var, true, true) != 0; + bool x_in_exp = CHILD(1).containsRepresentativeOf(x_var, true, true) != 0; + if(x_in_base && !x_in_exp) { + // (f(x)^a)'=f'*a*f^(a-1) + MathStructure *exp_mstruct = new MathStructure(CHILD(1)); + if(!CHILD(1).isNumber() || !CHILD(1).number().add(-1)) CHILD(1) += m_minus_one; + if(!CHILD(0).equals(x_var)) { + MathStructure *base_mstruct = new MathStructure(CHILD(0)); + base_mstruct->differentiate(x_var, eo); + multiply_nocopy(base_mstruct); + } + multiply_nocopy(exp_mstruct); + } else if(!x_in_base && x_in_exp) { + // (a^f(x))'=f'*ln(a)*a^f + MathStructure *exp_mstruct = new MathStructure(CHILD(1)); + exp_mstruct->differentiate(x_var, eo); + if(!CHILD(0).isVariable() || CHILD(0).variable()->id() != VARIABLE_ID_E) { + MathStructure *mstruct = new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &CHILD(0), NULL); + multiply_nocopy(mstruct); + } + multiply_nocopy(exp_mstruct); + } else if(x_in_base && x_in_exp) { + // (f(x)^g(x))'=f^g*(ln(f)*g'+f'/f*g) + MathStructure *exp_mstruct = new MathStructure(CHILD(1)); + MathStructure *base_mstruct = new MathStructure(CHILD(0)); + exp_mstruct->differentiate(x_var, eo); + base_mstruct->differentiate(x_var, eo); + base_mstruct->divide(CHILD(0)); + base_mstruct->multiply(CHILD(1)); + MathStructure *mstruct = new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &CHILD(0), NULL); + mstruct->multiply_nocopy(exp_mstruct); + mstruct->add_nocopy(base_mstruct); + multiply_nocopy(mstruct); + } else { + clear(true); + } + break; + } + case STRUCT_FUNCTION: { + if(o_function->id() == FUNCTION_ID_SQRT && SIZE == 1) { + // sqrt(f)'=f'/(2*sqrt(f)) + SET_CHILD_MAP(0) + raise_nocopy(new MathStructure(-1, 2, 0)); + if(!CHILD(0).equals(x_var)) { + MathStructure *base_mstruct = new MathStructure(CHILD(0)); + base_mstruct->differentiate(x_var, eo); + multiply_nocopy(base_mstruct); + } + multiply_nocopy(new MathStructure(1, 2, 0)); + } else if(o_function->id() == FUNCTION_ID_ROOT && THIS_VALID_ROOT) { + // root(f,a)'=f'/(a*root(f,a)^(a-1)) + MathStructure *base_mstruct = new MathStructure(CHILD(0)); + MathStructure *mexp = new MathStructure(CHILD(1)); + mexp->negate(); + mexp->add(m_one); + raise_nocopy(mexp); + divide(CHILD(0)[1]); + base_mstruct->differentiate(x_var, eo); + multiply_nocopy(base_mstruct); + } else if(o_function->id() == FUNCTION_ID_CBRT && SIZE == 1) { + // cbrt(f)'=f'/(3*cbrt(x)^2) + raise_nocopy(new MathStructure(-2, 1, 0)); + if(!CHILD(0).equals(x_var)) { + MathStructure *base_mstruct = new MathStructure(CHILD(0)[0]); + base_mstruct->differentiate(x_var, eo); + multiply_nocopy(base_mstruct); + } + multiply_nocopy(new MathStructure(1, 3, 0)); + } else if((o_function->id() == FUNCTION_ID_LOG && SIZE == 1) || (o_function->id() == FUNCTION_ID_LOGN && SIZE == 2 && CHILD(1).isVariable() && CHILD(1).variable()->id() == VARIABLE_ID_E)) { + if(CHILD(0) == x_var) { + // ln(x)'=1/x + setToChild(1, true); + inverse(); + } else { + // ln(f)'=f'/f + MathStructure *mstruct = new MathStructure(CHILD(0)); + setToChild(1, true); + inverse(); + mstruct->differentiate(x_var, eo); + multiply_nocopy(mstruct); + } + } else if(o_function->id() == FUNCTION_ID_LOGN && SIZE == 2) { + // log(f,g)'=(log(f)/log(g))' + MathStructure *mstruct = new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &CHILD(1), NULL); + setFunctionId(FUNCTION_ID_LOG); + ERASE(1) + divide_nocopy(mstruct); + return differentiate(x_var, eo); + } else if(o_function->id() == FUNCTION_ID_BETA && SIZE == 2) { + // beta(f,g)')=beta(f,g)*((f'*digamma(f)-digamma(f+g))+g'*(digamma(g)-digamma(f+g))) + MathStructure mdigamma(CHILD(0)); + mdigamma += CHILD(1); + mdigamma.transformById(FUNCTION_ID_DIGAMMA); + MathStructure *m1 = NULL, *m2 = NULL; + if(CHILD(0).containsRepresentativeOf(x_var, true, true) != 0) { + m1 = new MathStructure(CHILD(0)); + m1->transformById(FUNCTION_ID_DIGAMMA); + m1->subtract(mdigamma); + MathStructure *mstruct = new MathStructure(CHILD(0)); + mstruct->differentiate(x_var, eo); + m1->multiply_nocopy(mstruct); + } + if(CHILD(1).containsRepresentativeOf(x_var, true, true) != 0) { + m2 = new MathStructure(CHILD(1)); + m2->transformById(FUNCTION_ID_DIGAMMA); + m2->subtract(mdigamma); + MathStructure *mstruct = new MathStructure(CHILD(1)); + mstruct->differentiate(x_var, eo); + m2->multiply_nocopy(mstruct); + } + if(m1) { + if(m2) m1->add_nocopy(m2); + multiply_nocopy(m1); + } else { + multiply_nocopy(m2); + } + } else if(o_function->id() == FUNCTION_ID_ARG && SIZE == 1) { + // arg(x)'=f'*-pi*dirac(f) + MathStructure mstruct(CHILD(0)); + setFunctionId(FUNCTION_ID_DIRAC); + mstruct.differentiate(x_var, eo); + multiply(mstruct); + multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + negate(); + } else if(o_function->id() == FUNCTION_ID_GAMMA && SIZE == 1) { + // gamma(f)'=f'*digamma(f) + MathStructure mstruct(CHILD(0)); + MathStructure mstruct2(*this); + mstruct2.setFunctionId(FUNCTION_ID_DIGAMMA); + multiply(mstruct2); + mstruct.differentiate(x_var, eo); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_FACTORIAL && SIZE == 1) { + // (f!)'=gamma(f+1)'=(f+1)'*digamma(f+1) + MathStructure mstruct(CHILD(0)); + CHILD(0) += m_one; + MathStructure mstruct2(*this); + mstruct2.setFunctionId(FUNCTION_ID_DIGAMMA); + multiply(mstruct2); + mstruct.differentiate(x_var, eo); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_BESSELJ && SIZE == 2 && CHILD(0).isInteger()) { + // besselj(n,f)'=f'*(besselj(n-1,f)-besselj(n+1,f))/2 + MathStructure mstruct(CHILD(1)); + MathStructure mstruct2(*this); + CHILD(0) += m_minus_one; + mstruct2[0] += m_one; + subtract(mstruct2); + mstruct.differentiate(x_var, eo); + multiply(mstruct); + multiply(nr_half); + } else if(o_function->id() == FUNCTION_ID_BESSELY && SIZE == 2 && CHILD(0).isInteger()) { + // bessely(n,f)'=f'*(bessely(n-1,f)-bessely(n+1,f))/2 + MathStructure mstruct(CHILD(1)); + MathStructure mstruct2(*this); + CHILD(0) += m_minus_one; + mstruct2[0] += m_one; + subtract(mstruct2); + mstruct.differentiate(x_var, eo); + multiply(mstruct); + multiply(nr_half); + } else if(o_function->id() == FUNCTION_ID_ERF && SIZE == 1) { + // erfi(f)'=f'*2/(e^(f^2)*sqrt(pi)) + MathStructure mdiff(CHILD(0)); + MathStructure mexp(CHILD(0)); + mexp ^= nr_two; + mexp.negate(); + set(CALCULATOR->getVariableById(VARIABLE_ID_E), true); + raise(mexp); + multiply(nr_two); + multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + LAST ^= Number(-1, 2); + mdiff.differentiate(x_var, eo); + multiply(mdiff); + } else if(o_function->id() == FUNCTION_ID_ERFI && SIZE == 1) { + // erfi(f)'=f'*2*e^(f^2)/sqrt(pi) + MathStructure mdiff(CHILD(0)); + MathStructure mexp(CHILD(0)); + mexp ^= nr_two; + set(CALCULATOR->getVariableById(VARIABLE_ID_E), true); + raise(mexp); + multiply(nr_two); + multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + LAST ^= Number(-1, 2); + mdiff.differentiate(x_var, eo); + multiply(mdiff); + } else if(o_function->id() == FUNCTION_ID_ERFC && SIZE == 1) { + // erfc(f)'=f'*-2/(e^(f^2)*sqrt(pi)) + MathStructure mdiff(CHILD(0)); + MathStructure mexp(CHILD(0)); + mexp ^= nr_two; + mexp.negate(); + set(CALCULATOR->getVariableById(VARIABLE_ID_E), true); + raise(mexp); + multiply(Number(-2, 1)); + multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + LAST ^= Number(-1, 2); + mdiff.differentiate(x_var, eo); + multiply(mdiff); + } else if(o_function->id() == FUNCTION_ID_FRESNEL_S && SIZE == 1) { + // fresnels(f)'=f'*fresnels(f^2*pi/2) + setFunctionId(FUNCTION_ID_SIN); + MathStructure mstruct(CHILD(0)); + CHILD(0) ^= nr_two; + CHILD(0) *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + CHILD(0) *= nr_half; + CHILD(0) *= CALCULATOR->getRadUnit(); + mstruct.differentiate(x_var, eo); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_FRESNEL_C && SIZE == 1) { + // fresnelc(f)'=f'*cos(f^2*pi/2) + setFunctionId(FUNCTION_ID_COS); + MathStructure mstruct(CHILD(0)); + CHILD(0) ^= nr_two; + CHILD(0) *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + CHILD(0) *= nr_half; + CHILD(0) *= CALCULATOR->getRadUnit(); + mstruct.differentiate(x_var, eo); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_LOGINT && SIZE == 1) { + // li(f)'=f'/ln(f) + setFunctionId(FUNCTION_ID_LOG); + MathStructure mstruct(CHILD(0)); + inverse(); + mstruct.differentiate(x_var, eo); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_POLYLOG && SIZE == 2 && CHILD(0).containsRepresentativeOf(x_var, true, true) == 0) { + // Li(a,f)'=f'*Li(a-1,f)/f + CHILD(0) += m_minus_one; + MathStructure mstruct(CHILD(1)); + divide(mstruct); + mstruct.differentiate(x_var, eo); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_EXPINT && SIZE == 1) { + // Ei(f)'=f'*e^f/f + MathStructure mexp(CALCULATOR->getVariableById(VARIABLE_ID_E)); + mexp ^= CHILD(0); + MathStructure mdiff(CHILD(0)); + mdiff.differentiate(x_var, eo); + mexp *= mdiff; + setToChild(1, true); + inverse(); + multiply(mexp); + } else if(o_function->id() == FUNCTION_ID_SININT && SIZE == 1) { + // Si(f)'=f'*sinc(f) + setFunctionId(FUNCTION_ID_SINC); + CHILD_UPDATED(0) + MathStructure mdiff(CHILD(0)); + mdiff.differentiate(x_var, eo); + multiply(mdiff); + } else if(o_function->id() == FUNCTION_ID_COSINT && SIZE == 1) { + // Ci(f)'=f'*cos(f)/f + setFunctionId(FUNCTION_ID_COS); + MathStructure marg(CHILD(0)); + MathStructure mdiff(CHILD(0)); + CHILD(0) *= CALCULATOR->getRadUnit(); + mdiff.differentiate(x_var, eo); + divide(marg); + multiply(mdiff); + } else if(o_function->id() == FUNCTION_ID_SINHINT && SIZE == 1) { + // Shi(f)'=f'*sinh(f)/f + setFunctionId(FUNCTION_ID_SINH); + MathStructure marg(CHILD(0)); + MathStructure mdiff(CHILD(0)); + mdiff.differentiate(x_var, eo); + divide(marg); + multiply(mdiff); + } else if(o_function->id() == FUNCTION_ID_COSHINT && SIZE == 1) { + // Chi(f)'=f'*cosh(f)/f + setFunctionId(FUNCTION_ID_COSH); + MathStructure marg(CHILD(0)); + MathStructure mdiff(CHILD(0)); + mdiff.differentiate(x_var, eo); + divide(marg); + multiply(mdiff); + } else if(o_function->id() == FUNCTION_ID_ABS && SIZE == 1) { + // abs(f)'=f'*f/abs(f) + MathStructure mstruct(CHILD(0)); + inverse(); + multiply(mstruct); + mstruct.differentiate(x_var, eo); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_SIGNUM && SIZE == 2) { + // sgn(f)'=f'*2*dirac(f) + MathStructure mstruct(CHILD(0)); + ERASE(1) + setFunctionId(FUNCTION_ID_DIRAC); + multiply_nocopy(new MathStructure(2, 1, 0)); + mstruct.differentiate(x_var, eo); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_HEAVISIDE && SIZE == 1) { + // heaviside(f)'=f'*dirac(f) + MathStructure mstruct(CHILD(0)); + setFunctionId(FUNCTION_ID_DIRAC); + mstruct.differentiate(x_var, eo); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_LAMBERT_W && SIZE >= 1) { + // lambertw(f)'=f'*lambertw(f)/(f*(1+lambertw(f))) + MathStructure *mstruct = new MathStructure(*this); + MathStructure *mstruct2 = new MathStructure(CHILD(0)); + mstruct->add(m_one); + mstruct->multiply(CHILD(0)); + mstruct2->differentiate(x_var, eo); + multiply_nocopy(mstruct2); + divide_nocopy(mstruct); + } else if(o_function->id() == FUNCTION_ID_SIN && SIZE == 1) { + // sin(f)'=f'*cos(f) + setFunctionId(FUNCTION_ID_COS); + MathStructure mstruct(CHILD(0)); + mstruct.calculateDivide(CALCULATOR->getRadUnit(), eo); + if(mstruct != x_var) { + mstruct.differentiate(x_var, eo); + multiply(mstruct); + } + } else if(o_function->id() == FUNCTION_ID_COS && SIZE == 1) { + // cos(f)'=f'*sin(f) + setFunctionId(FUNCTION_ID_SIN); + MathStructure mstruct(CHILD(0)); + negate(); + mstruct.calculateDivide(CALCULATOR->getRadUnit(), eo); + if(mstruct != x_var) { + mstruct.differentiate(x_var, eo); + multiply(mstruct); + } + } else if(o_function->id() == FUNCTION_ID_TAN && SIZE == 1) { + // tan(f)'=f'*(1+tan(f)^2) + setFunctionId(FUNCTION_ID_TAN); + MathStructure mstruct(CHILD(0)); + raise(2); + add(nr_one); + mstruct.differentiate(x_var, eo); + multiply(mstruct, true); + if(CALCULATOR->getRadUnit()) divide(CALCULATOR->getRadUnit()); + } else if(o_function->id() == FUNCTION_ID_SINH && SIZE == 1) { + // sinh(f)'=f'*cosh(f) + setFunctionId(FUNCTION_ID_COSH); + MathStructure mstruct(CHILD(0)); + mstruct.differentiate(x_var, eo); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_COSH && SIZE == 1) { + // cosh(f)'=f'*sinh(f) + setFunctionId(FUNCTION_ID_SINH); + MathStructure mstruct(CHILD(0)); + mstruct.differentiate(x_var, eo); + multiply(mstruct, true); + } else if(o_function->id() == FUNCTION_ID_TANH && SIZE == 1) { + // tanh(f)'=f'*(1-tanh(f)^2) + setFunctionId(FUNCTION_ID_TANH); + MathStructure mstruct(CHILD(0)); + raise(2); + negate(); + add(nr_one); + mstruct.differentiate(x_var, eo); + multiply(mstruct, true); + } else if(o_function->id() == FUNCTION_ID_ASIN && SIZE == 1) { + // asin(f)'=f'/sqrt(1-f^2) + MathStructure mstruct(CHILD(0)); + mstruct.differentiate(x_var, eo); + SET_CHILD_MAP(0); + raise(2); + negate(); + add(m_one); + raise(Number(-1, 2)); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_ACOS && SIZE == 1) { + // acos(f)'=-f'/sqrt(1-f^2) + MathStructure mstruct(CHILD(0)); + mstruct.differentiate(x_var, eo); + SET_CHILD_MAP(0); + raise(2); + negate(); + add(m_one); + raise(Number(-1, 2)); + negate(); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_ATAN && SIZE == 1) { + // asin(f)'=f'/(1+f^2) + MathStructure mstruct(CHILD(0)); + mstruct.differentiate(x_var, eo); + SET_CHILD_MAP(0); + raise(2); + add(m_one); + raise(m_minus_one); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_ASINH && SIZE == 1) { + // asinh(f)'=f'/sqrt(1+f^2) + MathStructure mstruct(CHILD(0)); + mstruct.differentiate(x_var, eo); + SET_CHILD_MAP(0); + raise(2); + add(m_one); + raise(Number(-1, 2)); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_ACOSH && SIZE == 1) { + // acosh(f)'=f'/(sqrt(f-1)*sqrt(f+1)) + MathStructure mstruct(CHILD(0)); + mstruct.differentiate(x_var, eo); + SET_CHILD_MAP(0); + MathStructure mfac(*this); + add(m_minus_one); + raise(Number(-1, 2)); + mfac.add(m_one); + mfac.raise(Number(-1, 2)); + multiply(mfac); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_ATANH && SIZE == 1) { + // atanh(f)'=f'/(1-x^2) + MathStructure mstruct(CHILD(0)); + mstruct.differentiate(x_var, eo); + SET_CHILD_MAP(0); + raise(2); + negate(); + add(m_one); + raise(m_minus_one); + multiply(mstruct); + } else if(o_function->id() == FUNCTION_ID_SINC && SIZE == 1) { + // sinc(f)'=f'*(cos(f)/f-sin(f)/f^2) + MathStructure m_cos(CALCULATOR->getFunctionById(FUNCTION_ID_COS), &CHILD(0), NULL); + if(CALCULATOR->getRadUnit()) m_cos[0].multiply(CALCULATOR->getRadUnit()); + m_cos.divide(CHILD(0)); + MathStructure m_sin(CALCULATOR->getFunctionById(FUNCTION_ID_SIN), &CHILD(0), NULL); + if(CALCULATOR->getRadUnit()) m_sin[0].multiply(CALCULATOR->getRadUnit()); + MathStructure mstruct(CHILD(0)); + mstruct.raise(Number(-2, 1, 0)); + m_sin.multiply(mstruct); + MathStructure mdiff(CHILD(0)); + mdiff.differentiate(x_var, eo); + set(m_sin); + negate(); + add(m_cos); + multiply(mdiff); + } else if(o_function->id() == FUNCTION_ID_STRIP_UNITS && SIZE == 1) { + // nounit(f)'=nounit(f') + CHILD(0).differentiate(x_var, eo); + } else if(o_function->id() == FUNCTION_ID_INTEGRATE && SIZE >= 4 && CHILD(3) == x_var && CHILD(1).isUndefined() && CHILD(2).isUndefined()) { + // integrate(f,undefined,undefined,x)'=f + SET_CHILD_MAP(0); + } else if(o_function->id() == FUNCTION_ID_DIFFERENTIATE && (SIZE == 3 || (SIZE == 4 && CHILD(3).isUndefined())) && CHILD(1) == x_var) { + // diff(f,x,a)'=diff(f,x,a+1) + CHILD(2) += m_one; + } else if(o_function->id() == FUNCTION_ID_DIFFERENTIATE && SIZE == 2 && CHILD(1) == x_var) { + // diff(f,x)'=diff(f,x,2) + APPEND(MathStructure(2, 1, 0)); + } else if(o_function->id() == FUNCTION_ID_DIFFERENTIATE && SIZE == 1 && x_var == CALCULATOR->getVariableById(VARIABLE_ID_X)) { + // diff(f)'=diff(f,x,2) + APPEND(x_var); + APPEND(MathStructure(2, 1, 0)); + } else { + // calculate non-differentiable function and try again + if(!eo.calculate_functions || !calculateFunctions(eo, false)) { + transformById(FUNCTION_ID_DIFFERENTIATE); + addChild(x_var); + addChild(m_one); + addChild(m_undefined); + return false; + } else { + return differentiate(x_var, eo); + } + } + break; + } + case STRUCT_MULTIPLICATION: { + // product rule: (f(x)g(x))'=f'g+fg' + MathStructure mstruct, vstruct; + size_t idiv = 0; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isPower() && CHILD(i)[1].isNumber() && CHILD(i)[1].number().isNegative()) { + if(idiv == 0) { + if(CHILD(i)[1].isMinusOne()) { + vstruct = CHILD(i)[0]; + } else { + vstruct = CHILD(i); + vstruct[1].number().negate(); + } + } else { + if(CHILD(i)[1].isMinusOne()) { + vstruct.multiply(CHILD(i)[0], true); + } else { + vstruct.multiply(CHILD(i), true); + vstruct[vstruct.size() - 1][1].number().negate(); + } + } + idiv++; + } + } + if(idiv == SIZE) { + set(-1, 1); + MathStructure mdiv(vstruct); + mdiv ^= MathStructure(2, 1, 0); + mdiv.inverse(); + multiply(mdiv); + MathStructure diff_u(vstruct); + diff_u.differentiate(x_var, eo); + multiply(diff_u, true); + break; + } else if(idiv > 0) { + idiv = 0; + for(size_t i = 0; i < SIZE; i++) { + if(!CHILD(i).isPower() || !CHILD(i)[1].isNumber() || !CHILD(i)[1].number().isNegative()) { + if(idiv == 0) { + mstruct = CHILD(i); + } else { + mstruct.multiply(CHILD(i), true); + } + idiv++; + } + } + MathStructure mdiv(vstruct); + mdiv ^= MathStructure(2, 1, 0); + MathStructure diff_v(vstruct); + diff_v.differentiate(x_var, eo); + MathStructure diff_u(mstruct); + diff_u.differentiate(x_var, eo); + vstruct *= diff_u; + mstruct *= diff_v; + set_nocopy(vstruct, true); + subtract(mstruct); + divide(mdiv); + break; + } + if(SIZE > 2) { + mstruct.set(*this); + mstruct.delChild(mstruct.size()); + MathStructure mstruct2(LAST); + MathStructure mstruct3(mstruct); + mstruct.differentiate(x_var, eo); + mstruct2.differentiate(x_var, eo); + mstruct *= LAST; + mstruct2 *= mstruct3; + set(mstruct, true); + add(mstruct2); + } else { + mstruct = CHILD(0); + MathStructure mstruct2(CHILD(1)); + mstruct.differentiate(x_var, eo); + mstruct2.differentiate(x_var, eo); + mstruct *= CHILD(1); + mstruct2 *= CHILD(0); + set(mstruct, true); + add(mstruct2); + } + break; + } + case STRUCT_SYMBOLIC: { + // y'=0 + if(representsNumber(true)) { + clear(true); + } else { + transformById(FUNCTION_ID_DIFFERENTIATE); + addChild(x_var); + addChild(m_one); + addChild(m_undefined); + return false; + } + break; + } + case STRUCT_VARIABLE: { + // differentiate value of variable + if(eo.calculate_variables && o_variable->isKnown()) { + if(eo.approximation != APPROXIMATION_EXACT || !o_variable->isApproximate()) { + set(((KnownVariable*) o_variable)->get(), true); + unformat(eo); + return differentiate(x_var, eo); + } else { + transformById(FUNCTION_ID_DIFFERENTIATE); + addChild(x_var); + addChild(m_one); + addChild(m_undefined); + return false; + } + } + } + default: { + // ?'=diff(?,x,1) + transformById(FUNCTION_ID_DIFFERENTIATE); + addChild(x_var); + addChild(m_one); + addChild(m_undefined); + return false; + } + } + remove_zero_mul(*this); + return true; +} + diff -Nru libqalculate-3.6.0/libqalculate/MathStructure-eval.cc libqalculate-3.7.0/libqalculate/MathStructure-eval.cc --- libqalculate-3.6.0/libqalculate/MathStructure-eval.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure-eval.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,2309 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "MathStructure.h" +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "Number.h" +#include "Function.h" +#include "Variable.h" +#include "Unit.h" +#include "Prefix.h" +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +/* + Functions for simple handling of interval variables +*/ + +#define IS_VAR_EXP(x, ofa) ((x.isVariable() && x.variable()->isKnown() && (!ofa || x.variable()->title() == "\b")) || (x.isPower() && x[0].isVariable() && x[0].variable()->isKnown() && (!ofa || x[0].variable()->title() == "\b"))) + +void factorize_variable(MathStructure &mstruct, const MathStructure &mvar, bool deg2) { + if(deg2) { + // ax^2+bx = (sqrt(b)*x+(a/sqrt(b))/2)^2-((a/sqrt(b))/2)^2 + MathStructure a_struct, b_struct, mul_struct(1, 1, 0); + for(size_t i2 = 0; i2 < mstruct.size();) { + bool b = false; + if(mstruct[i2] == mvar) { + a_struct.set(1, 1, 0); + b = true; + } else if(mstruct[i2].isPower() && mstruct[i2][0] == mvar && mstruct[i2][1].isNumber() && mstruct[i2][1].number().isTwo()) { + b_struct.set(1, 1, 0); + b = true; + } else if(mstruct[i2].isMultiplication()) { + for(size_t i3 = 0; i3 < mstruct[i2].size(); i3++) { + if(mstruct[i2][i3] == mvar) { + a_struct = mstruct[i2]; + a_struct.delChild(i3 + 1); + b = true; + break; + } else if(mstruct[i2][i3].isPower() && mstruct[i2][i3][0] == mvar && mstruct[i2][i3][1].isNumber() && mstruct[i2][i3][1].number().isTwo()) { + b_struct = mstruct[i2]; + b_struct.delChild(i3 + 1); + b = true; + break; + } + } + } + if(b) { + mstruct.delChild(i2 + 1); + } else { + i2++; + } + } + if(b_struct == a_struct) { + if(a_struct.isMultiplication() && a_struct.size() == 1) mul_struct = a_struct[0]; + else mul_struct = a_struct; + a_struct.set(1, 1, 0); + b_struct.set(1, 1, 0); + } else if(b_struct.isMultiplication() && a_struct.isMultiplication()) { + size_t i3 = 0; + for(size_t i = 0; i < a_struct.size();) { + bool b = false; + for(size_t i2 = i3; i2 < b_struct.size(); i2++) { + if(a_struct[i] == b_struct[i2]) { + i3 = i2; + if(mul_struct.isOne()) mul_struct = a_struct[i]; + else mul_struct.multiply(a_struct[i], true); + a_struct.delChild(i + 1); + b_struct.delChild(i2 + 1); + b = true; + break; + } + } + if(!b) i++; + } + } + if(a_struct.isMultiplication() && a_struct.size() == 0) a_struct.set(1, 1, 0); + else if(a_struct.isMultiplication() && a_struct.size() == 1) a_struct.setToChild(1); + if(b_struct.isMultiplication() && b_struct.size() == 0) b_struct.set(1, 1, 0); + else if(b_struct.isMultiplication() && b_struct.size() == 1) b_struct.setToChild(1); + if(!b_struct.isOne()) { + b_struct.raise(nr_half); + a_struct.divide(b_struct); + } + a_struct.multiply(nr_half); + if(b_struct.isOne()) b_struct = mvar; + else b_struct *= mvar; + b_struct += a_struct; + b_struct.raise(nr_two); + a_struct.raise(nr_two); + a_struct.negate(); + b_struct += a_struct; + if(!mul_struct.isOne()) b_struct *= mul_struct; + if(mstruct.size() == 0) mstruct = b_struct; + else mstruct.addChild(b_struct); + } else { + vector left_structs; + for(size_t i2 = 0; i2 < mstruct.size();) { + bool b = false; + if(mstruct[i2] == mvar) { + mstruct[i2].set(1, 1, 0, true); + b = true; + } else if(mstruct[i2].isMultiplication()) { + for(size_t i3 = 0; i3 < mstruct[i2].size(); i3++) { + if(mstruct[i2][i3] == mvar) { + mstruct[i2].delChild(i3 + 1, true); + b = true; + break; + } + } + } + if(b) { + i2++; + } else { + mstruct[i2].ref(); + left_structs.push_back(&mstruct[i2]); + mstruct.delChild(i2 + 1); + } + } + mstruct.multiply(mvar); + for(size_t i = 0; i < left_structs.size(); i++) { + mstruct.add_nocopy(left_structs[i], true); + mstruct.evalSort(false); + } + } +} +bool var_contains_interval(const MathStructure &mstruct) { + if(mstruct.isNumber()) return mstruct.number().isInterval(); + if(mstruct.isFunction() && (mstruct.function()->id() == FUNCTION_ID_INTERVAL || mstruct.function()->id() == FUNCTION_ID_UNCERTAINTY)) return true; + if(mstruct.isVariable() && mstruct.variable()->isKnown()) return var_contains_interval(((KnownVariable*) mstruct.variable())->get()); + for(size_t i = 0; i < mstruct.size(); i++) { + if(var_contains_interval(mstruct[i])) return true; + } + return false; +} + +bool factorize_variables(MathStructure &mstruct, const EvaluationOptions &eo, bool ofa = false) { + bool b = false; + if(mstruct.type() == STRUCT_ADDITION) { + vector variables; + vector variable_count; + vector term_sgn; + vector term_deg2; + for(size_t i = 0; i < mstruct.size(); i++) { + if(CALCULATOR->aborted()) break; + if(mstruct[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { + if(CALCULATOR->aborted()) break; + if(IS_VAR_EXP(mstruct[i][i2], ofa)) { + bool b_found = false; + for(size_t i3 = 0; i3 < variables.size(); i3++) { + if(variables[i3] == mstruct[i][i2]) { + variable_count[i3]++; + b_found = true; + if(term_sgn[i3] == 1 && !mstruct[i].representsNonNegative(true)) term_sgn[i3] = 0; + else if(term_sgn[i3] == -1 && !mstruct[i].representsNonPositive(true)) term_sgn[i3] = 0; + break; + } + } + if(!b_found) { + variables.push_back(mstruct[i][i2]); + variable_count.push_back(1); + term_deg2.push_back(false); + if(mstruct[i].representsNonNegative(true)) term_sgn.push_back(1); + else if(mstruct[i].representsNonPositive(true)) term_sgn.push_back(-1); + else term_sgn.push_back(0); + } + } + } + } else if(IS_VAR_EXP(mstruct[i], ofa)) { + bool b_found = false; + for(size_t i3 = 0; i3 < variables.size(); i3++) { + if(variables[i3] == mstruct[i]) { + variable_count[i3]++; + b_found = true; + if(term_sgn[i3] == 1 && !mstruct[i].representsNonNegative(true)) term_sgn[i3] = 0; + else if(term_sgn[i3] == -1 && !mstruct[i].representsNonPositive(true)) term_sgn[i3] = 0; + break; + } + } + if(!b_found) { + variables.push_back(mstruct[i]); + variable_count.push_back(1); + term_deg2.push_back(false); + if(mstruct[i].representsNonNegative(true)) term_sgn.push_back(1); + else if(mstruct[i].representsNonPositive(true)) term_sgn.push_back(-1); + else term_sgn.push_back(0); + } + } + } + for(size_t i = 0; i < variables.size();) { + bool b_erase = false; + if(!var_contains_interval(variables[i])) { + b_erase = true; + } else if(variable_count[i] == 1 || term_sgn[i] != 0) { + b_erase = true; + if(!variables[i].isPower() || (variables[i][1].isNumber() && variables[i][1].number().isTwo())) { + for(size_t i2 = i + 1; i2 < variables.size(); i2++) { + if((variables[i].isPower() && !variables[i2].isPower() && variables[i][0] == variables[i2])|| (!variables[i].isPower() && variables[i2].isPower() && variables[i2][0] == variables[i] && variables[i2][1].isNumber() && variables[i2][1].number().isTwo())) { + bool b_erase2 = false; + if(variable_count[i2] == 1) { + if(term_sgn[i] == 0 || term_sgn[i2] != term_sgn[i]) { + if(variable_count[i] == 1) { + term_deg2[i] = true; + variable_count[i] = 2; + term_sgn[i] = 0; + if(variables[i].isPower()) variables[i].setToChild(1); + } else { + term_sgn[i] = 0; + } + b_erase = false; + } + b_erase2 = true; + } else if(term_sgn[i2] != 0) { + if(term_sgn[i] == 0 || term_sgn[i2] != term_sgn[i]) { + if(variable_count[i] != 1) { + term_sgn[i] = 0; + b_erase = false; + } + term_sgn[i2] = 0; + } else { + b_erase2 = true; + } + } + if(b_erase2) { + variable_count.erase(variable_count.begin() + i2); + variables.erase(variables.begin() + i2); + term_deg2.erase(term_deg2.begin() + i2); + term_sgn.erase(term_sgn.begin() + i2); + } + break; + } + } + } + } + if(b_erase) { + variable_count.erase(variable_count.begin() + i); + variables.erase(variables.begin() + i); + term_deg2.erase(term_deg2.begin() + i); + term_sgn.erase(term_sgn.begin() + i); + } else if(variable_count[i] == mstruct.size()) { + factorize_variable(mstruct, variables[i], term_deg2[i]); + if(CALCULATOR->aborted()) return true; + factorize_variables(mstruct, eo, ofa); + return true; + } else { + i++; + } + } + if(variables.size() == 1) { + factorize_variable(mstruct, variables[0], term_deg2[0]); + if(CALCULATOR->aborted()) return true; + factorize_variables(mstruct, eo, ofa); + return true; + } + Number uncertainty; + size_t u_index = 0; + for(size_t i = 0; i < variables.size(); i++) { + const MathStructure *v_ms; + Number nr; + if(variables[i].isPower()) v_ms = &((KnownVariable*) variables[i][0].variable())->get(); + else v_ms = &((KnownVariable*) variables[i].variable())->get(); + if(v_ms->isNumber()) nr = v_ms->number(); + else if(v_ms->isMultiplication() && v_ms->size() > 0 && (*v_ms)[0].isNumber()) nr = (v_ms)[0].number(); + else { + MathStructure mtest(*v_ms); + mtest.unformat(eo); + mtest.calculatesub(eo, eo, true); + if(mtest.isNumber()) nr = mtest.number(); + else if(mtest.isMultiplication() && mtest.size() > 0 && mtest[0].isNumber()) nr = mtest[0].number(); + } + if(nr.isInterval()) { + Number u_candidate(nr.uncertainty()); + if(variables[i].isPower() && variables[i][1].isNumber() && variables[i][1].number().isReal()) u_candidate.raise(variables[i][1].number()); + u_candidate.multiply(variable_count[i]); + if(u_candidate.isGreaterThan(uncertainty)) { + uncertainty = u_candidate; + u_index = i; + } + } + } + if(!uncertainty.isZero()) { + factorize_variable(mstruct, variables[u_index], term_deg2[u_index]); + if(CALCULATOR->aborted()) return true; + factorize_variables(mstruct, eo, ofa); + return true; + } + + } + for(size_t i = 0; i < mstruct.size(); i++) { + if(factorize_variables(mstruct[i], eo, ofa)) { + mstruct.childUpdated(i + 1); + b = true; + } + if(CALCULATOR->aborted()) return b; + } + return b; +} +bool contains_duplicate_interval_variables_eq(const MathStructure &mstruct, const MathStructure &xvar, vector &vars) { + if(mstruct.isVariable() && mstruct.variable()->isKnown() && ((KnownVariable*) mstruct.variable())->get().containsInterval(false, true, false, false)) { + KnownVariable *v = (KnownVariable*) mstruct.variable(); + for(size_t i = 0; i < vars.size(); i++) { + if(vars[i] == v) { + return true; + } + } + vars.push_back(v); + } + for(size_t i = 0; i < mstruct.size(); i++) { + if(contains_duplicate_interval_variables_eq(mstruct[i], xvar, vars)) return true; + } + return false; +} +bool fix_eqs(MathStructure &m, const EvaluationOptions &eo) { + for(size_t i = 0; i < m.size(); i++) { + if(fix_eqs(m[i], eo)) m.childUpdated(i + 1); + } + if(m.isComparison()) { + if(CALCULATOR->aborted()) return false; + const MathStructure *x_var; + if(eo.isolate_var && m.contains(*eo.isolate_var)) x_var = eo.isolate_var; + else x_var = &m.find_x_var(); + if(!x_var->isUndefined()) { + vector vars; + if(contains_duplicate_interval_variables_eq(m, *x_var, vars)) { + if(!m[0].contains(*x_var)) { + m.swapChildren(1, 2); + } else if(m[0].isAddition()) { + for(size_t i = 0; i < m[0].size();) { + if(!m[0][i].contains(*x_var)) { + m[0][i].calculateNegate(eo); + m[0][i].ref(); + m[1].add_nocopy(&m[0][i], true); + m[1].calculateAddLast(eo); + m[0].delChild(i + 1); + } else { + i++; + } + } + if(m[0].size() == 1) m[0].setToChild(1, true); + else if(m[0].size() == 0) m[0].clear(true); + m.childrenUpdated(); + } + if(m[1].isAddition()) { + for(size_t i = 0; i < m[1].size();) { + if(m[1][i].contains(*x_var)) { + m[1][i].calculateNegate(eo); + m[1][i].ref(); + m[0].add_nocopy(&m[1][i], true); + m[0].calculateAddLast(eo); + m[1].delChild(i + 1); + } else { + i++; + } + } + if(m[1].size() == 1) m[1].setToChild(1, true); + else if(m[1].size() == 0) m[1].clear(true); + m.childrenUpdated(); + } else if(m[1].contains(*x_var)) { + m[0].calculateSubtract(m[1], eo); + m[1].clear(true); + } + vars.clear(); + if(m[0].containsType(STRUCT_ADDITION) && contains_duplicate_interval_variables_eq(m[0], *x_var, vars)) m[0].factorize(eo, false, false, 0, false, 1, NULL, m_undefined, false, false, 3); + return true; + } + } + } + return false; +} +// end functions for simple handling of interval variables + + +/* + + Functions for handling of interval variables using interval arithmetic. Calculates the derivative of the expression for each interval variable, searches points where the derivative is zero, and calculates the epxression separately for approriate subintervals. + +*/ + +void find_interval_variables(const MathStructure &mstruct, vector &vars, vector &v_count, vector &v_prec) { + if(mstruct.isVariable() && mstruct.variable()->isKnown()) { + KnownVariable *v = (KnownVariable*) mstruct.variable(); + int var_prec = PRECISION + 11; + const MathStructure &mv = v->get(); + for(size_t i = 0; i < vars.size(); i++) { + if(vars[i] == v) { + v_count[i]++; + return; + } + } + if(mv.isNumber()) { + if(mv.number().isInterval()) var_prec = mv.number().precision(1); + else if(CALCULATOR->usesIntervalArithmetic() && mv.number().precision() >= 0) var_prec = mv.number().precision(); + } else if(mv.isMultiplication()) { + for(size_t i = 0; i < mv.size(); i++) { + if(mv[i].isNumber()) { + if(mv[i].number().isInterval()) {var_prec = mv[i].number().precision(1); break;} + else if(mv[i].number().precision() >= 0) {var_prec = mv[i].number().precision(); break;} + } + } + } + if(var_prec <= PRECISION + 10) { + bool b = false; + for(size_t i = 0; i < v_prec.size(); i++) { + if(var_prec < v_prec[i]) { + v_prec.insert(v_prec.begin() + i, var_prec); + v_count.insert(v_count.begin() + i, 1); + vars.insert(vars.begin() + i, v); + b = true; + break; + } + } + if(!b) { + v_prec.push_back(var_prec); + v_count.push_back(1); + vars.push_back(v); + } + } + } + for(size_t i = 0; i < mstruct.size(); i++) { + find_interval_variables(mstruct[i], vars, v_count, v_prec); + } +} +bool contains_not_nonzero(MathStructure &m) { + if(m.isNumber() && !m.number().isNonZero()) { + return true; + } else if(m.isMultiplication()) { + for(size_t i = 0; i < m.size(); i++) { + if(contains_not_nonzero(m[i])) return true; + } + } + return false; +} +bool contains_undefined(MathStructure &m, const EvaluationOptions &eo = default_evaluation_options, bool calc = false, const MathStructure &x_var = m_zero, const MathStructure &m_intval = nr_zero) { + if(m.isPower() && (m[1].representsNegative() || (m[1].isNumber() && !m[1].number().isNonNegative()))) { + if(calc) { + m[0].replace(x_var, m_intval, true); + m[0].calculatesub(eo, eo, true); + } + if(contains_not_nonzero(m[0])) return true; + } + for(size_t i = 0; i < m.size(); i++) { + if(contains_undefined(m[i], eo, calc, x_var, m_intval)) return true; + } + return false; +} + +// search for values where the expression is non-zero, using intervals of diminishing width +bool find_interval_zeroes(const MathStructure &mstruct, MathStructure &malts, const MathStructure &mvar, const Number &nr_intval, const EvaluationOptions &eo, int depth, const Number &nr_prec, int orig_prec = 0, int is_real = -1, int undef_depth = 0) { + if(CALCULATOR->aborted()) return false; + if(depth == 0) orig_prec = nr_intval.precision(1); + MathStructure mtest(mstruct); + mtest.replace(mvar, nr_intval); + mtest.eval(eo); + if(is_real < 0) is_real = mtest.representsNonComplex(true); + ComparisonResult cmp; + if(is_real == 0) { + MathStructure m_re(CALCULATOR->getFunctionById(FUNCTION_ID_RE), &mtest, NULL); + m_re.calculateFunctions(eo); + cmp = m_re.compare(m_zero); + MathStructure m_im(CALCULATOR->getFunctionById(FUNCTION_ID_IM), &mtest, NULL); + m_im.calculateFunctions(eo); + ComparisonResult cmp2 = m_im.compare(m_zero); + if(COMPARISON_IS_NOT_EQUAL(cmp) || cmp2 == COMPARISON_RESULT_EQUAL || cmp == COMPARISON_RESULT_UNKNOWN) cmp = cmp2; + } else { + cmp = mtest.compare(m_zero); + } + if(COMPARISON_IS_NOT_EQUAL(cmp)) { + return true; + } else if(cmp != COMPARISON_RESULT_UNKNOWN || (undef_depth <= 5 && contains_undefined(mtest))) { + if(cmp == COMPARISON_RESULT_EQUAL || (nr_intval.precision(1) > (orig_prec > PRECISION ? orig_prec + 5 : PRECISION + 5) || (!nr_intval.isNonZero() && nr_intval.uncertainty().isLessThan(nr_prec)))) { + if(cmp == COMPARISON_RESULT_EQUAL && depth <= 3) return false; + if(malts.size() > 0 && (cmp = malts.last().compare(nr_intval)) != COMPARISON_RESULT_UNKNOWN && COMPARISON_MIGHT_BE_EQUAL(cmp)) { + malts.last().number().setInterval(malts.last().number(), nr_intval); + if(malts.last().number().precision(1) < (orig_prec > PRECISION ? orig_prec + 3 : PRECISION + 3)) { + return false; + } + } else { + malts.addChild(nr_intval); + } + return true; + } + vector splits; + nr_intval.splitInterval(2, splits); + for(size_t i = 0; i < splits.size(); i++) { + if(!find_interval_zeroes(mstruct, malts, mvar, splits[i], eo, depth + 1, nr_prec, orig_prec, is_real, cmp == COMPARISON_RESULT_UNKNOWN ? undef_depth + 1 : 0)) return false; + } + return true; + } + return false; +} +bool contains_interval_variable(const MathStructure &m, int i_type = 0) { + if(i_type == 0 && m.isVariable() && m.containsInterval(true, true, false, 1, false)) return true; + else if(i_type == 1 && m.containsInterval(true, false, false, 1, true)) return true; + else if(i_type == 2 && m.containsInterval(true, true, false, 1, true)) return true; + for(size_t i = 0; i < m.size(); i++) { + if(contains_interval_variable(m[i])) return true; + } + return false; +} +bool calculate_differentiable_functions(MathStructure &m, const EvaluationOptions &eo, bool recursive = true, bool do_unformat = true) { + if(m.isFunction() && m.function() != eo.protected_function && function_differentiable(m.function())) { + return m.calculateFunctions(eo, recursive, do_unformat); + } + bool b = false; + if(recursive) { + for(size_t i = 0; i < m.size(); i++) { + if(CALCULATOR->aborted()) break; + if(calculate_differentiable_functions(m[i], eo, recursive, do_unformat)) { + m.childUpdated(i + 1); + b = true; + } + } + } + return b; +} +bool calculate_nondifferentiable_functions(MathStructure &m, const EvaluationOptions &eo, bool recursive, bool do_unformat, int i_type) { + if(m.isFunction() && m.function() != eo.protected_function) { + if((i_type <= 0 && !function_differentiable(m.function())) || (i_type >= 0 && !contains_interval_variable(m, i_type))) { + if(m.calculateFunctions(eo, false, do_unformat)) { + if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type); + return true; + } + } else if(m.function()->id() == FUNCTION_ID_ABS && m.size() == 1) { + EvaluationOptions eo3 = eo; + eo3.split_squares = false; + eo3.assume_denominators_nonzero = false; + if(eo.approximation == APPROXIMATION_APPROXIMATE && !m.containsUnknowns()) eo3.approximation = APPROXIMATION_EXACT_VARIABLES; + else eo3.approximation = APPROXIMATION_EXACT; + m[0].calculatesub(eo3, eo); + m.childUpdated(1); + if(m[0].representsNegative(true)) { + m.setToChild(1); + m.negate(); + if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type); + return true; + } + if(m[0].representsNonNegative(true)) { + m.setToChild(1); + if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type); + return true; + } + if(m[0].isMultiplication()) { + m.setToChild(1); + for(size_t i = 0; i < m.size(); i++) { + m[i].transformById(FUNCTION_ID_ABS); + } + m.childrenUpdated(); + if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type); + return true; + } + if(eo.approximation != APPROXIMATION_EXACT) { + eo3.approximation = APPROXIMATION_APPROXIMATE; + MathStructure mtest(m[0]); + mtest.calculatesub(eo3, eo); + if(mtest.representsNegative(true)) { + m.setToChild(1); + m.negate(); + if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type); + return true; + } + if(mtest.representsNonNegative(true)) { + m.setToChild(1); + if(recursive) calculate_nondifferentiable_functions(m, eo, recursive, do_unformat, i_type); + return true; + } + } + } + } + bool b = false; + if(recursive) { + for(size_t i = 0; i < m.size(); i++) { + if(CALCULATOR->aborted()) break; + if(calculate_nondifferentiable_functions(m[i], eo, recursive, do_unformat, i_type)) { + m.childUpdated(i + 1); + b = true; + } + } + } + return b; +} + +void remove_nonzero_mul(MathStructure &msolve, const MathStructure &u_var, const EvaluationOptions &eo) { + if(!msolve.isMultiplication()) return; + for(size_t i = 0; i < msolve.size();) { + if(!msolve[i].contains(u_var, true)) { + msolve[i].eval(eo); + if(msolve[i].representsNonZero(true)) { + if(msolve.size() == 2) { + msolve.delChild(i + 1, true); + break; + } + msolve.delChild(i + 1, true); + } else { + remove_nonzero_mul(msolve[i], u_var, eo); + i++; + } + } else { + remove_nonzero_mul(msolve[i], u_var, eo); + i++; + } + } +} + +void solve_intervals2(MathStructure &mstruct, vector vars, const EvaluationOptions &eo_pre) { + if(vars.size() > 0) { + EvaluationOptions eo = eo_pre; + eo.approximation = APPROXIMATION_EXACT_VARIABLES; + eo.expand = false; + if(eo.calculate_functions) calculate_differentiable_functions(mstruct, eo); + KnownVariable *v = vars[0]; + vars.erase(vars.begin()); + UnknownVariable *u_var = new UnknownVariable("", "u"); + Number nr_intval; + MathStructure mvar(u_var); + const MathStructure &mv = v->get(); + MathStructure mmul(1, 1, 0); + if(mv.isMultiplication()) { + for(size_t i = 0; i < mv.size(); i++) { + if(mv[i].isNumber() && mv[i].number().isInterval()) { + mmul = mv; + mmul.unformat(eo); + mmul.delChild(i + 1, true); + mvar.multiply(mmul); + nr_intval = mv[i].number(); + u_var->setInterval(nr_intval); + break; + } + } + } else { + nr_intval = mv.number(); + u_var->setInterval(mv); + } + MathStructure msolve(mstruct); + msolve.replace(v, mvar); + bool b = true; + CALCULATOR->beginTemporaryStopMessages(); + + if(!msolve.differentiate(u_var, eo) || msolve.countTotalChildren(false) > 10000 || contains_diff_for(msolve, u_var) || CALCULATOR->aborted()) { + b = false; + } + + MathStructure malts; + malts.clearVector(); + if(b) { + eo.keep_zero_units = false; + eo.approximation = APPROXIMATION_APPROXIMATE; + eo.expand = eo_pre.expand; + // test if derivative is non-zero, replacing each occurrence of the variable with independent intervals + MathStructure mtest(msolve); + mtest.replace(u_var, nr_intval); + mtest.eval(eo); + if(mtest.countTotalChildren(false) < 100) { + if(mtest.representsNonComplex(true)) { + ComparisonResult cmp = mtest.compare(m_zero); + if(!COMPARISON_IS_EQUAL_OR_GREATER(cmp) && !COMPARISON_IS_EQUAL_OR_LESS(cmp)) b = false; + } else { + MathStructure m_re(CALCULATOR->getFunctionById(FUNCTION_ID_RE), &mtest, NULL); + m_re.calculateFunctions(eo); + ComparisonResult cmp = m_re.compare(m_zero); + if(!COMPARISON_IS_EQUAL_OR_GREATER(cmp) && !COMPARISON_IS_EQUAL_OR_LESS(cmp)) { + b = false; + } else { + MathStructure m_im(CALCULATOR->getFunctionById(FUNCTION_ID_IM), &mtest, NULL); + m_im.calculateFunctions(eo); + ComparisonResult cmp = m_im.compare(m_zero); + if(!COMPARISON_IS_EQUAL_OR_GREATER(cmp) && !COMPARISON_IS_EQUAL_OR_LESS(cmp)) b = false; + } + } + } else { + b = false; + } + eo.expand = false; + eo.approximation = APPROXIMATION_EXACT_VARIABLES; + if(!b) { + b = true; + msolve.calculatesub(eo, eo, true); + eo.approximation = APPROXIMATION_APPROXIMATE; + eo.expand = eo_pre.expand; + msolve.factorize(eo, false, false, 0, false, true, NULL, m_undefined, false, false, 1); + remove_nonzero_mul(msolve, u_var, eo); + if(msolve.isZero()) { + } else if(contains_undefined(msolve) || msolve.countTotalChildren(false) > 1000 || msolve.containsInterval(true, true, false, 1, true)) { + b = false; + } else { + MathStructure mtest(mstruct); + mtest.replace(v, u_var); + mtest.calculatesub(eo, eo, true); + if(contains_undefined(mtest, eo, true, u_var, mv)) { + b = false; + } else { + Number nr_prec(1, 1, -(PRECISION + 10)); + nr_prec *= nr_intval.uncertainty(); + // search for values where derivative is non-zero + b = find_interval_zeroes(msolve, malts, u_var, nr_intval, eo, 0, nr_prec); + } + } + eo.expand = false; + eo.approximation = APPROXIMATION_EXACT_VARIABLES; + } + eo.keep_zero_units = eo_pre.keep_zero_units; + } + CALCULATOR->endTemporaryStopMessages(); + CALCULATOR->beginTemporaryStopMessages(); + if(b) { + malts.addChild(nr_intval.lowerEndPoint()); + malts.addChild(nr_intval.upperEndPoint()); + MathStructure mnew; + for(size_t i = 0; i < malts.size(); i++) { + MathStructure mlim(mstruct); + if(!mmul.isOne()) malts[i] *= mmul; + mlim.replace(v, malts[i]); + mlim.calculatesub(eo, eo, true); + vector vars2 = vars; + solve_intervals2(mlim, vars2, eo_pre); + if(i == 0) { + mnew = mlim; + } else { + MathStructure mlim1(mnew); + if(!create_interval(mnew, mlim1, mlim)) { + eo.approximation = APPROXIMATION_APPROXIMATE; + eo.expand = eo_pre.expand; + mlim.eval(eo); + if(!create_interval(mnew, mlim1, mlim)) { + mlim1.eval(eo); + eo.expand = false; + eo.approximation = APPROXIMATION_EXACT_VARIABLES; + if(!create_interval(mnew, mlim1, mlim)) { + b = false; + break; + } + } + } + } + } + if(b) mstruct = mnew; + } + CALCULATOR->endTemporaryStopMessages(b); + if(!b) { + CALCULATOR->error(false, MESSAGE_CATEGORY_WIDE_INTERVAL, _("Interval potentially calculated wide."), NULL); + mstruct.replace(v, v->get()); + mstruct.unformat(eo_pre); + solve_intervals2(mstruct, vars, eo_pre); + } + u_var->destroy(); + } +} +KnownVariable *fix_find_interval_variable(MathStructure &mstruct) { + if(mstruct.isVariable() && mstruct.variable()->isKnown()) { + const MathStructure &m = ((KnownVariable*) mstruct.variable())->get(); + if(contains_interval_variable(m)) return (KnownVariable*) mstruct.variable(); + } + for(size_t i = 0; i < mstruct.size(); i++) { + KnownVariable *v = fix_find_interval_variable(mstruct[i]); + if(v) return v; + } + return NULL; +} +KnownVariable *fix_find_interval_variable2(MathStructure &mstruct) { + if(mstruct.isVariable() && mstruct.variable()->isKnown()) { + const MathStructure &m = ((KnownVariable*) mstruct.variable())->get(); + if(m.isNumber()) return NULL; + if(m.isMultiplication()) { + bool b_intfound = false;; + for(size_t i = 0; i < m.size(); i++) { + if(m[i].containsInterval(true, false, false, 1)) { + if(b_intfound || !m[i].isNumber()) return (KnownVariable*) mstruct.variable(); + b_intfound = true; + } + } + } else if(m.containsInterval(true, false, false, 1)) { + return (KnownVariable*) mstruct.variable(); + } + } + for(size_t i = 0; i < mstruct.size(); i++) { + KnownVariable *v = fix_find_interval_variable2(mstruct[i]); + if(v) return v; + } + return NULL; +} +bool replace_intervals(MathStructure &m) { + if(m.isNumber()) { + int var_prec = 0; + if(m.number().isInterval()) var_prec = m.number().precision(1); + else if(CALCULATOR->usesIntervalArithmetic() && m.number().precision() >= 0) var_prec = m.number().precision(); + if(var_prec <= PRECISION + 10) { + Variable *v = new KnownVariable("", format_and_print(m), m); + m.set(v, true); + v->destroy(); + } + } + bool b = false; + for(size_t i = 0; i < m.size(); i++) { + if(replace_intervals(m[i])) { + m.childUpdated(i + 1); + b = true; + } + } + return b; +} +void fix_interval_variable(KnownVariable *v, MathStructure &mvar) { + mvar = v->get(); + replace_intervals(mvar); +} + +void solve_intervals(MathStructure &mstruct, const EvaluationOptions &eo, const EvaluationOptions &feo) { + bool b = false; + while(true) { + KnownVariable *v = fix_find_interval_variable(mstruct); + if(!v) break; + b = true; + MathStructure mvar; + fix_interval_variable(v, mvar); + mstruct.replace(v, mvar); + } + while(true) { + KnownVariable *v = fix_find_interval_variable2(mstruct); + if(!v) break; + b = true; + MathStructure mvar; + fix_interval_variable(v, mvar); + mstruct.replace(v, mvar); + } + if(b) { + mstruct.unformat(eo); + EvaluationOptions eo2 = eo; + eo2.expand = false; + mstruct.calculatesub(eo2, feo, true); + } + vector vars; vector v_count; vector v_prec; + find_interval_variables(mstruct, vars, v_count, v_prec); + for(size_t i = 0; i < v_count.size();) { + if(v_count[i] < 2 || (feo.approximation == APPROXIMATION_EXACT && vars[i]->title() != "\b")) { + v_count.erase(v_count.begin() + i); + v_prec.erase(v_prec.begin() + i); + vars.erase(vars.begin() + i); + } else { + i++; + } + } + if(mstruct.isComparison()) { + if(feo.test_comparisons || feo.isolate_x) { + mstruct[0].subtract(mstruct[1]); + solve_intervals2(mstruct[0], vars, eo); + mstruct[1].clear(true); + } else { + solve_intervals2(mstruct[0], vars, eo); + solve_intervals2(mstruct[1], vars, eo); + } + return; + } + solve_intervals2(mstruct, vars, eo); +} +// end functions for handling of interval variables using interval arithmetic + + +/* + + Functions for uncertainty calculation using variance formula + +*/ + +void find_interval_create_var(const Number &nr, MathStructure &m, MathStructure &unc, MathStructure &unc2, KnownVariable **v, KnownVariable **v2) { + if(nr.hasImaginaryPart() && nr.internalImaginary()->isInterval()) { + if(nr.hasRealPart() && nr.isInterval(false)) { + unc = nr.internalImaginary()->uncertainty(); + unc2 = nr.realPart().uncertainty(); + Number nmid(*nr.internalImaginary()); + nmid.intervalToMidValue(); + Number nmid2(nr.realPart()); + nmid2.intervalToMidValue(); + *v = new KnownVariable("", string("(") + format_and_print(nmid) + ")", nmid); + (*v)->setApproximate(false); + *v2 = new KnownVariable("", string("(") + format_and_print(nmid2) + ")", nmid2); + (*v2)->setApproximate(false); + m.set(*v); + m.multiply(nr_one_i); + m.add(*v2); + (*v)->destroy(); + (*v2)->destroy(); + } else { + unc = nr.internalImaginary()->uncertainty(); + Number nmid(*nr.internalImaginary()); + nmid.intervalToMidValue(); + *v = new KnownVariable("", string("(") + format_and_print(nmid) + ")", nmid); + (*v)->setApproximate(false); + m.set(*v); + m.multiply(nr_one_i); + (*v)->destroy(); + } + } else { + unc = nr.uncertainty(); + Number nmid(nr); + nmid.intervalToMidValue(); + *v = new KnownVariable("", string("(") + format_and_print(nmid) + ")", nmid); + (*v)->setApproximate(false); + m.set(*v); + (*v)->destroy(); + } +} + +KnownVariable *find_interval_replace_var(MathStructure &m, MathStructure &unc, MathStructure &unc2, KnownVariable **v2, const EvaluationOptions &eo, MathStructure *mnew, Variable **prev_v, bool &b_failed) { + if(eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables && m.isVariable() && m.variable()->isKnown() && (eo.approximation != APPROXIMATION_EXACT || m.variable()->title() == "\b")) { + const MathStructure &mvar = ((KnownVariable*) m.variable())->get(); + if(!mvar.containsInterval(true, true, false, 1, true)) return NULL; + if(mvar.isNumber()) { + m.variable()->ref(); + *prev_v = m.variable(); + KnownVariable *v = NULL; + find_interval_create_var(mvar.number(), m, unc, unc2, &v, v2); + *mnew = m; + return v; + } else if(mvar.isMultiplication() && mvar[0].isNumber()) { + if(mvar[0].number().isInterval(false)) { + bool b = true; + for(size_t i = 1; i < mvar.size(); i++) { + if(mvar[i].containsInterval(true, true, false, 1, true)) { + b = false; + break; + } + } + if(b) { + m.variable()->ref(); + *prev_v = m.variable(); + KnownVariable *v = NULL; + find_interval_create_var(mvar[0].number(), m, unc, unc2, &v, v2); + for(size_t i = 1; i < mvar.size(); i++) { + m.multiply(mvar[i], true); + } + *mnew = m; + return v; + } + } + } else if(mvar.isFunction() && mvar.function()->id() == FUNCTION_ID_INTERVAL && mvar.size() == 2 && !mvar[0].containsInterval(true, true, false, 1, true) && !mvar[1].containsInterval(true, true, false, 1, true)) { + if(mvar[0].isAddition() && mvar[0].size() == 2 && mvar[1].isAddition() && mvar[1].size() == 2) { + const MathStructure *mmid = NULL, *munc = NULL; + if(mvar[0][0].equals(mvar[1][0])) { + mmid = &mvar[0][0]; + if(mvar[0][1].isNegate() && mvar[0][1][0].equals(mvar[1][1])) munc = &mvar[1][1]; + if(mvar[1][1].isNegate() && mvar[1][1][0].equals(mvar[0][1])) munc = &mvar[0][1]; + } else if(mvar[0][1].equals(mvar[1][1])) { + mmid = &mvar[0][1]; + if(mvar[0][0].isNegate() && mvar[0][0][0].equals(mvar[1][0])) munc = &mvar[1][0]; + if(mvar[1][0].isNegate() && mvar[1][0][0].equals(mvar[0][0])) munc = &mvar[0][0]; + } else if(mvar[0][0].equals(mvar[1][1])) { + mmid = &mvar[0][0]; + if(mvar[0][1].isNegate() && mvar[0][1][0].equals(mvar[1][0])) munc = &mvar[1][0]; + if(mvar[1][0].isNegate() && mvar[1][0][0].equals(mvar[0][1])) munc = &mvar[0][1]; + } else if(mvar[0][1].equals(mvar[1][0])) { + mmid = &mvar[0][0]; + if(mvar[0][0].isNegate() && mvar[0][0][0].equals(mvar[1][1])) munc = &mvar[1][1]; + if(mvar[1][1].isNegate() && mvar[1][1][0].equals(mvar[0][0])) munc = &mvar[0][0]; + } + if(mmid && munc) { + unc = *munc; + MathStructure mmid2(*mmid); + KnownVariable *v = new KnownVariable("", string("(") + format_and_print(*mmid) + ")", mmid2); + m.set(v); + v->destroy(); + return v; + } + } + unc = mvar[1]; + unc -= mvar[0]; + unc *= nr_half; + MathStructure mmid(mvar[0]); + mmid += mvar[1]; + mmid *= nr_half; + KnownVariable *v = new KnownVariable("", string("(") + format_and_print(mmid) + ")", mmid); + m.variable()->ref(); + *prev_v = m.variable(); + m.set(v); + *mnew = m; + v->destroy(); + return v; + } else if(mvar.isFunction() && mvar.function()->id() == FUNCTION_ID_UNCERTAINTY && mvar.size() == 3 && mvar[2].isNumber() && !mvar[0].containsInterval(true, true, false, 1, true) && !mvar[1].containsInterval(true, true, false, 1, true)) { + if(mvar[2].number().getBoolean()) { + unc = mvar[1]; + unc *= mvar[0]; + } else { + unc = mvar[1]; + } + KnownVariable *v = new KnownVariable("", string("(") + format_and_print(mvar[0]) + ")", mvar[0]); + m.variable()->ref(); + *prev_v = m.variable(); + m.set(v); + *mnew = m; + v->destroy(); + return v; + } + b_failed = true; + } else if(m.isNumber() && m.number().isInterval(false) && m.number().precision(true) <= PRECISION + 10) { + KnownVariable *v = NULL; + find_interval_create_var(m.number(), m, unc, unc2, &v, v2); + return v; + } else if(m.isFunction() && m.function()->id() == FUNCTION_ID_INTERVAL && m.size() == 2 && !m[0].containsInterval(true, true, false, 1, true) && !m[1].containsInterval(true, true, false, 1, true)) { + if(m[0].isAddition() && m[0].size() == 2 && m[1].isAddition() && m[1].size() == 2) { + MathStructure *mmid = NULL, *munc = NULL; + if(m[0][0].equals(m[1][0])) { + mmid = &m[0][0]; + if(m[0][1].isNegate() && m[0][1][0].equals(m[1][1])) munc = &m[1][1]; + if(m[1][1].isNegate() && m[1][1][0].equals(m[0][1])) munc = &m[0][1]; + } else if(m[0][1].equals(m[1][1])) { + mmid = &m[0][1]; + if(m[0][0].isNegate() && m[0][0][0].equals(m[1][0])) munc = &m[1][0]; + if(m[1][0].isNegate() && m[1][0][0].equals(m[0][0])) munc = &m[0][0]; + } else if(m[0][0].equals(m[1][1])) { + mmid = &m[0][0]; + if(m[0][1].isNegate() && m[0][1][0].equals(m[1][0])) munc = &m[1][0]; + if(m[1][0].isNegate() && m[1][0][0].equals(m[0][1])) munc = &m[0][1]; + } else if(m[0][1].equals(m[1][0])) { + mmid = &m[0][0]; + if(m[0][0].isNegate() && m[0][0][0].equals(m[1][1])) munc = &m[1][1]; + if(m[1][1].isNegate() && m[1][1][0].equals(m[0][0])) munc = &m[0][0]; + } + if(mmid && munc) { + unc = *munc; + KnownVariable *v = new KnownVariable("", string("(") + format_and_print(*mmid) + ")", *mmid); + m.set(v); + v->destroy(); + return v; + } + } + unc = m[1]; + unc -= m[0]; + unc *= nr_half; + MathStructure mmid(m[0]); + mmid += m[1]; + mmid *= nr_half; + KnownVariable *v = new KnownVariable("", string("(") + format_and_print(mmid) + ")", mmid); + m.set(v); + v->destroy(); + return v; + } else if(m.isFunction() && m.function()->id() == FUNCTION_ID_UNCERTAINTY && m.size() == 3 && m[2].isNumber() && !m[0].containsInterval(true, true, false, 1, true) && !m[1].containsInterval(true, true, false, 1, true)) { + if(m[2].number().getBoolean()) { + unc = m[1]; + unc *= m[0]; + } else { + unc = m[1]; + } + KnownVariable *v = new KnownVariable("", string("(") + format_and_print(m[0]) + ")", m[0]); + m.set(v); + v->destroy(); + return v; + } + for(size_t i = 0; i < m.size(); i++) { + KnownVariable *v = find_interval_replace_var(m[i], unc, unc2, v2, eo, mnew, prev_v, b_failed); + if(b_failed) return NULL; + if(v) return v; + } + return NULL; +} + +bool find_interval_replace_var_nr(MathStructure &m) { + if((m.isNumber() && m.number().isInterval(false) && m.number().precision(true) <= PRECISION + 10) || (m.isFunction() && m.function()->id() == FUNCTION_ID_INTERVAL && m.size() == 2) || (m.isFunction() && m.function()->id() == FUNCTION_ID_UNCERTAINTY && m.size() == 3)) { + KnownVariable *v = new KnownVariable("", string("(") + format_and_print(m) + ")", m); + m.set(v); + v->destroy(); + return true; + } + bool b = false; + for(size_t i = 0; i < m.size(); i++) { + if(find_interval_replace_var_nr(m[i])) b = true; + } + return b; +} + + +bool replace_variables_with_interval(MathStructure &m, const EvaluationOptions &eo, bool in_nounit = false, bool only_argument_vars = false) { + if(m.isVariable() && m.variable()->isKnown() && (!only_argument_vars || m.variable()->title() == "\b")) { + const MathStructure &mvar = ((KnownVariable*) m.variable())->get(); + if(!mvar.containsInterval(true, true, false, 1, true)) return false; + if(mvar.isNumber()) { + return false; + } else if(mvar.isMultiplication() && mvar[0].isNumber()) { + if(mvar[0].number().isInterval(false)) { + bool b = true; + for(size_t i = 1; i < mvar.size(); i++) { + if(mvar[i].containsInterval(true, true, false, 1, true)) { + b = false; + break; + } + } + if(b) return false; + } + } + m.set(mvar, true); + if(in_nounit) m.removeType(STRUCT_UNIT); + else m.unformat(eo); + return true; + } + bool b = false; + if(m.isFunction() && m.function()->id() == FUNCTION_ID_STRIP_UNITS && m.size() == 1) { + b = replace_variables_with_interval(m[0], eo, true, only_argument_vars); + if(b && m[0].containsType(STRUCT_UNIT, false, true, true) == 0) { + m.setToChild(1, true); + } + return b; + } + for(size_t i = 0; i < m.size(); i++) { + if(replace_variables_with_interval(m[i], eo, in_nounit, only_argument_vars)) b = true; + } + return b; +} + +bool contains_diff_for(const MathStructure &m, const MathStructure &x_var) { + if(m.isFunction() && m.function() && m.function()->id() == FUNCTION_ID_DIFFERENTIATE && m.size() >= 2 && m[1] == x_var) return true; + for(size_t i = 0; i < m.size(); i++) { + if(contains_diff_for(m[i], x_var)) return true; + } + return false; +} + +MathStructure calculate_uncertainty(MathStructure &m, const EvaluationOptions &eo, bool &b_failed) { + vector vars; + vector uncs; + MathStructure unc, unc2; + if(eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) replace_variables_with_interval(m, eo, false, eo.approximation == APPROXIMATION_EXACT); + while(true) { + Variable *prev_v = NULL; + MathStructure mnew; + KnownVariable *v2 = NULL; + KnownVariable *v = find_interval_replace_var(m, unc, unc2, &v2, eo, &mnew, &prev_v, b_failed); + if(!v) break; + if(!mnew.isZero()) { + m.replace(prev_v, mnew); + prev_v->unref(); + } + vars.push_back(v); + uncs.push_back(unc); + if(v2) { + vars.push_back(v2); + uncs.push_back(unc2); + } + } + m.unformat(eo); + if(eo.sync_units && eo.approximation != APPROXIMATION_EXACT) sync_approximate_units(m, eo, &vars, &uncs, true); + if(b_failed || vars.empty()) return m_zero; + MathStructure munc; + UnknownVariable *uv = new UnknownVariable("", "x"); + MathStructure muv(uv); + MathStructure *munc_i = NULL; + for(size_t i = 0; i < vars.size(); i++) { + if(!vars[i]->get().representsNonComplex(true)) { + b_failed = true; return m_zero; + } + MathStructure *mdiff = new MathStructure(m); + uv->setInterval(vars[i]->get()); + mdiff->replace(vars[i], muv); + if(!mdiff->differentiate(muv, eo) || contains_diff_for(*mdiff, muv) || CALCULATOR->aborted()) { + b_failed = true; + return m_zero; + } + mdiff->replace(muv, vars[i]); + if(!mdiff->representsNonComplex(true)) { + MathStructure *mdiff_i = new MathStructure(*mdiff); + mdiff->transformById(FUNCTION_ID_RE); + mdiff_i->transformById(FUNCTION_ID_IM); + mdiff_i->raise(nr_two); + mdiff_i->multiply(uncs[i]); + mdiff_i->last().raise(nr_two); + if(!munc_i) {munc_i = mdiff_i;} + else munc_i->add_nocopy(mdiff_i, true); + } + mdiff->raise(nr_two); + mdiff->multiply(uncs[i]); + mdiff->last().raise(nr_two); + if(munc.isZero()) {munc.set_nocopy(*mdiff); mdiff->unref();} + else munc.add_nocopy(mdiff, true); + } + uv->destroy(); + munc.raise(nr_half); + if(munc_i) { + munc_i->raise(nr_half); + munc_i->multiply(nr_one_i); + munc.add_nocopy(munc_i); + } + return munc; +} + +Variable *find_interval_replace_var_comp(MathStructure &m, const EvaluationOptions &eo, Variable **v) { + if(eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables && m.isVariable() && m.variable()->isKnown() && ((KnownVariable*) m.variable())->get().containsInterval(true, true, false, 1, true)) { + UnknownVariable *uv = new UnknownVariable("", format_and_print(m)); + uv->setInterval(m); + *v = m.variable(); + m.set(uv, true); + return uv; + } else if((m.isNumber() && m.number().isInterval(false) && m.number().precision(true) <= PRECISION + 10) || (m.isFunction() && m.function()->id() == FUNCTION_ID_INTERVAL && m.size() == 2) || (m.isFunction() && m.function()->id() == FUNCTION_ID_UNCERTAINTY && m.size() == 3)) { + Variable *uv = NULL; + if(eo.approximation == APPROXIMATION_EXACT || eo.approximation == APPROXIMATION_EXACT_VARIABLES) { + uv = new KnownVariable("", string("(") + format_and_print(m) + ")", m); + } else { + uv = new UnknownVariable("", string("(") + format_and_print(m) + ")"); + ((UnknownVariable*) uv)->setInterval(m); + } + *v = NULL; + m.set(uv, true); + return uv; + } + for(size_t i = 0; i < m.size(); i++) { + Variable *uv = find_interval_replace_var_comp(m[i], eo, v); + if(uv) return uv; + } + return NULL; +} + +bool eval_comparison_sides(MathStructure &m, const EvaluationOptions &eo) { + if(m.isComparison()) { + MathStructure mbak(m); + if(!m[0].isUnknown()) { + bool ret = true; + CALCULATOR->beginTemporaryStopMessages(); + m[0].eval(eo); + if(m[0].containsFunctionId(FUNCTION_ID_UNCERTAINTY) && !mbak[0].containsFunctionId(FUNCTION_ID_UNCERTAINTY)) { + CALCULATOR->endTemporaryStopMessages(); + m[0] = mbak[0]; + ret = false; + } else { + CALCULATOR->endTemporaryStopMessages(true); + } + CALCULATOR->beginTemporaryStopMessages(); + m[1].eval(eo); + if(m[1].containsFunctionId(FUNCTION_ID_UNCERTAINTY) && !mbak[1].containsFunctionId(FUNCTION_ID_UNCERTAINTY)) { + CALCULATOR->endTemporaryStopMessages(); + m[1] = mbak[1]; + ret = false; + } else { + CALCULATOR->endTemporaryStopMessages(true); + } + if(ret && !m.containsUnknowns()) { + m.calculatesub(eo, eo, false); + return true; + } + return false; + } else { + m[1].eval(eo); + m.calculatesub(eo, eo, false); + return true; + } + } else if(m.containsType(STRUCT_COMPARISON)) { + bool ret = true; + for(size_t i = 0; i < m.size(); i++) { + if(!eval_comparison_sides(m[i], eo)) ret = false; + } + m.childrenUpdated(); + m.calculatesub(eo, eo, false); + return ret; + } else { + m.eval(eo); + } + return true; +} + +bool separate_unit_vars(MathStructure &m, const EvaluationOptions &eo, bool only_approximate, bool dry_run) { + if(m.isVariable() && m.variable()->isKnown()) { + const MathStructure &mvar = ((KnownVariable*) m.variable())->get(); + if(mvar.isMultiplication()) { + bool b = false; + for(size_t i = 0; i < mvar.size(); i++) { + if(is_unit_multiexp(mvar[i])) { + if(!b) b = !only_approximate || contains_approximate_relation_to_base(mvar[i], true); + } else if(mvar[i].containsType(STRUCT_UNIT, false, true, true) != 0) { + b = false; + break; + } + } + if(!b) return false; + if(dry_run) return true; + m.transformById(FUNCTION_ID_STRIP_UNITS); + for(size_t i = 0; i < mvar.size(); i++) { + if(is_unit_multiexp(mvar[i])) { + m.multiply(mvar[i], i); + } + } + m.unformat(eo); + return true; + } + } + if(m.isFunction() && m.function()->id() == FUNCTION_ID_STRIP_UNITS) return false; + bool b = false; + for(size_t i = 0; i < m.size(); i++) { + if(separate_unit_vars(m[i], eo, only_approximate, dry_run)) { + b = true; + if(dry_run) return true; + } + } + return b; +} +// end functions for uncertainty calculation using variance formula + +// Functions for handling of function arguments with intervals replaced by temporary variables +int contains_interval_var(const MathStructure &m, bool structural_only, bool check_variables, bool check_functions, int ignore_high_precision_interval, bool include_interval_function); +int contains_function_interval(const MathStructure &m, bool structural_only = true, bool check_variables = false, bool check_functions = false, int ignore_high_precision_interval = 0, bool include_interval_function = false) { + for(size_t i = 0; i < m.size(); i++) { + if(contains_function_interval(m[i], structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function)) return true; + } + if(m.isVariable() && m.variable()->isKnown() && m.variable()->title() == "\b") { + if(ignore_high_precision_interval == 0) return true; + return contains_interval_var(((KnownVariable*) m.variable())->get(), structural_only, check_variables, check_functions, ignore_high_precision_interval, include_interval_function); + } + return false; +} +bool replace_function_vars(MathStructure &m) { + for(size_t i = 0; i < m.size(); i++) { + if(replace_function_vars(m[i])) return true; + } + if(m.isVariable() && m.variable()->isKnown() && m.variable()->title() == "\b") { + m.set(((KnownVariable*) m.variable())->get(), true); + } + return false; +} + +// Simplify expressions by combining sin() and cos() +bool simplify_functions(MathStructure &mstruct, const EvaluationOptions &eo, const EvaluationOptions &feo, const MathStructure &x_var) { + if(!mstruct.isAddition()) { + bool b = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(CALCULATOR->aborted()) break; + if(simplify_functions(mstruct[i], eo, feo, x_var)) {b = true; mstruct.childUpdated(i + 1);} + } + return b; + } + if(mstruct.containsFunctionId(FUNCTION_ID_SIN, false, false, false) > 0 && mstruct.containsFunctionId(FUNCTION_ID_COS, false, false, false)) { + if(x_var.isUndefined()) { + // a*(sin(x)+cos(x))=a*sqrt(2)*sin(x+pi/4) + bool b_ret = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isFunction() && mstruct[i].size() == 1 && mstruct[i].function()->id() == FUNCTION_ID_SIN) { + for(size_t i2 = 0; i2 < mstruct.size(); i2++) { + if(i != i2 && mstruct[i2].isFunction() && mstruct[i2].size() == 1 && mstruct[i2].function()->id() == FUNCTION_ID_COS && mstruct[i][0] == mstruct[i2][0]) { + MathStructure madd(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + madd /= Number(4, 1); + madd *= CALCULATOR->getRadUnit(); + madd.calculatesub(eo, feo, true); + mstruct[i][0].calculateAdd(madd, eo); + mstruct[i].childUpdated(1); + mstruct.childUpdated(i + 1); + MathStructure mmul(nr_two); + mmul.calculateRaise(nr_half, eo); + mstruct[i].calculateMultiply(mmul, eo); + mstruct.delChild(i2 + 1); + b_ret = true; + break; + } + } + } else if(mstruct[i].isMultiplication()) { + for(size_t i3 = 0; i3 < mstruct[i].size(); i3++) { + if(mstruct[i][i3].isFunction() && mstruct[i][i3].size() == 1 && mstruct[i][i3].function()->id() == FUNCTION_ID_SIN) { + mstruct[i][i3].setFunctionId(FUNCTION_ID_COS); + bool b = false; + for(size_t i2 = 0; i2 < mstruct.size(); i2++) { + if(i != i2 && mstruct[i2] == mstruct[i]) { + MathStructure madd(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + madd /= Number(4, 1); + madd *= CALCULATOR->getRadUnit(); + madd.calculatesub(eo, feo, true); + mstruct[i][i3].setFunctionId(FUNCTION_ID_SIN); + mstruct[i][i3][0].calculateAdd(madd, eo); + mstruct[i][i3].childUpdated(1); + mstruct[i].childUpdated(i3 + 1); + mstruct.childUpdated(i + 1); + MathStructure mmul(nr_two); + mmul.calculateRaise(nr_half, eo); + mstruct[i].calculateMultiply(mmul, eo); + mstruct.delChild(i2 + 1); + b = true; + break; + } + } + if(b) { + b_ret = true; + break; + } else { + mstruct[i][i3].setFunctionId(FUNCTION_ID_SIN); + } + } + } + } + } + if(mstruct.size() == 1) mstruct.setToChild(1, true); + return b_ret; + } else { + // a*sin(x)+b*cos(x)=a*sqrt((b/a)^2+1)*sin(x+atan(b/a)) + MathStructure *marg = NULL; + bool b_cos = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isFunction() && mstruct[i].size() == 1 && (mstruct[i].function()->id() == FUNCTION_ID_SIN || mstruct[i].function()->id() == FUNCTION_ID_COS) && mstruct[i][0].contains(x_var)) { + marg = &mstruct[i][0]; + b_cos = mstruct[i].function()->id() == FUNCTION_ID_COS; + } else if(mstruct[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { + if(!marg && mstruct[i][i2].isFunction() && mstruct[i][i2].size() == 1 && (mstruct[i][i2].function()->id() == FUNCTION_ID_SIN || mstruct[i][i2].function()->id() == FUNCTION_ID_COS) && mstruct[i][i2][0].contains(x_var)) { + marg = &mstruct[i][i2][0]; + b_cos = mstruct[i][i2].function()->id() == FUNCTION_ID_COS; + } else if(mstruct[i][i2].contains(x_var)) { + marg = NULL; + break; + } + } + } + if(marg) { + bool b = false; + for(size_t i3 = i + 1; i3 < mstruct.size(); i3++) { + if(mstruct[i3].isFunction() && mstruct[i3].size() == 1 && mstruct[i3].function()->id() == (b_cos ? FUNCTION_ID_SIN : FUNCTION_ID_COS) && mstruct[i3][0] == *marg) { + b = true; + } else if(mstruct[i3].isMultiplication()) { + bool b2 = false; + for(size_t i2 = 0; i2 < mstruct[i3].size(); i2++) { + if(!b2 && mstruct[i3][i2].isFunction() && mstruct[i3][i2].size() == 1 && (mstruct[i3][i2].function()->id() == FUNCTION_ID_SIN || mstruct[i3][i2].function()->id() == FUNCTION_ID_COS) && mstruct[i3][i2][0] == *marg) { + if((mstruct[i3][i2].function()->id() == FUNCTION_ID_SIN) == b_cos) b = true; + b2 = true; + } else if(mstruct[i3][i2].contains(x_var)) { + marg = NULL; + break; + } + } + if(!marg) break; + } + } + if(!b) marg = NULL; + } + if(marg) { + marg->ref(); + MathStructure m_a, m_b; + for(size_t i3 = i; i3 < mstruct.size();) { + bool b = false; + if(mstruct[i3].isFunction() && mstruct[i3].size() == 1 && mstruct[i3].function()->id() == FUNCTION_ID_SIN && mstruct[i3][0] == *marg) { + if(m_a.isZero()) m_a = m_one; + else m_a.add(m_one, true); + b = true; + } else if(mstruct[i3].isFunction() && mstruct[i3].size() == 1 && mstruct[i3].function()->id() == FUNCTION_ID_COS && mstruct[i3][0] == *marg) { + if(m_b.isZero()) m_a = m_one; + else m_b.add(m_one, true); + b = true; + } else if(mstruct[i3].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct[i3].size(); i2++) { + if(mstruct[i3][i2].isFunction() && mstruct[i3][i2].size() == 1 && mstruct[i3][i2].function()->id() == FUNCTION_ID_SIN && mstruct[i3][i2][0] == *marg) { + mstruct[i3].delChild(i2 + 1, true); + if(m_a.isZero()) m_a.set_nocopy(mstruct[i3]); + else {mstruct[i3].ref(); m_a.add_nocopy(&mstruct[i3], true);} + b = true; + break; + } else if(mstruct[i3][i2].isFunction() && mstruct[i3][i2].size() == 1 && mstruct[i3][i2].function()->id() == FUNCTION_ID_COS && mstruct[i3][i2][0] == *marg) { + mstruct[i3].delChild(i2 + 1, true); + if(m_b.isZero()) m_b.set_nocopy(mstruct[i3]); + else {mstruct[i3].ref(); m_b.add_nocopy(&mstruct[i3], true);} + b = true; + break; + } + } + } + if(b) { + mstruct.delChild(i3 + 1); + } else { + i3++; + } + } + MathStructure *m_sin = new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SIN), NULL); + m_sin->addChild_nocopy(marg); + m_b.calculateDivide(m_a, eo); + MathStructure *m_atan = new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_ATAN), &m_b, NULL); + if(m_atan->calculateFunctions(feo)) m_atan->calculatesub(eo, feo, true); + if(eo.parse_options.angle_unit != ANGLE_UNIT_NONE) m_atan->calculateMultiply(CALCULATOR->getRadUnit(), eo); + (*m_sin)[0].add_nocopy(m_atan); + (*m_sin)[0].calculateAddLast(eo); + m_sin->childUpdated(1); + m_b.calculateRaise(nr_two, eo); + m_b.calculateAdd(m_one, eo); + m_b.calculateRaise(nr_half, eo); + m_sin->calculateMultiply(m_b, eo); + m_sin->calculateMultiply(m_a, eo); + if(mstruct.size() == 0) {mstruct.set_nocopy(*m_sin); m_sin->unref();} + else mstruct.insertChild_nocopy(m_sin, i + 1); + simplify_functions(mstruct, eo, feo, x_var); + return true; + } + } + } + } + return false; +} + +// Simplify expressions by combining logarithms +bool simplify_ln(MathStructure &mstruct) { + bool b_ret = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(simplify_ln(mstruct[i])) b_ret = true; + } + if(mstruct.isAddition()) { + size_t i_ln = (size_t) -1, i_ln_m = (size_t) -1; + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isFunction() && mstruct[i].function()->id() == FUNCTION_ID_LOG && mstruct[i].size() == 1 && mstruct[i][0].isNumber() && mstruct[i][0].number().isReal()) { + if(i_ln == (size_t) -1) { + i_ln = i; + } else { + bool b = true; + if(mstruct[i_ln].isMultiplication()) { + if(mstruct[i_ln][1][0].number().raise(mstruct[i_ln][0].number(), true)) {mstruct[i_ln].setToChild(2, true); b_ret = true;} + else b = false; + } + if(b && mstruct[i_ln][0].number().multiply(mstruct[i][0].number())) { + mstruct.delChild(i + 1); + i--; + b_ret = true; + } + } + } else if(mstruct[i].isMultiplication() && mstruct[i].size() == 2 && mstruct[i][1].isFunction() && mstruct[i][1].function()->id() == FUNCTION_ID_LOG && mstruct[i][1].size() == 1 && mstruct[i][1][0].isNumber() && mstruct[i][1][0].number().isReal() && mstruct[i][0].isInteger() && mstruct[i][0].number().isLessThan(1000) && mstruct[i][0].number().isGreaterThan(-1000)) { + if(mstruct[i][0].number().isPositive()) { + if(i_ln == (size_t) -1) { + i_ln = i; + } else { + bool b = true; + if(mstruct[i_ln].isMultiplication()) { + if(mstruct[i_ln][1][0].number().raise(mstruct[i_ln][0].number())) {mstruct[i_ln].setToChild(2, true); b_ret = true;} + else b = false; + } + if(b && mstruct[i][1][0].number().raise(mstruct[i][0].number(), true)) { + if(mstruct[i_ln][0].number().multiply(mstruct[i][1][0].number())) { + mstruct.delChild(i + 1); + i--; + } else { + mstruct[i].setToChild(1, true); + } + b_ret = true; + } + } + } else if(mstruct[i][0].number().isNegative()) { + if(i_ln_m == (size_t) -1) { + i_ln_m = i; + } else { + bool b = mstruct[i_ln_m][0].number().isMinusOne(); + if(!b && mstruct[i_ln_m][1][0].number().raise(-mstruct[i_ln_m][0].number())) {mstruct[i_ln_m][0].set(m_minus_one, true); b_ret = true; b = true;} + bool b_m1 = b && mstruct[i][0].number().isMinusOne(); + if(b && (b_m1 || mstruct[i][1][0].number().raise(-mstruct[i][0].number(), true))) { + if(mstruct[i_ln_m][1][0].number().multiply(mstruct[i][1][0].number())) { + mstruct.delChild(i + 1); + b_ret = true; + i--; + } else if(!b_m1) b_ret = true; + } + } + } + } + } + if(mstruct.size() == 1) mstruct.setToChild(1, true); + } + return b_ret; +} + +// Convert complex numbers from rectangular form +bool MathStructure::complexToExponentialForm(const EvaluationOptions &eo) { + if(m_type == STRUCT_NUMBER && o_number.hasImaginaryPart()) { + EvaluationOptions eo2 = eo; + eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; + eo2.parse_options.angle_unit = ANGLE_UNIT_RADIANS; + MathStructure mabs(CALCULATOR->getFunctionById(FUNCTION_ID_ABS), this, NULL); + MathStructure marg(CALCULATOR->getFunctionById(FUNCTION_ID_ARG), this, NULL); + marg *= nr_one_i; + marg.eval(eo2); + set(CALCULATOR->getVariableById(VARIABLE_ID_E), true); + raise(marg); + mabs.eval(eo2); + if(!mabs.isOne()) multiply(mabs); + evalSort(false); + return true; + } + if(m_type == STRUCT_POWER) return false; + bool b = false; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).complexToExponentialForm(eo)) {b = true; CHILD_UPDATED(i);} + } + return b; +} +bool MathStructure::complexToPolarForm(const EvaluationOptions &eo) { + if(m_type == STRUCT_NUMBER && o_number.hasImaginaryPart()) { + MathStructure mabs(CALCULATOR->getFunctionById(FUNCTION_ID_ABS), this, NULL); + MathStructure marg(CALCULATOR->getFunctionById(FUNCTION_ID_ARG), this, NULL); + EvaluationOptions eo2 = eo; + eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; + mabs.eval(eo2); + marg.eval(eo2); + switch(eo2.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {marg.multiply(CALCULATOR->getDegUnit(), true);} break;} + case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {marg.multiply(CALCULATOR->getGraUnit(), true);} break;} + case ANGLE_UNIT_RADIANS: {if(CALCULATOR->getRadUnit()) {marg.multiply(CALCULATOR->getRadUnit(), true);} break;} + default: {break;} + } + set(marg, true); + transformById(FUNCTION_ID_SIN); + multiply(nr_one_i); + add_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_COS), &marg, NULL)); + if(!mabs.isOne()) multiply(mabs); + evalSort(true); + return true; + } else if(m_type == STRUCT_POWER && CHILD(0).isVariable() && CHILD(0).variable()->id() == VARIABLE_ID_E && CHILD(1).isNumber() && CHILD(1).number().hasImaginaryPart() && !CHILD(1).number().hasRealPart()) { + MathStructure marg(CHILD(1).number().imaginaryPart()); + EvaluationOptions eo2 = eo; + eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; + switch(eo2.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {marg.calculateMultiply(Number(180, 1), eo2); marg.calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); marg.multiply(CALCULATOR->getDegUnit(), true);} break;} + case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {marg.calculateMultiply(Number(200, 1), eo2); marg.calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); marg.multiply(CALCULATOR->getGraUnit(), true);} break;} + case ANGLE_UNIT_RADIANS: {if(CALCULATOR->getRadUnit()) {marg.multiply(CALCULATOR->getRadUnit(), true);} break;} + default: {break;} + } + set(marg, true); + transformById(FUNCTION_ID_SIN); + multiply(nr_one_i); + add_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_COS), &marg, NULL)); + evalSort(true); + return true; + } else if(m_type == STRUCT_MULTIPLICATION && SIZE == 2 && CHILD(1).isPower() && CHILD(1)[0].isVariable() && CHILD(1)[0].variable()->id() == VARIABLE_ID_E && CHILD(1)[1].isNumber() && CHILD(1)[1].number().hasImaginaryPart() && !CHILD(1)[1].number().hasRealPart() && CHILD(0).isNumber() && !CHILD(0).number().hasImaginaryPart()) { + MathStructure marg(CHILD(1)[1].number().imaginaryPart()); + EvaluationOptions eo2 = eo; + eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; + switch(eo2.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {marg.calculateMultiply(Number(180, 1), eo2); marg.calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); marg.multiply(CALCULATOR->getDegUnit(), true);} break;} + case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {marg.calculateMultiply(Number(200, 1), eo2); marg.calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); marg.multiply(CALCULATOR->getGraUnit(), true);} break;} + case ANGLE_UNIT_RADIANS: {if(CALCULATOR->getRadUnit()) {marg.multiply(CALCULATOR->getRadUnit(), true);} break;} + default: {break;} + } + CHILD(1).set(marg, true); + CHILD(1).transformById(FUNCTION_ID_SIN); + CHILD(1).multiply(nr_one_i); + CHILD(1).add_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_COS), &marg, NULL)); + CHILD_UPDATED(1) + evalSort(true); + return true; + } + if(m_type == STRUCT_POWER || m_type == STRUCT_FUNCTION) return false; + bool b = false; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).complexToPolarForm(eo)) {b = true; CHILD_UPDATED(i);} + } + return b; +} +bool MathStructure::complexToCisForm(const EvaluationOptions &eo) { + if(m_type == STRUCT_NUMBER && o_number.hasImaginaryPart()) { + MathStructure mabs(CALCULATOR->getFunctionById(FUNCTION_ID_ABS), this, NULL); + MathStructure marg(CALCULATOR->getFunctionById(FUNCTION_ID_ARG), this, NULL); + EvaluationOptions eo2 = eo; + eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; + mabs.eval(eo2); + marg.eval(eo2); + switch(eo2.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {marg.multiply(CALCULATOR->getDegUnit(), true);} break;} + case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {marg.multiply(CALCULATOR->getGraUnit(), true);} break;} + default: {break;} + } + set(marg, true); + transformById(FUNCTION_ID_CIS); + multiply(mabs); + evalSort(true); + return true; + } else if(m_type == STRUCT_POWER && CHILD(0).isVariable() && CHILD(0).variable()->id() == VARIABLE_ID_E && CHILD(1).isNumber() && CHILD(1).number().hasImaginaryPart() && !CHILD(1).number().hasRealPart()) { + set(CHILD(1).number().imaginaryPart(), true); + EvaluationOptions eo2 = eo; + eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; + switch(eo2.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {calculateMultiply(Number(180, 1), eo2); calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); multiply(CALCULATOR->getDegUnit(), true);} break;} + case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {calculateMultiply(Number(200, 1), eo2); calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); multiply(CALCULATOR->getGraUnit(), true);} break;} + default: {break;} + } + transformById(FUNCTION_ID_CIS); + multiply(m_one); + evalSort(true); + return true; + } else if(m_type == STRUCT_MULTIPLICATION && SIZE == 2 && CHILD(1).isPower() && CHILD(1)[0].isVariable() && CHILD(1)[0].variable()->id() == VARIABLE_ID_E && CHILD(1)[1].isNumber() && CHILD(1)[1].number().hasImaginaryPart() && !CHILD(1)[1].number().hasRealPart() && CHILD(0).isNumber() && !CHILD(0).number().hasImaginaryPart()) { + CHILD(1).set(CHILD(1)[1].number().imaginaryPart(), true); + EvaluationOptions eo2 = eo; + eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; + switch(eo2.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {if(CALCULATOR->getDegUnit()) {CHILD(1).calculateMultiply(Number(180, 1), eo2); CHILD(1).calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); CHILD(1).multiply(CALCULATOR->getDegUnit(), true);} break;} + case ANGLE_UNIT_GRADIANS: {if(CALCULATOR->getGraUnit()) {CHILD(1).calculateMultiply(Number(200, 1), eo2); CHILD(1).calculateDivide(CALCULATOR->getVariableById(VARIABLE_ID_PI), eo2); CHILD(1).multiply(CALCULATOR->getGraUnit(), true);} break;} + default: {break;} + } + CHILD(1).transformById(FUNCTION_ID_CIS); + CHILD_UPDATED(1) + return true; + } + bool b = false; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).complexToCisForm(eo)) {b = true; CHILD_UPDATED(i);} + } + return b; +} + +bool convert_to_default_angle_unit(MathStructure &m, const EvaluationOptions &eo) { + bool b = false; + for(size_t i = 0; i < m.size(); i++) { + if(convert_to_default_angle_unit(m[i], eo)) b = true; + if(m.isFunction() && m.function()->getArgumentDefinition(i + 1) && m.function()->getArgumentDefinition(i + 1)->type() == ARGUMENT_TYPE_ANGLE) { + Unit *u = NULL; + if(eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES) u = CALCULATOR->getDegUnit(); + else if(eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS) u = CALCULATOR->getGraUnit(); + if(u && m[i].contains(CALCULATOR->getRadUnit(), false, false, false)) { + m[i].divide(u); + m[i].multiply(u); + EvaluationOptions eo2 = eo; + if(eo.approximation == APPROXIMATION_TRY_EXACT) eo2.approximation = APPROXIMATION_APPROXIMATE; + eo2.calculate_functions = false; + eo2.sync_units = true; + m[i].calculatesub(eo2, eo2, true); + b = true; + } + } + } + return b; +} + +// Remove zero unit values if remaining value is not zero (e.g. 5 s + 0 m = 5 s) +bool remove_add_zero_unit(MathStructure &m) { + if(m.isAddition() && m.size() > 1) { + bool b = false, b2 = false; + for(size_t i = 0; i < m.size(); i++) { + if(m[i].isMultiplication() && m[i].size() > 1 && m[i][0].isZero() && !m[i].isApproximate()) { + b = true; + } else { + b2 = true; + } + if(b && b2) break; + } + if(!b || !b2) return false; + b = false; + for(size_t i = 0; i < m.size();) { + b2 = false; + if(m[i].isMultiplication() && m[i].size() > 1 && m[i][0].isZero() && !m[i].isApproximate()) { + b2 = true; + for(size_t i2 = 1; i2 < m[i].size(); i2++) { + if(!m[i][i2].isUnit_exp() || (m[i][i2].isPower() && m[i][i2][0].unit()->hasNonlinearRelationToBase()) || (m[i][i2].isUnit() && m[i][i2].unit()->hasNonlinearRelationToBase())) { + b2 = false; + break; + } + } + if(b2) { + b = true; + m.delChild(i + 1); + if(m.size() == 1) { + m.setToChild(1, true); + break; + } + } + } + if(!b2) i++; + } + return b; + } + return false; +} + +// Functions for handling log-bases units +Unit *find_log_unit(const MathStructure &m, bool toplevel = true) { + if(!toplevel && m.isUnit() && m.unit()->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) m.unit())->hasNonlinearExpression() && (((AliasUnit*) m.unit())->expression().find("log") != string::npos || ((AliasUnit*) m.unit())->inverseExpression().find("log") != string::npos || ((AliasUnit*) m.unit())->expression().find("ln") != string::npos || ((AliasUnit*) m.unit())->inverseExpression().find("ln") != string::npos)) { + return ((AliasUnit*) m.unit())->firstBaseUnit(); + } + if(m.isMultiplication() && toplevel && m.last().isUnit()) { + Unit *u = find_log_unit(m.last(), false); + if(u) { + for(size_t i = 0; i < m.size(); i++) { + if(m[i].containsType(STRUCT_UNIT, true)) return u; + } + return NULL; + } + } + for(size_t i = 0; i < m.size(); i++) { + Unit *u = find_log_unit(m[i], false); + if(u) return u; + } + return NULL; +} +void convert_log_units(MathStructure &m, const EvaluationOptions &eo) { + while(true) { + Unit *u = find_log_unit(m); + if(!u) break; + CALCULATOR->error(false, "Log-based units were converted before calculation.", NULL); + m.convert(u, true, NULL, false, eo); + } +} +bool warn_ratio_units(MathStructure &m, bool top_level = true) { + if(!top_level && m.isUnit() && ((m.unit()->subtype() == SUBTYPE_BASE_UNIT && m.unit()->referenceName() == "Np") || (m.unit()->subtype() == SUBTYPE_ALIAS_UNIT && ((AliasUnit*) m.unit())->baseUnit()->referenceName() == "Np"))) { + CALCULATOR->error(true, "Logarithmic ratio units is treated as other units and the result might not be as expected.", NULL); + return true; + } + if(m.isMultiplication() && top_level && m.last().isUnit()) { + if(m.size() < 2) return false; + for(size_t i = 0; i < m.size() - 1; i++) { + if(warn_ratio_units(m[i], false)) return true; + } + } else { + for(size_t i = 0; i < m.size(); i++) { + if(warn_ratio_units(m[i], false)) return true; + } + } + return false; +} + +void clean_multiplications(MathStructure &mstruct) { + if(mstruct.isMultiplication()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isMultiplication()) { + size_t i2 = 0; + for(; i2 < mstruct[i + i2].size(); i2++) { + mstruct[i + i2][i2].ref(); + mstruct.insertChild_nocopy(&mstruct[i + i2][i2], i + i2 + 1); + } + mstruct.delChild(i + i2 + 1); + } + } + } + for(size_t i = 0; i < mstruct.size(); i++) { + clean_multiplications(mstruct[i]); + } +} + +// Attempt to isolate x and test validity afterwards +bool try_isolate_x(MathStructure &mstruct, EvaluationOptions &eo3, const EvaluationOptions &eo) { + if(mstruct.isProtected()) return false; + if(mstruct.isComparison()) { + CALCULATOR->beginTemporaryStopMessages(); + MathStructure mtest(mstruct); + eo3.test_comparisons = false; + eo3.warn_about_denominators_assumed_nonzero = false; + mtest[0].calculatesub(eo3, eo); + mtest[1].calculatesub(eo3, eo); + eo3.test_comparisons = eo.test_comparisons; + const MathStructure *x_var2; + if(eo.isolate_var) x_var2 = eo.isolate_var; + else x_var2 = &mstruct.find_x_var(); + if(x_var2->isUndefined() || (mtest[0] == *x_var2 && !mtest[1].contains(*x_var2))) { + CALCULATOR->endTemporaryStopMessages(); + return false; + } + if(mtest.isolate_x(eo3, eo, *x_var2, false)) { + if(test_comparisons(mstruct, mtest, *x_var2, eo3) >= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mstruct = mtest; + return true; + } + } + CALCULATOR->endTemporaryStopMessages(); + } else { + bool b = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(try_isolate_x(mstruct[i], eo3, eo)) b = true; + } + return b; + } + return false; +} + +bool MathStructure::simplify(const EvaluationOptions &eo, bool unfactorize) { + if(SIZE == 0) return false; + if(unfactorize) { + unformat(); + EvaluationOptions eo2 = eo; + eo2.expand = true; + eo2.combine_divisions = false; + eo2.sync_units = false; + calculatesub(eo2, eo2); + bool b = do_simplification(*this, eo2, true, false, false); + return combination_factorize(*this) || b; + } + return combination_factorize(*this); +} +bool MathStructure::expand(const EvaluationOptions &eo, bool unfactorize) { + if(SIZE == 0) return false; + EvaluationOptions eo2 = eo; + eo2.sync_units = false; + eo2.expand = true; + if(unfactorize) calculatesub(eo2, eo2); + do_simplification(*this, eo2, true, false, false); + return false; +} +bool MathStructure::structure(StructuringMode structuring, const EvaluationOptions &eo, bool restore_first) { + switch(structuring) { + case STRUCTURING_NONE: { + if(restore_first) { + EvaluationOptions eo2 = eo; + eo2.sync_units = false; + calculatesub(eo2, eo2); + } + return false; + } + case STRUCTURING_FACTORIZE: { + return factorize(eo, restore_first, 3, 0, true, 2, NULL, m_undefined, true, false, -1); + } + default: { + return simplify(eo, restore_first); + } + } +} + +#define FORMAT_COMPLEX_NUMBERS if(eo.complex_number_form == COMPLEX_NUMBER_FORM_EXPONENTIAL) complexToExponentialForm(eo); \ + else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_POLAR) complexToPolarForm(eo); \ + else if(eo.complex_number_form == COMPLEX_NUMBER_FORM_CIS) complexToCisForm(eo); + +MathStructure &MathStructure::eval(const EvaluationOptions &eo) { + + if(m_type == STRUCT_NUMBER) {FORMAT_COMPLEX_NUMBERS; return *this;} + + if(eo.structuring != STRUCTURING_NONE) warn_ratio_units(*this); + + unformat(eo); + + if(m_type == STRUCT_UNDEFINED || m_type == STRUCT_ABORTED || m_type == STRUCT_DATETIME || m_type == STRUCT_UNIT || m_type == STRUCT_SYMBOLIC || (m_type == STRUCT_VARIABLE && !o_variable->isKnown())) return *this; + + if(eo.structuring != STRUCTURING_NONE && eo.sync_units) convert_log_units(*this, eo); + + EvaluationOptions feo = eo; + feo.structuring = STRUCTURING_NONE; + feo.do_polynomial_division = false; + feo.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; + EvaluationOptions eo2 = eo; + eo2.structuring = STRUCTURING_NONE; + eo2.expand = false; + eo2.test_comparisons = false; + eo2.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; + eo2.isolate_x = false; + + if(m_type == STRUCT_NUMBER) {FORMAT_COMPLEX_NUMBERS; return *this;} + + if(eo.interval_calculation == INTERVAL_CALCULATION_INTERVAL_ARITHMETIC) { + if(eo.calculate_functions) calculate_nondifferentiable_functions(*this, feo, true, true, 0); + if(((eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) && containsInterval(true, true, false, 1, true)) || (eo.sync_units && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.approximation != APPROXIMATION_EXACT && sync_approximate_units(*this, eo)) || (eo.approximation == APPROXIMATION_EXACT && contains_function_interval(*this, true, true, false, 1, true))) { + EvaluationOptions eo3 = eo2; + eo3.split_squares = false; + eo3.assume_denominators_nonzero = false; + if(eo.approximation == APPROXIMATION_APPROXIMATE && !containsUnknowns()) eo3.approximation = APPROXIMATION_EXACT_VARIABLES; + else eo3.approximation = APPROXIMATION_EXACT; + vector vars; + vector uncs; + calculatesub(eo3, eo3); + while(eo.sync_units && (separate_unit_vars(*this, feo, true) || sync_approximate_units(*this, feo, &vars, &uncs, false))) { + calculatesub(eo3, eo3); + } + eo3.approximation = APPROXIMATION_APPROXIMATE; + if(eo.sync_units) { + sync_approximate_units(*this, feo, &vars, &uncs, true); + } + factorize_variables(*this, eo3); + if(eo.approximation == APPROXIMATION_APPROXIMATE && !containsUnknowns()) eo3.approximation = APPROXIMATION_EXACT_VARIABLES; + else eo3.approximation = APPROXIMATION_EXACT; + eo3.expand = eo.expand; + eo3.assume_denominators_nonzero = eo.assume_denominators_nonzero; + solve_intervals(*this, eo3, feo); + } + if(eo.calculate_functions) calculate_differentiable_functions(*this, feo); + } else if(eo.interval_calculation == INTERVAL_CALCULATION_VARIANCE_FORMULA) { + if(eo.calculate_functions) calculate_nondifferentiable_functions(*this, feo, true, true, -1); + if(!isNumber() && (((eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) && containsInterval(true, true, false, 1, true)) || containsInterval(true, false, false, 1, true) || (eo.sync_units && eo.approximation != APPROXIMATION_EXACT && sync_approximate_units(*this, eo)) || (eo.approximation == APPROXIMATION_EXACT && contains_function_interval(*this, true, true, false, 1, true)))) { + + // calculate non-differentiable functions (not handled by variance formula) and functions without uncertainties + if(eo.calculate_functions) calculate_nondifferentiable_functions(*this, feo, true, true, (eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) ? 2 : 1); + + MathStructure munc, mbak(*this); + if(eo.approximation != APPROXIMATION_EXACT && eo.approximation != APPROXIMATION_EXACT_VARIABLES && eo.calculate_variables) { + // replace intervals with variables and calculate exact + find_interval_replace_var_nr(*this); + EvaluationOptions eo3 = eo2; + eo3.split_squares = false; + if(eo.expand && eo.expand >= -1) eo3.expand = -1; + eo3.assume_denominators_nonzero = eo.assume_denominators_nonzero; + eo3.approximation = APPROXIMATION_EXACT; + vector vars; + vector uncs; + calculatesub(eo3, eo3); + // remove units from variables with uncertainties + while(eo.sync_units && (separate_unit_vars(*this, feo, true) || sync_approximate_units(*this, feo, &vars, &uncs, false))) { + calculatesub(eo3, eo3); + } + } + bool b_failed = false; + if(containsType(STRUCT_COMPARISON)) { + + // Handle comparisons by exact calculation followed by calculation of each side of comparisons separately + + EvaluationOptions eo3 = eo; + eo3.approximation = APPROXIMATION_EXACT; + eo3.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; + eo3.structuring = STRUCTURING_NONE; + eo3.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; + + // replace uncertain values with variables + vector vars; + while(true) { + Variable *v = NULL; + Variable *uv = find_interval_replace_var_comp(*this, eo3, &v); + if(!uv) break; + if(v) replace(v, uv); + vars.push_back(uv); + } + + eval(eo3); + + // restore uncertain values + for(size_t i = 0; i < vars.size(); i++) { + if(vars[i]->isKnown()) replace(vars[i], ((KnownVariable*) vars[i])->get()); + else replace(vars[i], ((UnknownVariable*) vars[i])->interval()); + vars[i]->destroy(); + } + + if(CALCULATOR->aborted()) return *this; + + // calculate each side of comparisons separately + if(eval_comparison_sides(*this, feo)) { + if(eo.structuring != STRUCTURING_NONE) simplify_ln(*this); + structure(eo.structuring, eo2, false); + if(eo.structuring != STRUCTURING_NONE) simplify_ln(*this); + clean_multiplications(*this); + } else if(!CALCULATOR->aborted()) { + CALCULATOR->error(false, _("Calculation of uncertainty propagation partially failed (using interval arithmetic instead when necessary)."), NULL); + EvaluationOptions eo4 = eo; + eo4.interval_calculation = INTERVAL_CALCULATION_INTERVAL_ARITHMETIC; + eval(eo4); + } + return *this; + + } else { + + CALCULATOR->beginTemporaryStopMessages(); + + // calcute uncertainty + munc = calculate_uncertainty(*this, eo, b_failed); + + if(!b_failed && !munc.isZero()) { + + EvaluationOptions eo3 = eo; + eo3.keep_zero_units = false; + eo3.structuring = STRUCTURING_NONE; + eo3.complex_number_form = COMPLEX_NUMBER_FORM_RECTANGULAR; + eo3.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; + if(eo3.approximation == APPROXIMATION_TRY_EXACT) eo3.approximation = APPROXIMATION_APPROXIMATE; + + // evaluate uncertainty and expression without uncertainty + munc.eval(eo3); + eo3.keep_zero_units = eo.keep_zero_units; + eval(eo3); + + // Add uncertainty to calculated value + if(eo.keep_zero_units) remove_add_zero_unit(*this); + b_failed = true; + if(munc.isFunction() && munc.function()->id() == FUNCTION_ID_ABS && munc.size() == 1) { + munc.setToChild(1); + } + bool one_prepended = false; + test_munc: + if(munc.isNumber()) { + if(munc.isZero()) { + CALCULATOR->endTemporaryStopMessages(true); + return *this; + } else if(isNumber()) { + o_number.setUncertainty(munc.number()); + numberUpdated(); + CALCULATOR->endTemporaryStopMessages(true); + return *this; + } else if(isAddition()) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isNumber()) { + b_failed = false; + CHILD(i).number().setUncertainty(munc.number()); + CHILD(i).numberUpdated(); + CHILD_UPDATED(i); + break; + } + } + } + } else { + if(munc.isMultiplication()) { + if(!munc[0].isNumber()) { + munc.insertChild(m_one, 1); + one_prepended = true; + } + } else { + munc.transform(STRUCT_MULTIPLICATION); + munc.insertChild(m_one, 1); + one_prepended = true; + } + if(munc.isMultiplication()) { + if(munc.size() == 2) { + if(isMultiplication() && CHILD(0).isNumber() && (munc[1] == CHILD(1) || (munc[1].isFunction() && munc[1].function()->id() == FUNCTION_ID_ABS && munc[1].size() == 1 && CHILD(1) == munc[1][0]))) { + CHILD(0).number().setUncertainty(munc[0].number()); + CHILD(0).numberUpdated(); + CHILD_UPDATED(0) + b_failed = false; + } else if(equals(munc[1]) || (munc[1].isFunction() && munc[1].function()->id() == FUNCTION_ID_ABS && munc[1].size() == 1 && equals(munc[1][0]))) { + transform(STRUCT_MULTIPLICATION); + PREPEND(m_one); + CHILD(0).number().setUncertainty(munc[0].number()); + CHILD(0).numberUpdated(); + CHILD_UPDATED(0) + b_failed = false; + } + } else if(isMultiplication()) { + size_t i2 = 0; + if(CHILD(0).isNumber()) i2++; + if(SIZE + 1 - i2 == munc.size()) { + bool b = true; + for(size_t i = 1; i < munc.size(); i++, i2++) { + if(!munc[i].equals(CHILD(i2)) && !(munc[i].isFunction() && munc[i].function()->id() == FUNCTION_ID_ABS && munc[i].size() == 1 && CHILD(i2) == munc[i][0])) { + b = false; + break; + } + } + if(b) { + if(!CHILD(0).isNumber()) { + PREPEND(m_one); + } + CHILD(0).number().setUncertainty(munc[0].number()); + CHILD(0).numberUpdated(); + CHILD_UPDATED(0) + b_failed = false; + } + } + } + if(b_failed) { + bool b = false; + for(size_t i = 0; i < munc.size(); i++) { + if(munc[i].isFunction() && munc[i].function()->id() == FUNCTION_ID_ABS && munc[i].size() == 1) { + munc[i].setToChild(1); + b = true; + } + } + if(b) { + munc.eval(eo3); + goto test_munc; + } + } + } + } + if(b_failed && munc.countTotalChildren(false) < 50) { + if(one_prepended && munc.isMultiplication() && munc[0].isOne()) munc.delChild(1, true); + if(eo.structuring != STRUCTURING_NONE) {simplify_ln(*this); simplify_ln(munc);} + structure(eo.structuring, eo2, false); + munc.structure(eo.structuring, eo2, false); + if(eo.structuring != STRUCTURING_NONE) {simplify_ln(*this); simplify_ln(munc);} + clean_multiplications(*this); + clean_multiplications(munc); + transformById(FUNCTION_ID_UNCERTAINTY); + addChild(munc); + addChild(m_zero); + CALCULATOR->endTemporaryStopMessages(true); + return *this; + } + if(!b_failed) { + CALCULATOR->endTemporaryStopMessages(true); + if(eo.structuring != STRUCTURING_NONE) simplify_ln(*this); + structure(eo.structuring, eo2, false); + if(eo.structuring != STRUCTURING_NONE) simplify_ln(*this); + clean_multiplications(*this); + return *this; + } + } + CALCULATOR->endTemporaryStopMessages(!b_failed); + if(b_failed) { + set(mbak); + if(CALCULATOR->aborted()) return *this; + CALCULATOR->error(false, _("Calculation of uncertainty propagation failed (using interval arithmetic instead)."), NULL); + EvaluationOptions eo3 = eo; + eo3.interval_calculation = INTERVAL_CALCULATION_INTERVAL_ARITHMETIC; + eval(eo3); + return *this; + } + } + } + if(eo.calculate_functions) calculate_differentiable_functions(*this, feo); + } else if(eo.calculate_functions) { + calculateFunctions(feo); + } + + if(m_type == STRUCT_NUMBER) {FORMAT_COMPLEX_NUMBERS; return *this;} + + if(eo2.interval_calculation == INTERVAL_CALCULATION_INTERVAL_ARITHMETIC || eo2.interval_calculation == INTERVAL_CALCULATION_VARIANCE_FORMULA) eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; + + // do exact calculations first and handle variables with intervals + if(eo2.approximation == APPROXIMATION_TRY_EXACT || (eo2.approximation == APPROXIMATION_APPROXIMATE && (containsUnknowns() || containsInterval(false, true, false, 0)))) { + EvaluationOptions eo3 = eo2; + if(eo.approximation == APPROXIMATION_APPROXIMATE && !containsUnknowns()) eo3.approximation = APPROXIMATION_EXACT_VARIABLES; + else eo3.approximation = APPROXIMATION_EXACT; + eo3.split_squares = false; + eo3.assume_denominators_nonzero = false; + calculatesub(eo3, feo); + if(m_type == STRUCT_NUMBER) {FORMAT_COMPLEX_NUMBERS; return *this;} + if(eo.interval_calculation < INTERVAL_CALCULATION_INTERVAL_ARITHMETIC && eo.expand && eo.expand >= -1 && !containsType(STRUCT_COMPARISON, true, true, true)) { + unformat(eo); + eo3.expand = -1; + calculatesub(eo3, feo); + } + eo3.approximation = APPROXIMATION_APPROXIMATE; + if(eo2.interval_calculation >= INTERVAL_CALCULATION_INTERVAL_ARITHMETIC && containsInterval(false, true, false, -1)) factorize_variables(*this, eo3); + if(containsType(STRUCT_COMPARISON) && containsInterval(false, true, false, false)) { + eo3.approximation = APPROXIMATION_EXACT; + fix_eqs(*this, eo3); + } + eo2.approximation = APPROXIMATION_APPROXIMATE; + } else if(eo2.approximation == APPROXIMATION_EXACT && contains_function_interval(*this, false, true, false, -1)) { + EvaluationOptions eo3 = eo2; + eo3.split_squares = false; + eo3.assume_denominators_nonzero = false; + calculatesub(eo3, feo); + eo3.approximation = APPROXIMATION_APPROXIMATE; + if(eo2.interval_calculation >= INTERVAL_CALCULATION_INTERVAL_ARITHMETIC) factorize_variables(*this, eo3, true); + } + if(eo2.approximation == APPROXIMATION_EXACT) replace_function_vars(*this); + + calculatesub(eo2, feo); + + if(m_type == STRUCT_NUMBER) {FORMAT_COMPLEX_NUMBERS; return *this;} + if(m_type == STRUCT_UNDEFINED || m_type == STRUCT_ABORTED || m_type == STRUCT_DATETIME || m_type == STRUCT_UNIT || m_type == STRUCT_SYMBOLIC || (m_type == STRUCT_VARIABLE && !o_variable->isKnown())) return *this; + if(CALCULATOR->aborted()) return *this; + + eo2.sync_units = false; + eo2.isolate_x = eo.isolate_x; + + // Try isolate x without expanding expression + if(eo2.isolate_x) { + eo2.assume_denominators_nonzero = false; + if(isolate_x(eo2, feo)) { + if(CALCULATOR->aborted()) return *this; + if(eo.assume_denominators_nonzero) eo2.assume_denominators_nonzero = 2; + calculatesub(eo2, feo); + } else { + if(eo.assume_denominators_nonzero) eo2.assume_denominators_nonzero = 2; + } + if(CALCULATOR->aborted()) return *this; + } + + // Try isolate x after expanding expression and perform simplification using gcd and polynomial division + if(eo.expand != 0 || (eo.test_comparisons && containsType(STRUCT_COMPARISON))) { + eo2.test_comparisons = eo.test_comparisons; + eo2.expand = eo.expand; + if(eo2.expand && (!eo.test_comparisons || !containsType(STRUCT_COMPARISON))) eo2.expand = -2; + bool b = eo2.test_comparisons; + if(!b && isAddition()) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).containsType(STRUCT_ADDITION, false) == 1) { + b = true; + break; + } + } + } else if(!b) { + b = containsType(STRUCT_ADDITION, false) == 1; + } + if(b) { + calculatesub(eo2, feo); + if(CALCULATOR->aborted()) return *this; + if(eo.do_polynomial_division) do_simplification(*this, eo2, true, eo.structuring == STRUCTURING_NONE || eo.structuring == STRUCTURING_FACTORIZE, false, true, true); + if(CALCULATOR->aborted()) return *this; + if(eo2.isolate_x) { + eo2.assume_denominators_nonzero = false; + if(isolate_x(eo2, feo)) { + if(CALCULATOR->aborted()) return *this; + if(eo.assume_denominators_nonzero) eo2.assume_denominators_nonzero = 2; + calculatesub(eo2, feo); + if(containsType(STRUCT_ADDITION, false) == 1 && eo.do_polynomial_division) do_simplification(*this, eo2, true, eo.structuring == STRUCTURING_NONE || eo.structuring == STRUCTURING_FACTORIZE, false, true, true); + } else { + if(eo.assume_denominators_nonzero) eo2.assume_denominators_nonzero = 2; + } + if(CALCULATOR->aborted()) return *this; + } + } + } + + // Final attempt to isolate x, by assuming denominators is non zero and testing validity afterwards + if(eo2.isolate_x && containsType(STRUCT_COMPARISON) && eo2.assume_denominators_nonzero) { + eo2.assume_denominators_nonzero = 2; + if(try_isolate_x(*this, eo2, feo)) { + if(CALCULATOR->aborted()) return *this; + calculatesub(eo2, feo); + if(containsType(STRUCT_ADDITION, false) == 1 && eo.do_polynomial_division) do_simplification(*this, eo2, true, eo.structuring == STRUCTURING_NONE || eo.structuring == STRUCTURING_FACTORIZE, false, true, true); + } + } + + simplify_functions(*this, eo2, feo); + + if(CALCULATOR->aborted()) return *this; + + if(eo.structuring != STRUCTURING_NONE) { + + if(eo.parse_options.angle_unit == ANGLE_UNIT_GRADIANS || eo.parse_options.angle_unit == ANGLE_UNIT_DEGREES) convert_to_default_angle_unit(*this, eo); + simplify_ln(*this); + + if(eo.keep_zero_units) remove_add_zero_unit(*this); + + structure(eo.structuring, eo2, false); + + simplify_ln(*this); + + } + + clean_multiplications(*this); + + FORMAT_COMPLEX_NUMBERS + + return *this; +} + diff -Nru libqalculate-3.6.0/libqalculate/MathStructure-factor.cc libqalculate-3.7.0/libqalculate/MathStructure-factor.cc --- libqalculate-3.6.0/libqalculate/MathStructure-factor.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure-factor.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,3284 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "MathStructure.h" +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "Number.h" +#include "Function.h" +#include "Variable.h" +#include "Unit.h" +#include "Prefix.h" +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::ostream; +using std::endl; + +bool factorize_fix_root_power(MathStructure &m) { + if(!m[0].isFunction() || m[0].function()->id() != FUNCTION_ID_ROOT || !VALID_ROOT(m[0])) return false; + if(m[1].isNumber() && m[1].number().isInteger() && !m[1].number().isMinusOne()) { + if(m[1] == m[0][1]) { + // root(x, a)^a=x + m.setToChild(1, true); + m.setToChild(1, true); + return true; + } else if(m[1].number().isIntegerDivisible(m[0][1].number())) { + // root(x, a)^(2a)=x^2 + if(m[1].number().divide(m[0][1].number())) { + m[0].setToChild(1, true); + return true; + } + } else if(m[0][1].number().isIntegerDivisible(m[1].number())) { + // root(x, 3a)^(a)=root(x, 3) + if(m[0][1].number().divide(m[1].number())) { + m.setToChild(1, true); + m.childUpdated(2); + return true; + } + } + } + return false; +} + +bool sqrfree_differentiate(const MathStructure &mpoly, const MathStructure &x_var, MathStructure &mdiff, const EvaluationOptions &eo) { + if(mpoly == x_var) { + mdiff.set(1, 1, 0); + return true; + } + switch(mpoly.type()) { + case STRUCT_ADDITION: { + mdiff.clear(); + mdiff.setType(STRUCT_ADDITION); + for(size_t i = 0; i < mpoly.size(); i++) { + mdiff.addChild(m_zero); + if(!sqrfree_differentiate(mpoly[i], x_var, mdiff[i], eo)) return false; + } + mdiff.calculatesub(eo, eo, false); + break; + } + case STRUCT_VARIABLE: {} + case STRUCT_FUNCTION: {} + case STRUCT_SYMBOLIC: {} + case STRUCT_UNIT: {} + case STRUCT_NUMBER: { + mdiff.clear(); + break; + } + case STRUCT_POWER: { + if(mpoly[0] == x_var) { + mdiff = mpoly[1]; + mdiff.multiply(x_var); + if(!mpoly[1].number().isTwo()) { + mdiff[1].raise(mpoly[1]); + mdiff[1][1].number()--; + } + mdiff.evalSort(true); + } else { + mdiff.clear(); + } + break; + } + case STRUCT_MULTIPLICATION: { + if(mpoly.size() < 1) { + mdiff.clear(); + break; + } else if(mpoly.size() < 2) { + return sqrfree_differentiate(mpoly[0], x_var, mdiff, eo); + } + mdiff.clear(); + for(size_t i = 0; i < mpoly.size(); i++) { + if(mpoly[i] == x_var) { + if(mpoly.size() == 2) { + if(i == 0) mdiff = mpoly[1]; + else mdiff = mpoly[0]; + } else { + mdiff.setType(STRUCT_MULTIPLICATION); + for(size_t i2 = 0; i2 < mpoly.size(); i2++) { + if(i2 != i) { + mdiff.addChild(mpoly[i2]); + } + } + } + break; + } else if(mpoly[i].isPower() && mpoly[i][0] == x_var) { + mdiff = mpoly; + if(mpoly[i][1].number().isTwo()) { + mdiff[i].setToChild(1); + } else { + mdiff[i][1].number()--; + } + if(mdiff[0].isNumber()) { + mdiff[0].number() *= mpoly[i][1].number(); + } else { + mdiff.insertChild(mpoly[i][1].number(), 1); + } + mdiff.evalSort(); + break; + } + } + break; + } + default: { + return false; + } + } + return true; +} +bool fix_root_pow(MathStructure &m, const MathStructure &xvar, const EvaluationOptions &eo) { + if(m.isPower() && m[0].contains(xvar) && m[1].isNumber()) { + return m.calculateRaiseExponent(eo); + } + bool b_ret = false; + for(size_t i = 0; i < m.size(); i++) { + if(fix_root_pow(m[i], xvar, eo)) {m.childUpdated(i + 1); b_ret = true;} + } + if(b_ret) m.calculatesub(eo, eo, false); + return b_ret; +} + +bool sqrfree_yun(const MathStructure &a, const MathStructure &xvar, MathStructure &factors, const EvaluationOptions &eo) { + MathStructure w(a); + MathStructure z; + if(!sqrfree_differentiate(a, xvar, z, eo)) { + return false; + } + MathStructure g; + if(!MathStructure::gcd(w, z, g, eo)) { + return false; + } + if(g.isOne()) { + factors.addChild(a); + return true; + } + MathStructure y; + MathStructure tmp; + do { + tmp = w; + if(!MathStructure::polynomialQuotient(tmp, g, xvar, w, eo)) { + return false; + } + if(!MathStructure::polynomialQuotient(z, g, xvar, y, eo)) { + return false; + } + if(!sqrfree_differentiate(w, xvar, tmp, eo)) { + return false; + } + z = y; + z.calculateSubtract(tmp, eo); + if(!MathStructure::gcd(w, z, g, eo)) { + return false; + } + factors.addChild(g); + } while (!z.isZero()); + return true; +} + +bool sqrfree_simple(const MathStructure &a, const MathStructure &xvar, MathStructure &factors, const EvaluationOptions &eo) { + MathStructure w(a); + size_t i = 0; + while(true) { + MathStructure z, zmod; + if(!sqrfree_differentiate(w, xvar, z, eo)) return false; + polynomial_smod(z, nr_three, zmod, eo); + if(z == w) { + factors.addChild(w); + break; + } + MathStructure mgcd; + if(!MathStructure::gcd(w, z, mgcd, eo)) return false; + if(mgcd.isOne() || mgcd == w) { + factors.addChild(w); + break; + } + MathStructure tmp(w); + if(!MathStructure::polynomialQuotient(tmp, mgcd, xvar, w, eo)) return false; + if(!sqrfree_simple(mgcd, xvar, factors, eo)) return false; + i++; + } + return true; +} + +void lcmcoeff(const MathStructure &e, const Number &l, Number &nlcm); +void lcmcoeff(const MathStructure &e, const Number &l, Number &nlcm) { + if(e.isNumber() && e.number().isRational()) { + nlcm = e.number().denominator(); + nlcm.lcm(l); + } else if(e.isAddition()) { + nlcm.set(1, 1, 0); + for(size_t i = 0; i < e.size(); i++) { + Number c(nlcm); + lcmcoeff(e[i], c, nlcm); + } + nlcm.lcm(l); + } else if(e.isMultiplication()) { + nlcm.set(1, 1, 0); + for(size_t i = 0; i < e.size(); i++) { + Number c(nlcm); + lcmcoeff(e[i], nr_one, c); + nlcm *= c; + } + nlcm.lcm(l); + } else if(e.isPower()) { + if(IS_A_SYMBOL(e[0]) || e[0].isUnit()) { + nlcm = l; + } else { + lcmcoeff(e[0], l, nlcm); + nlcm ^= e[1].number(); + } + } else { + nlcm = l; + } +} + +void lcm_of_coefficients_denominators(const MathStructure &e, Number &nlcm) { + return lcmcoeff(e, nr_one, nlcm); +} + +void multiply_lcm(const MathStructure &e, const Number &lcm, MathStructure &mmul, const EvaluationOptions &eo) { + if(e.isMultiplication()) { + Number lcm_accum(1, 1); + mmul.clear(); + for(size_t i = 0; i < e.size(); i++) { + Number op_lcm; + lcmcoeff(e[i], nr_one, op_lcm); + if(mmul.isZero()) { + multiply_lcm(e[i], op_lcm, mmul, eo); + if(mmul.isOne()) mmul.clear(); + } else { + mmul.multiply(m_one, true); + multiply_lcm(e[i], op_lcm, mmul[mmul.size() - 1], eo); + if(mmul[mmul.size() - 1].isOne()) { + mmul.delChild(i + 1); + if(mmul.size() == 1) mmul.setToChild(1); + } + } + lcm_accum *= op_lcm; + } + Number lcm2(lcm); + lcm2 /= lcm_accum; + if(mmul.isZero()) { + mmul = lcm2; + } else if(!lcm2.isOne()) { + if(mmul.size() > 0 && mmul[0].isNumber()) { + mmul[0].number() *= lcm2; + } else { + mmul.multiply(lcm2, true); + } + } + mmul.evalSort(); + } else if(e.isAddition()) { + mmul.clear(); + for (size_t i = 0; i < e.size(); i++) { + if(mmul.isZero()) { + multiply_lcm(e[i], lcm, mmul, eo); + } else { + mmul.add(m_zero, true); + multiply_lcm(e[i], lcm, mmul[mmul.size() - 1], eo); + } + } + mmul.evalSort(); + } else if(e.isPower()) { + if(IS_A_SYMBOL(e[0]) || e[0].isUnit()) { + mmul = e; + if(!lcm.isOne()) { + mmul *= lcm; + mmul.evalSort(); + } + } else { + mmul = e; + Number lcm_exp = e[1].number(); + lcm_exp.recip(); + multiply_lcm(e[0], lcm ^ lcm_exp, mmul[0], eo); + if(mmul[0] != e[0]) { + mmul.calculatesub(eo, eo, false); + } + } + } else if(e.isNumber()) { + mmul = e; + mmul.number() *= lcm; + } else if(IS_A_SYMBOL(e) || e.isUnit()) { + mmul = e; + if(!lcm.isOne()) { + mmul *= lcm; + mmul.evalSort(); + } + } else { + mmul = e; + if(!lcm.isOne()) { + mmul.calculateMultiply(lcm, eo); + mmul.evalSort(); + } + } +} + +//from GiNaC +bool sqrfree(MathStructure &mpoly, const EvaluationOptions &eo) { + vector symbols; + collect_symbols(mpoly, symbols); + return sqrfree(mpoly, symbols, eo); +} +bool sqrfree(MathStructure &mpoly, const vector &symbols, const EvaluationOptions &eo) { + + EvaluationOptions eo2 = eo; + eo2.assume_denominators_nonzero = true; + eo2.warn_about_denominators_assumed_nonzero = false; + eo2.reduce_divisions = true; + eo2.keep_zero_units = false; + eo2.do_polynomial_division = false; + eo2.sync_units = false; + eo2.expand = true; + eo2.calculate_functions = false; + eo2.protected_function = CALCULATOR->getFunctionById(FUNCTION_ID_SIGNUM); + + if(mpoly.size() == 0) { + return true; + } + if(symbols.empty()) return true; + + size_t symbol_index = 0; + if(symbols.size() > 1) { + for(size_t i = 1; i < symbols.size(); i++) { + if(mpoly.degree(symbols[symbol_index]).isGreaterThan(mpoly.degree(symbols[i]))) symbol_index = i; + } + } + + MathStructure xvar(symbols[symbol_index]); + + UnknownVariable *var = NULL; + if(xvar.size() > 0) { + var = new UnknownVariable("", format_and_print(xvar)); + var->setAssumptions(xvar); + mpoly.replace(xvar, var); + xvar = var; + } + + Number nlcm; + lcm_of_coefficients_denominators(mpoly, nlcm); + + MathStructure tmp; + multiply_lcm(mpoly, nlcm, tmp, eo2); + + MathStructure factors; + factors.clearVector(); + + if(!sqrfree_yun(tmp, xvar, factors, eo2)) { + if(var) tmp.replace(var, symbols[symbol_index]); + factors.clearVector(); + factors.addChild(tmp); + } else { + if(var) tmp.replace(var, symbols[symbol_index]); + } + if(var) {mpoly.replace(var, symbols[symbol_index]); var->destroy();} + + vector newsymbols; + for(size_t i = 0; i < symbols.size(); i++) { + if(i != symbol_index) newsymbols.push_back(symbols[i]); + } + + if(newsymbols.size() > 0) { + for(size_t i = 0; i < factors.size(); i++) { + if(!sqrfree(factors[i], newsymbols, eo)) return false; + } + } + + mpoly.set(1, 1, 0); + for(size_t i = 0; i < factors.size(); i++) { + if(CALCULATOR->aborted()) return false; + if(!factors[i].isOne()) { + if(mpoly.isOne()) { + mpoly = factors[i]; + if(i != 0) mpoly.raise(MathStructure((long int) i + 1, 1L, 0L)); + } else { + mpoly.multiply(factors[i], true); + mpoly[mpoly.size() - 1].raise(MathStructure((long int) i + 1, 1L, 0L)); + } + } + } + + if(CALCULATOR->aborted()) return false; + if(mpoly.isZero()) { + CALCULATOR->error(true, "mpoly is zero: %s. %s", format_and_print(tmp).c_str(), _("This is a bug. Please report it."), NULL); + return false; + } + MathStructure mquo; + MathStructure mpoly_expand(mpoly); + EvaluationOptions eo3 = eo; + eo3.expand = true; + mpoly_expand.calculatesub(eo3, eo3); + + MathStructure::polynomialQuotient(tmp, mpoly_expand, xvar, mquo, eo2); + + if(CALCULATOR->aborted()) return false; + if(mquo.isZero()) { + //CALCULATOR->error(true, "quo is zero: %s. %s", format_and_print(tmp).c_str(), _("This is a bug. Please report it."), NULL); + return false; + } + if(newsymbols.size() > 0) { + if(!sqrfree(mquo, newsymbols, eo)) return false; + } + if(!mquo.isOne()) { + mpoly.multiply(mquo, true); + } + if(!nlcm.isOne()) { + nlcm.recip(); + mpoly.multiply(nlcm, true); + } + + eo3.expand = false; + mpoly.calculatesub(eo3, eo3, false); + + return true; + +} + +bool MathStructure::integerFactorize() { + if(!isNumber()) return false; + vector factors; + if(!o_number.factorize(factors)) return false; + if(factors.size() <= 1) return true; + clear(true); + bool b_pow = false; + Number *lastnr = NULL; + for(size_t i = 0; i < factors.size(); i++) { + if(lastnr && factors[i] == *lastnr) { + if(!b_pow) { + LAST.raise(m_one); + b_pow = true; + } + LAST[1].number()++; + } else { + APPEND(factors[i]); + b_pow = false; + } + lastnr = &factors[i]; + } + m_type = STRUCT_MULTIPLICATION; + return true; +} +size_t count_powers(const MathStructure &mstruct) { + if(mstruct.isPower()) { + if(mstruct[1].isInteger()) { + bool overflow = false; + int c = mstruct.number().intValue(&overflow) - 1; + if(overflow) return 0; + if(c < 0) return -c; + return c; + } + } + size_t c = 0; + for(size_t i = 0; i < mstruct.size(); i++) { + c += count_powers(mstruct[i]); + } + return c; +} + +bool gather_factors(const MathStructure &mstruct, const MathStructure &x_var, MathStructure &madd, MathStructure &mmul, MathStructure &mexp, bool mexp_as_x2 = false) { + madd.clear(); + if(mexp_as_x2) mexp = m_zero; + else mexp = m_one; + mmul = m_zero; + if(mstruct == x_var) { + mmul = m_one; + return true; + } else if(mexp_as_x2 && mstruct.isPower()) { + if(mstruct[1].isNumber() && mstruct[1].number().isTwo() && mstruct[0] == x_var) { + mexp = m_one; + return true; + } + } else if(!mexp_as_x2 && mstruct.isPower() && mstruct[1].isInteger() && mstruct[0] == x_var) { + if(mstruct[0] == x_var) { + mexp = mstruct[1]; + mmul = m_one; + return true; + } + } else if(mstruct.isMultiplication() && mstruct.size() >= 2) { + bool b_x = false; + bool b2 = false; + size_t i_x = 0; + for(size_t i = 0; i < mstruct.size(); i++) { + if(!b_x && mstruct[i] == x_var) { + b_x = true; + i_x = i; + } else if(!b_x && mexp_as_x2 && mstruct[i].isPower() && mstruct[i][1].isNumber() && mstruct[i][1].number().isTwo() && mstruct[i][0] == x_var) { + b_x = true; + b2 = true; + i_x = i; + } else if(!b_x && !mexp_as_x2 && mstruct[i].isPower() && mstruct[i][1].isInteger() && mstruct[i][0] == x_var) { + b_x = true; + i_x = i; + mexp = mstruct[i][1]; + } else if(mstruct[i].containsRepresentativeOf(x_var, true, true) != 0) { + return false; + } + } + if(!b_x) return false; + if(mstruct.size() == 1) { + if(b2) mexp = m_one; + else mmul = m_one; + } else if(mstruct.size() == 2) { + if(b2) { + if(i_x == 1) mexp = mstruct[0]; + else mexp = mstruct[1]; + } else { + if(i_x == 1) mmul = mstruct[0]; + else mmul = mstruct[1]; + } + } else { + if(b2) { + mexp = mstruct; + mexp.delChild(i_x + 1, true); + } else { + mmul = mstruct; + mmul.delChild(i_x + 1, true); + } + } + return true; + } else if(mstruct.isAddition()) { + mmul.setType(STRUCT_ADDITION); + if(mexp_as_x2) mexp.setType(STRUCT_ADDITION); + madd.setType(STRUCT_ADDITION); + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i] == x_var) { + if(mexp_as_x2 || mexp.isOne()) mmul.addChild(m_one); + else return false; + } else if(mexp_as_x2 && mstruct[i].isPower() && mstruct[i][1].isNumber() && mstruct[i][1].number().isTwo() && mstruct[i][0] == x_var) { + mexp.addChild(m_one); + } else if(!mexp_as_x2 && mstruct[i].isPower() && mstruct[i][1].isInteger() && mstruct[i][0] == x_var) { + if(mmul.size() == 0) { + mexp = mstruct[i][1]; + } else if(mexp != mstruct[i][1]) { + return false; + } + mmul.addChild(m_one); + } else if(mstruct[i].isMultiplication()) { + bool b_x = false; + bool b2 = false; + size_t i_x = 0; + for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { + if(!b_x && mstruct[i][i2] == x_var) { + if(!mexp_as_x2 && !mexp.isOne()) return false; + i_x = i2; + b_x = true; + } else if(!b_x && mexp_as_x2 && mstruct[i][i2].isPower() && mstruct[i][i2][1].isNumber() && mstruct[i][i2][1].number().isTwo() && mstruct[i][i2][0] == x_var) { + b2 = true; + i_x = i2; + b_x = true; + } else if(!b_x && !mexp_as_x2 && mstruct[i][i2].isPower() && mstruct[i][i2][1].isInteger() && mstruct[i][i2][0] == x_var) { + if(mmul.size() == 0) { + mexp = mstruct[i][i2][1]; + } else if(mexp != mstruct[i][i2][1]) { + return false; + } + i_x = i2; + b_x = true; + } else if(mstruct[i][i2].containsRepresentativeOf(x_var, true, true) != 0) { + return false; + } + } + if(b_x) { + if(mstruct[i].size() == 1) { + if(b2) mexp.addChild(m_one); + else mmul.addChild(m_one); + } else { + if(b2) { + mexp.addChild(mstruct[i]); + mexp[mexp.size() - 1].delChild(i_x + 1, true); + mexp.childUpdated(mexp.size()); + } else { + mmul.addChild(mstruct[i]); + mmul[mmul.size() - 1].delChild(i_x + 1, true); + mmul.childUpdated(mmul.size()); + } + } + } else { + madd.addChild(mstruct[i]); + } + } else if(mstruct[i].containsRepresentativeOf(x_var, true, true) != 0) { + return false; + } else { + madd.addChild(mstruct[i]); + } + } + if(mmul.size() == 0 && (!mexp_as_x2 || mexp.size() == 0)) { + mmul.clear(); + if(mexp_as_x2) mexp.clear(); + return false; + } + if(mmul.size() == 0) mmul.clear(); + else if(mmul.size() == 1) mmul.setToChild(1); + if(mexp_as_x2) { + if(mexp.size() == 0) mexp.clear(); + else if(mexp.size() == 1) mexp.setToChild(1); + } + if(madd.size() == 0) madd.clear(); + else if(madd.size() == 1) madd.setToChild(1); + return true; + } + return false; +} + +bool factorize_find_multiplier(const MathStructure &mstruct, MathStructure &mnew, MathStructure &factor_mstruct, bool only_units) { + factor_mstruct.set(m_one); + switch(mstruct.type()) { + case STRUCT_ADDITION: { + if(!only_units) { + bool bfrac = false, bint = true; + idm1(mstruct, bfrac, bint); + if(bfrac || bint) { + Number gcd(1, 1); + idm2(mstruct, bfrac, bint, gcd); + if((bint || bfrac) && !gcd.isOne()) { + if(bfrac) gcd.recip(); + factor_mstruct.set(gcd); + } + } + } + if(mstruct.size() > 0) { + size_t i = 0; + const MathStructure *cur_mstruct; + while(true) { + if(mstruct[0].isMultiplication()) { + if(i >= mstruct[0].size()) { + break; + } + cur_mstruct = &mstruct[0][i]; + } else { + cur_mstruct = &mstruct[0]; + } + if(!cur_mstruct->containsInterval(true) && !cur_mstruct->isNumber() && (!only_units || cur_mstruct->isUnit_exp())) { + const MathStructure *exp = NULL; + const MathStructure *bas; + if(cur_mstruct->isPower() && IS_REAL((*cur_mstruct)[1]) && !(*cur_mstruct)[0].isNumber()) { + exp = cur_mstruct->exponent(); + bas = cur_mstruct->base(); + } else { + bas = cur_mstruct; + } + bool b = true; + for(size_t i2 = 1; i2 < mstruct.size(); i2++) { + b = false; + size_t i3 = 0; + const MathStructure *cmp_mstruct; + while(true) { + if(mstruct[i2].isMultiplication()) { + if(i3 >= mstruct[i2].size()) { + break; + } + cmp_mstruct = &mstruct[i2][i3]; + } else { + cmp_mstruct = &mstruct[i2]; + } + if(cmp_mstruct->equals(*bas)) { + if(exp) { + exp = NULL; + } + b = true; + break; + } else if(cmp_mstruct->isPower() && IS_REAL((*cmp_mstruct)[1]) && cmp_mstruct->base()->equals(*bas)) { + if(exp) { + if(cmp_mstruct->exponent()->number().isLessThan(exp->number())) { + exp = cmp_mstruct->exponent(); + } + b = true; + break; + } else { + b = true; + break; + } + } + if(!mstruct[i2].isMultiplication()) { + break; + } + i3++; + } + if(!b) break; + } + if(b) { + b = !factor_mstruct.isOne(); + if(exp) { + MathStructure *mstruct = new MathStructure(*bas); + mstruct->raise(*exp); + if(factor_mstruct.isOne()) { + factor_mstruct.set_nocopy(*mstruct); + mstruct->unref(); + } else { + factor_mstruct.multiply_nocopy(mstruct, true); + } + } else { + if(factor_mstruct.isOne()) factor_mstruct.set(*bas); + else factor_mstruct.multiply(*bas, true); + } + if(b) { + size_t i3 = 0; + const MathStructure *cmp_mstruct; + b = false; + while(true) { + if(i3 >= factor_mstruct.size() - 1) { + break; + } + cmp_mstruct = &factor_mstruct[i3]; + if(cmp_mstruct->equals(factor_mstruct.last())) { + if(exp) { + exp = NULL; + } + b = true; + break; + } else if(cmp_mstruct->isPower() && IS_REAL((*cmp_mstruct)[1]) && cmp_mstruct->base()->equals(factor_mstruct.last())) { + if(exp) { + if(cmp_mstruct->exponent()->number().isLessThan(exp->number())) { + exp = cmp_mstruct->exponent(); + } + b = true; + break; + } else { + b = true; + break; + } + } + i3++; + } + if(b) factor_mstruct.delChild(factor_mstruct.size(), true); + } + } + } + if(!mstruct[0].isMultiplication()) { + break; + } + i++; + } + } + if(!factor_mstruct.isOne()) { + if(&mstruct != &mnew) mnew.set(mstruct); + MathStructure *mfactor; + size_t i = 0; + while(true) { + if(factor_mstruct.isMultiplication()) { + if(i >= factor_mstruct.size()) break; + mfactor = &factor_mstruct[i]; + } else { + mfactor = &factor_mstruct; + } + for(size_t i2 = 0; i2 < mnew.size(); i2++) { + switch(mnew[i2].type()) { + case STRUCT_NUMBER: { + if(mfactor->isNumber()) { + mnew[i2].number() /= mfactor->number(); + } + break; + } + case STRUCT_POWER: { + if(!IS_REAL(mnew[i2][1])) { + if(mfactor->isNumber()) { + mnew[i2].transform(STRUCT_MULTIPLICATION); + mnew[i2].insertChild(MathStructure(1, 1, 0), 1); + mnew[i2][0].number() /= mfactor->number(); + } else { + mnew[i2].set(m_one); + } + } else if(mfactor->isNumber()) { + mnew[i2].transform(STRUCT_MULTIPLICATION); + mnew[i2].insertChild(MathStructure(1, 1, 0), 1); + mnew[i2][0].number() /= mfactor->number(); + } else if(mfactor->isPower() && IS_REAL((*mfactor)[1])) { + if(mfactor->equals(mnew[i2])) { + mnew[i2].set(m_one); + } else { + mnew[i2][1].number() -= mfactor->exponent()->number(); + if(mnew[i2][1].number().isOne()) { + mnew[i2].setToChild(1, true); + } else if(factorize_fix_root_power(mnew[i2])) { + mnew.childUpdated(i2 + 1); + } + } + } else { + mnew[i2][1].number() -= 1; + if(mnew[i2][1].number().isOne()) { + mnew[i2].setToChild(1); + } else if(mnew[i2][1].number().isZero()) { + mnew[i2].set(m_one); + } else if(factorize_fix_root_power(mnew[i2])) { + mnew.childUpdated(i2 + 1); + } + } + break; + } + case STRUCT_MULTIPLICATION: { + bool b = true; + if(mfactor->isNumber() && (mnew[i2].size() < 1 || !mnew[i2][0].isNumber())) { + mnew[i2].insertChild(MathStructure(1, 1, 0), 1); + } + for(size_t i3 = 0; i3 < mnew[i2].size() && b; i3++) { + switch(mnew[i2][i3].type()) { + case STRUCT_NUMBER: { + if(mfactor->isNumber()) { + if(mfactor->equals(mnew[i2][i3])) { + mnew[i2].delChild(i3 + 1); + } else { + mnew[i2][i3].number() /= mfactor->number(); + } + b = false; + } + break; + } + case STRUCT_POWER: { + if(!IS_REAL(mnew[i2][i3][1])) { + if(mfactor->equals(mnew[i2][i3])) { + mnew[i2].delChild(i3 + 1); + b = false; + } + } else if(mfactor->isPower() && IS_REAL((*mfactor)[1]) && mfactor->base()->equals(mnew[i2][i3][0])) { + if(mfactor->equals(mnew[i2][i3])) { + mnew[i2].delChild(i3 + 1); + } else { + mnew[i2][i3][1].number() -= mfactor->exponent()->number(); + if(mnew[i2][i3][1].number().isOne()) { + MathStructure mstruct2(mnew[i2][i3][0]); + mnew[i2][i3] = mstruct2; + } else if(mnew[i2][i3][1].number().isZero()) { + mnew[i2].delChild(i3 + 1); + } else if(factorize_fix_root_power(mnew[i2][i3])) { + mnew[i2].childUpdated(i3 + 1); + mnew.childUpdated(i2 + 1); + } + } + b = false; + } else if(mfactor->equals(mnew[i2][i3][0])) { + if(mnew[i2][i3][1].number() == 2) { + MathStructure mstruct2(mnew[i2][i3][0]); + mnew[i2][i3] = mstruct2; + } else if(mnew[i2][i3][1].number().isOne()) { + mnew[i2].delChild(i3 + 1); + } else { + mnew[i2][i3][1].number() -= 1; + if(factorize_fix_root_power(mnew[i2][i3])) { + mnew[i2].childUpdated(i3 + 1); + mnew.childUpdated(i2 + 1); + } + } + b = false; + } + break; + } + default: { + if(mfactor->equals(mnew[i2][i3])) { + mnew[i2].delChild(i3 + 1); + b = false; + } + } + } + } + if(mnew[i2].size() == 1) { + MathStructure mstruct2(mnew[i2][0]); + mnew[i2] = mstruct2; + } + break; + } + default: { + if(mfactor->isNumber()) { + mnew[i2].transform(STRUCT_MULTIPLICATION); + mnew[i2].insertChild(MathStructure(1, 1, 0), 1); + mnew[i2][0].number() /= mfactor->number(); + } else { + mnew[i2].set(m_one); + } + } + } + } + if(factor_mstruct.isMultiplication()) { + i++; + } else { + break; + } + } + return true; + } + } + default: {} + } + return false; +} + +bool polynomial_divide_integers(const vector &vnum, const vector &vden, vector &vquotient) { + + vquotient.clear(); + + long int numdeg = vnum.size() - 1; + long int dendeg = vden.size() - 1; + Number dencoeff(vden[dendeg]); + + if(numdeg < dendeg) return false; + + vquotient.resize(numdeg - dendeg + 1, nr_zero); + + vector vrem = vnum; + + while(numdeg >= dendeg) { + Number numcoeff(vrem[numdeg]); + numdeg -= dendeg; + if(!numcoeff.isIntegerDivisible(dencoeff)) break; + numcoeff /= dencoeff; + vquotient[numdeg] += numcoeff; + for(size_t i = 0; i < vden.size(); i++) { + vrem[numdeg + i] -= (vden[i] * numcoeff); + } + while(true) { + if(vrem.back().isZero()) vrem.pop_back(); + else break; + if(vrem.size() == 0) return true; + } + numdeg = (long int) vrem.size() - 1; + } + return false; +} + +bool combination_factorize_is_complicated(MathStructure &m) { + if(m.isPower()) { + return combination_factorize_is_complicated(m[0]) || combination_factorize_is_complicated(m[1]); + } + return m.size() > 0; +} + +bool combination_factorize(MathStructure &mstruct) { + bool retval = false; + switch(mstruct.type()) { + case STRUCT_ADDITION: { + bool b = false; + // 5/y + x/y + z = (5 + x)/y + z + MathStructure mstruct_units(mstruct); + MathStructure mstruct_new(mstruct); + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(mstruct_units[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct_units[i].size();) { + if(!mstruct_units[i][i2].isPower() || !mstruct_units[i][i2][1].hasNegativeSign()) { + mstruct_units[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); + else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); + for(size_t i2 = 0; i2 < mstruct_new[i].size();) { + if(mstruct_new[i][i2].isPower() && mstruct_new[i][i2][1].hasNegativeSign()) { + mstruct_new[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); + else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); + } else if(mstruct_new[i].isPower() && mstruct_new[i][1].hasNegativeSign()) { + mstruct_new[i].set(1, 1, 0); + } else { + mstruct_units[i].setUndefined(); + } + } + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(!mstruct_units[i].isUndefined()) { + for(size_t i2 = i + 1; i2 < mstruct_units.size();) { + if(mstruct_units[i2] == mstruct_units[i]) { + mstruct_new[i].add(mstruct_new[i2], true); + mstruct_new.delChild(i2 + 1); + mstruct_units.delChild(i2 + 1); + b = true; + } else { + i2++; + } + } + if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); + else mstruct_new[i].multiply(mstruct_units[i], true); + } + } + if(b) { + if(mstruct_new.size() == 1) { + mstruct.set(mstruct_new[0], true); + } else { + mstruct = mstruct_new; + } + b = false; + retval = true; + } + if(mstruct.isAddition()) { + // y*f(x) + z*f(x) = (y+z)*f(x) + MathStructure mstruct_units(mstruct); + MathStructure mstruct_new(mstruct); + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(mstruct_units[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct_units[i].size();) { + if(!combination_factorize_is_complicated(mstruct_units[i][i2])) { + mstruct_units[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); + else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); + for(size_t i2 = 0; i2 < mstruct_new[i].size();) { + if(combination_factorize_is_complicated(mstruct_new[i][i2])) { + mstruct_new[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); + else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); + } else if(combination_factorize_is_complicated(mstruct_units[i])) { + mstruct_new[i].set(1, 1, 0); + } else { + mstruct_units[i].setUndefined(); + } + } + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(!mstruct_units[i].isUndefined()) { + for(size_t i2 = i + 1; i2 < mstruct_units.size();) { + if(mstruct_units[i2] == mstruct_units[i]) { + mstruct_new[i].add(mstruct_new[i2], true); + mstruct_new.delChild(i2 + 1); + mstruct_units.delChild(i2 + 1); + b = true; + } else { + i2++; + } + } + if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); + else mstruct_new[i].multiply(mstruct_units[i], true); + } + } + if(b) { + if(mstruct_new.size() == 1) mstruct.set(mstruct_new[0], true); + else mstruct = mstruct_new; + retval = true; + } + } + if(mstruct.isAddition()) { + // 5x + pi*x + 5y + xy = (5 + pi)x + 5y + xy + MathStructure mstruct_units(mstruct); + MathStructure mstruct_new(mstruct); + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(mstruct_units[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct_units[i].size();) { + if(!mstruct_units[i][i2].containsType(STRUCT_UNIT, true) && !mstruct_units[i][i2].containsUnknowns()) { + mstruct_units[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); + else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); + for(size_t i2 = 0; i2 < mstruct_new[i].size();) { + if(mstruct_new[i][i2].containsType(STRUCT_UNIT, true) || mstruct_new[i][i2].containsUnknowns()) { + mstruct_new[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); + else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); + } else if(mstruct_units[i].containsType(STRUCT_UNIT, true) || mstruct_units[i].containsUnknowns()) { + mstruct_new[i].set(1, 1, 0); + } else { + mstruct_units[i].setUndefined(); + } + } + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(!mstruct_units[i].isUndefined()) { + for(size_t i2 = i + 1; i2 < mstruct_units.size();) { + if(mstruct_units[i2] == mstruct_units[i]) { + mstruct_new[i].add(mstruct_new[i2], true); + mstruct_new.delChild(i2 + 1); + mstruct_units.delChild(i2 + 1); + b = true; + } else { + i2++; + } + } + if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); + else mstruct_new[i].multiply(mstruct_units[i], true); + } + } + if(b) { + if(mstruct_new.size() == 1) mstruct.set(mstruct_new[0], true); + else mstruct = mstruct_new; + retval = true; + } + } + //if(retval) return retval; + } + default: { + bool b = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(combination_factorize(mstruct[i])) { + mstruct.childUpdated(i); + b = true; + } + } + if(b) retval = true; + } + } + return retval; +} + +bool MathStructure::factorize(const EvaluationOptions &eo_pre, bool unfactorize, int term_combination_levels, int max_msecs, bool only_integers, int recursive, struct timeval *endtime_p, const MathStructure &force_factorization, bool complete_square, bool only_sqrfree, int max_factor_degree) { + + if(CALCULATOR->aborted()) return false; + struct timeval endtime; + if(max_msecs > 0 && !endtime_p) { +#ifndef CLOCK_MONOTONIC + gettimeofday(&endtime, NULL); +#else + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + endtime.tv_sec = ts.tv_sec; + endtime.tv_usec = ts.tv_nsec / 1000; +#endif + endtime.tv_sec += max_msecs / 1000; + long int usecs = endtime.tv_usec + (long int) (max_msecs % 1000) * 1000; + if(usecs >= 1000000) { + usecs -= 1000000; + endtime.tv_sec++; + } + endtime.tv_usec = usecs; + max_msecs = 0; + endtime_p = &endtime; + } + + EvaluationOptions eo = eo_pre; + eo.sync_units = false; + eo.structuring = STRUCTURING_NONE; + if(unfactorize) { + unformat(eo_pre); + EvaluationOptions eo2 = eo; + eo2.expand = true; + eo2.combine_divisions = false; + eo2.sync_units = false; + calculatesub(eo2, eo2); + do_simplification(*this, eo, true, false, true); + } else if(term_combination_levels && isAddition()) { + MathStructure *mdiv = new MathStructure; + mdiv->setType(STRUCT_ADDITION); + for(size_t i = 0; i < SIZE; ) { + bool b = false; + if(CHILD(i).isMultiplication()) { + for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { + if(CHILD(i)[i2].isPower() && CHILD(i)[i2][1].hasNegativeSign()) { + b = true; + break; + } + } + } else if(CHILD(i).isPower() && CHILD(i)[1].hasNegativeSign()) { + b = true; + } + if(b) { + CHILD(i).ref(); + mdiv->addChild_nocopy(&CHILD(i)); + ERASE(i) + } else { + i++; + } + } + if(mdiv->size() > 0) { + bool b_ret = false; + if(SIZE == 1 && recursive) { + b_ret = CHILD(0).factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + } else if(SIZE > 1) { + b_ret = factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + } + if(mdiv->size() > 1) { + // 5/y + x/y + z = (5 + x)/y + z + MathStructure mstruct_units(*mdiv); + MathStructure mstruct_new(*mdiv); + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(mstruct_units[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct_units[i].size();) { + if(!mstruct_units[i][i2].isPower() || !mstruct_units[i][i2][1].hasNegativeSign()) { + mstruct_units[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); + else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); + for(size_t i2 = 0; i2 < mstruct_new[i].size();) { + if(mstruct_new[i][i2].isPower() && mstruct_new[i][i2][1].hasNegativeSign()) { + mstruct_new[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); + else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); + } else if(mstruct_new[i].isPower() && mstruct_new[i][1].hasNegativeSign()) { + mstruct_new[i].set(1, 1, 0); + } else { + mstruct_units[i].setUndefined(); + } + } + bool b = false; + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(!mstruct_units[i].isUndefined()) { + for(size_t i2 = i + 1; i2 < mstruct_units.size();) { + if(mstruct_units[i2] == mstruct_units[i]) { + mstruct_new[i].add(mstruct_new[i2], true); + mstruct_new.delChild(i2 + 1); + mstruct_units.delChild(i2 + 1); + b = true; + } else { + i2++; + } + } + if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); + else mstruct_new[i].multiply(mstruct_units[i], true); + } + } + if(b) { + if(mstruct_new.size() == 1) { + mdiv->set_nocopy(mstruct_new[0], true); + } else { + mdiv->set_nocopy(mstruct_new); + } + b_ret = true; + } + } + size_t index = 1; + if(isAddition()) index = SIZE; + if(index == 0) { + set_nocopy(*mdiv); + } else if(mdiv->isAddition()) { + for(size_t i = 0; i < mdiv->size(); i++) { + (*mdiv)[i].ref(); + add_nocopy(&(*mdiv)[i], true); + } + mdiv->unref(); + } else { + add_nocopy(mdiv, true); + } + if(recursive) { + for(; index < SIZE; index++) { + b_ret = CHILD(index).factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree) || b_ret; + } + } + return b_ret; + } + mdiv->unref(); + } + + MathStructure mden, mnum; + evalSort(true); + + if(term_combination_levels >= -1 && isAddition() && isRationalPolynomial()) { + MathStructure msqrfree(*this); + eo.protected_function = CALCULATOR->getFunctionById(FUNCTION_ID_SIGNUM); + if(sqrfree(msqrfree, eo)) { + if((!only_sqrfree || msqrfree.isPower()) && !equals(msqrfree) && (!msqrfree.isMultiplication() || msqrfree.size() != 2 || (!(msqrfree[0].isNumber() && msqrfree[1].isAddition()) && !(msqrfree[1].isNumber() && msqrfree[0].isAddition())))) { + MathStructure mcopy(msqrfree); + EvaluationOptions eo2 = eo; + eo2.expand = true; + eo2.calculate_functions = false; + CALCULATOR->beginTemporaryStopMessages(); + mcopy.calculatesub(eo2, eo2); + CALCULATOR->endTemporaryStopMessages(); + bool b_equal = equals(mcopy); + if(!b_equal && !CALCULATOR->aborted()) { + MathStructure mcopy2(*this); + CALCULATOR->beginTemporaryStopMessages(); + mcopy.calculatesub(eo2, eo2, true); + mcopy2.calculatesub(eo2, eo2, true); + CALCULATOR->endTemporaryStopMessages(); + b_equal = mcopy.equals(mcopy2); + } + if(!b_equal) { + eo.protected_function = eo_pre.protected_function; + if(CALCULATOR->aborted()) return false; + CALCULATOR->error(true, "factorized result is wrong: %s != %s. %s", format_and_print(msqrfree).c_str(), format_and_print(*this).c_str(), _("This is a bug. Please report it."), NULL); + } else { + eo.protected_function = eo_pre.protected_function; + set(msqrfree); + if(!isAddition()) { + if(isMultiplication()) flattenMultiplication(*this); + if(isMultiplication() && SIZE >= 2 && CHILD(0).isNumber()) { + for(size_t i = 1; i < SIZE; i++) { + if(CHILD(i).isNumber()) { + CHILD(i).number() *= CHILD(0).number(); + CHILD(0).set(CHILD(i)); + delChild(i); + } else if(CHILD(i).isPower() && CHILD(i)[0].isMultiplication() && CHILD(i)[0].size() >= 2 && CHILD(i)[0][0].isNumber() && CHILD(i)[0][0].number().isRational() && !CHILD(i)[0][0].number().isInteger() && CHILD(i)[1].isInteger()) { + CHILD(i)[0][0].number().raise(CHILD(i)[1].number()); + CHILD(0).number().multiply(CHILD(i)[0][0].number()); + CHILD(i)[0].delChild(1); + if(CHILD(i)[0].size() == 1) CHILD(i)[0].setToChild(1, true); + } + } + if(SIZE > 1 && CHILD(0).isOne()) { + ERASE(0); + } + if(SIZE == 1) SET_CHILD_MAP(0); + } + if(isMultiplication() && SIZE >= 2 && CHILD(0).isNumber() && CHILD(0).number().isRational() && !CHILD(0).number().isInteger()) { + Number den = CHILD(0).number().denominator(); + for(size_t i = 1; i < SIZE; i++) { + if(CHILD(i).isAddition()) { + bool b = true; + for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { + if(CHILD(i)[i2].isNumber()) { + if(!CHILD(i)[i2].number().isIntegerDivisible(den)) {b = false; break;} + } else if(CHILD(i)[i2].isMultiplication() && CHILD(i)[i2][0].isNumber()) { + if(!CHILD(i)[i2][0].number().isIntegerDivisible(den)) {b = false; break;} + } else { + b = false; + break; + } + } + if(b) { + for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { + if(CHILD(i)[i2].isNumber()) { + CHILD(i)[i2].number().divide(den); + } else if(CHILD(i)[i2].isMultiplication()) { + CHILD(i)[i2][0].number().divide(den); + if(CHILD(i)[i2][0].isOne() && CHILD(i)[i2].size() > 1) { + CHILD(i)[i2].delChild(1); + if(CHILD(i)[i2].size() == 1) { + CHILD(i)[i2].setToChild(1, true); + } + } + } + } + CHILD(0).set(CHILD(0).number().numerator(), true); + if(SIZE > 1 && CHILD(0).isOne()) { + ERASE(0); + } + if(SIZE == 1) SET_CHILD_MAP(0); + break; + } + } + } + } + if(isMultiplication()) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isPower() && CHILD(i)[1].isInteger()) { + if(CHILD(i)[0].isAddition()) { + bool b = true; + for(size_t i2 = 0; i2 < CHILD(i)[0].size(); i2++) { + if((!CHILD(i)[0][i2].isNumber() || !CHILD(i)[0][i2].number().isNegative()) && (!CHILD(i)[0][i2].isMultiplication() || CHILD(i)[0][i2].size() < 2 || !CHILD(i)[0][i2][0].isNumber() || !CHILD(i)[0][i2][0].number().isNegative())) { + b = false; + break; + } + } + if(b) { + for(size_t i2 = 0; i2 < CHILD(i)[0].size(); i2++) { + if(CHILD(i)[0][i2].isNumber()) { + CHILD(i)[0][i2].number().negate(); + } else { + CHILD(i)[0][i2][0].number().negate(); + if(CHILD(i)[0][i2][0].isOne() && CHILD(i)[0][i2].size() > 1) { + CHILD(i)[0][i2].delChild(1); + if(CHILD(i)[0][i2].size() == 1) { + CHILD(i)[0][i2].setToChild(1, true); + } + } + } + } + if(CHILD(i)[1].number().isOdd()) { + if(CHILD(0).isNumber()) CHILD(0).number().negate(); + else { + PREPEND(MathStructure(-1, 1, 0)); + i++; + } + } + } + } else if(CHILD(i)[0].isMultiplication() && CHILD(i)[0].size() >= 2 && CHILD(i)[0][0].isNumber() && CHILD(i)[0][0].number().isNegative()) { + CHILD(i)[0][0].number().negate(); + if(CHILD(i)[0][0].isOne() && CHILD(i)[0].size() > 1) { + CHILD(i)[0].delChild(1); + if(CHILD(i)[0].size() == 1) { + CHILD(i)[0].setToChild(1, true); + } + } + if(CHILD(i)[1].number().isOdd()) { + if(CHILD(0).isNumber()) CHILD(0).number().negate(); + else { + PREPEND(MathStructure(-1, 1, 0)); + i++; + } + } + } + } else if(CHILD(i).isAddition()) { + bool b = true; + for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { + if((!CHILD(i)[i2].isNumber() || !CHILD(i)[i2].number().isNegative()) && (!CHILD(i)[i2].isMultiplication() || CHILD(i)[i2].size() < 2 || !CHILD(i)[i2][0].isNumber() || !CHILD(i)[i2][0].number().isNegative())) { + b = false; + break; + } + } + if(b) { + for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { + if(CHILD(i)[i2].isNumber()) { + CHILD(i)[i2].number().negate(); + } else { + CHILD(i)[i2][0].number().negate(); + if(CHILD(i)[i2][0].isOne() && CHILD(i)[i2].size() > 1) { + CHILD(i)[i2].delChild(1); + if(CHILD(i)[i2].size() == 1) { + CHILD(i)[i2].setToChild(1, true); + } + } + } + } + if(CHILD(0).isNumber()) CHILD(0).number().negate(); + else { + PREPEND(MathStructure(-1, 1, 0)); + i++; + } + } + } + } + if(SIZE > 1 && CHILD(0).isOne()) { + ERASE(0); + } + if(SIZE == 1) SET_CHILD_MAP(0); + } + if(isPower() && CHILD(1).isInteger()) { + if(CHILD(0).isAddition()) { + bool b = true; + for(size_t i2 = 0; i2 < CHILD(0).size(); i2++) { + if((!CHILD(0)[i2].isNumber() || !CHILD(0)[i2].number().isNegative()) && (!CHILD(0)[i2].isMultiplication() || CHILD(0)[i2].size() < 2 || !CHILD(0)[i2][0].isNumber() || !CHILD(0)[i2][0].number().isNegative())) { + b = false; + break; + } + } + if(b) { + for(size_t i2 = 0; i2 < CHILD(0).size(); i2++) { + if(CHILD(0)[i2].isNumber()) { + CHILD(0)[i2].number().negate(); + } else { + CHILD(0)[i2][0].number().negate(); + if(CHILD(0)[i2][0].isOne() && CHILD(0)[i2].size() > 1) { + CHILD(0)[i2].delChild(1); + if(CHILD(0)[i2].size() == 1) { + CHILD(0)[i2].setToChild(1, true); + } + } + } + } + if(CHILD(1).number().isOdd()) { + multiply(MathStructure(-1, 1, 0)); + CHILD_TO_FRONT(1) + } + } + } else if(CHILD(0).isMultiplication() && CHILD(0).size() >= 2 && CHILD(0)[0].isNumber() && CHILD(0)[0].number().isNegative()) { + CHILD(0)[0].number().negate(); + if(CHILD(0)[0].isOne() && CHILD(0).size() > 1) { + CHILD(0).delChild(1); + if(CHILD(0).size() == 1) { + CHILD(0).setToChild(1, true); + } + } + if(CHILD(1).number().isOdd()) { + multiply(MathStructure(-1, 1, 0)); + CHILD_TO_FRONT(1) + } + } + } + } + evalSort(true); + factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + return true; + } + } + } + eo.protected_function = eo_pre.protected_function; + } + + switch(type()) { + case STRUCT_ADDITION: { + + if(CALCULATOR->aborted()) return false; + if(term_combination_levels >= -1 && !only_sqrfree && max_factor_degree != 0) { + + if(SIZE <= 3 && SIZE > 1) { + MathStructure *xvar = NULL; + Number nr2(1, 1); + if(CHILD(0).isPower() && CHILD(0)[0].size() == 0 && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isTwo()) { + xvar = &CHILD(0)[0]; + } else if(CHILD(0).isMultiplication() && CHILD(0).size() == 2 && CHILD(0)[0].isNumber()) { + if(CHILD(0)[1].isPower()) { + if(CHILD(0)[1][0].size() == 0 && CHILD(0)[1][1].isNumber() && CHILD(0)[1][1].number().isTwo()) { + xvar = &CHILD(0)[1][0]; + nr2.set(CHILD(0)[0].number()); + } + } + } + if(xvar) { + bool factorable = false; + Number nr1, nr0; + if(SIZE == 2 && CHILD(1).isNumber()) { + factorable = true; + nr0 = CHILD(1).number(); + } else if(SIZE == 3 && CHILD(2).isNumber()) { + nr0 = CHILD(2).number(); + if(CHILD(1).isMultiplication()) { + if(CHILD(1).size() == 2 && CHILD(1)[0].isNumber() && xvar->equals(CHILD(1)[1])) { + nr1 = CHILD(1)[0].number(); + factorable = true; + } + } else if(xvar->equals(CHILD(1))) { + nr1.set(1, 1, 0); + factorable = true; + } + } + if(factorable) { + Number nr4ac(4, 1, 0); + nr4ac *= nr2; + nr4ac *= nr0; + Number nr2a(2, 1, 0); + nr2a *= nr2; + Number sqrtb24ac(nr1); + sqrtb24ac.raise(nr_two); + sqrtb24ac -= nr4ac; + if(sqrtb24ac.isNegative()) factorable = false; + MathStructure mstructb24(sqrtb24ac); + if(factorable) { + if(!only_integers) { + if(eo.approximation == APPROXIMATION_EXACT && !sqrtb24ac.isApproximate()) { + sqrtb24ac.raise(nr_half); + if(sqrtb24ac.isApproximate()) { + mstructb24.raise(nr_half); + } else { + mstructb24.set(sqrtb24ac); + } + } else { + mstructb24.number().raise(nr_half); + } + } else { + mstructb24.number().raise(nr_half); + if((!sqrtb24ac.isApproximate() && mstructb24.number().isApproximate()) || (sqrtb24ac.isInteger() && !mstructb24.number().isInteger())) { + factorable = false; + } + } + } + if(factorable) { + MathStructure m1(nr1), m2(nr1); + Number mul1(1, 1), mul2(1, 1); + if(mstructb24.isNumber()) { + m1.number() += mstructb24.number(); + m1.number() /= nr2a; + if(m1.number().isRational() && !m1.number().isInteger()) { + mul1 = m1.number().denominator(); + m1.number() *= mul1; + } + m2.number() -= mstructb24.number(); + m2.number() /= nr2a; + if(m2.number().isRational() && !m2.number().isInteger()) { + mul2 = m2.number().denominator(); + m2.number() *= mul2; + } + } else { + m1.calculateAdd(mstructb24, eo); + m1.calculateDivide(nr2a, eo); + if(m1.isNumber()) { + if(m1.number().isRational() && !m1.number().isInteger()) { + mul1 = m1.number().denominator(); + m1.number() *= mul1; + } + } else { + bool bint = false, bfrac = false; + idm1(m1, bfrac, bint); + if(bfrac) { + idm2(m1, bfrac, bint, mul1); + idm3(m1, mul1, true); + } + } + m2.calculateSubtract(mstructb24, eo); + m2.calculateDivide(nr2a, eo); + if(m2.isNumber()) { + if(m2.number().isRational() && !m2.number().isInteger()) { + mul2 = m2.number().denominator(); + m2.number() *= mul2; + } + } else { + bool bint = false, bfrac = false; + idm1(m2, bfrac, bint); + if(bfrac) { + idm2(m2, bfrac, bint, mul2); + idm3(m2, mul2, true); + } + } + } + nr2 /= mul1; + nr2 /= mul2; + if(m1 == m2 && mul1 == mul2) { + MathStructure xvar2(*xvar); + if(!mul1.isOne()) xvar2 *= mul1; + set(m1); + add(xvar2, true); + raise(MathStructure(2, 1, 0)); + if(!nr2.isOne()) { + multiply(nr2); + } + } else { + m1.add(*xvar, true); + if(!mul1.isOne()) m1[m1.size() - 1] *= mul1; + m2.add(*xvar, true); + if(!mul2.isOne()) m2[m2.size() - 1] *= mul2; + clear(true); + m_type = STRUCT_MULTIPLICATION; + if(!nr2.isOne()) { + APPEND_NEW(nr2); + } + APPEND(m1); + APPEND(m2); + } + EvaluationOptions eo2 = eo; + eo2.expand = false; + calculatesub(eo2, eo2, false); + evalSort(true); + return true; + } + } + } + } + + MathStructure *factor_mstruct = new MathStructure(1, 1, 0); + MathStructure mnew; + if(factorize_find_multiplier(*this, mnew, *factor_mstruct) && !factor_mstruct->isZero() && !mnew.isZero()) { + mnew.factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + factor_mstruct->factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + clear(true); + m_type = STRUCT_MULTIPLICATION; + APPEND_REF(factor_mstruct); + APPEND(mnew); + EvaluationOptions eo2 = eo; + eo2.expand = false; + calculatesub(eo2, eo2, false); + factor_mstruct->unref(); + evalSort(true); + return true; + } + factor_mstruct->unref(); + + if(SIZE > 1 && CHILD(SIZE - 1).isNumber() && CHILD(SIZE - 1).number().isInteger() && max_factor_degree != 0) { + MathStructure *xvar = NULL; + Number qnr(1, 1); + int degree = 1; + bool overflow = false; + int qcof = 1; + if(CHILD(0).isPower() && !CHILD(0)[0].isNumber() && CHILD(0)[0].size() == 0 && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isInteger() && CHILD(0)[1].number().isPositive()) { + xvar = &CHILD(0)[0]; + degree = CHILD(0)[1].number().intValue(&overflow); + } else if(CHILD(0).isMultiplication() && CHILD(0).size() == 2 && CHILD(0)[0].isNumber() && CHILD(0)[0].number().isInteger()) { + if(CHILD(0)[1].isPower()) { + if(CHILD(0)[1][0].size() == 0 && !CHILD(0)[1][0].isNumber() && CHILD(0)[1][1].isNumber() && CHILD(0)[1][1].number().isInteger() && CHILD(0)[1][1].number().isPositive()) { + xvar = &CHILD(0)[1][0]; + qcof = CHILD(0)[0].number().intValue(&overflow); + if(!overflow) { + if(qcof < 0) qcof = -qcof; + degree = CHILD(0)[1][1].number().intValue(&overflow); + } + } + } + } + + int pcof = 1; + if(!overflow) { + pcof = CHILD(SIZE - 1).number().intValue(&overflow); + if(pcof < 0) pcof = -pcof; + } + + if(xvar && !overflow && degree <= 1000 && degree > 2 && qcof != 0 && pcof != 0) { + bool b = true, b2 = true; + for(size_t i = 1; b && i < SIZE - 1; i++) { + switch(CHILD(i).type()) { + case STRUCT_NUMBER: { + b = false; + break; + } + case STRUCT_POWER: { + if(!CHILD(i)[1].isNumber() || !xvar->equals(CHILD(i)[0]) || !CHILD(i)[1].number().isInteger() || !CHILD(i)[1].number().isPositive()) { + b = false; + } + break; + } + case STRUCT_MULTIPLICATION: { + if(!(CHILD(i).size() == 2) || !CHILD(i)[0].isNumber()) { + b = false; + } else if(CHILD(i)[1].isPower()) { + if(!CHILD(i)[1][1].isNumber() || !xvar->equals(CHILD(i)[1][0]) || !CHILD(i)[1][1].number().isInteger() || !CHILD(i)[1][1].number().isPositive()) { + b = false; + } + } else if(!xvar->equals(CHILD(i)[1])) { + b = false; + } + if(b && b2 && !CHILD(i)[0].isInteger()) b2 = false; + break; + } + default: { + if(!xvar->equals(CHILD(i))) { + b = false; + } + } + } + } + + if(b) { + vector factors; + factors.resize(degree + 1, Number()); + factors[0] = CHILD(SIZE - 1).number(); + vector ps; + vector qs; + vector zeroes; + int curdeg = 1, prevdeg = 0; + for(size_t i = 0; b && i < SIZE - 1; i++) { + switch(CHILD(i).type()) { + case STRUCT_POWER: { + curdeg = CHILD(i)[1].number().intValue(&overflow); + if(curdeg == prevdeg || curdeg > degree || (prevdeg > 0 && curdeg > prevdeg) || overflow) { + b = false; + } else { + factors[curdeg].set(1, 1, 0); + } + break; + } + case STRUCT_MULTIPLICATION: { + if(CHILD(i)[1].isPower()) { + curdeg = CHILD(i)[1][1].number().intValue(&overflow); + } else { + curdeg = 1; + } + if(curdeg == prevdeg || curdeg > degree || (prevdeg > 0 && curdeg > prevdeg) || overflow) { + b = false; + } else { + factors[curdeg] = CHILD(i)[0].number(); + } + break; + } + default: { + curdeg = 1; + factors[curdeg].set(1, 1, 0); + } + } + prevdeg = curdeg; + } + + while(b && degree > 2) { + for(int i = 1; i <= 1000; i++) { + if(i > pcof) break; + if(pcof % i == 0) ps.push_back(i); + } + for(int i = 1; i <= 1000; i++) { + if(i > qcof) break; + if(qcof % i == 0) qs.push_back(i); + } + Number itest; + int i2; + size_t pi = 0, qi = 0; + if(ps.empty() || qs.empty()) break; + Number nrtest(ps[0], qs[0], 0); + while(true) { + itest.clear(); i2 = degree; + while(true) { + itest += factors[i2]; + if(i2 == 0) break; + itest *= nrtest; + i2--; + } + if(itest.isZero()) { + break; + } + if(nrtest.isPositive()) { + nrtest.negate(); + } else { + qi++; + if(qi == qs.size()) { + qi = 0; + pi++; + if(pi == ps.size()) { + break; + } + } + nrtest.set(ps[pi], qs[qi], 0); + } + } + if(itest.isZero()) { + itest.clear(); i2 = degree; + Number ntmp(factors[i2]); + for(; i2 > 0; i2--) { + itest += ntmp; + ntmp = factors[i2 - 1]; + factors[i2 - 1] = itest; + itest *= nrtest; + } + degree--; + nrtest.negate(); + zeroes.push_back(nrtest); + if(degree == 2) { + break; + } + qcof = factors[degree].intValue(&overflow); + if(!overflow) { + if(qcof < 0) qcof = -qcof; + pcof = factors[0].intValue(&overflow); + if(!overflow) { + if(pcof < 0) pcof = -pcof; + } + } + if(overflow || qcof == 0 || pcof == 0) { + break; + } + } else { + break; + } + ps.clear(); + qs.clear(); + } + + if(zeroes.size() > 0) { + MathStructure mleft; + MathStructure mtmp; + MathStructure *mcur; + for(int i = degree; i >= 0; i--) { + if(!factors[i].isZero()) { + if(mleft.isZero()) { + mcur = &mleft; + } else { + mleft.add(m_zero, true); + mcur = &mleft[mleft.size() - 1]; + } + if(i > 1) { + if(!factors[i].isOne()) { + mcur->multiply(*xvar); + (*mcur)[0].set(factors[i]); + mcur = &(*mcur)[1]; + } else { + mcur->set(*xvar); + } + mtmp.set(i, 1, 0); + mcur->raise(mtmp); + } else if(i == 1) { + if(!factors[i].isOne()) { + mcur->multiply(*xvar); + (*mcur)[0].set(factors[i]); + } else { + mcur->set(*xvar); + } + } else { + mcur->set(factors[i]); + } + } + } + mleft.factorize(eo, false, 0, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + vector powers; + vector powers_i; + int dupsfound = 0; + for(size_t i = 0; i < zeroes.size() - 1; i++) { + while(i + 1 < zeroes.size() && zeroes[i] == zeroes[i + 1]) { + dupsfound++; + zeroes.erase(zeroes.begin() + (i + 1)); + } + if(dupsfound > 0) { + powers_i.push_back(i); + powers.push_back(dupsfound + 1); + dupsfound = 0; + } + } + MathStructure xvar2(*xvar); + Number *nrmul; + if(mleft.isMultiplication()) { + set(mleft); + evalSort(); + if(CHILD(0).isNumber()) { + nrmul = &CHILD(0).number(); + } else if(CHILD(0).isMultiplication() && CHILD(0).size() > 0 && CHILD(0)[0].isNumber()) { + nrmul = &CHILD(0)[0].number(); + } else { + PREPEND(m_one); + nrmul = &CHILD(0).number(); + } + } else { + clear(true); + m_type = STRUCT_MULTIPLICATION; + APPEND(m_one); + APPEND(mleft); + nrmul = &CHILD(0).number(); + } + size_t pi = 0; + for(size_t i = 0; i < zeroes.size(); i++) { + if(zeroes[i].isInteger()) { + APPEND(xvar2); + } else { + APPEND(m_zero); + } + mcur = &CHILD(SIZE - 1); + if(pi < powers_i.size() && powers_i[pi] == i) { + mcur->raise(MathStructure(powers[pi], 1L, 0L)); + mcur = &(*mcur)[0]; + if(zeroes[i].isInteger()) { + mcur->add(zeroes[i]); + } else { + Number nr(zeroes[i].denominator()); + mcur->add(zeroes[i].numerator()); + (*mcur)[0] *= xvar2; + (*mcur)[0][0].number() = nr; + nr.raise(powers[pi]); + nrmul->divide(nr); + } + pi++; + } else { + if(zeroes[i].isInteger()) { + mcur->add(zeroes[i]); + } else { + nrmul->divide(zeroes[i].denominator()); + mcur->add(zeroes[i].numerator()); + (*mcur)[0] *= xvar2; + (*mcur)[0][0].number() = zeroes[i].denominator(); + } + } + } + if(CHILD(0).isNumber() && CHILD(0).number().isOne()) { + ERASE(0); + } else if(CHILD(0).isMultiplication() && CHILD(0).size() > 0 && CHILD(0)[0].isNumber() && CHILD(0)[0].number().isOne()) { + if(CHILD(0).size() == 1) { + ERASE(0); + } else if(CHILD(0).size() == 2) { + CHILD(0).setToChild(2, true); + } else { + CHILD(0).delChild(1); + } + } + evalSort(true); + Number dupspow; + for(size_t i = 0; i < SIZE - 1; i++) { + mcur = NULL; + if(CHILD(i).isPower()) { + if(CHILD(i)[0].isAddition() && CHILD(i)[1].isNumber()) { + mcur = &CHILD(i)[0]; + } + } else if(CHILD(i).isAddition()) { + mcur = &CHILD(i); + } + while(mcur && i + 1 < SIZE) { + if(CHILD(i + 1).isPower()) { + if(CHILD(i + 1)[0].isAddition() && CHILD(i + 1)[1].isNumber() && mcur->equals(CHILD(i + 1)[0])) { + dupspow += CHILD(i + 1)[1].number(); + } else { + mcur = NULL; + } + } else if(CHILD(i + 1).isAddition() && mcur->equals(CHILD(i + 1))) { + dupspow++; + } else { + mcur = NULL; + } + if(mcur) { + ERASE(i + 1); + } + } + if(!dupspow.isZero()) { + if(CHILD(i).isPower()) { + CHILD(i)[1].number() += dupspow; + } else { + dupspow++; + CHILD(i) ^= dupspow; + } + dupspow.clear(); + } + } + if(SIZE == 1) { + setToChild(1, true); + } else { + EvaluationOptions eo2 = eo; + eo2.expand = false; + calculatesub(eo2, eo2, false); + } + evalSort(true); + return true; + } + } + + if(b && b2 && (max_factor_degree < 0 || max_factor_degree >= 2) && degree > 3 && degree < 50) { + // Kronecker method + vector vnum; + vnum.resize(degree + 1, nr_zero); + bool overflow = false; + for(size_t i = 0; b && i < SIZE; i++) { + switch(CHILD(i).type()) { + case STRUCT_POWER: { + if(CHILD(i)[0] == *xvar && CHILD(i)[1].isInteger()) { + int curdeg = CHILD(i)[1].number().intValue(&overflow); + if(curdeg < 0 || overflow || curdeg > degree) b = false; + else vnum[curdeg] += 1; + } else { + b = false; + } + break; + } + case STRUCT_MULTIPLICATION: { + if(CHILD(i).size() == 2 && CHILD(i)[0].isInteger()) { + long int icoeff = CHILD(i)[0].number().intValue(&overflow); + if(!overflow && CHILD(i)[1].isPower() && CHILD(i)[1][0] == *xvar && CHILD(i)[1][1].isInteger()) { + int curdeg = CHILD(i)[1][1].number().intValue(&overflow); + if(curdeg < 0 || overflow || curdeg > degree) b = false; + else vnum[curdeg] += icoeff; + } else if(!overflow && CHILD(i)[1] == *xvar) { + vnum[1] += icoeff; + } else { + b = false; + } + } else { + b = false; + } + break; + } + default: { + if(CHILD(i).isInteger()) { + long int icoeff = CHILD(i).number().intValue(&overflow); + if(overflow) b = false; + else vnum[0] += icoeff; + } else if(CHILD(i) == *xvar) { + vnum[1] += 1; + } else { + b = false; + } + break; + } + } + } + + long int lcoeff = vnum[degree].lintValue(); + vector vs; + if(b && lcoeff != 0) { + degree /= 2; + if(max_factor_degree > 0 && degree > max_factor_degree) degree = max_factor_degree; + for(int i = 0; i <= degree; i++) { + if(CALCULATOR->aborted()) return false; + MathStructure mcalc(*this); + mcalc.calculateReplace(*xvar, Number((i / 2 + i % 2) * (i % 2 == 0 ? -1 : 1), 1), eo); + mcalc.calculatesub(eo, eo, false); + if(!mcalc.isInteger()) break; + bool overflow = false; + int v = ::abs(mcalc.number().intValue(&overflow)); + if(overflow) { + if(i > 2) degree = i; + else b = false; + break; + } + vs.push_back(v); + } + } + + if(b) { + vector factors0, factorsl; + factors0.push_back(1); + for(int i = 2; i < vs[0] / 3 && i < 1000; i++) { + if(vs[0] % i == 0) factors0.push_back(i); + } + if(vs[0] % 3 == 0) factors0.push_back(vs[0] / 3); + if(vs[0] % 2 == 0) factors0.push_back(vs[0] / 2); + factors0.push_back(vs[0]); + for(int i = 2; i < lcoeff / 3 && i < 1000; i++) { + if(lcoeff % i == 0) factorsl.push_back(i); + } + factorsl.push_back(1); + if(lcoeff % 3 == 0) factorsl.push_back(lcoeff / 3); + if(lcoeff % 2 == 0) factorsl.push_back(lcoeff / 2); + factorsl.push_back(lcoeff); + + long long int cmax = 500000LL / (factors0.size() * factorsl.size()); + if(term_combination_levels != 0) cmax *= 10; + if(degree >= 2 && cmax > 10) { + vector vden; + vector vquo; + vden.resize(3, nr_zero); + long int c0; + for(size_t i = 0; i < factors0.size() * 2; i++) { + c0 = factors0[i / 2]; + if(i % 2 == 1) c0 = -c0; + long int c2; + for(size_t i2 = 0; i2 < factorsl.size(); i2++) { + c2 = factorsl[i2]; + long int c1max = vs[1] - c0 - c2, c1min; + if(c1max < 0) {c1min = c1max; c1max = -vs[1] - c0 - c2;} + else {c1min = -vs[1] - c0 - c2;} + if(-(vs[2] - c0 - c2) < -(-vs[2] - c0 - c2)) { + if(c1max > -(-vs[2] - c0 - c2)) c1max = -(-vs[2] - c0 - c2); + if(c1min < -(vs[2] - c0 - c2)) c1min = -(vs[2] - c0 - c2); + } else { + if(c1max > -(vs[2] - c0 - c2)) c1max = -(vs[2] - c0 - c2); + if(c1min < -(-vs[2] - c0 - c2)) c1min = -(-vs[2] - c0 - c2); + } + if(c1min < -cmax / 2) c1min = -cmax / 2; + for(long int c1 = c1min; c1 <= c1max && c1 <= cmax / 2; c1++) { + long int v1 = ::labs(c2 + c1 + c0); + long int v2 = ::labs(c2 - c1 + c0); + if(v1 != 0 && v2 != 0 && v1 <= vs[1] && v2 <= vs[2] && (c1 != 0 || c2 != 0) && vs[1] % v1 == 0 && vs[2] % v2 == 0) { + vden[0] = c0; vden[1] = c1; vden[2] = c2; + if(CALCULATOR->aborted()) return false; + if(polynomial_divide_integers(vnum, vden, vquo)) { + MathStructure mtest; + mtest.setType(STRUCT_ADDITION); + if(c2 != 0) { + MathStructure *mpow = new MathStructure(); + mpow->setType(STRUCT_POWER); + mpow->addChild(*xvar); + mpow->addChild_nocopy(new MathStructure(2, 1, 0)); + if(c2 == 1) { + mtest.addChild_nocopy(mpow); + } else { + MathStructure *mterm = new MathStructure(); + mterm->setType(STRUCT_MULTIPLICATION); + mterm->addChild_nocopy(new MathStructure(c2, 1L, 0L)); + mterm->addChild_nocopy(mpow); + mtest.addChild_nocopy(mterm); + } + } + if(c1 == 1) { + mtest.addChild(*xvar); + } else if(c1 != 0) { + MathStructure *mterm = new MathStructure(); + mterm->setType(STRUCT_MULTIPLICATION); + mterm->addChild_nocopy(new MathStructure(c1, 1L, 0L)); + mterm->addChild(*xvar); + mtest.addChild_nocopy(mterm); + } + mtest.addChild_nocopy(new MathStructure(c0, 1L, 0L)); + MathStructure mthis(*this); + MathStructure mquo; + if(mtest.size() > 1 && polynomialDivide(mthis, mtest, mquo, eo, false)) { + mquo.factorize(eo, false, 0, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + set(mquo, true); + multiply(mtest, true); + return true; + } + } + } + } + } + } + } + for(int i_d = 3; i_d <= degree; i_d++) { + if(CALCULATOR->aborted()) return false; + long int t1max = ::pow(cmax / (i_d - 1), 1.0 / (i_d - 1)); + if(t1max < 1) break; + if(t1max > 1000) t1max = 1000; + long int c2totalmax = t1max; + long int c2cur; + for(int i = 0; i < i_d - 3; i++) { + c2totalmax *= t1max; + } + vector vden; + vector vquo; + long int *vc = (long int*) malloc(sizeof(long int) * (i_d + 1)); + vden.resize(i_d + 1, nr_zero); + int in = 0; + for(size_t i = 0; i < factors0.size() * 2; i++) { + vc[0] = factors0[i / 2] * (i % 2 == 1 ? -1 : 1); + for(size_t i2 = 0; i2 < factorsl.size(); i2++) { + vc[i_d] = factorsl[i2]; + for(long int c2p = 0; c2p <= c2totalmax; c2p++) { + c2cur = c2p; + for(int i = 2; i < i_d; i++) { + vc[i] = c2cur % t1max; + if(vc[i] % 2 == 1) vc[i] = -vc[i]; + vc[i] = vc[i] / 2 + vc[i] % 2; + c2cur /= t1max; + } + long int c1max = t1max / 2 + t1max % 2, c1min = -t1max / 2 - t1max % 2; + for(size_t i = 1; i < vs.size(); i++) { + long int vsmax = vs[i] - vc[0]; + long int vsmin = -vs[i] - vc[0]; + int ix = (i / 2 + i % 2) * (i % 2 == 0 ? -1 : 1); + int ixi = ix; + for(int i2 = 2; i2 <= i_d; i2++) { + ixi *= ix; + vsmax -= vc[i2] * ixi; + } + vsmax /= ix; + vsmin /= ix; + if(vsmax < vsmin) { + if(c1max > vsmin) c1max = vsmin; + if(c1min < vsmax) c1min = vsmax; + } else { + if(c1max > vsmax) c1max = vsmax; + if(c1min < vsmin) c1min = vsmin; + } + } + for(long int c1 = c1min; c1 <= c1max; c1++) { + vc[1] = c1; + bool b = true; + for(size_t i = 1; i < vs.size(); i++) { + long int v = vc[0]; + int ix = (i / 2 + i % 2) * (i % 2 == 0 ? -1 : 1); + int ixi = 1; + for(int i2 = 1; i2 <= i_d; i2++) { + ixi *= ix; + v += vc[i2] * ixi; + } + if(v < 0) v = -v; + if(v == 0 || v > vs[i] || vs[i] % v != 0) { + b = false; + break; + } + } + in++; + if(b) { + if(CALCULATOR->aborted()) return false; + for(size_t iden = 0; iden < vden.size(); iden++) { + vden[iden] = vc[iden]; + } + if(polynomial_divide_integers(vnum, vden, vquo)) { + MathStructure mtest; + mtest.setType(STRUCT_ADDITION); + for(int i2 = i_d; i2 >= 2; i2--) { + if(vc[i2] != 0) { + MathStructure *mpow = new MathStructure(); + mpow->setType(STRUCT_POWER); + mpow->addChild(*xvar); + mpow->addChild_nocopy(new MathStructure(i2, 1, 0)); + if(vc[i2] == 1) { + mtest.addChild_nocopy(mpow); + } else { + MathStructure *mterm = new MathStructure(); + mterm->setType(STRUCT_MULTIPLICATION); + mterm->addChild_nocopy(new MathStructure(vc[i2], 1L, 0L)); + mterm->addChild_nocopy(mpow); + mtest.addChild_nocopy(mterm); + } + } + } + if(vc[1] == 1) { + mtest.addChild(*xvar); + } else if(vc[1] != 0) { + MathStructure *mterm = new MathStructure(); + mterm->setType(STRUCT_MULTIPLICATION); + mterm->addChild_nocopy(new MathStructure(vc[1], 1L, 0L)); + mterm->addChild(*xvar); + mtest.addChild_nocopy(mterm); + } + mtest.addChild_nocopy(new MathStructure(vc[0], 1L, 0L)); + MathStructure mthis(*this); + MathStructure mquo; + if(mtest.size() > 1 && polynomialDivide(mthis, mtest, mquo, eo, false)) { + mquo.factorize(eo, false, 0, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + free(vc); + set(mquo, true); + multiply(mtest, true); + return true; + } + } + } + } + } + } + } + free(vc); + } + } + } + + } + } + + if(SIZE == 2 && max_factor_degree != 0) { + Number nr1(1, 1, 0), nr2(1, 1, 0); + bool b = true, b_nonnum = false; + bool b1_neg = false, b2_neg = false; + for(size_t i = 0; i < SIZE && b; i++) { + b = false; + if(CHILD(i).isInteger() && CHILD(i).number().integerLength() < 100) { + b = true; + if(i == 0) nr1 = CHILD(i).number(); + else nr2 = CHILD(i).number(); + } else if(CHILD(i).isMultiplication() && CHILD(i).size() > 1) { + b_nonnum = true; + b = true; + size_t i2 = 0; + if(CHILD(i)[0].isInteger() && CHILD(i).number().integerLength() < 100) { + if(i == 0) nr1 = CHILD(i)[0].number(); + else nr2 = CHILD(i)[0].number(); + i2++; + } + for(; i2 < CHILD(i).size(); i2++) { + if(!CHILD(i)[i2].isPower() || !CHILD(i)[i2][1].isInteger() || !CHILD(i)[i2][1].number().isPositive() || !CHILD(i)[i2][1].number().isEven() || CHILD(i)[1].number().integerLength() >= 100 || !CHILD(i)[i2][0].representsNonMatrix()) { + b = false; + break; + } + } + } else if(CHILD(i).isPower() && CHILD(i)[1].isNumber() && CHILD(i)[1].number().isInteger() && CHILD(i)[1].number().isPositive() && CHILD(i)[1].number().isEven() && CHILD(i)[1].number().integerLength() < 100 && CHILD(i)[0].representsNonMatrix()) { + b_nonnum = true; + b = true; + } + } + if(!b_nonnum) b = false; + if(b) { + b1_neg = nr1.isNegative(); + b2_neg = nr2.isNegative(); + if(b1_neg == b2_neg) b = false; + } + if(b) { + if(b1_neg) b = nr1.negate(); + if(b && !nr1.isOne()) { + b = nr1.isPerfectSquare() && nr1.isqrt(); + } + } + if(b) { + if(b2_neg) nr2.negate(); + if(!nr2.isOne()) { + b = nr2.isPerfectSquare() && nr2.isqrt(); + } + } + if(b) { + bool calc = false; + MathStructure *mmul = new MathStructure(*this); + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isNumber()) { + if(i == 0) { + CHILD(i).number() = nr1; + if(b1_neg) nr1.negate(); + (*mmul)[i].number() = nr1; + } else { + CHILD(i).number() = nr2; + if(b2_neg) nr2.negate(); + (*mmul)[i].number() = nr2; + } + } else if(CHILD(i).isMultiplication() && CHILD(i).size() > 1) { + b = true; + size_t i2 = 0; + if(CHILD(i)[0].isNumber()) { + if(i == 0) { + CHILD(i)[0].number() = nr1; + if(b1_neg) nr1.negate(); + (*mmul)[i][0].number() = nr1; + } else { + CHILD(i)[0].number() = nr2; + if(b2_neg) nr2.negate(); + (*mmul)[i][0].number() = nr2; + } + i2++; + } + for(; i2 < CHILD(i).size(); i2++) { + if(CHILD(i)[i2][1].number().isTwo()) { + CHILD(i)[i2].setToChild(1, true); + (*mmul)[i][i2].setToChild(1, true); + } else { + CHILD(i)[i2][1].number().divide(2); + (*mmul)[i][i2][1].number().divide(2); + } + CHILD(i).childUpdated(i2 + 1); + (*mmul)[i].childUpdated(i2 + 1); + } + if(CHILD(i)[0].isOne()) CHILD(i).delChild(1, true); + if((*mmul)[i][0].isOne()) (*mmul)[i].delChild(1, true); + } else if(CHILD(i).isPower()) { + if(CHILD(i)[1].number().isTwo()) { + CHILD(i).setToChild(1, true); + (*mmul)[i].setToChild(1, true); + } else { + CHILD(i)[1].number().divide(2); + (*mmul)[i][1].number().divide(2); + } + } + if(CHILD(i).isAddition()) calc = true; + CHILD_UPDATED(i) + mmul->childUpdated(i + 1); + } + if(calc) { + calculatesub(eo, eo, false); + mmul->calculatesub(eo, eo, false); + } + if(recursive) { + factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + mmul->factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + } + multiply_nocopy(mmul); + evalSort(true); + return true; + } + } + + //x^3-y^3=(x-y)(x^2+xy+y^2) + if(max_factor_degree != 0 && SIZE == 2 && CHILD(0).isPower() && CHILD(0)[1].isNumber() && CHILD(0)[1].number() == 3 && CHILD(1).isMultiplication() && CHILD(1).size() == 2 && CHILD(1)[0].isMinusOne() && CHILD(1)[1].isPower() && CHILD(1)[1][1].isNumber() && CHILD(1)[1][1].number() == 3) { + if(CHILD(0)[0].representsNonMatrix() && CHILD(1)[1][0].representsNonMatrix()) { + MathStructure *m2 = new MathStructure(*this); + (*m2)[0].setToChild(1, true); + (*m2)[1][1].setToChild(1, true); + EvaluationOptions eo2 = eo; + eo2.expand = false; + m2->calculatesub(eo2, eo2, false); + CHILD(0)[1].set(2, 1, 0, true); + CHILD(1).setToChild(2, true); + CHILD(1)[1].set(2, 1, 0, true); + MathStructure *m3 = new MathStructure(CHILD(0)[0]); + m3->calculateMultiply(CHILD(1)[0], eo2); + add_nocopy(m3, true); + calculatesub(eo2, eo2, false); + multiply_nocopy(m2, true); + evalSort(true); + return true; + } + } + //-x^3+y^3=(-x+y)(x^2+xy+y^2) + if(max_factor_degree != 0 && SIZE == 2 && CHILD(1).isPower() && CHILD(1)[1].isNumber() && CHILD(1)[1].number() == 3 && CHILD(0).isMultiplication() && CHILD(0).size() == 2 && CHILD(0)[0].isMinusOne() && CHILD(0)[1].isPower() && CHILD(0)[1][1].isNumber() && CHILD(0)[1][1].number() == 3) { + if(CHILD(1)[0].representsNonMatrix() && CHILD(0)[1][0].representsNonMatrix()) { + MathStructure *m2 = new MathStructure(*this); + (*m2)[1].setToChild(1, true); + (*m2)[0][1].setToChild(1, true); + EvaluationOptions eo2 = eo; + eo2.expand = false; + m2->calculatesub(eo2, eo2, false); + CHILD(1)[1].set(2, 1, 0, true); + CHILD(0).setToChild(2, true); + CHILD(0)[1].set(2, 1, 0, true); + MathStructure *m3 = new MathStructure(CHILD(0)[0]); + m3->calculateMultiply(CHILD(1)[0], eo2); + add_nocopy(m3, true); + calculatesub(eo2, eo2, false); + multiply_nocopy(m2, true); + evalSort(true); + return true; + } + } + + if(max_factor_degree != 0 && !only_integers && !force_factorization.isUndefined() && SIZE >= 2) { + MathStructure mexp, madd, mmul; + if(gather_factors(*this, force_factorization, madd, mmul, mexp) && !madd.isZero() && !mmul.isZero() && mexp.isInteger() && mexp.number().isGreaterThan(nr_two)) { + if(!mmul.isOne()) madd.calculateDivide(mmul, eo); + bool overflow = false; + int n = mexp.number().intValue(&overflow); + if(!overflow) { + if(n % 4 == 0) { + int i_u = 1; + if(n != 4) { + i_u = n / 4; + } + MathStructure m_sqrt2(2, 1, 0); + m_sqrt2.calculateRaise(nr_half, eo); + MathStructure m_sqrtb(madd); + m_sqrtb.calculateRaise(nr_half, eo); + MathStructure m_bfourth(madd); + m_bfourth.calculateRaise(Number(1, 4), eo); + m_sqrt2.calculateMultiply(m_bfourth, eo); + MathStructure m_x(force_factorization); + if(i_u != 1) m_x ^= i_u; + m_sqrt2.calculateMultiply(m_x, eo); + MathStructure *m2 = new MathStructure(force_factorization); + m2->raise(Number(i_u * 2, 1)); + m2->add(m_sqrtb); + m2->calculateAdd(m_sqrt2, eo); + set(force_factorization, true); + raise(Number(i_u * 2, 1)); + add(m_sqrtb); + calculateSubtract(m_sqrt2, eo); + multiply_nocopy(m2); + } else { + int i_u = 1; + if(n % 2 == 0) { + i_u = 2; + n /= 2; + } + MathStructure *m2 = new MathStructure(madd); + m2->calculateRaise(Number(n - 1, n), eo); + for(int i = 1; i < n - 1; i++) { + MathStructure *mterm = new MathStructure(madd); + mterm->calculateRaise(Number(n - i - 1, n), eo); + mterm->multiply(force_factorization); + if(i != 1 || i_u != 1) { + mterm->last().raise(Number(i * i_u, 1)); + mterm->childUpdated(mterm->size()); + } + if(i % 2 == 1) mterm->calculateMultiply(m_minus_one, eo); + m2->add_nocopy(mterm, true); + } + MathStructure *mterm = new MathStructure(force_factorization); + mterm->raise(Number((n - 1) * i_u, 1)); + m2->add_nocopy(mterm, true); + mterm = new MathStructure(force_factorization); + if(i_u != 1) mterm->raise(Number(i_u, 1)); + set(madd, true); + calculateRaise(Number(1, n), eo); + add_nocopy(mterm); + multiply_nocopy(m2); + } + if(!mmul.isOne()) multiply(mmul, true); + evalSort(true); + return true; + } + } + } + + //-x-y = -(x+y) + bool b = true; + for(size_t i2 = 0; i2 < SIZE; i2++) { + if((!CHILD(i2).isNumber() || !CHILD(i2).number().isNegative()) && (!CHILD(i2).isMultiplication() || CHILD(i2).size() < 2 || !CHILD(i2)[0].isNumber() || !CHILD(i2)[0].number().isNegative())) { + b = false; + break; + } + } + if(b) { + for(size_t i2 = 0; i2 < SIZE; i2++) { + if(CHILD(i2).isNumber()) { + CHILD(i2).number().negate(); + } else { + CHILD(i2)[0].number().negate(); + if(CHILD(i2)[0].isOne() && CHILD(i2).size() > 1) { + CHILD(i2).delChild(1); + if(CHILD(i2).size() == 1) { + CHILD(i2).setToChild(1, true); + } + } + } + } + multiply(MathStructure(-1, 1, 0)); + CHILD_TO_FRONT(1) + } + + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isMultiplication() && CHILD(i).size() > 1) { + for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { + if(CHILD(i)[i2].isAddition()) { + for(size_t i3 = i + 1; i3 < SIZE; i3++) { + if(CHILD(i3).isMultiplication() && CHILD(i3).size() > 1) { + for(size_t i4 = 0; i4 < CHILD(i3).size(); i4++) { + if(CHILD(i3)[i4].isAddition() && CHILD(i3)[i4] == CHILD(i)[i2]) { + MathStructure *mfac = &CHILD(i)[i2]; + mfac->ref(); + CHILD(i).delChild(i2 + 1, true); + CHILD(i3).delChild(i4 + 1, true); + CHILD(i3).ref(); + CHILD(i).add_nocopy(&CHILD(i3)); + CHILD(i).calculateAddLast(eo); + CHILD(i).multiply_nocopy(mfac); + CHILD_UPDATED(i) + delChild(i3 + 1, true); + evalSort(true); + factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + return true; + } + } + } + } + if(SIZE > 2) { + MathStructure mtest(*this); + mtest.delChild(i + 1); + if(mtest == CHILD(i)[i2]) { + CHILD(i).delChild(i2 + 1, true); + SET_CHILD_MAP(i); + add(m_one, true); + multiply(mtest); + evalSort(true); + factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + return true; + } + } + } + } + } + } + } + + //complete the square + if(max_factor_degree != 0 && (term_combination_levels != 0 || complete_square)) { + if(only_integers) { + if(SIZE <= 3 && SIZE > 1) { + MathStructure *xvar = NULL; + Number nr2(1, 1); + if(CHILD(0).isPower() && CHILD(0)[0].size() == 0 && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isTwo()) { + xvar = &CHILD(0)[0]; + } else if(CHILD(0).isMultiplication() && CHILD(0).size() == 2 && CHILD(0)[0].isNumber()) { + if(CHILD(0)[1].isPower()) { + if(CHILD(0)[1][0].size() == 0 && CHILD(0)[1][1].isNumber() && CHILD(0)[1][1].number().isTwo()) { + xvar = &CHILD(0)[1][0]; + nr2.set(CHILD(0)[0].number()); + } + } + } + if(xvar) { + bool factorable = false; + Number nr1, nr0; + if(SIZE == 2 && CHILD(1).isNumber()) { + factorable = true; + nr0 = CHILD(1).number(); + } else if(SIZE == 3 && CHILD(2).isNumber()) { + nr0 = CHILD(2).number(); + if(CHILD(1).isMultiplication()) { + if(CHILD(1).size() == 2 && CHILD(1)[0].isNumber() && xvar->equals(CHILD(1)[1])) { + nr1 = CHILD(1)[0].number(); + factorable = true; + } + } else if(xvar->equals(CHILD(1))) { + nr1.set(1, 1, 0); + factorable = true; + } + } + if(factorable && !nr2.isZero() && !nr1.isZero()) { + Number nrh(nr1); + nrh /= 2; + nrh /= nr2; + if(nrh.isInteger()) { + Number nrk(nrh); + if(nrk.square()) { + nrk *= nr2; + nrk.negate(); + nrk += nr0; + set(MathStructure(*xvar), true); + add(nrh); + raise(nr_two); + if(!nr2.isOne()) multiply(nr2); + if(!nrk.isZero()) add(nrk); + evalSort(true); + return true; + } + } + } + } + } + } else { + MathStructure m2, m1, m0; + const MathStructure *xvar = NULL; + if(!force_factorization.isUndefined()) { + xvar = &force_factorization; + } else { + if(CHILD(0).isPower() && CHILD(0)[0].size() == 0 && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isTwo()) { + xvar = &CHILD(0)[0]; + } else if(CHILD(0).isMultiplication()) { + for(size_t i2 = 0; i2 < CHILD(0).size(); i2++) { + if(CHILD(0).isPower() && CHILD(0)[i2][0].size() == 0 && CHILD(0)[i2][1].isNumber() && CHILD(0)[i2][1].number().isTwo()) { + xvar = &CHILD(0)[0]; + } + } + } + } + if(xvar && gather_factors(*this, *xvar, m0, m1, m2, true) && !m1.isZero() && !m2.isZero()) { + MathStructure *mx = new MathStructure(*xvar); + set(m1, true); + calculateMultiply(nr_half, eo); + if(!m2.isOne()) calculateDivide(m2, eo); + add_nocopy(mx); + calculateAddLast(eo); + raise(nr_two); + if(!m2.isOne()) multiply(m2); + if(!m1.isOne()) m1.calculateRaise(nr_two, eo); + m1.calculateMultiply(Number(-1, 4), eo); + if(!m2.isOne()) { + m2.calculateInverse(eo); + m1.calculateMultiply(m2, eo); + } + m0.calculateAdd(m1, eo); + if(!m0.isZero()) add(m0); + if(recursive) { + CHILD(0).factorize(eo, false, 0, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + CHILD(1).factorize(eo, false, 0, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + CHILDREN_UPDATED + } + evalSort(true); + return true; + } + } + } + + //Try factorize combinations of terms + if(SIZE > 2 && term_combination_levels > 0) { + bool b = false, b_ret = false; + // 5/y + x/y + z = (5 + x)/y + z + MathStructure mstruct_units(*this); + MathStructure mstruct_new(*this); + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(mstruct_units[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct_units[i].size();) { + if(!mstruct_units[i][i2].isPower() || !mstruct_units[i][i2][1].hasNegativeSign()) { + mstruct_units[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); + else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); + for(size_t i2 = 0; i2 < mstruct_new[i].size();) { + if(mstruct_new[i][i2].isPower() && mstruct_new[i][i2][1].hasNegativeSign()) { + mstruct_new[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); + else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); + } else if(mstruct_new[i].isPower() && mstruct_new[i][1].hasNegativeSign()) { + mstruct_new[i].set(1, 1, 0); + } else { + mstruct_units[i].setUndefined(); + } + } + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(!mstruct_units[i].isUndefined()) { + for(size_t i2 = i + 1; i2 < mstruct_units.size();) { + if(mstruct_units[i2] == mstruct_units[i]) { + mstruct_new[i].add(mstruct_new[i2], true); + mstruct_new.delChild(i2 + 1); + mstruct_units.delChild(i2 + 1); + b = true; + } else { + i2++; + } + } + if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); + else mstruct_new[i].multiply(mstruct_units[i], true); + } + } + if(b) { + if(mstruct_new.size() == 1) { + set(mstruct_new[0], true); + factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + return true; + } else { + set(mstruct_new); + } + b = false; + b_ret = true; + } + // a*y + a*z + x = a(y + z) + x + vector syms; + vector counts; + collect_symbols(*this, syms); + size_t max_count = 0, max_i = 0; + Number min_pow; + for(size_t i = 0; i < syms.size(); i++) { + if(syms[i].containsUnknowns()) { + size_t count = 0; + Number min_pow_i; + for(size_t i2 = 0; i2 < SIZE; i2++) { + if(CHILD(i2).isMultiplication()) { + for(size_t i3 = 0; i3 < CHILD(i2).size(); i3++) { + if(CHILD(i2)[i3].isPower() && CHILD(i2)[i3][1].isNumber() && CHILD(i2)[i3][1].number().isRational() && CHILD(i2)[i3][1].number().isNegative() && CHILD(i2)[i3][0] == syms[i]) { + if(min_pow_i.isZero() || CHILD(i2)[i3][1].number() > min_pow_i) min_pow_i = CHILD(i2)[i3][1].number(); + count++; + break; + } + } + } else if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isRational() && CHILD(i2)[1].number().isNegative() && CHILD(i2)[0] == syms[i]) { + if(min_pow_i.isZero() || CHILD(i2)[1].number() > min_pow_i) min_pow_i = CHILD(i2)[1].number(); + count++; + } + } + if(count > 1 && count > max_count) { + max_count = count; + min_pow = min_pow_i; + max_i = i; + } + } + } + if(!max_count) { + for(size_t i = 0; i < syms.size(); i++) { + if(syms[i].containsUnknowns()) { + size_t count = 0; + Number min_pow_i; + for(size_t i2 = 0; i2 < SIZE; i2++) { + if(CHILD(i2).isMultiplication()) { + for(size_t i3 = 0; i3 < CHILD(i2).size(); i3++) { + if(CHILD(i2)[i3].isPower() && CHILD(i2)[i3][1].isNumber() && CHILD(i2)[i3][1].number().isRational() && CHILD(i2)[i3][1].number().isPositive() && CHILD(i2)[i3][0] == syms[i]) { + if(min_pow_i.isZero() || CHILD(i2)[i3][1].number() < min_pow_i) min_pow_i = CHILD(i2)[i3][1].number(); + count++; + break; + } else if(CHILD(i2)[i3] == syms[i]) { + if(min_pow_i.isZero() || min_pow_i > 1) min_pow_i = 1; + count++; + break; + } + } + } else if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isRational() && CHILD(i2)[1].number().isPositive() && CHILD(i2)[0] == syms[i]) { + if(min_pow_i.isZero() || CHILD(i2)[1].number() < min_pow_i) min_pow_i = CHILD(i2)[1].number(); + count++; + } else if(CHILD(i2) == syms[i]) { + if(min_pow_i.isZero() || min_pow_i > 1) min_pow_i = 1; + count++; + } + } + if(count > 1 && count > max_count) { + max_count = count; + min_pow = min_pow_i; + max_i = i; + } + } + } + } + if(max_count > 0) { + size_t i = max_i; + vector mleft; + for(size_t i2 = 0; i2 < SIZE;) { + b = false; + if(CHILD(i2).isMultiplication()) { + for(size_t i3 = 0; i3 < CHILD(i2).size(); i3++) { + if(CHILD(i2)[i3].isPower() && CHILD(i2)[i3][1].isNumber() && CHILD(i2)[i3][1].number().isRational() && (min_pow.isPositive() ? CHILD(i2)[i3][1].number().isPositive() : CHILD(i2)[i3][1].number().isNegative()) && CHILD(i2)[i3][0] == syms[i]) { + if(CHILD(i2)[i3][1] == min_pow) CHILD(i2).delChild(i3 + 1, true); + else if(CHILD(i2)[i3][1] == min_pow + 1) CHILD(i2)[i3].setToChild(1, true); + else { + CHILD(i2)[i3][1].number() -= min_pow; + factorize_fix_root_power(CHILD(i2)[i3]); + } + b = true; + break; + } else if(min_pow.isPositive() && CHILD(i2)[i3] == syms[i]) { + if(min_pow.isOne()) CHILD(i2).delChild(i3 + 1, true); + else { + CHILD(i2)[i3].raise((-min_pow) + 1); + factorize_fix_root_power(CHILD(i2)[i3]); + } + b = true; + break; + } + } + } else if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isRational() && (min_pow.isPositive() ? CHILD(i2)[1].number().isPositive() : CHILD(i2)[1].number().isNegative()) && CHILD(i2)[0] == syms[i]) { + if(CHILD(i2)[1] == min_pow) CHILD(i2).set(1, 1, 0, true); + else if(CHILD(i2)[1] == min_pow + 1) CHILD(i2).setToChild(1, true); + else { + CHILD(i2)[1].number() -= min_pow; + factorize_fix_root_power(CHILD(i2)); + } + b = true; + } else if(min_pow.isPositive() && CHILD(i2) == syms[i]) { + if(min_pow.isOne()) CHILD(i2).set(1, 1, 0, true); + else { + CHILD(i2).raise((-min_pow) + 1); + factorize_fix_root_power(CHILD(i2)); + } + b = true; + } + if(b) { + i2++; + } else { + CHILD(i2).ref(); + mleft.push_back(&CHILD(i2)); + ERASE(i2) + } + } + multiply(syms[i]); + if(!min_pow.isOne()) LAST ^= min_pow; + for(size_t i2 = 0; i2 < mleft.size(); i2++) { + add_nocopy(mleft[i2], true); + } + factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + return true; + } + if(LAST.isNumber()) { + MathStructure *mdel = &LAST; + mdel->ref(); + delChild(SIZE, true); + b = factorize(eo, false, term_combination_levels - 1, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + add_nocopy(mdel, true); + if(term_combination_levels == 1) return b || b_ret; + if(b) b_ret = true; + } + for(size_t i = 0; !b && i < SIZE; i++) { + MathStructure *mdel = &CHILD(i); + mdel->ref(); + delChild(i + 1, true); + b = true; + if(mdel->isMultiplication()) { + for(size_t i2 = 0; i2 < mdel->size(); i2++) { + if((*mdel)[i2].isPower() && (*mdel)[i2][0].containsUnknowns()) { + if(contains((*mdel)[i2][0], false, false, false) > 0) {b = false; break;} + } else if((*mdel)[i2].containsUnknowns()) { + if(contains((*mdel)[i2], false, false, false) > 0) {b = false; break;} + } + } + + } else { + b = contains(*mdel, false, false, false) <= 0; + } + if(b) { + b = factorize(eo, false, term_combination_levels - 1, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + if(recursive) mdel->factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + add_nocopy(mdel, true); + if(term_combination_levels == 1) return b || b_ret; + if(b) b_ret = true; + break; + } else { + insertChild_nocopy(mdel, i + 1); + } + } + b = false; + // a*y + a*z + x = a(y + z) + x + syms.clear(); + counts.clear(); + collect_symbols(*this, syms); + max_count = 0; max_i = 0; + for(size_t i = 0; i < syms.size(); i++) { + size_t count = 0; + Number min_pow_i; + for(size_t i2 = 0; i2 < SIZE; i2++) { + if(CHILD(i2).isMultiplication()) { + for(size_t i3 = 0; i3 < CHILD(i2).size(); i3++) { + if(CHILD(i2)[i3].isPower() && CHILD(i2)[i3][1].isNumber() && CHILD(i2)[i3][1].number().isRational() && CHILD(i2)[i3][1].number().isNegative() && CHILD(i2)[i3][0] == syms[i]) { + if(min_pow_i.isZero() || CHILD(i2)[i3][1].number() > min_pow_i) min_pow_i = CHILD(i2)[i3][1].number(); + count++; + break; + } + } + } else if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isRational() && CHILD(i2)[1].number().isNegative() && CHILD(i2)[0] == syms[i]) { + if(min_pow_i.isZero() || CHILD(i2)[1].number() > min_pow_i) min_pow_i = CHILD(i2)[1].number(); + count++; + } + } + if(count > 1 && count > max_count) { + max_count = count; + min_pow = min_pow_i; + max_i = i; + } + } + if(!max_count) { + for(size_t i = 0; i < syms.size(); i++) { + size_t count = 0; + Number min_pow_i; + for(size_t i2 = 0; i2 < SIZE; i2++) { + if(CHILD(i2).isMultiplication()) { + for(size_t i3 = 0; i3 < CHILD(i2).size(); i3++) { + if(CHILD(i2)[i3].isPower() && CHILD(i2)[i3][1].isNumber() && CHILD(i2)[i3][1].number().isRational() && CHILD(i2)[i3][1].number().isPositive() && CHILD(i2)[i3][0] == syms[i]) { + if(min_pow_i.isZero() || CHILD(i2)[i3][1].number() < min_pow_i) min_pow_i = CHILD(i2)[i3][1].number(); + count++; + break; + } else if(CHILD(i2)[i3] == syms[i]) { + if(min_pow_i.isZero() || min_pow_i > 1) min_pow_i = 1; + count++; + break; + } + } + } else if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isRational() && CHILD(i2)[1].number().isPositive() && CHILD(i2)[0] == syms[i]) { + if(min_pow_i.isZero() || CHILD(i2)[1].number() < min_pow_i) min_pow_i = CHILD(i2)[1].number(); + count++; + } else if(CHILD(i2) == syms[i]) { + if(min_pow_i.isZero() || min_pow_i > 1) min_pow_i = 1; + count++; + } + } + if(count > 1 && count > max_count) { + max_count = count; + min_pow = min_pow_i; + max_i = i; + } + } + } + if(max_count > 0) { + size_t i = max_i; + vector mleft; + for(size_t i2 = 0; i2 < SIZE;) { + b = false; + if(CHILD(i2).isMultiplication()) { + for(size_t i3 = 0; i3 < CHILD(i2).size(); i3++) { + if(CHILD(i2)[i3].isPower() && CHILD(i2)[i3][1].isNumber() && CHILD(i2)[i3][1].number().isRational() && (min_pow.isPositive() ? CHILD(i2)[i3][1].number().isPositive() : CHILD(i2)[i3][1].number().isNegative()) && CHILD(i2)[i3][0] == syms[i]) { + if(CHILD(i2)[i3][1] == min_pow) CHILD(i2).delChild(i3 + 1, true); + else if(CHILD(i2)[i3][1] == min_pow + 1) CHILD(i2)[i3].setToChild(1, true); + else { + CHILD(i2)[i3][1].number() -= min_pow; + factorize_fix_root_power(CHILD(i2)[i3]); + } + b = true; + break; + } else if(min_pow.isPositive() && CHILD(i2)[i3] == syms[i]) { + if(min_pow.isOne()) CHILD(i2).delChild(i3 + 1, true); + else { + CHILD(i2)[i3].raise((-min_pow) + 1); + factorize_fix_root_power(CHILD(i2)[i3]); + } + b = true; + break; + } + } + } else if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isRational() && (min_pow.isPositive() ? CHILD(i2)[1].number().isPositive() : CHILD(i2)[1].number().isNegative()) && CHILD(i2)[0] == syms[i]) { + if(CHILD(i2)[1] == min_pow) CHILD(i2).set(1, 1, 0, true); + else if(CHILD(i2)[1] == min_pow + 1) CHILD(i2).setToChild(1, true); + else { + CHILD(i2)[1].number() -= min_pow; + factorize_fix_root_power(CHILD(i2)); + } + b = true; + } else if(min_pow.isPositive() && CHILD(i2) == syms[i]) { + if(min_pow.isOne()) CHILD(i2).set(1, 1, 0, true); + else { + CHILD(i2).raise((-min_pow) + 1); + factorize_fix_root_power(CHILD(i2)); + } + b = true; + } + if(b) { + i2++; + } else { + CHILD(i2).ref(); + mleft.push_back(&CHILD(i2)); + ERASE(i2) + } + } + multiply(syms[i]); + if(!min_pow.isOne()) LAST ^= min_pow; + for(size_t i2 = 0; i2 < mleft.size(); i2++) { + add_nocopy(mleft[i2], true); + } + factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + return true; + } + if(isAddition()) { + b = false; + // y*f(x) + z*f(x) = (y+z)*f(x) + mstruct_units.set(*this); + mstruct_new.set(*this); + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(mstruct_units[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct_units[i].size();) { + if(!combination_factorize_is_complicated(mstruct_units[i][i2])) { + mstruct_units[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); + else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); + for(size_t i2 = 0; i2 < mstruct_new[i].size();) { + if(combination_factorize_is_complicated(mstruct_new[i][i2])) { + mstruct_new[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); + else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); + } else if(combination_factorize_is_complicated(mstruct_units[i])) { + mstruct_new[i].set(1, 1, 0); + } else { + mstruct_units[i].setUndefined(); + } + } + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(!mstruct_units[i].isUndefined()) { + for(size_t i2 = i + 1; i2 < mstruct_units.size();) { + if(mstruct_units[i2] == mstruct_units[i]) { + mstruct_new[i].add(mstruct_new[i2], true); + mstruct_new.delChild(i2 + 1); + mstruct_units.delChild(i2 + 1); + b = true; + } else { + i2++; + } + } + if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); + else mstruct_new[i].multiply(mstruct_units[i], true); + } + } + if(b) { + if(mstruct_new.size() == 1) set(mstruct_new[0], true); + else set(mstruct_new); + factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + return true; + } + } + if(isAddition()) { + b = false; + mstruct_units.set(*this); + mstruct_new.set(*this); + // 5x + pi*x + 5y + xy = (5 + pi)x + 5y + xy + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(mstruct_units[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct_units[i].size();) { + if(!mstruct_units[i][i2].containsType(STRUCT_UNIT, true) && !mstruct_units[i][i2].containsUnknowns()) { + mstruct_units[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); + else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); + for(size_t i2 = 0; i2 < mstruct_new[i].size();) { + if(mstruct_new[i][i2].containsType(STRUCT_UNIT, true) || mstruct_new[i][i2].containsUnknowns()) { + mstruct_new[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); + else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); + } else if(mstruct_units[i].containsType(STRUCT_UNIT, true) || mstruct_units[i].containsUnknowns()) { + mstruct_new[i].set(1, 1, 0); + } else { + mstruct_units[i].setUndefined(); + } + } + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(!mstruct_units[i].isUndefined()) { + for(size_t i2 = i + 1; i2 < mstruct_units.size();) { + if(mstruct_units[i2] == mstruct_units[i]) { + mstruct_new[i].add(mstruct_new[i2], true); + mstruct_new.delChild(i2 + 1); + mstruct_units.delChild(i2 + 1); + b = true; + } else { + i2++; + } + } + if(mstruct_new[i].isOne()) mstruct_new[i].set(mstruct_units[i]); + else mstruct_new[i].multiply(mstruct_units[i], true); + } + } + if(b) { + if(mstruct_new.size() == 1) set(mstruct_new[0], true); + else set(mstruct_new); + factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + return true; + } + } + return b_ret; + } else if(term_combination_levels != 0 && SIZE > 2) { + int start_index = rand() % SIZE; + int index = start_index; + int best_index = -1; + int run_index = 0; + int max_run_index = SIZE - 3; + if(term_combination_levels < -1) { + run_index = -term_combination_levels - 2; + max_run_index = run_index; + } else if(term_combination_levels > 0 && term_combination_levels - 1 < max_run_index) { + max_run_index = term_combination_levels -1; + } + + MathStructure mbest; + do { + if(CALCULATOR->aborted()) break; + if(endtime_p && endtime_p->tv_sec > 0) { +#ifndef CLOCK_MONOTONIC + struct timeval curtime; + gettimeofday(&curtime, NULL); + if(curtime.tv_sec > endtime_p->tv_sec || (curtime.tv_sec == endtime_p->tv_sec && curtime.tv_usec > endtime_p->tv_usec)) { +#else + struct timespec curtime; + clock_gettime(CLOCK_MONOTONIC, &curtime); + if(curtime.tv_sec > endtime_p->tv_sec || (curtime.tv_sec == endtime_p->tv_sec && curtime.tv_nsec / 1000 > endtime_p->tv_usec)) { +#endif + CALCULATOR->error(false, _("Because of time constraints only a limited number of combinations of terms were tried during factorization. Repeat factorization to try other random combinations."), NULL); + break; + } + } + + MathStructure mtest(*this); + mtest.delChild(index + 1); + if(mtest.factorize(eo, false, run_index == 0 ? 0 : -1 - run_index, 0, only_integers, false, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree)) { + bool b = best_index < 0 || (mbest.isAddition() && !mtest.isAddition()); + if(!b && (mtest.isAddition() == mbest.isAddition())) { + b = mtest.isAddition() && (mtest.size() < mbest.size()); + if(!b && (!mtest.isAddition() || mtest.size() == mbest.size())) { + size_t c1 = mtest.countTotalChildren() + CHILD(index).countTotalChildren(); + size_t c2 = mbest.countTotalChildren() + CHILD(best_index).countTotalChildren(); + b = (c1 < c2); + if(c1 == c2) { + b = (count_powers(mtest) + count_powers(CHILD(index))) < (count_powers(mbest) + count_powers(CHILD(best_index))); + } + } + } + if(b) { + mbest = mtest; + best_index = index; + if(mbest.isPower()) { + break; + } + } + } + index++; + if(index == (int) SIZE) index = 0; + if(index == start_index) { + if(best_index >= 0) { + break; + } + run_index++; + if(run_index > max_run_index) break; + } + } while(true); + if(best_index >= 0) { + mbest.add(CHILD(best_index), true); + set(mbest); + if(term_combination_levels >= -1 && (run_index > 0 || recursive)) { + factorize(eo, false, term_combination_levels, 0, only_integers, true, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + } + return true; + } + } + } + default: { + if(term_combination_levels < -1) break; + bool b = false; + + if(isComparison()) { + EvaluationOptions eo2 = eo; + eo2.assume_denominators_nonzero = false; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).factorize(eo2, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree)) { + CHILD_UPDATED(i); + b = true; + } + } + } else if(recursive && (recursive > 1 || !isAddition())) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree)) { + CHILD_UPDATED(i); + b = true; + } + } + } + if(b) { + EvaluationOptions eo2 = eo; + eo2.expand = false; + calculatesub(eo2, eo2, false); + evalSort(true); + if(isAddition()) { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isMultiplication() && CHILD(i).size() > 1) { + for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { + if(CHILD(i)[i2].isAddition()) { + for(size_t i3 = i + 1; i3 < SIZE; i3++) { + if(CHILD(i3).isMultiplication() && CHILD(i3).size() > 1) { + for(size_t i4 = 0; i4 < CHILD(i3).size(); i4++) { + if(CHILD(i3)[i4].isAddition() && CHILD(i3)[i4] == CHILD(i)[i2]) { + MathStructure *mfac = &CHILD(i)[i2]; + mfac->ref(); + CHILD(i).delChild(i2 + 1, true); + CHILD(i3).delChild(i4 + 1, true); + CHILD(i3).ref(); + CHILD(i).add_nocopy(&CHILD(i3)); + CHILD(i).calculateAddLast(eo); + CHILD(i).multiply_nocopy(mfac); + CHILD_UPDATED(i) + delChild(i3 + 1, true); + evalSort(true); + factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + return true; + } + } + } + } + if(SIZE > 2) { + MathStructure mtest(*this); + mtest.delChild(i + 1); + if(mtest == CHILD(i)[i2]) { + CHILD(i).delChild(i2 + 1, true); + SET_CHILD_MAP(i); + add(m_one, true); + multiply(mtest); + evalSort(true); + factorize(eo, false, term_combination_levels, 0, only_integers, recursive, endtime_p, force_factorization, complete_square, only_sqrfree, max_factor_degree); + return true; + } + } + } + } + } + } + } + return true; + } + } + } + return false; +} + diff -Nru libqalculate-3.6.0/libqalculate/MathStructure-gcd.cc libqalculate-3.7.0/libqalculate/MathStructure-gcd.cc --- libqalculate-3.6.0/libqalculate/MathStructure-gcd.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure-gcd.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,1511 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "MathStructure.h" +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "Number.h" +#include "Function.h" +#include "Variable.h" +#include "Unit.h" +#include "Prefix.h" + +#if HAVE_UNORDERED_MAP +# include + using std::unordered_map; +#elif defined(__GNUC__) + +# ifndef __has_include +# define __has_include(x) 0 +# endif + +# if (defined(__clang__) && __has_include()) || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 3) +# include + namespace Sgi = std; +# define unordered_map std::tr1::unordered_map +# else +# if __GNUC__ < 3 +# include + namespace Sgi { using ::hash_map; }; // inherit globals +# else +# include +# if __GNUC__ == 3 && __GNUC_MINOR__ == 0 + namespace Sgi = std; // GCC 3.0 +# else + namespace Sgi = ::__gnu_cxx; // GCC 3.1 and later +# endif +# endif +# define unordered_map Sgi::hash_map +# endif +#else // ... there are other compilers, right? + namespace Sgi = std; +# define unordered_map Sgi::hash_map +#endif + +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +bool sr_gcd(const MathStructure &m1, const MathStructure &m2, MathStructure &mgcd, const sym_desc_vec &sym_stats, size_t var_i, const EvaluationOptions &eo) { + + if(var_i >= sym_stats.size()) return false; + const MathStructure &xvar = sym_stats[var_i].sym; + + MathStructure c, d; + Number adeg = m1.degree(xvar); + Number bdeg = m2.degree(xvar); + Number cdeg, ddeg; + if(adeg.isGreaterThanOrEqualTo(bdeg)) { + c = m1; + d = m2; + cdeg = adeg; + ddeg = bdeg; + } else { + c = m2; + d = m1; + cdeg = bdeg; + ddeg = adeg; + } + + MathStructure cont_c, cont_d; + c.polynomialContent(xvar, cont_c, eo); + d.polynomialContent(xvar, cont_d, eo); + + MathStructure gamma; + + if(!MathStructure::gcd(cont_c, cont_d, gamma, eo, NULL, NULL, false)) return false; + mgcd = gamma; + if(ddeg.isZero()) { + return true; + } + + MathStructure prim_c, prim_d; + c.polynomialPrimpart(xvar, cont_c, prim_c, eo); + d.polynomialPrimpart(xvar, cont_d, prim_d, eo); + c = prim_c; + d = prim_d; + + MathStructure r; + MathStructure ri(1, 1, 0); + MathStructure psi(1, 1, 0); + Number delta(cdeg); + delta -= ddeg; + + while(true) { + + if(CALCULATOR->aborted()) return false; + + if(!prem(c, d, xvar, r, eo, false)) return false; + + if(r.isZero()) { + mgcd = gamma; + MathStructure mprim; + d.polynomialPrimpart(xvar, mprim, eo); + if(CALCULATOR->aborted()) return false; + mgcd.calculateMultiply(mprim, eo); + return true; + } + + c = d; + cdeg = ddeg; + + MathStructure psi_pow(psi); + psi_pow.calculateRaise(delta, eo); + ri.calculateMultiply(psi_pow, eo); + + if(!divide_in_z(r, ri, d, sym_stats, var_i, eo)) { + return false; + } + + ddeg = d.degree(xvar); + if(ddeg.isZero()) { + if(r.isNumber()) { + mgcd = gamma; + } else { + r.polynomialPrimpart(xvar, mgcd, eo); + if(CALCULATOR->aborted()) return false; + mgcd.calculateMultiply(gamma, eo); + } + return true; + } + + c.lcoefficient(xvar, ri); + if(delta.isOne()) { + psi = ri; + } else if(!delta.isZero()) { + MathStructure ri_pow(ri); + ri_pow.calculateRaise(delta, eo); + MathStructure psi_pow(psi); + delta--; + psi_pow.calculateRaise(delta, eo); + divide_in_z(ri_pow, psi_pow, psi, sym_stats, var_i + 1, eo); + } + delta = cdeg; + delta -= ddeg; + + } + + return false; + +} + + +bool interpolate(const MathStructure &gamma, const Number &xi, const MathStructure &xvar, MathStructure &minterp, const EvaluationOptions &eo) { + MathStructure e(gamma); + Number rxi(xi); + rxi.recip(); + minterp.clear(); + for(long int i = 0; !e.isZero(); i++) { + if(CALCULATOR->aborted()) return false; + MathStructure gi; + polynomial_smod(e, xi, gi, eo); + if(minterp.isZero() && !gi.isZero()) { + minterp = gi; + if(i != 0) { + if(minterp.isOne()) { + minterp = xvar; + if(i != 1) minterp.raise(i); + } else { + minterp.multiply(xvar, true); + if(i != 1) minterp[minterp.size() - 1].raise(i); + minterp.calculateMultiplyLast(eo); + } + } + } else if(!gi.isZero()) { + minterp.add(gi, true); + if(i != 0) { + if(minterp[minterp.size() - 1].isOne()) { + minterp[minterp.size() - 1] = xvar; + if(i != 1) minterp[minterp.size() - 1].raise(i); + } else { + minterp[minterp.size() - 1].multiply(xvar, true); + if(i != 1) minterp[minterp.size() - 1][minterp[minterp.size() - 1].size() - 1].raise(i); + minterp[minterp.size() - 1].calculateMultiplyLast(eo); + } + } + } + if(!gi.isZero()) e.calculateSubtract(gi, eo); + e.calculateMultiply(rxi, eo); + } + minterp.calculatesub(eo, eo, false); + return true; +} + +bool heur_gcd(const MathStructure &m1, const MathStructure &m2, MathStructure &mgcd, const EvaluationOptions &eo, MathStructure *ca, MathStructure *cb, sym_desc_vec &sym_stats, size_t var_i) { + + if(m1.isZero() || m2.isZero()) return false; + + if(m1.isNumber() && m2.isNumber()) { + mgcd = m1; + if(!mgcd.number().gcd(m2.number())) mgcd.set(1, 1, 0); + if(ca) { + *ca = m1; + ca->number() /= mgcd.number(); + } + if(cb) { + *cb = m2; + cb->number() /= mgcd.number(); + } + return true; + } + + if(var_i >= sym_stats.size()) return false; + const MathStructure &xvar = sym_stats[var_i].sym; + + Number nr_gc; + integer_content(m1, nr_gc); + Number nr_rgc; + integer_content(m2, nr_rgc); + nr_gc.gcd(nr_rgc); + nr_rgc = nr_gc; + nr_rgc.recip(); + MathStructure p(m1); + p.calculateMultiply(nr_rgc, eo); + MathStructure q(m2); + q.calculateMultiply(nr_rgc, eo); + Number maxdeg(p.degree(xvar)); + Number maxdeg2(q.degree(xvar)); + if(maxdeg2.isGreaterThan(maxdeg)) maxdeg = maxdeg2; + Number mp(p.maxCoefficient()); + Number mq(q.maxCoefficient()); + Number xi; + if(mp.isGreaterThan(mq)) { + xi = mq; + } else { + xi = mp; + } + xi *= 2; + xi += 2; + + for(int t = 0; t < 6; t++) { + + if(CALCULATOR->aborted()) return false; + + if(!xi.isInteger() || (maxdeg * xi.integerLength()).isGreaterThan(100000L)) { + return false; + } + + MathStructure cp, cq; + MathStructure gamma; + MathStructure psub(p); + psub.calculateReplace(xvar, xi, eo, true); + MathStructure qsub(q); + qsub.calculateReplace(xvar, xi, eo, true); + + if(heur_gcd(psub, qsub, gamma, eo, &cp, &cq, sym_stats, var_i + 1)) { + + if(!interpolate(gamma, xi, xvar, mgcd, eo)) return false; + + Number ig; + integer_content(mgcd, ig); + ig.recip(); + mgcd.calculateMultiply(ig, eo); + + MathStructure dummy; + + if(divide_in_z(p, mgcd, ca ? *ca : dummy, sym_stats, var_i, eo) && divide_in_z(q, mgcd, cb ? *cb : dummy, sym_stats, var_i, eo)) { + mgcd.calculateMultiply(nr_gc, eo); + return true; + } + } + + Number xi2(xi); + xi2.isqrt(); + xi2.isqrt(); + xi *= xi2; + xi *= 73794L; + xi.iquo(27011L); + + } + + return false; + +} + +bool MathStructure::lcm(const MathStructure &m1, const MathStructure &m2, MathStructure &mlcm, const EvaluationOptions &eo, bool check_args) { + if(m1.isNumber() && m2.isNumber()) { + mlcm = m1; + return mlcm.number().lcm(m2.number()); + } + if(check_args && (!m1.isRationalPolynomial() || !m2.isRationalPolynomial())) { + return false; + } + MathStructure ca, cb; + if(!MathStructure::gcd(m1, m2, mlcm, eo, &ca, &cb, false)) return false; + mlcm.calculateMultiply(ca, eo); + mlcm.calculateMultiply(cb, eo); + return true; +} + +bool has_noninteger_coefficient(const MathStructure &mstruct) { + if(mstruct.isNumber() && mstruct.number().isRational() && !mstruct.number().isInteger()) return true; + if(mstruct.isFunction() || mstruct.isPower()) return false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(has_noninteger_coefficient(mstruct[i])) return true; + } + return false; +} + +bool MathStructure::gcd(const MathStructure &m1, const MathStructure &m2, MathStructure &mresult, const EvaluationOptions &eo2, MathStructure *ca, MathStructure *cb, bool check_args) { + + EvaluationOptions eo = eo2; + eo.keep_zero_units = false; + + if(ca) *ca = m1; + if(cb) *cb = m2; + mresult.set(1, 1, 0); + + if(CALCULATOR->aborted()) return false; + + if(m1.isOne() || m2.isOne()) { + return true; + } + if(m1.isNumber() && m2.isNumber()) { + mresult = m1; + if(!mresult.number().gcd(m2.number())) mresult.set(1, 1, 0); + if(ca || cb) { + if(mresult.isZero()) { + if(ca) ca->clear(); + if(cb) cb->clear(); + } else { + if(ca) { + *ca = m1; + ca->number() /= mresult.number(); + } + if(cb) { + *cb = m2; + cb->number() /= mresult.number(); + } + } + } + return true; + } + + if(m1 == m2) { + if(ca) ca->set(1, 1, 0); + if(cb) cb->set(1, 1, 0); + mresult = m1; + return true; + } + if(m1.isZero()) { + if(ca) ca->clear(); + if(cb) cb->set(1, 1, 0); + mresult = m2; + return true; + } + if(m2.isZero()) { + if(ca) ca->set(1, 1, 0); + if(cb) cb->clear(); + mresult = m1; + return true; + } + + if(check_args && (!m1.isRationalPolynomial() || !m2.isRationalPolynomial())) { + return false; + } + + if(has_noninteger_coefficient(m1) || has_noninteger_coefficient(m2)) { + Number nlcm1; + lcm_of_coefficients_denominators(m1, nlcm1); + Number nlcm2; + lcm_of_coefficients_denominators(m2, nlcm2); + nlcm1.lcm(nlcm2); + if(!nlcm1.isOne()) { + MathStructure mtmp1, mtmp2; + multiply_lcm(m1, nlcm1, mtmp1, eo); + multiply_lcm(m2, nlcm1, mtmp2, eo); + if(mtmp1.equals(m1, true, true) || mtmp2.equals(m2, true, true)) return false; + return gcd(mtmp1, mtmp2, mresult, eo, ca, cb, false); + } + } + + if(m1.isMultiplication()) { + if(m2.isMultiplication() && m2.size() > m1.size()) + goto factored_2; +factored_1: + mresult.clear(); + mresult.setType(STRUCT_MULTIPLICATION); + MathStructure acc_ca; + acc_ca.setType(STRUCT_MULTIPLICATION); + MathStructure part_2(m2); + MathStructure part_ca, part_cb; + for(size_t i = 0; i < m1.size(); i++) { + mresult.addChild(m_zero); + MathStructure::gcd(m1[i], part_2, mresult[i], eo, &part_ca, &part_cb, false); + if(CALCULATOR->aborted()) return false; + acc_ca.addChild(part_ca); + part_2 = part_cb; + } + mresult.calculatesub(eo, eo, false); + if(ca) { + *ca = acc_ca; + ca->calculatesub(eo, eo, false); + } + if(cb) *cb = part_2; + return true; + } else if(m2.isMultiplication()) { + if(m1.isMultiplication() && m1.size() > m2.size()) + goto factored_1; +factored_2: + mresult.clear(); + mresult.setType(STRUCT_MULTIPLICATION); + MathStructure acc_cb; + acc_cb.setType(STRUCT_MULTIPLICATION); + MathStructure part_1(m1); + MathStructure part_ca, part_cb; + for(size_t i = 0; i < m2.size(); i++) { + mresult.addChild(m_zero); + MathStructure::gcd(part_1, m2[i], mresult[i], eo, &part_ca, &part_cb, false); + if(CALCULATOR->aborted()) return false; + acc_cb.addChild(part_cb); + part_1 = part_ca; + } + mresult.calculatesub(eo, eo, false); + if(ca) *ca = part_1; + if(cb) { + *cb = acc_cb; + cb->calculatesub(eo, eo, false); + } + return true; + } + + if(m1.isPower()) { + MathStructure p(m1[0]); + if(m2.isPower()) { + if(m1[0] == m2[0]) { + if(m1[1].number().isLessThan(m2[1].number())) { + if(ca) ca->set(1, 1, 0); + if(cb) { + *cb = m2; + (*cb)[1].number() -= m1[1].number(); + POWER_CLEAN((*cb)) + } + mresult = m1; + return true; + } else { + if(ca) { + *ca = m1; + (*ca)[1].number() -= m2[1].number(); + POWER_CLEAN((*ca)) + } + if(cb) cb->set(1, 1, 0); + mresult = m2; + return true; + } + } else { + MathStructure p_co, pb_co; + MathStructure p_gcd; + if(!MathStructure::gcd(m1[0], m2[0], p_gcd, eo, &p_co, &pb_co, false)) return false; + if(p_gcd.isOne()) { + return true; + } else { + if(m1[1].number().isLessThan(m2[1].number())) { + mresult = p_gcd; + mresult.calculateRaise(m1[1], eo); + mresult.multiply(m_zero, true); + p_co.calculateRaise(m1[1], eo); + pb_co.calculateRaise(m2[1], eo); + p_gcd.raise(m2[1]); + p_gcd[1].number() -= m1[1].number(); + p_gcd.calculateRaiseExponent(eo); + p_gcd.calculateMultiply(pb_co, eo); + bool b = MathStructure::gcd(p_co, p_gcd, mresult[mresult.size() - 1], eo, ca, cb, false); + mresult.calculateMultiplyLast(eo); + return b; + } else { + mresult = p_gcd; + mresult.calculateRaise(m2[1], eo); + mresult.multiply(m_zero, true); + p_co.calculateRaise(m1[1], eo); + pb_co.calculateRaise(m2[1], eo); + p_gcd.raise(m1[1]); + p_gcd[1].number() -= m2[1].number(); + p_gcd.calculateRaiseExponent(eo); + p_gcd.calculateMultiply(p_co, eo); + bool b = MathStructure::gcd(p_gcd, pb_co, mresult[mresult.size() - 1], eo, ca, cb, false); + mresult.calculateMultiplyLast(eo); + return b; + } + } + } + } else { + if(m1[0] == m2) { + if(ca) { + *ca = m1; + (*ca)[1].number()--; + POWER_CLEAN((*ca)) + } + if(cb) cb->set(1, 1, 0); + mresult = m2; + return true; + } + MathStructure p_co, bpart_co; + MathStructure p_gcd; + if(!MathStructure::gcd(m1[0], m2, p_gcd, eo, &p_co, &bpart_co, false)) return false; + if(p_gcd.isOne()) { + return true; + } else { + mresult = p_gcd; + mresult.multiply(m_zero, true); + p_co.calculateRaise(m1[1], eo); + p_gcd.raise(m1[1]); + p_gcd[1].number()--; + p_gcd.calculateRaiseExponent(eo); + p_gcd.calculateMultiply(p_co, eo); + bool b = MathStructure::gcd(p_gcd, bpart_co, mresult[mresult.size() - 1], eo, ca, cb, false); + mresult.calculateMultiplyLast(eo); + return b; + } + } + } else if(m2.isPower()) { + if(m2[0] == m1) { + if(ca) ca->set(1, 1, 0); + if(cb) { + *cb = m2; + (*cb)[1].number()--; + POWER_CLEAN((*cb)) + } + mresult = m1; + return true; + } + MathStructure p_co, apart_co; + MathStructure p_gcd; + if(!MathStructure::gcd(m1, m2[0], p_gcd, eo, &apart_co, &p_co, false)) return false; + if(p_gcd.isOne()) { + return true; + } else { + mresult = p_gcd; + mresult.multiply(m_zero, true); + p_co.calculateRaise(m2[1], eo); + p_gcd.raise(m2[1]); + p_gcd[1].number()--; + p_gcd.calculateRaiseExponent(eo); + p_gcd.calculateMultiply(p_co, eo); + bool b = MathStructure::gcd(apart_co, p_gcd, mresult[mresult.size() - 1], eo, ca, cb, false); + mresult.calculateMultiplyLast(eo); + return b; + } + } + if(IS_A_SYMBOL(m1) || m1.isUnit()) { + MathStructure bex(m2); + bex.calculateReplace(m1, m_zero, eo); + if(!bex.isZero()) { + return true; + } + } + if(IS_A_SYMBOL(m2) || m2.isUnit()) { + MathStructure aex(m1); + aex.calculateReplace(m2, m_zero, eo); + if(!aex.isZero()) { + return true; + } + } + + sym_desc_vec sym_stats; + get_symbol_stats(m1, m2, sym_stats); + + if(sym_stats.empty()) return false; + + size_t var_i = 0; + const MathStructure &xvar = sym_stats[var_i].sym; + + /*for(size_t i = 0; i< sym_stats.size(); i++) { + if(sym_stats[i].sym.size() > 0) { + MathStructure m1b(m1), m2b(m2); + vector vars; + for(; i < sym_stats.size(); i++) { + if(sym_stats[i].sym.size() > 0) { + UnknownVariable *var = new UnknownVariable("", format_and_print(sym_stats[i].sym)); + m1b.replace(sym_stats[i].sym, var); + m2b.replace(sym_stats[i].sym, var); + vars.push_back(var); + } + } + bool b = gcd(m1b, m2, mresult, eo2, ca, cb, false); + size_t i2 = 0; + for(i = 0; i < sym_stats.size(); i++) { + if(sym_stats[i].sym.size() > 0) { + mresult.replace(vars[i2], sym_stats[i].sym); + if(ca) ca->replace(vars[i2], sym_stats[i].sym); + if(cb) cb->replace(vars[i2], sym_stats[i].sym); + vars[i2]->destroy(); + i2++; + } + } + return b; + } + }*/ + + Number ldeg_a(sym_stats[var_i].ldeg_a); + Number ldeg_b(sym_stats[var_i].ldeg_b); + Number min_ldeg; + if(ldeg_a.isLessThan(ldeg_b)) { + min_ldeg = ldeg_a; + } else { + min_ldeg = ldeg_b; + } + + if(min_ldeg.isPositive()) { + MathStructure aex(m1), bex(m2); + MathStructure common(xvar); + if(!min_ldeg.isOne()) common.raise(min_ldeg); + aex.calculateDivide(common, eo); + bex.calculateDivide(common, eo); + MathStructure::gcd(aex, bex, mresult, eo, ca, cb, false); + mresult.calculateMultiply(common, eo); + return true; + } + + if(sym_stats[var_i].deg_a.isZero()) { + if(cb) { + MathStructure c, mprim; + int u; + m2.polynomialUnitContentPrimpart(xvar, u, c, mprim, eo); + if(!m2.equals(c, true, true)) MathStructure::gcd(m1, c, mresult, eo, ca, cb, false); + if(CALCULATOR->aborted()) { + if(ca) *ca = m1; + if(cb) *cb = m2; + mresult.set(1, 1, 0); + return false; + } + if(u == -1) { + cb->calculateNegate(eo); + } + cb->calculateMultiply(mprim, eo); + } else { + MathStructure c; + m2.polynomialContent(xvar, c, eo); + if(!m2.equals(c, true, true)) MathStructure::gcd(m1, c, mresult, eo, ca, cb, false); + } + return true; + } else if(sym_stats[var_i].deg_b.isZero()) { + if(ca) { + MathStructure c, mprim; + int u; + m1.polynomialUnitContentPrimpart(xvar, u, c, mprim, eo); + if(!m1.equals(c, true, true)) MathStructure::gcd(c, m2, mresult, eo, ca, cb, false); + if(CALCULATOR->aborted()) { + if(ca) *ca = m1; + if(cb) *cb = m2; + mresult.set(1, 1, 0); + return false; + } + if(u == -1) { + ca->calculateNegate(eo); + } + ca->calculateMultiply(mprim, eo); + } else { + MathStructure c; + m1.polynomialContent(xvar, c, eo); + if(!m1.equals(c, true, true)) MathStructure::gcd(c, m2, mresult, eo, ca, cb, false); + } + return true; + } + + if(!heur_gcd(m1, m2, mresult, eo, ca, cb, sym_stats, var_i)) { + if(!sr_gcd(m1, m2, mresult, sym_stats, var_i, eo)) { + if(ca) *ca = m1; + if(cb) *cb = m2; + mresult.set(1, 1, 0); + return false; + } + if(!mresult.isOne()) { + if(ca) { + if(!MathStructure::polynomialDivide(m1, mresult, *ca, eo, false)) { + if(ca) *ca = m1; + if(cb) *cb = m2; + mresult.set(1, 1, 0); + return false; + } + } + if(cb) { + if(!MathStructure::polynomialDivide(m2, mresult, *cb, eo, false)) { + if(ca) *ca = m1; + if(cb) *cb = m2; + mresult.set(1, 1, 0); + return false; + } + } + } + if(CALCULATOR->aborted()) { + if(ca) *ca = m1; + if(cb) *cb = m2; + mresult.set(1, 1, 0); + return false; + } + } + + return true; +} + + +Number dos_count_points(const MathStructure &m, bool b_unknown) { + if(m.isPower() && (!b_unknown || m[0].containsUnknowns())) { + Number nr = dos_count_points(m[0], b_unknown); + if(!nr.isZero()) { + if(m[0].isNumber() && m[0].number().isNonZero()) { + nr *= m[1].number(); + if(nr.isNegative()) nr.negate(); + } else { + nr *= 2; + } + return nr; + } + } else if(m.size() == 0 && ((b_unknown && m.isUnknown()) || (!b_unknown && !m.isNumber()))) { + return nr_one; + } + Number nr; + for(size_t i = 0; i < m.size(); i++) { + nr += dos_count_points(m[i], b_unknown); + } + return nr; +} + +bool do_simplification(MathStructure &mstruct, const EvaluationOptions &eo, bool combine_divisions, bool only_gcd, bool combine_only, bool recursive, bool limit_size, int i_run) { + + if(!eo.expand || !eo.assume_denominators_nonzero) return false; + + if(recursive) { + bool b = false; + for(size_t i = 0; i < mstruct.size(); i++) { + b = do_simplification(mstruct[i], eo, combine_divisions, only_gcd || (!mstruct.isComparison() && !mstruct.isLogicalAnd() && !mstruct.isLogicalOr()), combine_only, true, limit_size) || b; + if(CALCULATOR->aborted()) return b; + } + if(b) mstruct.calculatesub(eo, eo, false); + return do_simplification(mstruct, eo, combine_divisions, only_gcd, combine_only, false, limit_size) || b; + } + if(mstruct.isPower() && mstruct[1].isNumber() && mstruct[1].number().isRational() && !mstruct[1].number().isInteger() && mstruct[0].isAddition() && mstruct[0].isRationalPolynomial()) { + MathStructure msqrfree(mstruct[0]); + if(sqrfree(msqrfree, eo) && msqrfree.isPower() && msqrfree.calculateRaise(mstruct[1], eo)) { + mstruct = msqrfree; + return true; + } + } else if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(mstruct) && mstruct[0].isAddition() && mstruct[0].isRationalPolynomial()) { + MathStructure msqrfree(mstruct[0]); + if(sqrfree(msqrfree, eo) && msqrfree.isPower() && msqrfree[1].isInteger() && msqrfree[1].number().isPositive()) { + if(msqrfree[1] == mstruct[1]) { + if(msqrfree[1].number().isEven()) { + if(!msqrfree[0].representsReal(true)) return false; + msqrfree.delChild(2); + msqrfree.setType(STRUCT_FUNCTION); + msqrfree.setFunctionId(FUNCTION_ID_ABS); + mstruct = msqrfree; + } else { + mstruct = msqrfree[0]; + } + return true; + } else if(msqrfree[1].number().isIntegerDivisible(mstruct[1].number())) { + if(msqrfree[1].number().isEven()) { + if(!msqrfree[0].representsReal(true)) return false; + msqrfree[0].transform(STRUCT_FUNCTION); + msqrfree[0].setFunctionId(FUNCTION_ID_ABS); + } + msqrfree[1].number().divide(mstruct[1].number()); + mstruct = msqrfree; + mstruct.calculatesub(eo, eo, false); + return true; + } else if(mstruct[1].number().isIntegerDivisible(msqrfree[1].number())) { + if(msqrfree[1].number().isEven()) { + if(!msqrfree[0].representsReal(true)) return false; + msqrfree[0].transform(STRUCT_FUNCTION); + msqrfree[0].setFunctionId(FUNCTION_ID_ABS); + } + Number new_root(mstruct[1].number()); + new_root.divide(msqrfree[1].number()); + mstruct[0] = msqrfree[0]; + mstruct[1] = new_root; + return true; + } + } + } + if(!mstruct.isAddition() && !mstruct.isMultiplication()) return false; + + if(combine_divisions) { + + MathStructure divs, nums, numleft, mleft; + + EvaluationOptions eo2 = eo; + eo2.do_polynomial_division = false; + eo2.keep_zero_units = false; + + if(!mstruct.isAddition()) mstruct.transform(STRUCT_ADDITION); + + // find division by polynomial + for(size_t i = 0; i < mstruct.size(); i++) { + if(CALCULATOR->aborted()) return false; + bool b = false; + if(mstruct[i].isMultiplication()) { + MathStructure div, num(1, 1, 0); + bool b_num = false; + for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { + if(mstruct[i][i2].isPower() && mstruct[i][i2][1].isInteger() && mstruct[i][i2][1].number().isNegative()) { + bool b_rat = mstruct[i][i2][0].isRationalPolynomial(); + if(!b_rat && mstruct[i][i2][0].isAddition() && mstruct[i][i2][0].size() > 1) { + b_rat = true; + for(size_t i3 = 0; i3 < mstruct[i][i2][0].size(); i3++) { + if(!mstruct[i][i2][0][i3].representsZero(true) && !mstruct[i][i2][0][i3].isRationalPolynomial()) { + b_rat = false; + break; + } + } + } + if(!b_rat) { + div.clear(); + break; + } + bool b_minone = mstruct[i][i2][1].isMinusOne(); + if(b_minone) { + if(div.isZero()) div = mstruct[i][i2][0]; + else div.multiply(mstruct[i][i2][0], true); + } else { + mstruct[i][i2][1].number().negate(); + if(div.isZero()) div = mstruct[i][i2]; + else div.multiply(mstruct[i][i2], true); + mstruct[i][i2][1].number().negate(); + } + } else if(mstruct[i][i2].isRationalPolynomial() || mstruct[i][i2].representsZero(true)) { + if(!b_num) {b_num = true; num = mstruct[i][i2];} + else num.multiply(mstruct[i][i2], true); + } else { + div.clear(); + break; + } + } + if(!div.isZero()) { + bool b_found = false; + for(size_t i3 = 0; i3 < divs.size(); i3++) { + if(divs[i3] == div) { + if(!num.representsZero(true)) { + if(num.isAddition()) { + for(size_t i4 = 0; i4 < num.size(); i4++) { + nums[i3].add(num[i4], true); + } + } else { + nums[i3].add(num, true); + } + } + b_found = true; + b = true; + break; + } + } + if(!b_found && (eo.assume_denominators_nonzero || div.representsNonZero(true)) && !div.representsZero(true)) { + if(!num.representsZero(true)) { + divs.addChild(div); + nums.addChild(num); + } + b = true; + } + } + } else if(mstruct[i].isPower() && mstruct[i][1].isInteger() && mstruct[i][1].number().isNegative()) { + bool b_rat = mstruct[i][0].isRationalPolynomial(); + if(!b_rat && mstruct[i][0].isAddition() && mstruct[i][0].size() > 1) { + b_rat = true; + for(size_t i2 = 0; i2 < mstruct[i][0].size(); i2++) { + if(!mstruct[i][0][i2].representsZero(true) && !mstruct[i][0].isRationalPolynomial()) { + b_rat = false; + break; + } + } + } + if(b_rat) { + bool b_minone = mstruct[i][1].isMinusOne(); + if(!b_minone) mstruct[i][1].number().negate(); + bool b_found = false; + for(size_t i3 = 0; i3 < divs.size(); i3++) { + if((b_minone && divs[i3] == mstruct[i][0]) || (!b_minone && divs[i3] == mstruct[i])) { + nums[i3].add(m_one, true); + b_found = true; + b = true; + break; + } + } + if(!b_found && (eo.assume_denominators_nonzero || mstruct[i][0].representsNonZero(true)) && !mstruct[i][0].representsZero(true)) { + if(b_minone) divs.addChild(mstruct[i][0]); + else divs.addChild(mstruct[i]); + nums.addChild(m_one); + b = true; + } + if(!b_minone) mstruct[i][1].number().negate(); + } + } + if(!b) { + if(i_run <= 1 && mstruct[i].isRationalPolynomial()) numleft.addChild(mstruct[i]); + else mleft.addChild(mstruct[i]); + } + } + + for(size_t i = 0; i < divs.size(); i++) { + if(divs[i].isAddition()) { + for(size_t i2 = 0; i2 < divs[i].size();) { + if(divs[i][i2].representsZero(true)) { + divs[i].delChild(i2 + 1); + } else i2++; + } + if(divs[i].size() == 1) divs[i].setToChild(1); + else if(divs[i].size() == 0) divs[i].clear(); + } + } + + if(divs.size() == 0) { + if(mstruct.size() == 1) mstruct.setToChild(1); + return false; + } + bool b_ret = false; + if(divs.size() > 1 || numleft.size() > 0) b_ret = true; + + /*divs.setType(STRUCT_VECTOR); + nums.setType(STRUCT_VECTOR); + numleft.setType(STRUCT_VECTOR); + mleft.setType(STRUCT_VECTOR); + cout << nums << ":" << divs << ":" << numleft << ":" << mleft << endl;*/ + + if(i_run > 1) { + for(size_t i = 0; i < divs.size();) { + bool b = true; + if(!divs[i].isRationalPolynomial() || !nums[i].isRationalPolynomial()) { + if(mstruct.size() == 1) mstruct.setToChild(1); + return false; + } + if(!combine_only && divs[i].isAddition() && nums[i].isAddition()) { + MathStructure ca, cb, mgcd; + if(MathStructure::gcd(nums[i], divs[i], mgcd, eo2, &ca, &cb, false) && !mgcd.isOne() && (!cb.isAddition() || !ca.isAddition() || ca.size() + cb.size() <= nums[i].size() + divs[i].size())) { + if(mgcd.representsNonZero(true) || !eo.warn_about_denominators_assumed_nonzero || warn_about_denominators_assumed_nonzero(mgcd, eo)) { + if(cb.isOne()) { + numleft.addChild(ca); + nums.delChild(i + 1); + divs.delChild(i + 1); + b = false; + } else { + nums[i] = ca; + divs[i] = cb; + } + b_ret = true; + } + } + } + if(CALCULATOR->aborted()) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} + if(b) i++; + } + + } else { + while(divs.size() > 0) { + bool b = true; + if(!divs[0].isRationalPolynomial() || !nums[0].isRationalPolynomial()) { + if(mstruct.size() == 1) mstruct.setToChild(1); + return false; + } + if(!combine_only && divs[0].isAddition() && nums[0].isAddition()) { + MathStructure ca, cb, mgcd; + if(MathStructure::gcd(nums[0], divs[0], mgcd, eo2, &ca, &cb, false) && !mgcd.isOne() && (!cb.isAddition() || !ca.isAddition() || ca.size() + cb.size() <= nums[0].size() + divs[0].size())) { + if(mgcd.representsNonZero(true) || !eo.warn_about_denominators_assumed_nonzero || warn_about_denominators_assumed_nonzero(mgcd, eo)) { + if(cb.isOne()) { + numleft.addChild(ca); + nums.delChild(1); + divs.delChild(1); + b = false; + } else { + nums[0] = ca; + divs[0] = cb; + } + b_ret = true; + } + } + } + if(CALCULATOR->aborted()) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} + if(b && divs.size() > 1) { + if(!combine_only && divs[1].isAddition() && nums[1].isAddition()) { + MathStructure ca, cb, mgcd; + EvaluationOptions eo3 = eo2; + eo3.transform_trigonometric_functions = false; + if(MathStructure::gcd(nums[1], divs[1], mgcd, eo3, &ca, &cb, false) && !mgcd.isOne() && (!cb.isAddition() || !ca.isAddition() || ca.size() + cb.size() <= nums[1].size() + divs[1].size())) { + if(mgcd.representsNonZero(true) || !eo.warn_about_denominators_assumed_nonzero || warn_about_denominators_assumed_nonzero(mgcd, eo)) { + if(cb.isOne()) { + numleft.addChild(ca); + nums.delChild(2); + divs.delChild(2); + b = false; + } else { + nums[1] = ca; + divs[1] = cb; + } + } + } + } + if(CALCULATOR->aborted()) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} + if(b) { + MathStructure ca, cb, mgcd; + b = MathStructure::gcd(divs[0], divs[1], mgcd, eo2, &ca, &cb, false) && !mgcd.isOne(); + if(CALCULATOR->aborted()) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} + bool b_merge = true; + if(b) { + if(limit_size && ((cb.isAddition() && ((divs[0].isAddition() && divs[0].size() * cb.size() > 200) || (nums[0].isAddition() && nums[0].size() * cb.size() > 200))) || (ca.isAddition() && nums[1].isAddition() && nums[1].size() * ca.size() > 200))) { + b_merge = false; + } else { + if(!cb.isOne()) { + divs[0].calculateMultiply(cb, eo2); + nums[0].calculateMultiply(cb, eo2); + } + if(!ca.isOne()) { + nums[1].calculateMultiply(ca, eo2); + } + } + } else { + if(limit_size && ((divs[1].isAddition() && ((divs[0].isAddition() && divs[0].size() * divs[1].size() > 200) || (nums[0].isAddition() && nums[0].size() * divs[1].size() > 200))) || (divs[0].isAddition() && nums[1].isAddition() && nums[1].size() * divs[0].size() > 200))) { + b_merge = false; + } else { + nums[0].calculateMultiply(divs[1], eo2); + nums[1].calculateMultiply(divs[0], eo2); + divs[0].calculateMultiply(divs[1], eo2); + } + } + if(b_merge) { + nums[0].calculateAdd(nums[1], eo2); + nums.delChild(2); + divs.delChild(2); + } else { + size_t size_1 = 2, size_2 = 2; + if(nums[0].isAddition()) size_1 += nums[0].size() - 1; + if(divs[0].isAddition()) size_1 += divs[0].size() - 1; + if(nums[1].isAddition()) size_2 += nums[1].size() - 1; + if(divs[1].isAddition()) size_2 += divs[1].size() - 1; + if(size_1 > size_2) { + nums[0].calculateDivide(divs[0], eo); + mleft.addChild(nums[0]); + nums.delChild(1); + divs.delChild(1); + } else { + nums[1].calculateDivide(divs[1], eo); + mleft.addChild(nums[1]); + nums.delChild(2); + divs.delChild(2); + } + } + } + } else if(b && numleft.size() > 0) { + if(limit_size && divs[0].isAddition() && numleft.size() > 0 && divs[0].size() * numleft.size() > 200) break; + if(numleft.size() == 1) numleft.setToChild(1); + else if(numleft.size() > 1) numleft.setType(STRUCT_ADDITION); + numleft.calculateMultiply(divs[0], eo2); + nums[0].calculateAdd(numleft, eo2); + numleft.clear(); + } else if(b) break; + } + + if(CALCULATOR->aborted()) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} + while(!combine_only && !only_gcd && divs.size() > 0 && divs[0].isAddition() && !nums[0].isNumber()) { + bool b_unknown = divs[0].containsUnknowns(); + if(!b_unknown || nums[0].containsUnknowns()) { + MathStructure mcomps; + mcomps.resizeVector(nums[0].isAddition() ? nums[0].size() : 1, m_zero); + if(nums[0].isAddition()) { + for(size_t i = 0; i < nums[0].size(); i++) { + if((b_unknown && nums[0][i].containsUnknowns()) || (!b_unknown && !nums[0][i].isNumber())) { + mcomps[i].setType(STRUCT_MULTIPLICATION); + if(nums[0][i].isMultiplication()) { + for(size_t i2 = 0; i2 < nums[0][i].size(); i2++) { + if((b_unknown && nums[0][i][i2].containsUnknowns()) || (!b_unknown && !nums[0][i][i2].isNumber())) { + nums[0][i][i2].ref(); + mcomps[i].addChild_nocopy(&nums[0][i][i2]); + } + } + } else { + nums[0][i].ref(); + mcomps[i].addChild_nocopy(&nums[0][i]); + } + } + } + } else { + mcomps[0].setType(STRUCT_MULTIPLICATION); + if(nums[0].isMultiplication()) { + for(size_t i2 = 0; i2 < nums[0].size(); i2++) { + if((b_unknown && nums[0][i2].containsUnknowns()) || (!b_unknown && !nums[0][i2].isNumber())) { + nums[0][i2].ref(); + mcomps[0].addChild_nocopy(&nums[0][i2]); + } + } + } else { + nums[0].ref(); + mcomps[0].addChild_nocopy(&nums[0]); + } + } + bool b_found = false; + unordered_map matches; + for(size_t i = 0; i < divs[0].size(); i++) { + if((b_unknown && divs[0][i].containsUnknowns()) || (!b_unknown && !divs[0][i].isNumber())) { + MathStructure mcomp1; + mcomp1.setType(STRUCT_MULTIPLICATION); + if(divs[0][i].isMultiplication()) { + for(size_t i2 = 0; i2 < divs[0][i].size(); i2++) { + if((b_unknown && divs[0][i][i2].containsUnknowns()) || (!b_unknown && !divs[0][i][i2].isNumber())) { + divs[0][i][i2].ref(); + mcomp1.addChild_nocopy(&divs[0][i][i2]); + } + } + } else { + divs[0][i].ref(); + mcomp1.addChild_nocopy(&divs[0][i]); + } + b_found = false; + for(size_t i2 = 0; i2 < mcomps.size(); i2++) { + if(mcomps[i2] == mcomp1) { + matches[i] = i2; + b_found = true; + break; + } + } + if(!b_found) break; + } + } + if(b_found) { + b_found = false; + size_t i_selected = 0; + if(nums[0].isAddition()) { + Number i_points; + for(size_t i = 0; i < divs[0].size(); i++) { + if((b_unknown && divs[0][i].containsUnknowns()) || (!b_unknown && !divs[0][i].isNumber())) { + Number new_points = dos_count_points(divs[0][i], b_unknown); + if(new_points > i_points) {i_points = new_points; i_selected = i;} + } + } + } + MathStructure mquo, mrem; + if(polynomial_long_division(nums[0].isAddition() ? nums[0][matches[i_selected]] : nums[0], divs[0], m_zero, mquo, mrem, eo2, false) && !mquo.isZero() && mrem != (nums[0].isAddition() ? nums[0][matches[i_selected]] : nums[0])) { + if(CALCULATOR->aborted()) return false; + if((nums[0].isAddition() && nums[0].size() > 1) || !mrem.isZero() || divs[0].representsNonZero(true) || (eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(divs[0], eo))) { + mleft.addChild(mquo); + if(nums[0].isAddition()) { + nums[0].delChild(matches[i_selected] + 1, true); + if(!mrem.isZero()) { + nums[0].calculateAdd(mrem, eo2); + } + } else { + if(mrem.isZero()) { + divs.clear(); + } else { + nums[0] = mrem; + } + } + b_ret = true; + b_found = true; + } + } + } + if(!b_found) break; + } else { + break; + } + } + + if(CALCULATOR->aborted()) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} + if(!combine_only && !only_gcd && divs.size() > 0 && divs[0].isAddition()) { + bool b_unknown = divs[0].containsUnknowns() || nums[0].containsUnknowns(); + MathStructure mquo, mrem; + vector symsd, symsn; + collect_symbols(nums[0], symsn); + if(!symsn.empty()) { + collect_symbols(divs[0], symsd); + } + for(size_t i = 0; i < symsd.size();) { + bool b_found = false; + if(!b_unknown || symsd[i].containsUnknowns()) { + for(size_t i2 = 0; i2 < symsn.size(); i2++) { + if(symsn[i2] == symsd[i]) { + b_found = (nums[0].degree(symsd[i]) >= divs[0].degree(symsd[i])); + break; + } + } + } + if(b_found) i++; + else symsd.erase(symsd.begin() + i); + } + for(size_t i = 0; i < symsd.size(); i++) { + if(polynomial_long_division(nums[0], divs[0], symsd[i], mquo, mrem, eo2, false) && !mquo.isZero() && mrem != nums[0]) { + if(CALCULATOR->aborted()) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} + if(!mrem.isZero() || divs[0].representsNonZero(true) || (eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(divs[0], eo))) { + if(mrem.isZero()) { + mleft.addChild(mquo); + divs.clear(); + b_ret = true; + break; + } else { + if(mquo.isAddition()) { + for(size_t i = 0; i < mquo.size(); ) { + MathStructure mtest(mquo[i]); + mtest.calculateMultiply(divs[0], eo2); + mtest.calculateAdd(mrem, eo2); + Number point = dos_count_points(mtest, b_unknown); + point -= dos_count_points(mquo[i], b_unknown); + point -= dos_count_points(mrem, b_unknown); + if(point <= 0) { + mquo.delChild(i + 1); + mrem = mtest; + } else { + i++; + } + } + if(mquo.size() == 0) mquo.clear(); + else if(mquo.size() == 1) mquo.setToChild(1); + } + if(!mquo.isZero()) { + Number point = dos_count_points(nums[0], b_unknown); + point -= dos_count_points(mquo, b_unknown); + point -= dos_count_points(mrem, b_unknown); + if(point > 0) { + mleft.addChild(mquo); + MathStructure ca, cb, mgcd; + if(mrem.isAddition() && MathStructure::gcd(mrem, divs[0], mgcd, eo2, &ca, &cb, false) && !mgcd.isOne() && (!cb.isAddition() || !ca.isAddition() || ca.size() + cb.size() <= mrem.size() + divs[0].size())) { + mrem = ca; + divs[0] = cb; + } + mrem.calculateDivide(divs[0], eo2); + mleft.addChild(mrem); + divs.clear(); + b_ret = true; + break; + } + } + } + } + } + } + } + } + + if(!b_ret) {if(mstruct.size() == 1) mstruct.setToChild(1); return false;} + + mstruct.clear(true); + for(size_t i = 0; i < divs.size() && (i == 0 || i_run > 1); i++) { + if(i == 0) mstruct = nums[0]; + else mstruct.add(nums[i], i > 1); + if(only_gcd || combine_only) { + divs[i].inverse(); + if(i == 0) mstruct.multiply(divs[i], true); + else mstruct.last().multiply(divs[i], true); + } else { + if(i == 0) mstruct.calculateDivide(divs[i], eo); + else mstruct.last().calculateDivide(divs[i], eo); + if(i == 0 && i_run <= 1 && mstruct.isAddition()) { + do_simplification(mstruct, eo, true, false, false, false, limit_size, 2); + } + } + } + for(size_t i = 0; i < mleft.size(); i++) { + if(i == 0 && mstruct.isZero()) mstruct = mleft[i]; + else mstruct.calculateAdd(mleft[i], eo); + } + for(size_t i = 0; i < numleft.size(); i++) { + if(i == 0 && mstruct.isZero()) mstruct = numleft[i]; + else mstruct.calculateAdd(numleft[i], eo); + } + + return true; + } + + MathStructure divs; + // find division by polynomial + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { + if(mstruct[i][i2].isPower() && (mstruct[i][i2][0].isAddition() || combine_divisions) && mstruct[i][i2][1].isMinusOne() && mstruct[i][i2][0].isRationalPolynomial()) { + bool b_found = false; + for(size_t i3 = 0; i3 < divs.size(); i3++) { + if(divs[i3] == mstruct[i][i2][0]) { + divs[i3].number()++; + b_found = true; + break; + } + } + if(!b_found) divs.addChild(mstruct[i][i2][0]); + break; + } + } + } else if(mstruct[i].isPower() && (mstruct[i][0].isAddition() || combine_divisions) && mstruct[i][1].isMinusOne() && mstruct[i][0].isRationalPolynomial()) { + bool b_found = false; + for(size_t i3 = 0; i3 < divs.size(); i3++) { + if(divs[i3] == mstruct[i][0]) { + divs[i3].number()++; + b_found = true; + break; + } + } + if(!b_found) divs.addChild(mstruct[i][0]); + } + } + + // check if denominators is zero + for(size_t i = 0; i < divs.size(); ) { + if((!combine_divisions && divs[i].number().isZero()) || (!eo.assume_denominators_nonzero && !divs[i].representsNonZero(true)) || divs[i].representsZero(true)) divs.delChild(i + 1); + else i++; + } + + if(divs.size() == 0) return false; + + // combine numerators with same denominator + MathStructure nums, numleft, mleft; + nums.resizeVector(divs.size(), m_zero); + for(size_t i = 0; i < mstruct.size(); i++) { + bool b = false; + if(mstruct[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { + if(mstruct[i][i2].isPower() && (mstruct[i][i2][0].isAddition() || combine_divisions) && mstruct[i][i2][1].isMinusOne() && mstruct[i][i2][0].isRationalPolynomial()) { + for(size_t i3 = 0; i3 < divs.size(); i3++) { + if(divs[i3] == mstruct[i][i2][0]) { + if(mstruct[i].size() == 1) nums[i3].addChild(m_one); + else if(mstruct[i].size() == 2) nums[i3].addChild(mstruct[i][i2 == 0 ? 1 : 0]); + else {nums[i3].addChild(mstruct[i]); nums[i3][nums[i3].size() - 1].delChild(i2 + 1);} + b = true; + break; + } + } + break; + } + } + } else if(mstruct[i].isPower() && (mstruct[i][0].isAddition() || combine_divisions) && mstruct[i][1].isMinusOne() && mstruct[i][0].isRationalPolynomial()) { + for(size_t i3 = 0; i3 < divs.size(); i3++) { + if(divs[i3] == mstruct[i][0]) { + nums[i3].addChild(m_one); + b = true; + break; + } + } + } + if(!b && combine_divisions) { + if(mstruct[i].isRationalPolynomial()) numleft.addChild(mstruct[i]); + else mleft.addChild(mstruct[i]); + } + } + + EvaluationOptions eo2 = eo; + eo2.do_polynomial_division = false; + eo2.keep_zero_units = false; + + // do polynomial division; give points to incomplete division + vector points(nums.size(), -1); + bool b = false, b_ready_candidate = false; + for(size_t i = 0; i < divs.size(); i++) { + if(CALCULATOR->aborted()) return false; + if(nums[i].size() > 1 && divs[i].isAddition()) { + nums[i].setType(STRUCT_ADDITION); + MathStructure xvar; + get_first_symbol(nums[i], xvar); + if(nums[i].isRationalPolynomial() && nums[i].degree(xvar).isLessThan(100) && divs[i].degree(xvar).isLessThan(100)) { + MathStructure mquo, mrem, ca, cb; + if(MathStructure::gcd(nums[i], divs[i], mquo, eo2, &ca, &cb, false) && !mquo.isOne()) { + if(!mquo.representsNonZero(true) && eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(mquo, eo)) { + nums[i].clear(); + } else { + points[i] = 1; + b_ready_candidate = true; + b = true; + } + if(ca.isOne()) { + if(cb.isOne()) { + nums[i].set(1, 1, 0, true); + } else { + nums[i] = cb; + nums[i].inverse(); + } + } else if(cb.isOne()) { + nums[i] = ca; + } else { + nums[i] = ca; + nums[i].calculateDivide(cb, eo); + } + } else if(!only_gcd && polynomial_long_division(nums[i], divs[i], xvar, mquo, mrem, eo2, false) && !mquo.isZero() && mrem != nums[i]) { + if(mrem.isZero() && !divs[i].representsNonZero(true) && eo.warn_about_denominators_assumed_nonzero && !warn_about_denominators_assumed_nonzero(divs[i], eo)) { + nums[i].clear(); + } else { + long int point = 1; + if(!mrem.isZero()) point = nums[i].size(); + nums[i].set(mquo); + if(!mrem.isZero()) { + if(mquo.isAddition()) point -= mquo.size(); + else point--; + if(mrem.isAddition()) point -= mrem.size(); + else point--; + mrem.calculateDivide(divs[i], eo2); + nums[i].calculateAdd(mrem, eo2); + } + b = true; + points[i] = point; + if(point >= 0) {b_ready_candidate = true;} + else if(b_ready_candidate) nums[i].clear(); + } + } else { + nums[i].clear(); + } + } + } else { + nums[i].clear(); + } + } + + if(!b) return false; + + if(b_ready_candidate) { + // remove polynomial divisions that inrease complexity + for(size_t i = 0; i < nums.size(); i++) { + if(!nums[i].isZero() && points[i] < 0) nums[i].clear(); + } + } else { + // no simplying polynomial division found; see if result can be combined with other terms + b = false; + for(size_t i = 0; i < nums.size(); i++) { + if(!nums[i].isZero()) { + if(b) { + nums[i].clear(); + } else { + long int point = points[i]; + for(size_t i2 = 0; i2 < nums[i].size(); i2++) { + bool b2 = false; + if(!nums[i][i2].contains(divs[i], false, false, false)) { + MathStructure mtest1(mstruct), mtest2(nums[i][i2]); + for(size_t i3 = 0; i3 < mtest1.size(); i3++) { + if(!mtest1[i3].contains(divs[i], false, false, false)) { + int ret = mtest1[i3].merge_addition(mtest2, eo); + if(ret > 0) { + b2 = true; + point++; + if(mtest1[i3].isZero()) point++; + break; + } + if(ret == 0) ret = mtest2.merge_addition(mtest1[i3], eo); + if(ret > 0) { + b2 = true; + point++; + if(mtest2.isZero()) point++; + break; + } + } + } + if(b2) break; + } + if(point >= 0) break; + } + if(point >= 0) b = true; + else nums[i].clear(); + } + } + } + } + + if(!b) return false; + // replace terms with polynomial division result + for(size_t i = 0; i < mstruct.size(); ) { + bool b_del = false; + if(mstruct[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { + if(mstruct[i][i2].isPower() && mstruct[i][i2][0].isAddition() && mstruct[i][i2][1].isMinusOne() && mstruct[i][i2][0].isRationalPolynomial()) { + for(size_t i3 = 0; i3 < divs.size(); i3++) { + if(divs[i3] == mstruct[i][i2][0]) { + b_del = !nums[i3].isZero(); + break; + } + } + break; + } + } + } else if(mstruct[i].isPower() && mstruct[i][0].isAddition() && mstruct[i][1].isMinusOne() && mstruct[i][0].isRationalPolynomial()) { + for(size_t i3 = 0; i3 < divs.size(); i3++) { + if(divs[i3] == mstruct[i][0]) { + b_del = !nums[i3].isZero(); + break; + } + } + } + if(b_del) mstruct.delChild(i + 1); + else i++; + } + for(size_t i = 0; i < nums.size(); ) { + if(nums[i].isZero()) { + nums.delChild(i + 1); + } else { + nums[i].evalSort(); + i++; + } + } + if(mstruct.size() == 0 && nums.size() == 1) { + mstruct.set(nums[0]); + } else { + for(size_t i = 0; i < nums.size(); i++) { + mstruct.addChild(nums[i]); + } + mstruct.evalSort(); + } + return true; +} + diff -Nru libqalculate-3.6.0/libqalculate/MathStructure.h libqalculate-3.7.0/libqalculate/MathStructure.h --- libqalculate-3.6.0/libqalculate/MathStructure.h 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure.h 2020-01-21 22:54:40.000000000 +0000 @@ -392,6 +392,7 @@ /** @name Functions for mathematical functions */ //@{ void setFunction(MathFunction *f); + void setFunctionId(int id); MathFunction *function() const; const MathStructure *functionValue() const; //@} @@ -644,6 +645,7 @@ void transform_nocopy(StructureType mtype, MathStructure *o); void transform(StructureType mtype); void transform(MathFunction *o); + void transformById(int id); void transform(ComparisonType ctype, const MathStructure &o); //@} @@ -816,6 +818,7 @@ int containsType(StructureType mtype, bool structural_only = true, bool check_variables = false, bool check_functions = false) const; int containsRepresentativeOfType(StructureType mtype, bool check_variables = false, bool check_functions = false) const; int containsFunction(MathFunction *f, bool structural_only = true, bool check_variables = false, bool check_functions = false) const; + int containsFunctionId(int id, bool structural_only = true, bool check_variables = false, bool check_functions = false) const; int containsInterval(bool structural_only = true, bool check_variables = false, bool check_functions = false, int ignore_high_precision_interval = 0, bool include_interval_function = false) const; int containsInfinity(bool structural_only = true, bool check_variables = false, bool check_functions = false) const; bool containsOpaqueContents() const; @@ -841,6 +844,7 @@ /** @name Differentiation and integration */ //@{ bool differentiate(const MathStructure &x_var, const EvaluationOptions &eo); + bool integrate(const MathStructure &lower_limit, const MathStructure &upper_limit, const MathStructure &x_var_pre, const EvaluationOptions &eo = default_evaluation_options, bool force_numerical = false, bool simplify_first = true); int integrate(const MathStructure &x_var, const EvaluationOptions &eo, bool simplify_first = true, int use_abs = 1, bool definite_integral = false, bool try_abs = true, int max_part_depth = 5, std::vector *parent_parts = NULL); //@} diff -Nru libqalculate-3.6.0/libqalculate/MathStructure-integrate.cc libqalculate-3.7.0/libqalculate/MathStructure-integrate.cc --- libqalculate-3.6.0/libqalculate/MathStructure-integrate.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure-integrate.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,7759 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "BuiltinFunctions.h" +#include "MathStructure.h" +#include "Calculator.h" +#include "Number.h" +#include "Function.h" +#include "Variable.h" +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +/* Collects x degree, coefficient, degree zero term. By default only one x term (a single exponent) is allowed. +If radunit is true all coefficient must be a multiple of the radian unit. The unit is then removed. Used for trigonometric functions. +If mexp_as_x2 is true, reuire a second degree polynomial and return second degree coefficient in mexp. +If mexp_as_fx is true allow x multipliers of any form (e.g. e^x or sin(x)) and return the the whole x multiplier in mexp. +*/ +bool integrate_info(const MathStructure &mstruct, const MathStructure &x_var, MathStructure &madd, MathStructure &mmul, MathStructure &mexp, bool radunit = false, bool mexp_as_x2 = false, bool mexp_as_fx = false) { + if(radunit && mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[1] == CALCULATOR->getRadUnit()) return integrate_info(mstruct[0], x_var, madd, mmul, mexp, false, mexp_as_x2, mexp_as_fx); + madd.clear(); + if(mexp_as_x2 || mexp_as_fx) mexp = m_zero; + else mexp = m_one; + mmul = m_zero; + if(!mexp_as_fx && mstruct == x_var) { + if(radunit) return false; + mmul = m_one; + return true; + } else if(mexp_as_x2 && mstruct.isPower()) { + if(radunit) return false; + if(mstruct[1].isNumber() && mstruct[1].number().isTwo() && mstruct[0] == x_var) { + mexp = m_one; + return true; + } + } else if(!mexp_as_fx && !mexp_as_x2 && mstruct.isPower() && mstruct[1].containsRepresentativeOf(x_var, true, true) == 0) { + if(radunit) return false; + if(mstruct[0] == x_var) { + mexp = mstruct[1]; + mmul = m_one; + return true; + } + } else if(mstruct.isMultiplication() && mstruct.size() >= 2) { + bool b_x = false; + bool b_rad = false; + bool b2 = false; + size_t i_x = 0, i_rad = 0; + for(size_t i = 0; i < mstruct.size(); i++) { + if(!b_x && !mexp_as_fx && mstruct[i] == x_var) { + b_x = true; + i_x = i; + } else if(!b_x && mexp_as_x2 && mstruct[i].isPower() && mstruct[i][1].isNumber() && mstruct[i][1].number().isTwo() && mstruct[i][0] == x_var) { + b_x = true; + b2 = true; + i_x = i; + } else if(!b_x && !mexp_as_fx && !mexp_as_x2 && mstruct[i].isPower() && mstruct[i][0] == x_var && mstruct[i][1].containsRepresentativeOf(x_var, true, true) == 0) { + b_x = true; + i_x = i; + mexp = mstruct[i][1]; + } else if(mstruct[i].containsRepresentativeOf(x_var, true, true) != 0) { + if(!b_x && mexp_as_fx && (mexp.isZero() || mexp == mstruct[i])) { + mexp = mstruct[i]; + b_x = true; + i_x = i; + } else { + return false; + } + } else if(!b_rad && radunit && mstruct[i] == CALCULATOR->getRadUnit()) { + b_rad = true; + i_rad = i; + } + } + if(!b_x || (radunit && !b_rad)) return false; + if(mstruct.size() == 1 || (radunit && mstruct.size() == 2)) { + if(b2) mexp = m_one; + else mmul = m_one; + } else if(mstruct.size() == 2) { + if(b2) { + if(i_x == 1) mexp = mstruct[0]; + else mexp = mstruct[1]; + } else { + if(i_x == 1) mmul = mstruct[0]; + else mmul = mstruct[1]; + } + } else if(radunit && mstruct.size() == 3) { + if((i_x == 1 && i_rad == 2) || (i_x == 2 && i_rad == 1)) { + if(b2) mexp = mstruct[0]; + else mmul = mstruct[0]; + } else if((i_x == 0 && i_rad == 2) || (i_x == 2 && i_rad == 0)) { + if(b2) mexp = mstruct[1]; + else mmul = mstruct[1]; + } else { + if(b2) mexp = mstruct[2]; + else mmul = mstruct[2]; + } + } else { + if(b2) { + mexp = mstruct; + mexp.delChild(i_x + 1, true); + if(radunit) { + mexp.delChild(i_rad < i_x ? i_rad + 1 : i_rad, true); + } + } else { + mmul = mstruct; + mmul.delChild(i_x + 1, true); + if(radunit) { + mmul.delChild(i_rad < i_x ? i_rad + 1 : i_rad, true); + } + } + } + return true; + } else if(mstruct.isAddition()) { + mmul.setType(STRUCT_ADDITION); + if(mexp_as_x2) mexp.setType(STRUCT_ADDITION); + madd.setType(STRUCT_ADDITION); + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mexp_as_fx && mstruct[i] == x_var) { + if(mexp_as_x2 || mexp.isOne()) mmul.addChild(m_one); + else return false; + } else if(mexp_as_x2 && mstruct[i].isPower() && mstruct[i][1].isNumber() && mstruct[i][1].number().isTwo() && mstruct[i][0] == x_var) { + mexp.addChild(m_one); + } else if(!mexp_as_fx && !mexp_as_x2 && mstruct[i].isPower() && mstruct[i][0] == x_var && mstruct[i][1].containsRepresentativeOf(x_var, true, true) == 0) { + if(mmul.size() == 0) { + mexp = mstruct[i][1]; + } else if(mexp != mstruct[i][1]) { + return false; + } + mmul.addChild(m_one); + } else if(mstruct[i].isMultiplication()) { + bool b_x = false; + bool b_rad = false; + bool b2 = false; + size_t i_x = 0, i_rad = 0; + for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { + if(!b_x && !mexp_as_fx && mstruct[i][i2] == x_var) { + if(!mexp_as_x2 && !mexp.isOne()) return false; + i_x = i2; + b_x = true; + } else if(!b_x && mexp_as_x2 && mstruct[i][i2].isPower() && mstruct[i][i2][1].isNumber() && mstruct[i][i2][1].number().isTwo() && mstruct[i][i2][0] == x_var) { + b2 = true; + i_x = i2; + b_x = true; + } else if(!b_x && !mexp_as_fx && !mexp_as_x2 && mstruct[i][i2].isPower() && mstruct[i][i2][0] == x_var && mstruct[i][i2][1].containsRepresentativeOf(x_var, true, true) == 0) { + if(mmul.size() == 0) { + mexp = mstruct[i][i2][1]; + } else if(mexp != mstruct[i][i2][1]) { + return false; + } + i_x = i2; + b_x = true; + } else if(mstruct[i][i2].containsRepresentativeOf(x_var, true, true) != 0) { + if(!b_x && mexp_as_fx && (mexp.isZero() || mexp == mstruct[i][i2])) { + mexp = mstruct[i][i2]; + i_x = i2; + b_x = true; + } else { + return false; + } + } else if(!b_rad && radunit && mstruct[i][i2] == CALCULATOR->getRadUnit()) { + b_rad = true; + i_rad = i2; + } + } + if(radunit && !b_rad) return false; + if(b_x) { + if(mstruct[i].size() == 1) { + if(b2) mexp.addChild(m_one); + else mmul.addChild(m_one); + } else if(radunit && mstruct[i].size() == 2) { + if(b2) mexp.addChild(m_one); + else mmul.addChild(m_one); + } else { + if(b2) { + mexp.addChild(mstruct[i]); + mexp[mexp.size() - 1].delChild(i_x + 1, true); + if(radunit) mexp[mexp.size() - 1].delChild(i_rad < i_x ? i_rad + 1 : i_rad, true); + mexp.childUpdated(mexp.size()); + } else { + mmul.addChild(mstruct[i]); + mmul[mmul.size() - 1].delChild(i_x + 1, true); + if(radunit) mmul[mmul.size() - 1].delChild(i_rad < i_x ? i_rad + 1 : i_rad, true); + mmul.childUpdated(mmul.size()); + } + } + } else { + madd.addChild(mstruct[i]); + if(radunit) { + madd[madd.size() - 1].delChild(i_rad + 1, true); + } + } + } else if(radunit && mstruct[i] == CALCULATOR->getRadUnit()) { + madd.addChild(mstruct[i]); + } else if(radunit || mstruct[i].containsRepresentativeOf(x_var, true, true) != 0) { + if(!radunit && mexp_as_fx && (mexp.isZero() || mexp == mstruct[i])) { + mexp = mstruct[i]; + mmul.addChild(m_one); + } else { + return false; + } + } else { + madd.addChild(mstruct[i]); + } + } + if(mmul.size() == 0 && (!mexp_as_x2 || mexp.size() == 0)) { + mmul.clear(); + if(mexp_as_x2) mexp.clear(); + return false; + } + if(mmul.size() == 0) mmul.clear(); + else if(mmul.size() == 1) mmul.setToChild(1); + if(mexp_as_x2) { + if(mexp.size() == 0) mexp.clear(); + else if(mexp.size() == 1) mexp.setToChild(1); + } + if(madd.size() == 0) madd.clear(); + else if(madd.size() == 1) madd.setToChild(1); + return true; + } else if(!radunit && mexp_as_fx && mstruct.contains(x_var, true)) { + mexp = mstruct; + mmul = m_one; + return true; + } + return false; +} + +/*bool test_absln_comp_cmplx(const MathStructure &mstruct) { + if(mstruct.number().isComplex() && (!mstruct.number().hasRealPart() || mstruct.number().hasPositiveSign()) && mstruct.number().internalImaginary()->isPositive()) return true; + if(mstruct.isPower() && mstruct[1].isNumber() && mstruct[1].number().numeratorIsOne() && mstruct[0].representsNonComplex(true)) return true; + if(mstruct.isMultiplication()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct[i].representsNonNegative(true)) { + if(!test_absln_comp_cmplx(mstruct[i])) { + return false; + } + } + } + return true; + } else if(mstruct.isAddition()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(!mstruct[i].representsNonNegative(true)) { + if(!test_absln_comp_cmplx(mstruct[i])) { + return false; + } + } + } + return true; + } + return false; +}*/ + +/* Transform mstruct to logarithm (ln(mstruct)). +If use_abs != 0, logarithms of negative numbers are avoided. ln(abs(mstruct)) is used if signedness is unknown and mstruct is not complex. If abs > 0, mstruct is assumed real if it is not possible to determine if mstruct is complex or not. +*/ +bool transform_absln(MathStructure &mstruct, int use_abs, bool definite_integral, const MathStructure &x_var, const EvaluationOptions &eo) { + if(use_abs != 0 && mstruct.representsNonComplex(true)) { + if(mstruct.representsNonPositive(true)) { + mstruct.negate(); + } else if(!mstruct.representsNonNegative(true)) { + mstruct.transformById(FUNCTION_ID_ABS); + } + mstruct.transformById(FUNCTION_ID_LOG); + } else if(use_abs != 0 && !mstruct.representsComplex(true)) { + if(definite_integral) use_abs = -1; + CALCULATOR->beginTemporaryStopMessages(); + MathStructure mtest(mstruct); + EvaluationOptions eo2 = eo; + eo2.expand = true; + eo2.approximation = APPROXIMATION_APPROXIMATE; + eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; + mtest.eval(eo2); + CALCULATOR->endTemporaryStopMessages(); + if(mtest.representsNonComplex(true)) { + if(mstruct.representsNonPositive(true)) { + mstruct.negate(); + } else if(!mtest.representsNonNegative(true)) { + mstruct.transformById(FUNCTION_ID_ABS); + } + mstruct.transformById(FUNCTION_ID_LOG); + } else if(mtest.representsComplex(true)) { + mstruct.transformById(FUNCTION_ID_LOG); + } else { + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + CALCULATOR->beginTemporaryStopMessages(); + KnownVariable *var = new KnownVariable("", format_and_print(x_var), ((UnknownVariable*) x_var.variable())->interval()); + mtest.replace(x_var, var); + mtest.eval(eo2); + CALCULATOR->endTemporaryStopMessages(); + if(mtest.representsNonComplex(true)) { + if(mstruct.representsNonPositive(true)) { + mstruct.negate(); + } else if(!mtest.representsNonNegative(true)) { + mstruct.transformById(FUNCTION_ID_ABS); + } + mstruct.transformById(FUNCTION_ID_LOG); + } else if(use_abs > 0) { + CALCULATOR->error(false, "Integral assumed real", NULL); + mstruct.transformById(FUNCTION_ID_ABS); + mstruct.transformById(FUNCTION_ID_LOG); + } else { + mstruct.transformById(FUNCTION_ID_LOG); + } + var->destroy(); + } else if(use_abs > 0) { + CALCULATOR->error(false, "Integral assumed real", NULL); + mstruct.transformById(FUNCTION_ID_ABS); + mstruct.transformById(FUNCTION_ID_LOG); + } else { + mstruct.transformById(FUNCTION_ID_LOG); + } + } + } else { + mstruct.transformById(FUNCTION_ID_LOG); + } + return true; +} + +// Make sure that m does not contains division by zero. Used after differentiation. +bool check_zero_div(const MathStructure &m, const MathStructure &x_var, const EvaluationOptions &eo, bool top = true) { + if(top && (!x_var.isVariable() || x_var.variable()->isKnown() || ((UnknownVariable*) x_var.variable())->interval().isUndefined())) return true; + if(m.isPower() && m[1].compare(m_zero) == COMPARISON_RESULT_GREATER && m[0].contains(x_var, true) > 0 && COMPARISON_MIGHT_BE_EQUAL(m[0].compare(m_zero))) return false; + for(size_t i = 0; i < m.size(); i++) { + if(!check_zero_div(m[i], x_var, eo)) return false; + } + /*if(m.isFunction() && m.size() == 1 && (m.function()->id() == FUNCTION_ID_TAN || m.function()->id() == FUNCTION_ID_TANH) && m[0].contains(x_var, true) > 0) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + eo2.interval_calculation = INTERVAL_CALCULATION_INTERVAL_ARITHMETIC; + eo2.assume_denominators_nonzero = false; + CALCULATOR->beginTemporaryStopMessages(); + MathStructure mfunc(m); + mfunc.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + bool b = mfunc.calculateFunctions(eo2); + CALCULATOR->endTemporaryStopMessages(); + if(!b) return false; + }*/ + return true; +} + +// 1/(ln(x)+5)=1/(ln(x*e^5)) if x>0 +bool combine_ln(MathStructure &m, const MathStructure &x_var, const EvaluationOptions &eo, int depth = 0) { + if(m.isAddition() && depth > 0 && m.containsFunctionId(FUNCTION_ID_LOG)) { + size_t i_log = 0, i_mul_log = 0; + bool b = false; + MathStructure *mi = NULL; + for(size_t i = 0; i < m.size(); i++) { + if(!b && m[i].isMultiplication() && m[i].containsFunctionId(FUNCTION_ID_LOG) && m[i].contains(x_var, true)) { + for(size_t i2 = 0; i2 < m[i].size(); i2++) { + if(!b && m[i][i2].isFunction() && m[i][i2].function()->id() == FUNCTION_ID_LOG && m[i][i2].size() == 1 && m[i][i2][0].contains(x_var)) { + b = true; + i_log = i; + i_mul_log = i2; + } else if(m[i][i2].containsRepresentativeOf(x_var, true, true) != 0 || !m[i][i2].representsReal(true)) { + b = false; + break; + } + } + if(!b) break; + } else if(!b && m[i].isFunction() && m[i].function()->id() == FUNCTION_ID_LOG && m[i].size() == 1 && m[i][0].contains(x_var)) { + b = true; + i_log = i; + break; + } else if(!mi && m[i].isMultiplication() && m[i].size() == 2 && m[i][1].isVariable() && m[i][1].variable()->id() == VARIABLE_ID_PI && m[i][0].isNumber() && m[i][0].number().hasImaginaryPart() && !m[i][0].number().hasRealPart() && m[i][0].number().internalImaginary()->isReal()) { + mi = &m[i][0]; + } else if(m[i].containsRepresentativeOf(x_var, true, true) != 0 || !m[i].representsReal(true)) { + b = false; + break; + } + } + if(b && ((m[i_log].isMultiplication() && m[i_log][i_mul_log][0].compare(m_zero) == COMPARISON_RESULT_LESS) || (m[i_log].isFunction() && m[i_log][0].compare(m_zero) == COMPARISON_RESULT_LESS))) { + MathStructure mmul(1, 1, 0); + if(mi) mmul = *mi->number().internalImaginary(); + MathStructure *m_e = new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_E)); + MathStructure *mpow = new MathStructure; + mpow->set_nocopy(m); + mpow->delChild(i_log + 1, true); + if(!mmul.isOne()) mpow->calculateDivide(mmul, eo); + m_e->raise_nocopy(mpow); + m_e->calculateRaiseExponent(eo); + m.setToChild(i_log + 1, true); + if(m.isMultiplication()) { + MathStructure *mexp = new MathStructure; + mexp->set_nocopy(m); + mexp->delChild(i_mul_log + 1, true); + if(!mmul.isOne()) mexp->calculateDivide(mmul, eo); + m.setToChild(i_mul_log + 1, true); + m[0].raise_nocopy(mexp); + m[0].calculateRaiseExponent(eo); + } else if(!mmul.isOne()) { + MathStructure *mexp = new MathStructure(mmul); + mexp->calculateInverse(eo); + m[0].raise_nocopy(mexp); + m[0].calculateRaiseExponent(eo); + } + m[0].multiply_nocopy(m_e); + m[0].calculateMultiplyLast(eo); + m.childUpdated(1); + if(!mmul.isOne()) {m.multiply(mmul); m.swapChildren(1, 2);} + return true; + } + } + bool b_ret = false; + for(size_t i = 0; i < m.size(); i++) { + if(combine_ln(m[i], x_var, eo, depth + 1)) { + m.childUpdated(i + 1); + b_ret = true; + } + } + if(b_ret) { + m.calculatesub(eo, eo, false); + } + return b_ret; +} + +/* Determines the integral of mfac * ((mpowmul * mstruct) + mpowadd)^mpow, where mstruct is a function with x_var in argument. +*/ +int integrate_function(MathStructure &mstruct, const MathStructure &x_var, const EvaluationOptions &eo, const MathStructure &mpow, const MathStructure &mfac, const MathStructure &mpowadd, const MathStructure &mpowmul, int use_abs, bool definite_integral, int max_part_depth, vector *parent_parts) { + if(mpow.containsRepresentativeOf(x_var, true, true) != 0) return false; + // mpow != x + if(!mpowadd.isZero() || !mpowmul.isOne()) { + if(!mfac.isOne() || !mpow.isMinusOne()) return false; + // mpowadd != 0, mpowmul != 1, mfac = 1, mpow = -1: 1/((mpowmul*mstruct)+mpowadd) + if((mstruct.function()->id() == FUNCTION_ID_SIN || mstruct.function()->id() == FUNCTION_ID_COS || mstruct.function()->id() == FUNCTION_ID_SINH || mstruct.function()->id() == FUNCTION_ID_COSH || mstruct.function()->id() == FUNCTION_ID_LOG) && mstruct.size() == 1) { + MathStructure mexp, mmul, madd; + if(integrate_info(mstruct[0], x_var, madd, mmul, mexp, (mstruct.function()->id() == FUNCTION_ID_SIN || mstruct.function()->id() == FUNCTION_ID_COS))) { + if(mexp.isOne()) { + bool neg_equals = false; + if((mstruct.function()->id() == FUNCTION_ID_SIN || mstruct.function()->id() == FUNCTION_ID_COS || mstruct.function()->id() == FUNCTION_ID_COSH) && mpowadd != mpowmul) { + MathStructure mpowaddneg(mpowadd); + mpowaddneg.calculateNegate(eo); + neg_equals = (mpowaddneg == mpowmul); + } + if(mstruct.function()->id() == FUNCTION_ID_SIN) { + if(mpowadd == mpowmul || neg_equals) { + //1/(c*sin(ax+b)+c): 2*sin((a x + b)/2)*(sin((a x + b)/2)+cos((a x + b)/2))/(a*(c*sin((a x + b))+c)) + MathStructure mdiv(mstruct); + mstruct[0] *= nr_half; + MathStructure msin(mstruct); + MathStructure mcos(mstruct); + mcos.setFunctionId(FUNCTION_ID_COS); + mstruct *= nr_two; + if(mpowadd != mpowmul) msin.negate(); + msin += mcos; + mstruct *= msin; + mdiv *= mpowmul; + mdiv += mpowadd; + if(!mmul.isOne()) mdiv *= mmul; + mstruct /= mdiv; + return true; + } else { + //1/(d*sin(ax+b)+c): (2 atan((c*tan((a x + b)/2)+d)/sqrt(c^2-d^2)))/(a*sqrt(c^2-d^2)) + if(definite_integral && x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure mtest(mstruct[0]); + mtest[0] /= CALCULATOR->getRadUnit(); + mtest[0] /= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mtest[0] /= nr_two; + mtest[0].transformById(FUNCTION_ID_ABS); + mtest[0].transformById(FUNCTION_ID_FRAC); + if(COMPARISON_MIGHT_BE_EQUAL(mtest.compare(nr_half))) return -1; + } + mstruct.setFunctionId(FUNCTION_ID_TAN); + mstruct[0] *= nr_half; + mstruct *= mpowadd; + mstruct += mpowmul; + MathStructure msqrtc2md2(mpowadd); + if(!mpowadd.isOne()) msqrtc2md2 ^= nr_two; + MathStructure mmpowmul2(mpowmul); + if(!mpowmul.isOne()) mmpowmul2 ^= nr_two; + mmpowmul2.negate(); + msqrtc2md2 += mmpowmul2; + msqrtc2md2 ^= Number(-1, 2, 0); + mstruct *= msqrtc2md2; + mstruct.transformById(FUNCTION_ID_ATAN); + mstruct *= msqrtc2md2; + if(!mmul.isOne()) mstruct /= mmul; + mstruct *= nr_two; + return true; + } + } else if(mstruct.function()->id() == FUNCTION_ID_COS) { + if(mpowadd == mpowmul) { + //1/(c*cos(ax+b)+c): tan((a x + b)/2)/(ac) + mstruct[0] *= nr_half; + mstruct.setFunctionId(FUNCTION_ID_TAN); + if(!mpowadd.isOne()) mstruct /= mpowadd; + if(!mmul.isOne()) mstruct /= mmul; + return true; + } else if(neg_equals) { + //1/(c*cos(ax+b)-c): cos((a x + b)/2)/(ac*sin((a x + b)/2)) + mstruct[0] *= nr_half; + MathStructure msin(mstruct); + msin.setFunctionId(FUNCTION_ID_SIN); + mstruct /= msin; + if(!mpowmul.isOne()) mstruct /= mpowmul; + if(!mmul.isOne()) mstruct /= mmul; + return true; + } else { + //1/(d*cos(ax+b)+c): -(2*atanh(((c-d)*tan((a x + b)/2))/sqrt(d^2-c^2)))/(a*sqrt(d^2-c^2)) + if(definite_integral && x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure mtest(mstruct[0]); + mtest[0] /= CALCULATOR->getRadUnit(); + mtest[0] /= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mtest[0] /= nr_two; + mtest[0].transformById(FUNCTION_ID_ABS); + mtest[0].transformById(FUNCTION_ID_FRAC); + if(COMPARISON_MIGHT_BE_EQUAL(mtest.compare(nr_half))) return -1; + } + mstruct.setFunctionId(FUNCTION_ID_TAN); + mstruct[0] *= nr_half; + mstruct *= mpowadd; + mstruct.last() -= mpowmul; + mstruct.childUpdated(mstruct.size()); + MathStructure msqrtc2md2(mpowadd); + if(!mpowadd.isOne()) msqrtc2md2 ^= nr_two; + msqrtc2md2.negate(); + MathStructure mmpowmul2(mpowmul); + if(!mpowmul.isOne()) mmpowmul2 ^= nr_two; + msqrtc2md2 += mmpowmul2; + msqrtc2md2 ^= Number(-1, 2, 0); + mstruct *= msqrtc2md2; + mstruct.transformById(FUNCTION_ID_ATANH); + mstruct *= msqrtc2md2; + if(!mmul.isOne()) mstruct /= mmul; + mstruct *= Number(-2, 1); + return true; + } + } else if(mstruct.function()->id() == FUNCTION_ID_SINH) { + //1/(d*sinh(ax+b)+c): (2 atan((-c*tan((a x + b)/2)+d)/sqrt(-c^2-d^2)))/(a*sqrt(-c^2-d^2)) + mstruct.setFunctionId(FUNCTION_ID_TANH); + mstruct[0] *= nr_half; + mstruct *= mpowadd; + mstruct.negate(); + mstruct += mpowmul; + MathStructure msqrtc2md2(mpowadd); + if(!mpowadd.isOne()) msqrtc2md2 ^= nr_two; + msqrtc2md2.negate(); + MathStructure mmpowmul2(mpowmul); + if(!mpowmul.isOne()) mmpowmul2 ^= nr_two; + mmpowmul2.negate(); + msqrtc2md2 += mmpowmul2; + msqrtc2md2 ^= Number(-1, 2, 0); + mstruct *= msqrtc2md2; + mstruct.transformById(FUNCTION_ID_ATAN); + mstruct *= msqrtc2md2; + if(!mmul.isOne()) mstruct /= mmul; + mstruct *= nr_two; + return true; + } else if(mstruct.function()->id() == FUNCTION_ID_COSH) { + if(mpowadd == mpowmul) { + //1/(c*cosh(ax+b)+c): tanh((a x + b)/2)/(ac) + mstruct[0] *= nr_half; + mstruct.setFunctionId(FUNCTION_ID_TANH); + if(!mpowadd.isOne()) mstruct /= mpowadd; + if(!mmul.isOne()) mstruct /= mmul; + return true; + } else if(neg_equals) { + //1/(c*cosh(ax+b)-c): -cosh((a x + b)/2)/(ac*sinh((a x + b)/2)) + mstruct[0] *= nr_half; + MathStructure msin(mstruct); + msin.setFunctionId(FUNCTION_ID_SINH); + mstruct.negate(); + mstruct /= msin; + if(!mpowmul.isOne()) mstruct /= mpowmul; + if(!mmul.isOne()) mstruct /= mmul; + return true; + } else { + //1/(d*cos(ax+b)+c): -(2*atan(((c-d)*tanh((a x + b)/2))/sqrt(d^2-c^2)))/(a*sqrt(d^2-c^2)) + mstruct.setFunctionId(FUNCTION_ID_TANH); + mstruct[0] *= nr_half; + mstruct *= mpowadd; + mstruct.last() -= mpowmul; + mstruct.childUpdated(mstruct.size()); + MathStructure msqrtc2md2(mpowadd); + if(!mpowadd.isOne()) msqrtc2md2 ^= nr_two; + msqrtc2md2.negate(); + MathStructure mmpowmul2(mpowmul); + if(!mpowmul.isOne()) mmpowmul2 ^= nr_two; + msqrtc2md2 += mmpowmul2; + msqrtc2md2 ^= Number(-1, 2, 0); + mstruct *= msqrtc2md2; + mstruct.transformById(FUNCTION_ID_ATAN); + mstruct *= msqrtc2md2; + if(!mmul.isOne()) mstruct /= mmul; + mstruct *= Number(-2, 1); + return true; + } + } else if(mstruct.function()->id() == FUNCTION_ID_LOG) { + //1/(d*ln(ax+b)+c): (e^(-c/d)*Ei(c/d+ln(ax+b)))/(a*d) + MathStructure mpadm(mpowadd); + if(!mpowmul.isOne()) mpadm /= mpowmul; + mstruct += mpadm; + mstruct.transformById(FUNCTION_ID_EXPINT); + mpadm.negate(); + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_E); + mstruct.last() ^= mpadm; + mstruct.childUpdated(mstruct.size()); + if(!mmul.isOne()) mstruct /= mmul; + if(!mpowmul.isOne()) mstruct /= mpowmul; + return true; + } + } else if(mstruct.function()->id() == FUNCTION_ID_LOG && madd.isZero()) { + //1/(d*ln(ax^b)+c): (x*(ax^b)^(-1/b)*e^(-c/(bd))*Ei((c+d*ln(ax^b))/(bd)))/(bd) + MathStructure mem(mexp); + if(!mpowmul.isOne()) mem *= mpowmul; + mem.inverse(); + MathStructure marg(mstruct[0]); + mexp.inverse(); + mexp.negate(); + marg ^= mexp; + MathStructure mexpe(CALCULATOR->getVariableById(VARIABLE_ID_E)); + if(!mpowadd.isZero()) { + MathStructure mepow(mpowadd); + mepow.negate(); + mepow *= mem; + mexpe ^= mepow; + } + if(!mpowmul.isOne()) mstruct *= mpowmul; + if(!mpowadd.isZero()) mstruct += mpowadd; + mstruct *= mem; + mstruct.transformById(FUNCTION_ID_EXPINT); + if(!mpowadd.isZero()) mstruct *= mexpe; + mstruct *= marg; + mstruct *= x_var; + mstruct *= mem; + return true; + } + } + } + return false; + } + // mpowadd=0 and mpowmul=1: mfac*mstruct^mpow + + if(mstruct.function()->id() == FUNCTION_ID_LOG && mstruct.size() == 1) { + if(mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(mstruct[0]) && mpow.isOne() && mfac.isOne() && (!definite_integral || COMPARISON_IS_NOT_EQUAL(mstruct[0][0].compare(m_zero)))) { + MathStructure mexp, mmul, madd; + if(integrate_info(mstruct[0][0], x_var, madd, mmul, mexp) && mexp.isOne()) { + if(madd.isZero()) { + if(mmul.isZero()) { + mstruct *= x_var; + mstruct += x_var; + mstruct.last().divide(mstruct[0][1]); + mstruct.childUpdated(mstruct.size()); + mstruct.last().negate(); + return true; + } + MathStructure mterm(mstruct[0]); + mterm ^= nr_two; + mterm *= mstruct[0]; + mterm.inverse(); + if(!mmul.isOne()) mterm *= mmul; + mterm *= x_var; + mterm.last() ^= nr_two; + mterm *= Number(-1, 3); + mstruct *= x_var; + mstruct += mterm; + return true; + } + MathStructure mterm1(x_var); + if(!mmul.isOne()) mterm1 *= mmul; + if(!madd.isOne()) mterm1 /= madd; + mterm1 += m_one; + if(!transform_absln(mterm1, use_abs, definite_integral, x_var, eo)) return -1; + if(!mmul.isOne()) mterm1 /= mmul; + if(!madd.isOne()) mterm1 *= madd; + mterm1 /= mstruct[0][1]; + MathStructure mterm2(x_var); + mterm2 /= mstruct[0][1]; + mstruct *= x_var; + mstruct += mterm1; + mstruct -= mterm2; + return true; + } + } + MathStructure mexp, mmul, madd; + if(integrate_info(mstruct[0], x_var, madd, mmul, mexp, false, false, true) && (mexp == x_var || (mexp.isPower() && mexp[0] == x_var && ((mexp[1] == x_var && madd.isZero() && mpow.isOne() && (!definite_integral || x_var.representsNonNegative(true))) || mexp[1].containsRepresentativeOf(x_var, true, true) == 0)) || (mpow.isOne() && madd.isZero() && mexp.isFunction() && mexp.function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(mexp) && mexp[0] == x_var) || (mpow.isOne() && madd.isZero() && mexp.isPower() && mexp[1].isInteger() && mexp[0].isFunction() && mexp[0].function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(mexp[0]) && mexp[0][0] == x_var))) { + bool b_root = false; + if(mexp == x_var) mexp.set(1, 1, 0); + else if(mexp.isPower() && mexp[0] == x_var) mexp.setToChild(2); + else if(mexp.isPower()) {mexp[0].setToChild(2); mexp[0].number().recip(); mexp[0].number() *= mexp[1].number(); mexp.setToChild(1); b_root = true;} + else {mexp.setToChild(2); mexp.number().recip(); b_root = true;} + bool do_if = false; + // if mstruct[0]=0 for lower or upper limit do if(mstruct[0]=0,0,f(x)) + if(definite_integral && x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure mtest(((UnknownVariable*) x_var.variable())->interval()); + mtest.eval(eo); + if(mtest.isNumber()) { + MathStructure mtest2(mstruct[0]); + mtest2.replace(x_var, mtest.number().lowerEndPoint()); + mtest2.eval(eo); + do_if = (mtest2.isNumber() && !mtest2.number().isNonZero()); + if(!do_if) { + mtest2 = mstruct[0]; + mtest2.replace(x_var, mtest.number().upperEndPoint()); + mtest2.eval(eo); + do_if = (mtest2.isNumber() && !mtest2.number().isNonZero()); + } + } + } + MathStructure mif; + MathStructure marg(mstruct[0]); + bool b = false; + if(mexp == x_var) { + if(mfac.isOne()) { + // ln(x^x): x*ln(x^x)-x^2*(ln(x)*2+1)/4 + mstruct *= x_var; + MathStructure mterm(x_var); + mterm.transformById(FUNCTION_ID_LOG); + mterm *= nr_two; + mterm += m_one; + mterm *= x_var; + mterm.last() ^= nr_two; + mterm *= Number(-1, 4); + mstruct += mterm; + b = true; + } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { + // ln(x^x)*x^a: -x(-(a+2)^2*ln(x^x)+(a+2)(x*ln(x))+(a+1)x)/((a+1)(a+2)^2) + if(mfac == x_var) mexp.set(1, 1, 0); + else mexp = mfac[1]; + MathStructure mexpp1(mexp); + mexpp1 += m_one; + MathStructure mexpp2(mexp); + mexpp2 += nr_two; + MathStructure mterm1(x_var); + mterm1.transformById(FUNCTION_ID_LOG); + mterm1 *= x_var; + mterm1 *= mexpp2; + MathStructure mterm2(x_var); + mterm2 *= mexpp1; + mstruct.negate(); + mexpp2 ^= nr_two; + mstruct *= mexpp2; + mstruct += mterm1; + mstruct += mterm2; + mstruct *= x_var; + mstruct.last() ^= mexpp1; + mexpp2 *= mexpp1; + mstruct /= mexpp2; + mstruct.negate(); + b = true; + } + } else if(mfac.isOne() && (mexp.isOne() || madd.isZero())) { + if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-1)) { + if(mpow.isOne()) { + if(madd.isZero()) { + // ln(ax^b): x(ln(ax^b)-b) + mstruct -= mexp; + mstruct.multiply(x_var); + b = true; + } else { + // ln(ax+b): (ax+b)(ln(ax)-1)/a + MathStructure marg(mstruct[0]); + mstruct *= marg; + mstruct -= marg; + if(!mmul.isOne()) mstruct.divide(mmul); + b = true; + } + } else if(mpow.number().isTwo()) { + // ln(ax+b)^2: (ln(ax+b)^2-2*ln(ax+b)+2)(ax+b)/a + // ln(ax^b)^2: x(ln(ax^b)^2-2*ln(ax^b)*b+2b^2) + MathStructure marg(mstruct[0]); + MathStructure mterm2(mstruct); + mstruct ^= mpow; + mterm2 *= Number(-2, 1); + if(mexp.isOne()) { + mterm2 += nr_two; + } else { + mterm2 *= mexp; + mterm2 += mexp; + mterm2.last() ^= nr_two; + mterm2.last() *= nr_two; + } + mstruct += mterm2; + if(madd.isZero()) { + mstruct.multiply(x_var); + } else { + mstruct *= marg; + if(!mmul.isOne()) mstruct /= mmul; + } + b = true; + } else if(mpow.number().isMinusOne()) { + if(mexp.isOne()) { + // ln(ax+b)^-1: li(ax+b)/a + if(!definite_integral || COMPARISON_IS_NOT_EQUAL(mstruct[0].compare(m_zero))) { + mstruct.setFunctionId(FUNCTION_ID_LOGINT); + if(!mmul.isOne()) mstruct /= mmul; + b = true; + do_if = false; + } + } + } else { + // ln(ax^b)^n: x*sum(ln(ax^b)^i*n!/i!*(-b)^(n-i), 0, n) + // ln(ax+b)^n: (ax+b)/a*sum(ln(ax+b)^i*n!/i!*(-1)^(n-i), 0, n) + unsigned long int n = mpow.number().uintValue(); + MathStructure marg(mstruct[0]); + Number nfac(mpow.number()); + nfac.factorial(); + for(size_t i = 0; i <= n; i++) { + MathStructure mterm(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &marg, NULL); + mterm ^= Number(i); + mterm *= nfac; + Number ifac(i); + ifac.factorial(); + mterm /= ifac; + MathStructure m1pow(mexp); + m1pow.negate(); + m1pow ^= Number(n - i); + mterm *= m1pow; + if(i == 0) mstruct = mterm; + else mstruct += mterm; + } + if(madd.isZero()) { + mstruct.multiply(x_var); + } else { + mstruct *= marg; + if(!mmul.isOne()) mstruct /= mmul; + } + b = true; + } + } + } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { + MathStructure mfacexp(1, 1, 0); + if(mfac != x_var) mfacexp = mfac[1]; + if(mfacexp.isMinusOne()) { + if(mpow.isMinusOne()) { + if(mexp.isOne() && madd.isZero()) { + mstruct.transformById(FUNCTION_ID_LOG); + b = true; + } + } else if(madd.isZero()) { + MathStructure mpowp1(mpow); + mpowp1 += m_one; + mstruct ^= mpowp1; + mstruct /= mpowp1; + if(!mexp.isOne()) mstruct /= mexp; + b = true; + } else if(mpow.isOne()) { + MathStructure m_axcb(x_var); + if(!mexp.isOne()) m_axcb ^= mexp; + if(!mmul.isOne()) m_axcb *= mmul; + if(!madd.isZero()) m_axcb /= madd; + mstruct *= m_axcb; + mstruct.last().negate(); + mstruct.last().transformById(FUNCTION_ID_LOG); + MathStructure mterm2(m_axcb); + mterm2 += m_one; + mterm2.transformById(FUNCTION_ID_POLYLOG); + mterm2.insertChild(nr_two, 1); + mstruct += mterm2; + if(!mexp.isOne()) mstruct /= mexp; + b = true; + } + do_if = do_if && !madd.isZero(); + } else if(madd.isZero()) { + if(mpow.isOne()) { + mfacexp += m_one; + mstruct *= mfacexp; + mstruct -= mexp; + mstruct *= x_var; + mstruct.last() ^= mfacexp; + mfacexp ^= Number(-2, 1); + mstruct *= mfacexp; + mstruct.childrenUpdated(); + b = true; + } else if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100)) { + if(mpow.isMinusOne()) { + if(!definite_integral || COMPARISON_IS_NOT_EQUAL(mstruct[0].compare(m_zero))) { + if(mexp.isOne()) { + MathStructure mmulfac(mmul); + if(!mmul.isOne()) { + mmulfac *= x_var; + mmulfac ^= mfacexp; + mmulfac[1].negate(); + mmulfac *= x_var; + mmulfac.last() ^= mfacexp; + mmulfac.childrenUpdated(true); + } + mfacexp += m_one; + mstruct *= mfacexp; + mstruct.transformById(FUNCTION_ID_EXPINT); + if(!mmul.isOne()) { + mstruct *= mmulfac; + mstruct /= mmul; + } + b = true; + } else { + MathStructure mepow(mstruct); + mfacexp += m_one; + mstruct *= mfacexp; + mstruct /= mexp; + mstruct.transformById(FUNCTION_ID_EXPINT); + mepow.negate(); + mepow += x_var; + mepow.last().transformById(FUNCTION_ID_LOG); + mepow.last() *= mexp; + mepow *= mfacexp; + mepow /= mexp; + MathStructure memul(CALCULATOR->getVariableById(VARIABLE_ID_E)); + memul ^= mepow; + mstruct *= memul; + mstruct /= mexp; + b = true; + } + } + } else if(mpow.number().isNegative()) { + if(mexp.isOne()) { + MathStructure mpowp1(mpow); + mpowp1 += m_one; + MathStructure mpowp1n(mpowp1); + mpowp1n.negate(); + MathStructure mterm(mstruct); + mstruct ^= mpowp1; + mstruct *= x_var; + mstruct.last() ^= mfacexp; + if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + mfacexp += m_one; + mstruct *= mfacexp; + mstruct /= mpowp1n; + mterm ^= mpowp1; + mterm *= x_var; + mterm.last() ^= mfacexp; + mterm /= mpowp1n; + mstruct -= mterm; + mstruct.childrenUpdated(true); + b = true; + } + } else { + MathStructure mterm(mstruct); + mstruct ^= mpow; + mstruct.last() += nr_minus_one; + mstruct *= x_var; + mstruct.last() ^= mfacexp; + if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + mstruct *= mpow; + mfacexp += m_one; + mstruct /= mfacexp; + mstruct.negate(); + mstruct *= mexp; + mterm ^= mpow; + mterm *= x_var; + mterm.last() ^= mfacexp; + mterm /= mfacexp; + mstruct += mterm; + mstruct.childrenUpdated(true); + b = true; + } + } + } else if(mfac == x_var && mexp.isOne()) { + if(mpow.isOne()) { + MathStructure mterm2(x_var); + if(!mmul.isOne()) mterm2 *= mmul; + mterm2 += madd; + mterm2.last() *= Number(-2, 1); + mterm2 *= x_var; + if(!mmul.isOne()) mterm2 /= mmul; + mterm2 *= Number(-1, 4); + MathStructure marg(x_var); + if(!mmul.isOne()) marg *= mmul; + marg += madd; + mstruct *= marg; + marg.last() *= nr_minus_one; + mstruct *= marg; + if(!mmul.isOne()) { + mstruct *= mmul; + mstruct.last() ^= Number(-2, 1); + } + mstruct *= nr_half; + mstruct += mterm2; + mstruct.childrenUpdated(true); + b = true; + if(do_if) mif = mterm2; + } + } + } else if(!b_root && mfac.isFunction() && mfac.function()->id() == FUNCTION_ID_LOG && mfac.size() == 1 && madd.isZero() && mpow.isOne()) { + MathStructure mexp2, mmul2, madd2; + if(integrate_info(mfac[0], x_var, madd2, mmul2, mexp2) && madd2.isZero()) { + MathStructure mterm2(mfac); + mterm2.negate(); + mterm2 += nr_two; + if(!mexp2.isOne()) { + mterm2.last() *= mexp2; + mterm2.childUpdated(mterm2.size()); + } + if(!mexp.isOne()) mterm2 *= mexp; + mstruct *= mfac; + mstruct.last() -= mexp2; + mstruct.childUpdated(mstruct.size()); + mstruct += mterm2; + mstruct *= x_var; + b = true; + } + } + if(b) { + if(do_if) { + mstruct.transformById(FUNCTION_ID_IF); + mstruct.insertChild(mif, 1); + mstruct.insertChild(marg, 1); + mstruct.addChild(m_zero); + mstruct[0].transform(COMPARISON_EQUALS, m_zero); + } + return true; + } + } + } else if(mstruct.function()->id() == FUNCTION_ID_LAMBERT_W && mstruct.size() >= 1) { + if(mfac == x_var && mpow.isOne() && mstruct[0] == x_var) { + MathStructure mthis(mstruct); + mstruct ^= nr_two; + mstruct *= nr_two; + mstruct += nr_one; + mstruct *= mthis; + mstruct.last() *= nr_two; + mstruct.last() += nr_minus_one; + mstruct *= x_var; + mstruct.last() ^= nr_two; + mstruct *= mthis; + mstruct.last() ^= Number(-2, 1); + mstruct *= Number(1, 8); + return true; + } else if(mfac.isPower() && mfac[0] == x_var && mfac[1].isMinusOne() && mpow.isOne() && mstruct[0] == x_var) { + MathStructure mthis(mstruct); + mstruct += nr_two; + mstruct *= mthis; + mstruct *= nr_half; + return true; + } else if((mpow.isOne() || (mpow.isNumber() && mpow.number().isTwo())) && mfac.isOne()) { + MathStructure mexp, mmul, madd; + if(integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { + if(mpow.isOne()) { + MathStructure mthis(mstruct); + mstruct ^= nr_two; + mstruct -= mthis; + mstruct += m_one; + mstruct *= mthis[0]; + mstruct /= mthis; + if(!mmul.isOne()) mstruct /= mmul; + return true; + } else { + MathStructure mthis(mstruct); + mstruct ^= nr_three; + mstruct += mthis; + mstruct.last() ^= nr_two; + mstruct.last() *= Number(-2, 1); + mstruct += mthis; + mstruct.last() *= Number(4, 1); + mstruct += Number(-4, 1); + mstruct *= mthis[0]; + mstruct /= mthis; + if(!mmul.isOne()) mstruct /= mmul; + return true; + } + } + } + return false; + } else if(mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2) { + if(mstruct[0].representsNonComplex(true) && mpow.isNumber() && mpow.number().isRational() && mpow.number().isPositive()) { + MathStructure minteg(x_var); + if(!mfac.isOne()) { + minteg = mfac; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + } + if(!mpow.number().isInteger()) { + MathStructure mmul(-1, 1, 0); + Number nr_frac(mpow.number()); + Number nr_int(mpow.number()); + nr_frac.frac(); + nr_int.trunc(); + mmul ^= nr_frac; + if(nr_int.isEven()) mmul += nr_minus_one; + else mmul += m_one; + mstruct *= mmul; + mstruct -= mmul[0]; + if(nr_int.isEven()) mstruct += nr_minus_one; + else mstruct += m_one; + if(nr_int.isEven()) mstruct.negate(); + mstruct /= nr_two; + } else if(mpow.number().isEven()) { + mstruct ^= nr_two; + mstruct += nr_three; + mstruct *= Number(1, 4); + } + mstruct *= minteg; + return true; + } + } else if(mstruct.function()->id() == FUNCTION_ID_DIRAC && mstruct.size() == 1 && mstruct[0].representsNonComplex(true)) { + MathStructure mexp, mmul, madd; + if(mpow.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { + if(mfac == x_var && madd.representsNonZero()) { + mstruct.setFunctionId(FUNCTION_ID_HEAVISIDE); + if(!mmul.isOne()) { + mmul ^= nr_two; + mstruct /= mmul; + } + mstruct *= madd; + mstruct.negate(); + return true; + } else if(mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0 && madd.representsNonZero()) { + mstruct.setFunctionId(FUNCTION_ID_HEAVISIDE); + madd.negate(); + madd ^= mfac[1]; + mstruct *= madd; + if(mmul.isOne()) { + mexp = mfac[1]; + mexp += m_one; + mexp.negate(); + mmul ^= mexp; + mstruct *= mmul; + } + return true; + } else if(mfac.isOne()) { + mstruct.setFunctionId(FUNCTION_ID_HEAVISIDE); + if(!mmul.isOne()) mstruct /= mmul; + return true; + } + } + return false; + } else if(mstruct.function()->id() == FUNCTION_ID_ARG && mstruct.size() == 1 && mstruct[0].representsNonComplex(true)) { + MathStructure mexp, mmul, madd; + if(mpow.representsPositive() && integrate_info(mstruct[0], x_var, madd, mmul, mexp)) { + MathStructure minteg(x_var); + if(!mfac.isOne()) { + minteg = mfac; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + } + mstruct.setFunctionId(FUNCTION_ID_SIGNUM); + mstruct += nr_minus_one; + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + if(!mpow.isOne()) { + mstruct.last() ^= mpow; + mstruct.childUpdated(mstruct.size()); + } + mstruct *= Number(-1, 2); + mstruct *= minteg; + return true; + } + return false; + } else if(mstruct.function()->id() == FUNCTION_ID_HEAVISIDE && mstruct.size() == 1) { + MathStructure mexp, mmul, madd; + if(mpow.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { + if(mfac.isOne()) { + if(mmul.representsNonNegative()) { + MathStructure mfacn(x_var); + if(!madd.isZero()) { + if(!mmul.isOne()) madd /= mmul; + mfacn += madd; + } + mstruct *= mfacn; + return true; + } else if(mmul.representsNegative()) { + if(madd.isZero()) { + mstruct[0] = x_var; + mstruct *= x_var; + mstruct.negate(); + mstruct += x_var; + return true; + } + mstruct.setToChild(1); + mmul.negate(); + madd.negate(); + mstruct /= mmul; + MathStructure mfacn(x_var); + mfacn *= mmul; + mfacn += madd; + mfacn.transformById(FUNCTION_ID_HEAVISIDE); + mstruct *= mfacn; + mstruct += x_var; + return true; + } + } + } + return false; + } else if(mstruct.function()->id() == FUNCTION_ID_SINC && mstruct.size() == 1) { + MathStructure mexp, mmul, madd; + if(mfac.isOne() && mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-2) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { + if(mpow.isOne()) { + mstruct.setFunctionId(FUNCTION_ID_SININT); + if(!mmul.isOne()) mstruct.divide(mmul); + return true; + } + } + } else if(mstruct.function()->id() == FUNCTION_ID_SIN && mstruct.size() == 1) { + MathStructure mexp, mmul, madd; + if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp, true)) { + if(mfac.isOne()) { + if(mexp.isOne()) { + if(mpow.isOne()) { + mstruct.setFunctionId(FUNCTION_ID_COS); + mstruct.multiply(m_minus_one); + if(!mmul.isOne()) mstruct.divide(mmul); + } else if(mpow.number().isTwo()) { + if(!madd.isZero()) { + mstruct[0] = x_var; + mstruct[0] *= CALCULATOR->getRadUnit(); + } + mstruct[0] *= nr_two; + mstruct /= 4; + if(madd.isZero() && !mmul.isOne()) mstruct /= mmul; + mstruct.negate(); + MathStructure xhalf(x_var); + xhalf *= nr_half; + mstruct += xhalf; + if(!madd.isZero()) { + MathStructure marg(x_var); + if(!mmul.isOne()) marg *= mmul; + marg += madd; + mstruct.replace(x_var, marg); + if(!mmul.isOne()) mstruct.divide(mmul); + } + } else if(mpow.number().isMinusOne()) { + MathStructure mcot(mstruct); + mcot.setFunctionId(FUNCTION_ID_TAN); + mcot.inverse(); + mstruct.inverse(); + mstruct += mcot; + if(!transform_absln(mstruct, use_abs, definite_integral, x_var, eo)) return -1; + if(!mmul.isOne()) mstruct.divide(mmul); + mstruct.negate(); + } else if(mpow.number() == -2) { + mstruct.setFunctionId(FUNCTION_ID_TAN); + mstruct.inverse(); + mstruct.negate(); + if(!mmul.isOne()) mstruct.divide(mmul); + } else if(mpow.number().isPositive()) { + MathStructure mbak(mstruct); + MathStructure nm1(mpow); + nm1 += nr_minus_one; + mstruct ^= nm1; + MathStructure mcos(mbak); + mcos.setFunctionId(FUNCTION_ID_COS); + mstruct *= mcos; + mstruct.negate(); + mmul *= mpow; + mstruct /= mmul; + MathStructure minteg(mbak); + MathStructure nm2(mpow); + nm2 += Number(-2, 1); + minteg ^= nm2; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + minteg *= nm1; + minteg /= mpow; + mstruct += minteg; + } else { + MathStructure mbak(mstruct); + MathStructure np1(mpow); + np1 += m_one; + mstruct ^= np1; + MathStructure mcos(mbak); + mcos.setFunctionId(FUNCTION_ID_COS); + mstruct *= mcos; + mstruct /= np1; + mstruct /= mmul; + MathStructure minteg(mbak); + MathStructure np2(mpow); + np2 += nr_two; + minteg ^= np2; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + minteg *= np2; + minteg /= np1; + mstruct += minteg; + } + return true; + } else if(mexp.isNumber() && mexp.number().isTwo() && madd.isZero() && mpow.isOne()) { + mstruct = nr_two; + mstruct /= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct ^= nr_half; + mstruct *= x_var; + mstruct *= mmul; + mstruct.last() ^= nr_half; + mstruct.transformById(FUNCTION_ID_FRESNEL_S); + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.last() *= nr_half; + mstruct.last() ^= nr_half; + mstruct *= mmul; + mstruct.last() ^= Number(-1, 2); + return true; + } + } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { + MathStructure mfacexp(1, 1, 0); + if(mfac != x_var) mfacexp = mfac[1]; + if(mfacexp.isMinusOne() && !mexp.isZero()) { + if(madd.isZero()) { + if(mpow.isOne()) { + mstruct[0] /= CALCULATOR->getRadUnit(); + mstruct.setFunctionId(FUNCTION_ID_SININT); + if(!mexp.isOne()) mstruct /= mexp; + return true; + } else if(mpow.number().isTwo()) { + mstruct[0] *= nr_two; + mstruct[0] /= CALCULATOR->getRadUnit(); + mstruct.setFunctionId(FUNCTION_ID_COSINT); + if(!mexp.isOne()) mstruct /= mexp; + mstruct.negate(); + mstruct += x_var; + if(!transform_absln(mstruct.last(), use_abs, definite_integral, x_var, eo)) return -1; + mstruct *= nr_half; + return true; + } else if(mpow.number() == 3) { + mstruct[0] /= CALCULATOR->getRadUnit(); + mstruct.setFunctionId(FUNCTION_ID_SININT); + MathStructure mterm2(mstruct); + mstruct[0] *= nr_three; + mterm2 *= Number(-3, 1); + mstruct += mterm2; + if(!mexp.isOne()) mstruct /= mexp; + mstruct *= Number(-1, 4); + return true; + } + } else if(mpow.isOne()) { + MathStructure mterm2; + mstruct = x_var; + if(!mexp.isOne()) mstruct ^= mexp; + if(!mmul.isOne()) mstruct *= mmul; + mstruct.transformById(FUNCTION_ID_SININT); + if(CALCULATOR->getRadUnit()) madd *= CALCULATOR->getRadUnit(); + mstruct *= MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_COS), &madd, NULL); + mterm2 = x_var; + if(!mexp.isOne()) mterm2 ^= mexp; + if(!mmul.isOne()) mterm2 *= mmul; + mterm2.transformById(FUNCTION_ID_COSINT); + mterm2 *= MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SIN), &madd, NULL); + mstruct += mterm2; + if(!mexp.isOne()) mstruct /= mexp; + return true; + } + } else if(mexp.isOne() && mpow.isOne()) { + if(mfacexp.isOne()) { + MathStructure mterm2(mstruct); + mterm2.setFunctionId(FUNCTION_ID_COS); + mterm2 *= x_var; + if(!mmul.isOne()) { + mterm2 /= mmul; + mmul ^= nr_two; + mstruct /= mmul; + } + mstruct -= mterm2; + return true; + } else if(mfacexp.isInteger() && mfacexp.number().isPositive() && mfacexp.number().isLessThan(100)) { + mstruct.setFunctionId(FUNCTION_ID_COS); + MathStructure mterm2(mstruct); + mterm2 *= x_var; + mterm2.last() ^= mfacexp; + mterm2.childUpdated(mterm2.size()); + if(!mmul.isOne()) mterm2 /= mmul; + mstruct *= x_var; + mstruct.last() ^= mfacexp; + mstruct.childUpdated(mstruct.size()); + mstruct.last().last() += nr_minus_one; + if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + mstruct *= mfacexp; + if(!mmul.isOne()) mstruct /= mmul; + mstruct -= mterm2; + return true; + } else if(madd.isZero() && mfacexp.isInteger() && mfacexp.number().isNegative() && mfacexp.number().isGreaterThan(-100)) { + mfacexp += m_one; + MathStructure mterm2(mstruct); + mterm2 *= x_var; + mterm2.last() ^= mfacexp; + mterm2.childUpdated(mterm2.size()); + mterm2 /= mfacexp; + mstruct.setFunctionId(FUNCTION_ID_COS); + mstruct *= x_var; + mstruct.last() ^= mfacexp; + mstruct.childUpdated(mstruct.size()); + if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + mstruct /= mfacexp; + mstruct.negate(); + if(!mmul.isOne()) mstruct *= mmul; + mstruct += mterm2; + return true; + } + } else if(mexp.isOne() && mpow.number().isTwo()) { + if(mfacexp.isOne()) { + MathStructure mterm2(mstruct); + MathStructure mterm3(x_var); + mterm3 ^= nr_two; + mterm3 *= Number(1, 4); + mterm2[0] *= nr_two; + mterm2 *= x_var; + if(!mmul.isOne()) mterm2 /= mmul; + mterm2 *= Number(-1, 4); + mstruct.setFunctionId(FUNCTION_ID_COS); + mstruct[0] *= nr_two; + if(!mmul.isOne()) { + mmul ^= nr_two; + mstruct /= mmul; + } + mstruct *= Number(-1, 8); + mstruct += mterm2; + mstruct += mterm3; + mstruct.childrenUpdated(true); + return true; + } else if(mfacexp.number().isTwo()) { + MathStructure mterm2(mstruct); + MathStructure mterm3(x_var); + mterm3 ^= nr_three; + mterm3 *= Number(1, 6); + mterm2[0] *= nr_two; + MathStructure mterm21(1, 8, 0); + if(!mmul.isOne()) { + mterm21 *= mmul; + mterm21.last() ^= Number(-3, 1); + } + MathStructure mterm22(x_var); + mterm22 ^= 2; + if(!mmul.isOne()) mterm22 /= mmul; + mterm22 *= Number(-1, 4); + mterm21 += mterm22; + mterm2 *= mterm21; + mstruct.setFunctionId(FUNCTION_ID_COS); + mstruct[0] *= nr_two; + mstruct *= x_var; + if(!mmul.isOne()) { + mmul ^= nr_two; + mstruct /= mmul; + } + mstruct *= Number(-1, 4); + mstruct += mterm2; + mstruct += mterm3; + mstruct.childrenUpdated(true); + return true; + } + } + } else if(mexp.isOne() && mfac.isFunction()) { + if(mfac.function()->id() == FUNCTION_ID_SIN && mfac.size() == 1 && mpow.isOne()) { + MathStructure mexpf, mmulf, maddf; + if(integrate_info(mfac[0], x_var, maddf, mmulf, mexpf, true) && mexpf.isOne() && mmul != mmulf) { + MathStructure mterm2(mstruct); + mterm2[0] += mfac[0]; + mstruct[0] -= mfac[0]; + MathStructure mden1(mmul); + mden1 -= mmulf; + mden1 *= nr_two; + MathStructure mden2(mmul); + mden2 += mmulf; + mden2 *= nr_two; + mterm2 /= mden2; + mstruct /= mden1; + mstruct -= mterm2; + return true; + } + } else if(mfac.function()->id() == FUNCTION_ID_COS && mfac.size() == 1) { + if(mstruct[0] == mfac[0]) { + UnknownVariable *var = new UnknownVariable("", format_and_print(mstruct)); + MathStructure mtest(var); + if(!mpow.isOne()) mtest ^= mpow; + CALCULATOR->beginTemporaryStopMessages(); + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(mstruct); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(mstruct); + } + if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mtest.replace(var, mstruct); + var->destroy(); + mstruct = mtest; + if(!mmul.isOne()) mstruct /= mmul; + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } else if(mpow.isOne()) { + MathStructure mexpf, mmulf, maddf; + if(integrate_info(mfac[0], x_var, maddf, mmulf, mexpf, true) && mexpf.isOne()) { + if(mmul != mmulf) { + mstruct.setFunctionId(FUNCTION_ID_COS); + MathStructure mterm2(mstruct); + mterm2[0] += mfac[0]; + mstruct[0] -= mfac[0]; + MathStructure mden1(mmul); + mden1 -= mmulf; + mden1 *= nr_two; + MathStructure mden2(mmul); + mden2 += mmulf; + mden2 *= nr_two; + mterm2 /= mden2; + mstruct /= mden1; + mstruct.negate(); + mstruct -= mterm2; + return true; + } else if(madd == maddf) { + mstruct ^= nr_two; + if(!mmul.isOne()) mstruct /= mmul; + mstruct *= nr_half; + return true; + } else { + MathStructure mterm2(mfac); + mterm2[0].add(mstruct[0]); + mterm2.childUpdated(1); + if(!mmul.isOne()) mterm2 /= mmul; + mterm2 *= Number(-1, 4); + mstruct[0] = maddf; + mstruct[0] -= madd; + mstruct[0] *= CALCULATOR->getRadUnit(); + mstruct.childUpdated(1); + mstruct *= x_var; + mstruct *= Number(-1, 2); + mstruct += mterm2; + return true; + } + } + } + } + } + } + } else if(mstruct.function()->id() == FUNCTION_ID_COS && mstruct.size() == 1) { + MathStructure mexp, mmul, madd; + if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp, true)) { + if(mfac.isOne()) { + if(mexp.isOne()) { + if(mpow.isOne()) { + mstruct.setFunctionId(FUNCTION_ID_SIN); + if(!mmul.isOne()) mstruct.divide(mmul); + } else if(mpow.number().isTwo()) { + mstruct.setFunctionId(FUNCTION_ID_SIN); + if(!madd.isZero()) { + mstruct[0] = x_var; + mstruct[0] *= CALCULATOR->getRadUnit(); + } + mstruct[0] *= nr_two; + mstruct /= 4; + if(madd.isZero() && !mmul.isOne()) mstruct /= mmul; + MathStructure xhalf(x_var); + xhalf *= nr_half; + mstruct += xhalf; + if(!madd.isZero()) { + MathStructure marg(x_var); + if(!mmul.isOne()) marg *= mmul; + marg += madd; + mstruct.replace(x_var, marg); + if(!mmul.isOne()) mstruct.divide(mmul); + } + } else if(mpow.number().isMinusOne()) { + MathStructure mtan(mstruct); + mtan.setFunctionId(FUNCTION_ID_TAN); + mstruct.inverse(); + mstruct += mtan; + if(!transform_absln(mstruct, use_abs, definite_integral, x_var, eo)) return -1; + if(!mmul.isOne()) mstruct.divide(mmul); + } else if(mpow.number() == -2) { + mstruct.setFunctionId(FUNCTION_ID_TAN); + if(!mmul.isOne()) mstruct.divide(mmul); + } else if(mpow.number().isPositive()) { + MathStructure mbak(mstruct); + MathStructure nm1(mpow); + nm1 += nr_minus_one; + mstruct ^= nm1; + MathStructure msin(mbak); + msin.setFunctionId(FUNCTION_ID_SIN); + mstruct *= msin; + mmul *= mpow; + mstruct /= mmul; + MathStructure minteg(mbak); + MathStructure nm2(mpow); + nm2 += Number(-2, 1); + minteg ^= nm2; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + minteg *= nm1; + minteg /= mpow; + mstruct += minteg; + } else { + MathStructure mbak(mstruct); + MathStructure np1(mpow); + np1 += m_one; + mstruct ^= np1; + MathStructure mcos(mbak); + mcos.setFunctionId(FUNCTION_ID_SIN); + mstruct *= mcos; + mstruct /= np1; + mstruct /= mmul; + mstruct.negate(); + MathStructure minteg(mbak); + MathStructure np2(mpow); + np2 += nr_two; + minteg ^= np2; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + minteg *= np2; + minteg /= np1; + mstruct += minteg; + } + return true; + } else if(mexp.isNumber() && mexp.number().isTwo() && madd.isZero() && mpow.isOne()) { + mstruct = nr_two; + mstruct /= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct ^= nr_half; + mstruct *= x_var; + mstruct *= mmul; + mstruct.last() ^= nr_half; + mstruct.transformById(FUNCTION_ID_FRESNEL_C); + mstruct *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct.last() *= nr_half; + mstruct.last() ^= nr_half; + mstruct *= mmul; + mstruct.last() ^= Number(-1, 2); + return true; + } + } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { + MathStructure mfacexp(1, 1, 0); + if(mfac != x_var) mfacexp = mfac[1]; + if(mfacexp.isMinusOne() && !mexp.isZero()) { + if(madd.isZero()) { + if(mpow.isOne()) { + mstruct[0] /= CALCULATOR->getRadUnit(); + mstruct.setFunctionId(FUNCTION_ID_COSINT); + if(!mexp.isOne()) mstruct /= mexp; + return true; + } else if(mpow.number().isTwo()) { + mstruct[0] *= nr_two; + mstruct[0] /= CALCULATOR->getRadUnit(); + mstruct.setFunctionId(FUNCTION_ID_COSINT); + if(!mexp.isOne()) mstruct /= mexp; + mstruct += x_var; + mstruct.last().transformById(FUNCTION_ID_LOG); + mstruct *= nr_half; + return true; + } else if(mpow.number() == 3) { + mstruct[0] /= CALCULATOR->getRadUnit(); + mstruct.setFunctionId(FUNCTION_ID_COSINT); + MathStructure mterm2(mstruct); + mstruct[0] *= nr_three; + mterm2 *= Number(3, 1); + mstruct += mterm2; + if(!mexp.isOne()) mstruct /= mexp; + mstruct *= Number(1, 4); + return true; + } + } else if(mpow.isOne()) { + MathStructure mterm2; + mstruct = x_var; + if(!mexp.isOne()) mstruct ^= mexp; + if(!mmul.isOne()) mstruct *= mmul; + mstruct.transformById(FUNCTION_ID_COSINT); + if(CALCULATOR->getRadUnit()) madd *= CALCULATOR->getRadUnit(); + mstruct *= MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_COS), &madd, NULL); + mterm2 = x_var; + if(!mexp.isOne()) mterm2 ^= mexp; + if(!mmul.isOne()) mterm2 *= mmul; + mterm2.transformById(FUNCTION_ID_SININT); + mterm2 *= MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SIN), &madd, NULL); + mstruct -= mterm2; + if(!mexp.isOne()) mstruct /= mexp; + return true; + } + } else if(mexp.isOne() && mpow.isOne()) { + if(mfacexp.isOne()) { + MathStructure mterm2(mstruct); + mterm2.setFunctionId(FUNCTION_ID_SIN); + mterm2 *= x_var; + if(!mmul.isOne()) { + mterm2 /= mmul; + mmul ^= nr_two; + mstruct /= mmul; + } + mstruct += mterm2; + return true; + } else if(mfacexp.isInteger() && mfacexp.number().isPositive() && mfacexp.number().isLessThan(100)) { + mstruct.setFunctionId(FUNCTION_ID_SIN); + MathStructure mterm2(mstruct); + mterm2 *= x_var; + mterm2.last() ^= mfacexp; + if(!mmul.isOne()) mterm2 /= mmul; + mstruct *= x_var; + mstruct.last() ^= mfacexp; + mstruct.last().last() += nr_minus_one; + if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + mstruct *= mfacexp; + if(!mmul.isOne()) mstruct /= mmul; + mstruct.negate(); + mstruct += mterm2; + mstruct.childrenUpdated(true); + return true; + } else if(madd.isZero() && mfacexp.isInteger() && mfacexp.number().isNegative() && mfacexp.number().isGreaterThan(-100)) { + mfacexp += m_one; + MathStructure mterm2(mstruct); + mterm2 *= x_var; + mterm2.last() ^= mfacexp; + mterm2.childUpdated(mterm2.size()); + mterm2 /= mfacexp; + mstruct.setFunctionId(FUNCTION_ID_SIN); + mstruct *= x_var; + mstruct.last() ^= mfacexp; + mstruct.childUpdated(mstruct.size()); + if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + mstruct /= mfacexp; + if(!mmul.isOne()) mstruct *= mmul; + mstruct += mterm2; + return true; + } + } else if(mexp.isOne() && mpow.number().isTwo()) { + if(mfacexp.isOne()) { + MathStructure mterm2(mstruct); + mterm2.setFunctionId(FUNCTION_ID_SIN); + MathStructure mterm3(x_var); + mterm3 ^= nr_two; + mterm3 *= Number(1, 4); + mterm2[0] *= nr_two; + mterm2 *= x_var; + if(!mmul.isOne()) mterm2 /= mmul; + mterm2 *= Number(1, 4); + mstruct[0] *= nr_two; + if(!mmul.isOne()) { + mmul ^= nr_two; + mstruct /= mmul; + } + mstruct *= Number(1, 8); + mstruct += mterm2; + mstruct += mterm3; + return true; + } else if(mfacexp.number().isTwo()) { + MathStructure mterm2(mstruct); + mterm2.setFunctionId(FUNCTION_ID_SIN); + MathStructure mterm3(x_var); + mterm3 ^= nr_three; + mterm3 *= Number(1, 6); + mterm2[0] *= nr_two; + MathStructure mterm21(-1, 8, 0); + if(!mmul.isOne()) { + mterm21 *= mmul; + mterm21.last() ^= Number(-3, 1); + } + MathStructure mterm22(x_var); + mterm22 ^= 2; + if(!mmul.isOne()) mterm22 /= mmul; + mterm22 *= Number(1, 4); + mterm21 += mterm22; + mterm2 *= mterm21; + mstruct[0] *= nr_two; + mstruct *= x_var; + if(!mmul.isOne()) { + mmul ^= nr_two; + mstruct /= mmul; + } + mstruct *= Number(1, 4); + mstruct += mterm2; + mstruct += mterm3; + mstruct.childrenUpdated(true); + return true; + } + } + } else if(mexp.isOne() && mfac.isFunction()) { + if(mfac.function()->id() == FUNCTION_ID_COS && mfac.size() == 1 && mpow.isOne()) { + MathStructure mexpf, mmulf, maddf; + if(integrate_info(mfac[0], x_var, maddf, mmulf, mexpf, true) && mexpf.isOne() && mmulf != mmul) { + mstruct.setFunctionId(FUNCTION_ID_SIN); + MathStructure mterm2(mstruct); + mterm2[0] += mfac[0]; + mstruct[0] -= mfac[0]; + MathStructure mden1(mmul); + mden1 -= mmulf; + mden1 *= nr_two; + MathStructure mden2(mmul); + mden2 += mmulf; + mden2 *= nr_two; + mterm2 /= mden2; + mstruct /= mden1; + mstruct += mterm2; + mstruct.childrenUpdated(true); + return true; + } + } else if(mfac.function()->id() == FUNCTION_ID_SIN && mfac.size() == 1) { + if(mstruct[0] == mfac[0]) { + UnknownVariable *var = new UnknownVariable("", format_and_print(mstruct)); + MathStructure mtest(var); + if(!mpow.isOne()) mtest ^= mpow; + mtest.negate(); + CALCULATOR->beginTemporaryStopMessages(); + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(mstruct); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(mstruct); + } + if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mtest.replace(var, mstruct); + var->destroy(); + mstruct = mtest; + if(!mmul.isOne()) mstruct /= mmul; + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } + } + } + } + } else if(mstruct.function()->id() == FUNCTION_ID_TAN && mstruct.size() == 1) { + MathStructure mexp, mmul, madd; + if(mfac.isOne() && mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-1) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp, true) && mexp.isOne() && (!definite_integral || mstruct[0].representsNonComplex(true))) { + if(mpow.isOne()) { + mstruct.setFunctionId(FUNCTION_ID_COS); + if(!transform_absln(mstruct, use_abs, definite_integral, x_var, eo)) return -1; + mstruct.negate(); + if(!mmul.isOne()) mstruct.divide(mmul); + } else if(mpow.number().isMinusOne()) { + mstruct.setFunctionId(FUNCTION_ID_SIN); + if(!transform_absln(mstruct, use_abs, definite_integral, x_var, eo)) return -1; + if(!mmul.isOne()) mstruct.divide(mmul); + } else if(mpow.number().isTwo()) { + MathStructure marg(x_var); + if(!mmul.isOne()) marg *= mmul; + marg += madd; + mstruct -= marg; + if(!mmul.isOne()) mstruct.divide(mmul); + } else { + MathStructure minteg(mstruct); + MathStructure nm1(mpow); + nm1 += nr_minus_one; + mstruct ^= nm1; + mmul *= nm1; + mstruct /= mmul; + MathStructure nm2(mpow); + nm2 += Number(-2, 1); + minteg ^= nm2; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + mstruct -= minteg; + } + return true; + } + } else if(mstruct.function()->id() == FUNCTION_ID_ASIN && mstruct.size() == 1) { + MathStructure mexp, mmul, madd; + if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp)) { + if(definite_integral && !madd.isZero() && (!mmul.representsNonComplex(true) || !mexp.representsInteger()) && COMPARISON_MIGHT_BE_EQUAL(x_var.compare(m_zero))) return false; + if(mexp.isOne() && mfac.isOne()) { + if(mpow.isOne()) { + MathStructure marg(mstruct[0]); + if(!madd.isZero()) mstruct[0] = x_var; + mstruct.multiply(x_var); + MathStructure mterm(x_var); + mterm ^= nr_two; + if(madd.isZero() && !mmul.isOne()) { + MathStructure mmul2(mmul); + mmul2 ^= nr_two; + mterm *= mmul2; + } + mterm.negate(); + mterm += m_one; + mterm ^= nr_half; + if(madd.isZero() && !mmul.isOne()) mterm /= mmul; + mstruct.add(mterm); + if(!madd.isZero()) { + mstruct.replace(x_var, marg); + if(!mmul.isOne()) mstruct.divide(mmul); + } + return true; + } else if(mpow.isMinusOne()) { + mstruct.transformById(FUNCTION_ID_COSINT); + if(!mmul.isOne()) mstruct /= mmul; + return true; + } else if(mpow.number() == -2) { + MathStructure mterm(mstruct[0]); + mterm ^= nr_two; + mterm.negate(); + mterm += m_one; + mterm ^= nr_half; + mterm /= mstruct; + mstruct.transformById(FUNCTION_ID_SININT); + mstruct += mterm; + if(!mmul.isOne()) mstruct /= mmul; + mstruct.negate(); + return true; + } else if(mpow.number().isPositive() && madd.isZero()) { + MathStructure mpowm1(mpow); + if(mpow == nr_two) mpowm1.set(1, 1, 0, true); + else mpowm1 += nr_minus_one; + MathStructure mterm(x_var); + mterm ^= nr_two; + if(!mmul.isOne()) { + mterm *= mmul; + mterm.last() ^= nr_two; + } + mterm.negate(); + mterm += m_one; + mterm ^= nr_half; + mterm *= mstruct; + if(!mpowm1.isOne()) mterm.last() ^= mpowm1; + mterm *= mpow; + if(!mmul.isOne()) mterm /= mmul; + MathStructure minteg; + if(mpowm1.isOne()) { + minteg = x_var; + } else { + minteg = mstruct; + minteg ^= mpow; + minteg.last() += Number(-2, 1); + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + } + minteg *= mpow; + if(!mpowm1.isOne()) minteg *= mpowm1; + mstruct ^= mpow; + mstruct *= x_var; + mstruct += mterm; + mstruct -= minteg; + return true; + } else if(madd.isZero()) { + MathStructure mpowp1(mpow); + mpowp1 += m_one; + MathStructure mpowp2(mpow); + mpowp2 += nr_two; + MathStructure mterm(x_var); + mterm ^= nr_two; + if(!mmul.isOne()) { + mterm *= mmul; + mterm.last() ^= nr_two; + } + mterm.negate(); + mterm += m_one; + mterm ^= nr_half; + mterm *= mstruct; + mterm.last() ^= mpowp1; + mterm /= mpowp1; + if(!mmul.isOne()) mterm /= mmul; + MathStructure minteg(mstruct); + minteg ^= mpowp2; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + minteg /= mpowp1; + minteg /= mpowp2; + mstruct ^= mpowp2; + mstruct *= x_var; + mstruct /= mpowp1; + mstruct /= mpowp2; + mstruct += mterm; + mstruct -= minteg; + return true; + } + } else if(mexp.isOne() && (mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0))) { + MathStructure mfacexp(1, 1, 0); + if(mfac != x_var) mfacexp = mfac[1]; + if(mpow.isOne()) { + if(mfacexp.isOne()) { + MathStructure mterm2(mstruct[0]); + mterm2 ^= nr_two; + mterm2.negate(); + mterm2 += m_one; + mterm2 ^= nr_half; + MathStructure mfac2(x_var); + if(!mmul.isOne()) mfac2 *= mmul; + if(!madd.isZero()) { + mfac2 += madd; + mfac2.last() *= Number(-3, 1); + } + mterm2 *= mfac2; + MathStructure mfac1(x_var); + mfac1 ^= nr_two; + if(!mmul.isOne()) { + mfac1 *= mmul; + mfac1.last() ^= nr_two; + } + mfac1 *= nr_two; + if(!madd.isZero()) { + mfac1 += madd; + mfac1.last() ^= nr_two; + mfac1.last() *= Number(-2, 1); + } + mfac1 += nr_minus_one; + mstruct *= mfac1; + mstruct += mterm2; + if(!mmul.isOne()) { + mstruct *= mmul; + mstruct.last() ^= Number(-2, 1); + } + mstruct *= Number(1, 4); + return true; + } else if(mfacexp == nr_two && madd.isZero()) { + mstruct *= x_var; + mstruct.last() ^= nr_three; + mstruct *= Number(1, 3); + MathStructure mterm(x_var); + mterm ^= nr_two; + if(!mmul.isOne()) { + mterm *= mmul; + mterm.last() ^= nr_two; + } + MathStructure mfac1(mterm); + mfac1 += nr_two; + mterm.negate(); + mterm += m_one; + mterm ^= nr_half; + mterm *= mfac1; + if(!mmul.isOne()) { + mmul ^= Number(-3, 1); + mterm *= mmul; + } + mterm *= Number(1, 9); + mstruct += mterm; + return true; + } else if(!mfacexp.isMinusOne() && madd.isZero()) { + mfacexp += m_one; + MathStructure minteg(x_var); + minteg ^= nr_two; + if(!mmul.isOne()) { + minteg *= mmul; + minteg.last() ^= nr_two; + } + minteg.negate(); + minteg += m_one; + minteg ^= Number(-1, 2); + minteg *= x_var; + minteg.last() ^= mfacexp; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + if(minteg.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + if(!mmul.isOne()) minteg *= mmul; + minteg /= mfacexp; + mstruct *= x_var; + mstruct.last() ^= mfacexp; + mstruct /= mfacexp; + mstruct -= minteg; + return true; + } + } + } + } + } + } else if(mstruct.function()->id() == FUNCTION_ID_ACOS && mstruct.size() == 1) { + MathStructure mexp, mmul, madd; + if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp)) { + if(definite_integral && !madd.isZero() && (!mmul.representsNonComplex(true) || !mexp.representsInteger()) && COMPARISON_MIGHT_BE_EQUAL(x_var.compare(m_zero))) return false; + if(mexp.isOne() && mfac.isOne()) { + if(mpow.isOne()) { + MathStructure marg(mstruct[0]); + if(!madd.isZero()) mstruct[0] = x_var; + mstruct.multiply(x_var); + MathStructure mterm(x_var); + mterm ^= nr_two; + if(madd.isZero() && !mmul.isOne()) { + MathStructure mmul2(mmul); + mmul2 ^= nr_two; + mterm *= mmul2; + } + mterm.negate(); + mterm += m_one; + mterm ^= nr_half; + if(madd.isZero() && !mmul.isOne()) mterm /= mmul; + mstruct.subtract(mterm); + if(!madd.isZero()) { + mstruct.replace(x_var, marg); + if(!mmul.isOne()) mstruct.divide(mmul); + } + return true; + } else if(mpow.isMinusOne()) { + mstruct.transformById(FUNCTION_ID_SININT); + mstruct.negate(); + if(!mmul.isOne()) mstruct /= mmul; + return true; + } else if(mpow.number() == -2) { + MathStructure mterm(mstruct[0]); + mterm ^= nr_two; + mterm.negate(); + mterm += m_one; + mterm ^= nr_half; + mterm /= mstruct; + mstruct.transformById(FUNCTION_ID_COSINT); + mstruct.negate(); + mstruct += mterm; + if(!mmul.isOne()) mstruct /= mmul; + return true; + } else if(mpow.number().isPositive() && madd.isZero()) { + MathStructure mpowm1(mpow); + if(mpow == nr_two) mpowm1.set(1, 1, 0, true); + else mpowm1 += nr_minus_one; + MathStructure mterm(x_var); + mterm ^= nr_two; + if(!mmul.isOne()) { + mterm *= mmul; + mterm.last() ^= nr_two; + } + mterm.negate(); + mterm += m_one; + mterm ^= nr_half; + mterm *= mstruct; + if(!mpowm1.isOne()) mterm.last() ^= mpowm1; + mterm *= mpow; + if(!mmul.isOne()) mterm /= mmul; + MathStructure minteg; + if(mpowm1.isOne()) { + minteg = x_var; + } else { + minteg = mstruct; + minteg ^= mpow; + minteg.last() += Number(-2, 1); + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + } + minteg *= mpow; + if(!mpowm1.isOne()) minteg *= mpowm1; + mstruct ^= mpow; + mstruct *= x_var; + mstruct -= mterm; + mstruct -= minteg; + return true; + } else if(madd.isZero()) { + MathStructure mpowp1(mpow); + mpowp1 += m_one; + MathStructure mpowp2(mpow); + mpowp2 += nr_two; + MathStructure mterm(x_var); + mterm ^= nr_two; + if(!mmul.isOne()) { + mterm *= mmul; + mterm.last() ^= nr_two; + } + mterm.negate(); + mterm += m_one; + mterm ^= nr_half; + mterm *= mstruct; + mterm.last() ^= mpowp1; + mterm /= mpowp1; + if(!mmul.isOne()) mterm /= mmul; + MathStructure minteg(mstruct); + minteg ^= mpowp2; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + minteg /= mpowp1; + minteg /= mpowp2; + mstruct ^= mpowp2; + mstruct *= x_var; + mstruct /= mpowp1; + mstruct /= mpowp2; + mstruct -= mterm; + mstruct -= minteg; + return true; + } + } else if(mexp.isOne() && (mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0))) { + MathStructure mfacexp(1, 1, 0); + if(mfac != x_var) mfacexp = mfac[1]; + if(mpow.isOne()) { + if(mfacexp.isOne()) { + MathStructure mterm2(mstruct[0]); + MathStructure mterm3(mstruct); + mterm2 ^= nr_two; + mterm2.negate(); + mterm2 += m_one; + mterm2 ^= nr_half; + MathStructure mfac2(x_var); + if(!mmul.isOne()) { + mfac2 *= mmul; + } + mfac2.negate(); + if(!madd.isZero()) { + mfac2 += madd; + mfac2.last() *= nr_three; + } + mterm2 *= mfac2; + mterm3.setFunctionId(FUNCTION_ID_ASIN); + MathStructure mfac3(1, 1, 0); + if(!madd.isZero()) { + mfac3 += madd; + mfac3.last() ^= nr_two; + mfac3.last() *= nr_two; + } + mterm3 *= mfac3; + mstruct *= x_var; + mstruct.last() ^= nr_two; + if(!mmul.isOne()) { + mstruct *= mmul; + mstruct.last() ^= nr_two; + } + mstruct *= nr_two; + mstruct += mterm2; + mstruct += mterm3; + if(!mmul.isOne()) { + mstruct *= mmul; + mstruct.last() ^= Number(-2, 1); + } + mstruct *= Number(1, 4); + return true; + } else if(mfacexp == nr_two && madd.isZero()) { + mstruct *= x_var; + mstruct.last() ^= nr_three; + mstruct *= Number(1, 3); + MathStructure mterm(x_var); + mterm ^= nr_two; + if(!mmul.isOne()) { + mterm *= mmul; + mterm.last() ^= nr_two; + } + MathStructure mfac1(mterm); + mfac1 += nr_two; + mterm.negate(); + mterm += m_one; + mterm ^= nr_half; + mterm *= mfac1; + if(!mmul.isOne()) { + mmul ^= Number(-3, 1); + mterm *= mmul; + } + mterm *= Number(-1, 9); + mstruct += mterm; + return true; + } else if(!mfacexp.isMinusOne() && madd.isZero()) { + mfacexp += m_one; + MathStructure minteg(x_var); + minteg ^= nr_two; + if(!mmul.isOne()) { + minteg *= mmul; + minteg.last() ^= nr_two; + } + minteg.negate(); + minteg += m_one; + minteg ^= Number(-1, 2); + minteg *= x_var; + minteg.last() ^= mfacexp; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + if(minteg.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + if(!mmul.isOne()) minteg *= mmul; + minteg /= mfacexp; + mstruct *= x_var; + mstruct.last() ^= mfacexp; + mstruct /= mfacexp; + mstruct += minteg; + return true; + } + } + } + } + } + } else if(mstruct.function()->id() == FUNCTION_ID_ATAN && mstruct.size() == 1) { + MathStructure mexp, mmul, madd; + if(mpow.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && (!definite_integral || x_var.representsNonZero(true) || madd.representsReal(true))) { + if(!mexp.isOne()) { + if(mexp.isMinusOne() && mfac.isOne() && madd.isZero()) { + mstruct *= x_var; + MathStructure mterm(x_var); + mterm ^= nr_two; + mterm += mmul; + if(!mmul.isOne()) mterm.last() ^= nr_two; + mterm.transformById(FUNCTION_ID_LOG); + if(!mmul.isOne()) mterm *= mmul; + mterm *= nr_half; + mstruct += mterm; + return true; + } + } else if(mfac.isOne()) { + MathStructure marg(mstruct[0]); + mstruct.multiply(marg); + MathStructure mterm(marg); + mterm ^= nr_two; + mterm += m_one; + if(!transform_absln(mterm, use_abs, definite_integral, x_var, eo)) return -1; + mterm *= Number(-1, 2); + mstruct += mterm; + if(!mmul.isOne()) mstruct.divide(mmul); + return true; + } else if(madd.isZero() && (mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0))) { + MathStructure mfacexp(1, 1, 0); + if(mfac != x_var) mfacexp = mfac[1]; + if(mfacexp.isMinusOne()) { + mstruct.setFunctionId(FUNCTION_ID_POLYLOG); + mstruct.insertChild(nr_two, 1); + MathStructure mterm(mstruct); + mstruct[1] *= nr_minus_i; + mterm[1] *= nr_one_i; + mterm.negate(); + mstruct += mterm; + mstruct *= nr_one_i; + mstruct *= nr_half; + return true; + } else if(mfacexp.isOne()) { + MathStructure mterm1(x_var); + mterm1 ^= nr_two; + mterm1 *= mstruct; + mterm1 *= nr_half; + MathStructure mterm2(x_var); + if(!mmul.isOne()) mterm2 /= mmul; + mterm2 *= nr_minus_half; + if(!mmul.isOne()) {mstruct *= mmul; mstruct.last() ^= Number(-2, 1);} + mstruct *= nr_half; + mstruct += mterm1; + mstruct += mterm2; + return true; + } else { + mfacexp += m_one; + MathStructure mxexp(x_var); + mxexp ^= mfacexp; + MathStructure minteg(x_var); + minteg ^= nr_two; + if(!mmul.isOne()) {minteg *= mmul; minteg.last() ^= nr_two;} + minteg += m_one; + if(!definite_integral || COMPARISON_IS_NOT_EQUAL(minteg.compare(m_zero))) { + minteg ^= nr_minus_one; + minteg *= mxexp; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + minteg /= mfacexp; + if(!mmul.isOne()) minteg *= mmul; + mstruct *= mxexp; + mstruct /= mfacexp; + mstruct -= minteg; + return true; + } + } + } + } + } else if(mstruct.function()->id() == FUNCTION_ID_SINH && mstruct.size() == 1) { + if(mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_LOG && mstruct[0].size() == 1 && (!definite_integral || COMPARISON_IS_NOT_EQUAL(mstruct[0][0].compare(m_zero)))) { + MathStructure mtest(mstruct[0][0]); + mtest *= Number(-2, 1); + mtest.inverse(); + mtest.add(mstruct[0][0]); + mtest.last() *= nr_half; + if(!mpow.isOne()) mtest ^= mpow; + if(!mfac.isOne()) mtest *= mfac; + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mstruct.set(mtest, true); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + } + MathStructure mexp, mmul, madd; + if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp)) { + if(mfac.isOne() && mexp.isOne()) { + if(mpow.isOne()) { + mstruct.setFunctionId(FUNCTION_ID_COSH); + if(!mmul.isOne()) mstruct.divide(mmul); + } else if(mpow.number().isTwo()) { + MathStructure marg(mstruct[0]); + if(!madd.isZero()) mstruct[0] = x_var; + mstruct[0] *= nr_two; + mstruct /= 4; + if(madd.isZero() && !mmul.isOne()) mstruct /= mmul; + MathStructure xhalf(x_var); + xhalf *= nr_half; + mstruct -= xhalf; + if(!madd.isZero()) { + mstruct.replace(x_var, marg); + if(!mmul.isOne()) mstruct.divide(mmul); + } + } else if(mpow.number().isMinusOne()) { + mstruct.setFunctionId(FUNCTION_ID_TANH); + mstruct[0] *= nr_half; + if(!transform_absln(mstruct, use_abs, definite_integral, x_var, eo)) return -1; + if(!mmul.isOne()) mstruct.divide(mmul); + } else if(mpow.number().isPositive()) { + MathStructure mbak(mstruct); + MathStructure nm1(mpow); + nm1 += nr_minus_one; + mstruct ^= nm1; + MathStructure mcos(mbak); + mcos.setFunctionId(FUNCTION_ID_COSH); + mstruct *= mcos; + mmul *= mpow; + mstruct /= mmul; + MathStructure minteg(mbak); + MathStructure nm2(mpow); + nm2 += Number(-2, 1); + minteg ^= nm2; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + minteg *= nm1; + minteg /= mpow; + mstruct -= minteg; + } else { + MathStructure mbak(mstruct); + MathStructure np1(mpow); + np1 += m_one; + MathStructure np2(mpow); + np2 += nr_two; + mstruct ^= np1; + MathStructure mcos(mbak); + mcos.setFunctionId(FUNCTION_ID_COSH); + mstruct *= mcos; + mstruct /= np1; + if(!mmul.isOne()) mstruct /= mmul; + MathStructure minteg(mbak); + minteg ^= np2; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + minteg *= np2; + minteg /= np1; + mstruct -= minteg; + } + return true; + } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { + MathStructure mfacexp(1, 1, 0); + if(mfac != x_var) mfacexp = mfac[1]; + if(mfacexp.isMinusOne() && !mexp.isZero()) { + if(madd.isZero()) { + if(mpow.isOne()) { + mstruct.setFunctionId(FUNCTION_ID_SINHINT); + if(!mexp.isOne()) mstruct /= mexp; + return true; + } else if(mpow.number().isTwo()) { + mstruct[0] *= nr_two; + mstruct.setFunctionId(FUNCTION_ID_COSHINT); + if(!mexp.isOne()) mstruct /= mexp; + mstruct += x_var; + mstruct.last().transformById(FUNCTION_ID_LOG); + mstruct.last().negate(); + mstruct *= nr_half; + return true; + } else if(mpow.number() == 3) { + mstruct.setFunctionId(FUNCTION_ID_SINHINT); + MathStructure mterm2(mstruct); + mstruct[0] *= nr_three; + mterm2 *= Number(-3, 1); + mstruct += mterm2; + if(!mexp.isOne()) mstruct /= mexp; + mstruct *= Number(1, 4); + return true; + } + } else if(mpow.isOne()) { + MathStructure mterm2; + mstruct = x_var; + if(!mexp.isOne()) mstruct ^= mexp; + if(!mmul.isOne()) mstruct *= mmul; + mstruct.transformById(FUNCTION_ID_SINHINT); + mstruct *= MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_COSH), &madd, NULL); + mterm2 = x_var; + if(!mexp.isOne()) mterm2 ^= mexp; + if(!mmul.isOne()) mterm2 *= mmul; + mterm2.transformById(FUNCTION_ID_COSHINT); + mterm2 *= MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SINH), &madd, NULL); + mstruct += mterm2; + if(!mexp.isOne()) mstruct /= mexp; + return true; + } + } else if(mexp.isOne() && mpow.isOne()) { + if(mfacexp.isOne()) { + MathStructure mterm2(mstruct); + mterm2.setFunctionId(FUNCTION_ID_COSH); + mterm2 *= x_var; + if(!mmul.isOne()) { + mterm2 /= mmul; + mmul ^= nr_two; + mstruct /= mmul; + } + mstruct.negate(); + mstruct += mterm2; + return true; + } else if(mfacexp.isInteger() && mfacexp.number().isPositive() && mfacexp.number().isLessThan(100)) { + mstruct.setFunctionId(FUNCTION_ID_COSH); + MathStructure mterm2(mstruct); + mterm2 *= x_var; + mterm2.last() ^= mfacexp; + if(!mmul.isOne()) mterm2 /= mmul; + mstruct *= x_var; + mstruct.last() ^= mfacexp; + mstruct.last().last() += nr_minus_one; + if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + mstruct *= mfacexp; + if(!mmul.isOne()) mstruct /= mmul; + mstruct.negate(); + mstruct += mterm2; + mstruct.childrenUpdated(true); + return true; + } else if(madd.isZero() && mfacexp.isInteger() && mfacexp.number().isNegative() && mfacexp.number().isGreaterThan(-100)) { + mfacexp += m_one; + MathStructure mterm2(mstruct); + mterm2 *= x_var; + mterm2.last() ^= mfacexp; + mterm2.childUpdated(mterm2.size()); + mterm2 /= mfacexp; + mstruct.setFunctionId(FUNCTION_ID_COSH); + mstruct *= x_var; + mstruct.last() ^= mfacexp; + mstruct.childUpdated(mstruct.size()); + if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + mstruct /= mfacexp; + mstruct.negate(); + if(!mmul.isOne()) mstruct *= mmul; + mstruct += mterm2; + return true; + } + } + } else if(mfac.isFunction() && mexp.isOne()) { + if(mfac.function()->id() == FUNCTION_ID_SINH && mfac.size() == 1 && mpow.isOne()) { + MathStructure mexpf, mmulf, maddf; + if(integrate_info(mfac[0], x_var, maddf, mmulf, mexpf) && mexpf.isOne() && mmul != mmulf) { + MathStructure mterm2(mstruct); + mterm2[0] += mfac[0]; + mstruct[0] -= mfac[0]; + MathStructure mden1(mmul); + mden1 -= mmulf; + mden1 *= nr_two; + MathStructure mden2(mmul); + mden2 += mmulf; + mden2 *= nr_two; + mterm2 /= mden2; + mstruct /= mden1; + mstruct.negate(); + mstruct += mterm2; + return true; + } + } else if(mfac.function()->id() == FUNCTION_ID_COSH && mfac.size() == 1) { + if(mstruct[0] == mfac[0]) { + UnknownVariable *var = new UnknownVariable("", format_and_print(mstruct)); + MathStructure mtest(var); + if(!mpow.isOne()) mtest ^= mpow; + CALCULATOR->beginTemporaryStopMessages(); + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(mstruct); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(mstruct); + } + if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mtest.replace(var, mstruct); + var->destroy(); + mstruct = mtest; + if(!mmul.isOne()) mstruct /= mmul; + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } + } + } + } + } else if(mstruct.function()->id() == FUNCTION_ID_COSH && mstruct.size() == 1) { + if(mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_LOG && mstruct[0].size() == 1 && (!definite_integral || COMPARISON_IS_NOT_EQUAL(mstruct[0][0].compare(m_zero)))) { + MathStructure mtest(mstruct[0][0]); + mtest *= nr_two; + mtest.inverse(); + mtest.add(mstruct[0][0]); + mtest.last() *= nr_half; + if(!mpow.isOne()) mtest ^= mpow; + if(!mfac.isOne()) mtest *= mfac; + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mstruct.set(mtest, true); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + } + MathStructure mexp, mmul, madd; + if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp)) { + if(mfac.isOne() && mexp.isOne()) { + if(mpow.isOne()) { + mstruct.setFunctionId(FUNCTION_ID_SINH); + if(!mmul.isOne()) mstruct.divide(mmul); + return true; + } else if(mpow.number().isTwo()) { + MathStructure marg(mstruct[0]); + if(!madd.isZero()) mstruct[0] = x_var; + mstruct.setFunctionId(FUNCTION_ID_SINH); + mstruct[0] *= nr_two; + mstruct /= 4; + if(madd.isZero() && !mmul.isOne()) mstruct /= mmul; + MathStructure xhalf(x_var); + xhalf *= nr_half; + mstruct += xhalf; + if(!madd.isZero()) { + mstruct.replace(x_var, marg); + if(!mmul.isOne()) mstruct.divide(mmul); + } + return true; + } else if(mpow.number().isMinusOne()) { + mstruct.setFunctionId(FUNCTION_ID_SINH); + mstruct.transformById(FUNCTION_ID_ATAN); + if(!mmul.isOne()) mstruct.divide(mmul); + return true; + } else if(mpow.number().isPositive()) { + MathStructure mbak(mstruct); + MathStructure nm1(mpow); + nm1 += nr_minus_one; + mstruct ^= nm1; + MathStructure msin(mbak); + msin.setFunctionId(FUNCTION_ID_SINH); + mstruct *= msin; + mmul *= mpow; + mstruct /= mmul; + MathStructure minteg(mbak); + MathStructure nm2(mpow); + nm2 += Number(-2, 1); + minteg ^= nm2; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + minteg *= nm1; + minteg /= mpow; + mstruct += minteg; + return true; + } else { + MathStructure mbak(mstruct); + MathStructure np1(mpow); + np1 += m_one; + MathStructure np2(mpow); + np2 += nr_two; + mstruct ^= np1; + MathStructure mcos(mbak); + mcos.setFunctionId(FUNCTION_ID_SINH); + mstruct *= mcos; + mstruct /= np1; + if(!mmul.isOne()) mstruct /= mmul; + mstruct.negate(); + MathStructure minteg(mbak); + minteg ^= np2; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + minteg *= np2; + minteg /= np1; + mstruct += minteg; + return true; + } + } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { + MathStructure mfacexp(1, 1, 0); + if(mfac != x_var) mfacexp = mfac[1]; + if(mfacexp.isMinusOne() && !mexp.isZero()) { + if(madd.isZero()) { + if(mpow.isOne()) { + mstruct.setFunctionId(FUNCTION_ID_COSHINT); + if(!mexp.isOne()) mstruct /= mexp; + return true; + } else if(mpow.number().isTwo()) { + mstruct[0] *= nr_two; + mstruct.setFunctionId(FUNCTION_ID_COSHINT); + if(!mexp.isOne()) mstruct /= mexp; + mstruct += x_var; + mstruct.last().transformById(FUNCTION_ID_LOG); + mstruct *= nr_half; + return true; + } else if(mpow.number() == 3) { + mstruct.setFunctionId(FUNCTION_ID_COSHINT); + MathStructure mterm2(mstruct); + mstruct[0] *= nr_three; + mterm2 *= nr_three; + mstruct += mterm2; + if(!mexp.isOne()) mstruct /= mexp; + mstruct *= Number(1, 4); + return true; + } + } else if(mpow.isOne()) { + MathStructure mterm2; + mstruct = x_var; + if(!mexp.isOne()) mstruct ^= mexp; + if(!mmul.isOne()) mstruct *= mmul; + mstruct.transformById(FUNCTION_ID_SINHINT); + mstruct *= MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SINH), &madd, NULL); + mterm2 = x_var; + if(!mexp.isOne()) mterm2 ^= mexp; + if(!mmul.isOne()) mterm2 *= mmul; + mterm2.transformById(FUNCTION_ID_COSHINT); + mterm2 *= MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_COSH), &madd, NULL); + mstruct += mterm2; + if(!mexp.isOne()) mstruct /= mexp; + return true; + } + } else if(mexp.isOne() && mpow.isOne()) { + if(mfacexp.isOne()) { + MathStructure mterm2(mstruct); + mterm2.setFunctionId(FUNCTION_ID_SINH); + mterm2 *= x_var; + if(!mmul.isOne()) { + mterm2 /= mmul; + mmul ^= nr_two; + mstruct /= mmul; + } + mstruct.negate(); + mstruct += mterm2; + return true; + } else if(mfacexp.isInteger() && mfacexp.number().isPositive() && mfacexp.number().isLessThan(100)) { + mstruct.setFunctionId(FUNCTION_ID_SINH); + MathStructure mterm2(mstruct); + mterm2 *= x_var; + mterm2.last() ^= mfacexp; + if(!mmul.isOne()) mterm2 /= mmul; + mstruct *= x_var; + mstruct.last() ^= mfacexp; + mstruct.last().last() += nr_minus_one; + if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + mstruct *= mfacexp; + if(!mmul.isOne()) mstruct /= mmul; + mstruct.negate(); + mstruct += mterm2; + mstruct.childrenUpdated(true); + return true; + } else if(madd.isZero() && mfacexp.isInteger() && mfacexp.number().isNegative() && mfacexp.number().isGreaterThan(-100)) { + mfacexp += m_one; + MathStructure mterm2(mstruct); + mterm2 *= x_var; + mterm2.last() ^= mfacexp; + mterm2.childUpdated(mterm2.size()); + mterm2 /= mfacexp; + mstruct.setFunctionId(FUNCTION_ID_SINH); + mstruct *= x_var; + mstruct.last() ^= mfacexp; + mstruct.childUpdated(mstruct.size()); + if(mstruct.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + mstruct /= mfacexp; + mstruct.negate(); + if(!mmul.isOne()) mstruct *= mmul; + mstruct += mterm2; + return true; + } + } + } else if(mfac.isFunction() && mexp.isOne()) { + if(mfac.function()->id() == FUNCTION_ID_COSH && mfac.size() == 1 && mpow.isOne()) { + MathStructure mexpf, mmulf, maddf; + if(integrate_info(mfac[0], x_var, maddf, mmulf, mexpf) && mexpf.isOne() && mmulf != mmul) { + mstruct.setFunctionId(FUNCTION_ID_SINH); + MathStructure mterm2(mstruct); + mterm2[0] += mfac[0]; + mstruct[0] -= mfac[0]; + MathStructure mden1(mmul); + mden1 -= mmulf; + mden1 *= nr_two; + MathStructure mden2(mmul); + mden2 += mmulf; + mden2 *= nr_two; + mterm2 /= mden2; + mstruct /= mden1; + mstruct += mterm2; + mstruct.childrenUpdated(true); + return true; + } + } else if(mfac.function()->id() == FUNCTION_ID_SINH && mfac.size() == 1) { + if(mstruct[0] == mfac[0]) { + UnknownVariable *var = new UnknownVariable("", format_and_print(mstruct)); + MathStructure mtest(var); + if(!mpow.isOne()) mtest ^= mpow; + CALCULATOR->beginTemporaryStopMessages(); + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(mstruct); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(mstruct); + } + if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mtest.replace(var, mstruct); + var->destroy(); + mstruct = mtest; + if(!mmul.isOne()) mstruct /= mmul; + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } + } + } + } + } else if(mstruct.function()->id() == FUNCTION_ID_TANH && mstruct.size() == 1) { + if(mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_LOG && mstruct[0].size() == 1 && (!definite_integral || COMPARISON_IS_NOT_EQUAL(mstruct[0][0].compare(m_zero)))) { + MathStructure mtest(mstruct[0][0]); + mtest ^= nr_two; + mtest += m_one; + mtest.inverse(); + mtest *= Number(-2, 1); + mtest += m_one; + if(!mpow.isOne()) mtest ^= mpow; + if(!mfac.isOne()) mtest *= mfac; + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mstruct.set(mtest, true); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + } + MathStructure mexp, mmul, madd; + if(mfac.isOne() && mpow.isInteger() && mpow.number().isLessThanOrEqualTo(10) && mpow.number().isGreaterThanOrEqualTo(-1) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne() && (!definite_integral || madd.representsNonComplex(true) || x_var.representsNonZero())) { + if(mpow.isOne()) { + mstruct.setFunctionId(FUNCTION_ID_COSH); + mstruct.transformById(FUNCTION_ID_LOG); + if(!mmul.isOne()) mstruct.divide(mmul); + } else if(mpow.number().isTwo()) { + MathStructure marg(mstruct[0]); + if(!madd.isZero()) mstruct[0] = x_var; + if(madd.isZero() && !mmul.isOne()) mstruct /= mmul; + mstruct.negate(); + mstruct += x_var; + if(!madd.isZero()) { + mstruct.replace(x_var, marg); + if(!mmul.isOne()) mstruct.divide(mmul); + } + } else if(mpow.number().isMinusOne()) { + mstruct.setFunctionId(FUNCTION_ID_SINH); + if(!transform_absln(mstruct, use_abs, definite_integral, x_var, eo)) return -1; + if(!mmul.isOne()) mstruct.divide(mmul); + } else { + MathStructure minteg(mstruct); + MathStructure nm1(mpow); + nm1 += nr_minus_one; + mstruct ^= nm1; + mmul *= nm1; + mstruct /= mmul; + mstruct.negate(); + MathStructure nm2(mpow); + nm2 += Number(-2, 1); + minteg ^= nm2; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + mstruct += minteg; + } + return true; + } + } else if(mstruct.function()->id() == FUNCTION_ID_ASINH && mstruct.size() == 1) { + MathStructure mexp, mmul, madd; + if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { + if(definite_integral && !madd.representsNonComplex(true) && COMPARISON_MIGHT_BE_EQUAL(x_var.compare(m_zero))) return false; + if(mfac.isOne()) { + if(mpow.isOne()) { + MathStructure marg(mstruct[0]); + if(!madd.isZero()) mstruct[0] = x_var; + mstruct.multiply(x_var); + MathStructure mterm(x_var); + mterm ^= nr_two; + if(madd.isZero() && !mmul.isOne()) { + MathStructure mmul2(mmul); + mmul2 ^= nr_two; + mterm *= mmul2; + } + mterm += m_one; + mterm ^= nr_half; + if(madd.isZero() && !mmul.isOne()) mterm /= mmul; + mstruct.subtract(mterm); + if(!madd.isZero()) { + mstruct.replace(x_var, marg); + if(!mmul.isOne()) mstruct.divide(mmul); + } + return true; + } else if(mpow.isMinusOne()) { + mstruct.transformById(FUNCTION_ID_COSHINT); + if(!mmul.isOne()) mstruct /= mmul; + return true; + } else if(mpow.number() == -2) { + MathStructure mterm(mstruct[0]); + mterm ^= nr_two; + mterm += m_one; + mterm ^= nr_half; + mterm /= mstruct; + mstruct.transformById(FUNCTION_ID_SINHINT); + mstruct -= mterm; + if(!mmul.isOne()) mstruct /= mmul; + return true; + } else if(madd.isZero()) { + if(mpow.number().isPositive()) { + MathStructure mpowm1(mpow); + if(mpow == nr_two) mpowm1.set(1, 1, 0, true); + else mpowm1 += nr_minus_one; + MathStructure mterm(mstruct); + if(!mpowm1.isOne()) mterm ^= mpowm1; + MathStructure mfac1(x_var); + mfac1 ^= nr_two; + if(!mmul.isOne()) { + mfac1 *= mmul; + mfac1.last() ^= nr_two; + } + mfac1 += m_one; + mfac1 ^= nr_half; + mterm *= mfac1; + mterm *= mpow; + if(!mmul.isOne()) mterm /= mmul; + MathStructure minteg; + if(mpowm1.isOne()) { + minteg = x_var; + } else { + minteg = mstruct; + minteg ^= mpow; + minteg.last() += Number(-2, 1); + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + } + minteg *= mpow; + if(!mpowm1.isOne()) minteg *= mpowm1; + mstruct ^= mpow; + mstruct *= x_var; + mstruct -= mterm; + mstruct += minteg; + return true; + } else { + MathStructure mpowp1(mpow); + mpowp1 += m_one; + MathStructure mpowp2(mpow); + mpowp2 += nr_two; + MathStructure mterm(mstruct); + mterm ^= mpowp1; + MathStructure mfac1(x_var); + mfac1 ^= nr_two; + if(!mmul.isOne()) { + mfac1 *= mmul; + mfac1.last() ^= nr_two; + } + mfac1 += m_one; + mfac1 ^= nr_half; + mterm *= mfac1; + if(!mmul.isOne()) mterm /= mmul; + mterm /= mpowp1; + MathStructure minteg(mstruct); + minteg ^= mpowp2; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + minteg /= mpowp1; + minteg /= mpowp2; + mstruct ^= mpowp2; + mstruct *= x_var; + mstruct /= mpowp1; + mstruct /= mpowp2; + mstruct.negate(); + mstruct += mterm; + mstruct += minteg; + return true; + } + } + } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { + MathStructure mfacexp(1, 1, 0); + if(mfac != x_var) mfacexp = mfac[1]; + if(mpow.isOne()) { + if(mfacexp.isOne()) { + MathStructure mterm2(mstruct[0]); + mterm2 ^= nr_two; + mterm2 += m_one; + mterm2 ^= nr_half; + MathStructure mfac2(x_var); + if(!mmul.isOne()) mfac2 *= mmul; + mfac2.negate(); + if(!madd.isZero()) { + mfac2 += madd; + mfac2.last() *= nr_three; + } + mterm2 *= mfac2; + MathStructure mfac1(x_var); + mfac1 ^= nr_two; + if(!mmul.isOne()) { + mfac1 *= mmul; + mfac1.last() ^= nr_two; + } + mfac1 *= nr_two; + if(!madd.isZero()) { + mfac1 += madd; + mfac1.last() ^= nr_two; + mfac1.last() *= Number(-2, 1); + } + mfac1 += m_one; + mstruct *= mfac1; + mstruct += mterm2; + if(!mmul.isOne()) { + mstruct *= mmul; + mstruct.last() ^= Number(-2, 1); + } + mstruct *= Number(1, 4); + return true; + } else if(mfacexp == nr_two && madd.isZero()) { + mstruct *= x_var; + mstruct.last() ^= nr_three; + mstruct *= Number(1, 3); + MathStructure mterm(x_var); + mterm ^= nr_two; + if(!mmul.isOne()) { + mterm *= mmul; + mterm.last() ^= nr_two; + } + MathStructure mfac1(mterm); + mfac1 += Number(-2, 1); + mterm += m_one; + mterm ^= nr_half; + mterm *= mfac1; + if(!mmul.isOne()) { + mmul ^= Number(-3, 1); + mterm *= mmul; + } + mterm *= Number(-1, 9); + mstruct += mterm; + return true; + } else if(!mfacexp.isMinusOne() && madd.isZero()) { + mfacexp += m_one; + MathStructure minteg(x_var); + minteg ^= nr_two; + if(!mmul.isOne()) { + minteg *= mmul; + minteg.last() ^= nr_two; + } + minteg += m_one; + minteg ^= Number(-1, 2); + minteg *= x_var; + minteg.last() ^= mfacexp; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + if(minteg.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + if(!mmul.isOne()) minteg *= mmul; + minteg /= mfacexp; + mstruct *= x_var; + mstruct.last() ^= mfacexp; + mstruct /= mfacexp; + mstruct -= minteg; + return true; + } + } + } + } + } + } else if(mstruct.function()->id() == FUNCTION_ID_ACOSH && mstruct.size() == 1) { + MathStructure mexp, mmul, madd; + if(mpow.isInteger() && mpow.number().isLessThanOrEqualTo(100) && mpow.number().isGreaterThanOrEqualTo(-100) && !mpow.isZero() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { + if(definite_integral && (!mmul.representsNonComplex(true) || !x_var.representsNonComplex(true))) return false; + if(mfac.isOne()) { + if(mpow.isOne()) { + MathStructure marg(mstruct[0]); + if(!madd.isZero()) mstruct[0] = x_var; + MathStructure mterm(mstruct[0]); + MathStructure msqrt2(mstruct[0]); + mstruct.multiply(x_var); + mterm += m_one; + mterm ^= nr_half; + msqrt2 += m_minus_one; + msqrt2 ^= nr_half; + mterm *= msqrt2; + if(madd.isZero() && !mmul.isOne()) { + mterm /= mmul; + } + mstruct.subtract(mterm); + if(!madd.isZero()) { + mstruct.replace(x_var, marg); + if(!mmul.isOne()) mstruct.divide(mmul); + } + return true; + } else if(mpow.isMinusOne()) { + mstruct.transformById(FUNCTION_ID_SINHINT); + if(!mmul.isOne()) mstruct /= mmul; + return true; + } else if(mpow.number() == -2) { + MathStructure msqrt(mstruct[0]); + msqrt += m_one; + msqrt.inverse(); + msqrt *= mstruct[0]; + msqrt.last() += nr_minus_one; + msqrt ^= nr_half; + MathStructure macosh(mstruct); + mstruct.transformById(FUNCTION_ID_COSHINT); + mstruct *= macosh; + mstruct *= msqrt; + mstruct += x_var; + if(!mmul.isOne()) mstruct.last() *= mmul; + mstruct.last().negate(); + if(!madd.isZero()) mstruct -= madd; + mstruct += m_one; + mstruct /= macosh; + mstruct /= msqrt; + if(!mmul.isOne()) mstruct /= mmul; + return true; + } else if(madd.isZero()) { + if(mpow.number().isPositive()) { + MathStructure mpowm1(mpow); + if(mpow == nr_two) mpowm1.set(1, 1, 0, true); + else mpowm1 += nr_minus_one; + MathStructure mterm(mstruct); + if(!mpowm1.isOne()) mterm ^= mpowm1; + MathStructure mfac1(x_var); + if(!mmul.isOne()) mfac1 *= mmul; + mfac1 += m_one; + mfac1 ^= nr_half; + MathStructure mfac2(x_var); + if(!mmul.isOne()) mfac2 *= mmul; + mfac2 += nr_minus_one; + mfac2 ^= nr_half; + mterm *= mfac1; + mterm *= mfac2; + mterm *= mpow; + if(!mmul.isOne()) mterm /= mmul; + MathStructure minteg; + if(mpowm1.isOne()) { + minteg = x_var; + } else { + minteg = mstruct; + minteg ^= mpow; + minteg.last() += Number(-2, 1); + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + } + minteg *= mpow; + if(!mpowm1.isOne()) minteg *= mpowm1; + mstruct ^= mpow; + mstruct *= x_var; + mstruct -= mterm; + mstruct += minteg; + return true; + } else { + MathStructure mpowp1(mpow); + mpowp1 += m_one; + MathStructure mpowp2(mpow); + mpowp2 += nr_two; + MathStructure mterm(mstruct); + mterm ^= mpowp1; + MathStructure mfac1(x_var); + if(!mmul.isOne()) mfac1 *= mmul; + mfac1 += m_one; + mfac1 ^= nr_half; + MathStructure mfac2(x_var); + if(!mmul.isOne()) mfac2 *= mmul; + mfac2 += nr_minus_one; + mfac2 ^= nr_half; + mterm *= mfac1; + mterm *= mfac2; + if(!mmul.isOne()) mterm /= mmul; + mterm /= mpowp1; + MathStructure minteg(mstruct); + minteg ^= mpowp2; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + minteg /= mpowp1; + minteg /= mpowp2; + mstruct ^= mpowp2; + mstruct *= x_var; + mstruct /= mpowp1; + mstruct /= mpowp2; + mstruct.negate(); + mstruct += mterm; + mstruct += minteg; + return true; + } + } + } else if(mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].containsRepresentativeOf(x_var, true, true) == 0)) { + MathStructure mfacexp(1, 1, 0); + if(mfac != x_var) mfacexp = mfac[1]; + if(mpow.isOne()) { + if(mfacexp.isOne()) { + MathStructure mterm2(mstruct[0]); + MathStructure mterm2b(mstruct[0]); + mterm2 += nr_minus_one; + mterm2 ^= nr_half; + mterm2b += m_one; + mterm2b ^= nr_half; + mterm2 *= mterm2b; + MathStructure mfac2(x_var); + if(!mmul.isOne()) { + mfac2 *= mmul; + } + mfac2.negate(); + if(!madd.isZero()) { + mfac2 += madd; + mfac2.last() *= nr_three; + } + mterm2 *= mfac2; + MathStructure mfac1(x_var); + mfac1 ^= nr_two; + if(!mmul.isOne()) { + mfac1 *= mmul; + mfac1.last() ^= nr_two; + } + mfac1 *= nr_two; + if(!madd.isZero()) { + mfac1 += madd; + mfac1.last() ^= nr_two; + mfac1.last() *= Number(-2, 1); + } + mfac1 += nr_minus_one; + mstruct *= mfac1; + mstruct += mterm2; + if(!mmul.isOne()) { + mstruct *= mmul; + mstruct.last() ^= Number(-2, 1); + } + mstruct *= Number(1, 4); + return true; + } else if(mfacexp == nr_two && madd.isZero()) { + mstruct *= x_var; + mstruct.last() ^= nr_three; + mstruct *= Number(1, 3); + MathStructure mterm(x_var); + if(!mmul.isOne()) mterm *= mmul; + mterm += m_one; + mterm ^= nr_half; + MathStructure mfac1(x_var); + if(!mmul.isOne()) mfac1 *= mmul; + mfac1 += nr_minus_one; + mfac1 ^= nr_half; + mterm *= mfac1; + MathStructure mfac2(x_var); + mfac2 ^= nr_two; + if(!mmul.isOne()) { + mfac2 *= mmul; + mfac2.last() ^= nr_two; + } + mfac2 += nr_two; + mterm *= mfac2; + if(!mmul.isOne()) { + mmul ^= Number(-3, 1); + mterm *= mmul; + } + mterm *= Number(-1, 9); + mstruct += mterm; + return true; + } else if(!mfacexp.isMinusOne() && madd.isZero()) { + mfacexp += m_one; + MathStructure minteg(x_var); + if(!mmul.isOne()) minteg *= mmul; + minteg += m_one; + minteg ^= Number(-1, 2); + MathStructure mfac1(x_var); + if(!mmul.isOne()) mfac1 *= mmul; + mfac1 += nr_minus_one; + mfac1 ^= Number(-1, 2); + minteg *= mfac1; + minteg *= x_var; + minteg.last() ^= mfacexp; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + if(minteg.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + if(!mmul.isOne()) minteg *= mmul; + minteg /= mfacexp; + mstruct *= x_var; + mstruct.last() ^= mfacexp; + mstruct /= mfacexp; + mstruct -= minteg; + return true; + } + } + } + } + } + } else if(mstruct.function()->id() == FUNCTION_ID_ATANH && mstruct.size() == 1) { + MathStructure mexp, mmul, madd; + if(mpow.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp)) { + if(!mexp.isOne()) { + if(mexp.isMinusOne() && mfac.isOne() && madd.isZero()) { + mstruct *= x_var; + if(madd.isZero()) { + MathStructure mterm(mmul); + if(!mmul.isOne()) mterm ^= nr_two; + mterm.negate(); + mterm += x_var; + mterm.last() ^= nr_two; + mterm.transformById(FUNCTION_ID_LOG); + if(!mmul.isOne()) mterm *= mmul; + mterm *= nr_half; + mstruct += mterm; + } else { + MathStructure mterm1(x_var); + mterm1 *= madd; + mterm1 += mmul; + MathStructure mterm2(mterm1); + mterm1 += x_var; + mterm2 -= x_var; + mterm1.transformById(FUNCTION_ID_LOG); + mterm2.transformById(FUNCTION_ID_LOG); + mterm1 *= mmul; + mterm2 *= mmul; + madd *= nr_two; + madd += nr_two; + mterm1 /= madd; + madd[0].negate(); + mterm2 /= madd; + mstruct += mterm1; + mstruct += mterm2; + } + return true; + } + } else if(mfac.isOne()) { + MathStructure marg(mstruct[0]); + mstruct.multiply(marg); + MathStructure mterm(marg); + mterm ^= nr_two; + mterm.negate(); + mterm += m_one; + mterm.transformById(FUNCTION_ID_LOG); + mterm *= nr_half; + mstruct.add(mterm); + if(!mmul.isOne()) mstruct.divide(mmul); + return true; + } else if(madd.isZero() && (mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].isInteger()))) { + MathStructure mfacexp(1, 1, 0); + if(mfac != x_var) mfacexp = mfac[1]; + if(mfacexp.isMinusOne()) { + mstruct.setFunctionId(FUNCTION_ID_POLYLOG); + mstruct.insertChild(nr_two, 1); + MathStructure mterm(mstruct); + mterm[1].negate(); + mterm.negate(); + mstruct += mterm; + mstruct *= nr_half; + return true; + } else if(mfacexp.isOne()) { + MathStructure mterm1(x_var); + mterm1 ^= nr_two; + mterm1 *= mstruct; + mterm1 *= nr_half; + MathStructure mterm2(x_var); + if(!mmul.isOne()) mterm2 /= mmul; + mterm2 *= nr_half; + if(!mmul.isOne()) {mstruct *= mmul; mstruct.last() ^= Number(-2, 1);} + mstruct *= nr_minus_half; + mstruct += mterm1; + mstruct += mterm2; + return true; + } else { + mfacexp += m_one; + MathStructure mxexp(x_var); + mxexp ^= mfacexp; + MathStructure minteg(x_var); + minteg ^= nr_two; + if(!mmul.isOne()) {minteg *= mmul; minteg.last() ^= nr_two;} + minteg.negate(); + minteg += m_one; + if(!definite_integral || COMPARISON_IS_NOT_EQUAL(minteg.compare(m_zero))) { + minteg ^= nr_minus_one; + minteg *= mxexp; + if(minteg.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) return -1; + minteg /= mfacexp; + if(!mmul.isOne()) minteg *= mmul; + mstruct *= mxexp; + mstruct /= mfacexp; + mstruct -= minteg; + return true; + } + } + } + } + } else if(mstruct.function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(mstruct)) { + MathStructure madd, mmul, mexp; + if(mpow.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { + if(mfac.isOne()) { + MathStructure np1(mstruct[1]); + mstruct.multiply(mstruct[0]); + np1.inverse(); + np1 += m_one; + if(!mmul.isOne()) np1 *= mmul; + mstruct.divide(np1); + return true; + } else if(mfac == x_var) { + MathStructure nm1(mstruct[1]); + nm1.inverse(); + nm1 += m_one; + MathStructure mnum(x_var); + mnum *= nm1; + if(!mmul.isOne()) mnum *= mmul; + if(!madd.isZero()) mnum -= madd; + MathStructure mden(mstruct[1]); + mden.inverse(); + mden += nr_two; + mden *= nm1; + if(!mmul.isOne()) { + mden *= mmul; + mden.last() ^= nr_two; + } + mstruct.multiply(mstruct[0]); + mstruct *= mnum; + mstruct /= mden; + return true; + } + } + } else if(mstruct.function()->id() == FUNCTION_ID_ERFC && mstruct.size() == 1) { + MathStructure mtest(mstruct); + mtest.setFunctionId(FUNCTION_ID_ERF); + mtest.negate(); + mtest += m_one; + if(!mpow.isOne()) mtest ^= mpow; + if(!mfac.isOne()) mtest *= mfac; + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth - 1, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE, true) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mstruct = mtest; + return true; + } + CALCULATOR->endTemporaryStopMessages(); + } else if(mstruct.function()->id() == FUNCTION_ID_ERF && mstruct.size() == 1) { + MathStructure madd, mmul, mexp; + if(mpow.isOne() && mfac.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { + MathStructure mterm2(CALCULATOR->getVariableById(VARIABLE_ID_E)); + mterm2 ^= mstruct[0]; + mterm2.last() ^= nr_two; + mterm2.last().negate(); + mterm2 *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mterm2.last() ^= Number(-1, 2); + if(!mmul.isOne()) mterm2 /= mmul; + if(madd.isZero()) { + mstruct *= x_var; + } else { + mstruct *= madd; + if(!mmul.isOne()) { + mstruct.last() /= mmul; + mstruct.childrenUpdated(); + } + mstruct.last() += x_var; + } + mstruct += mterm2; + return true; + } + } else if(mstruct.function()->id() == FUNCTION_ID_ERFI && mstruct.size() == 1) { + MathStructure madd, mmul, mexp; + if(mpow.isOne() && mfac.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { + MathStructure mterm2(CALCULATOR->getVariableById(VARIABLE_ID_E)); + mterm2 ^= mstruct[0]; + mterm2.last() ^= nr_two; + mterm2 *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mterm2.last() ^= Number(-1, 2); + if(!mmul.isOne()) mterm2 /= mmul; + if(madd.isZero()) { + mstruct *= x_var; + } else { + mstruct *= madd; + if(!mmul.isOne()) { + mstruct.last() /= mmul; + mstruct.childrenUpdated(); + } + mstruct.last() += x_var; + } + mstruct -= mterm2; + return true; + } + } else if(mstruct.function()->id() == FUNCTION_ID_FRESNEL_S && mstruct.size() == 1) { + MathStructure madd, mmul, mexp; + if(mpow.isOne() && mfac.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne() && madd.isOne()) { + MathStructure mterm(x_var); + mterm ^= nr_two; + if(!mmul.isOne()) { + mmul ^= nr_two; + mterm *= mmul; + } + mterm *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mterm *= nr_half; + mterm *= CALCULATOR->getRadUnit(); + mterm.transformById(FUNCTION_ID_COS); + if(!mmul.isOne()) mterm /= mmul; + mterm /= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct *= x_var; + mstruct += mterm; + return true; + } + } else if(mstruct.function()->id() == FUNCTION_ID_FRESNEL_C && mstruct.size() == 1) { + MathStructure madd, mmul, mexp; + if(mpow.isOne() && mfac.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne() && madd.isOne()) { + MathStructure mterm(x_var); + mterm ^= nr_two; + if(!mmul.isOne()) { + mmul ^= nr_two; + mterm *= mmul; + } + mterm *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mterm *= nr_half; + mterm *= CALCULATOR->getRadUnit(); + mterm.transformById(FUNCTION_ID_SIN); + if(!mmul.isOne()) mterm /= mmul; + mterm /= CALCULATOR->getVariableById(VARIABLE_ID_PI); + mstruct *= x_var; + mstruct -= mterm; + return true; + } + } else if(mstruct.function()->id() == FUNCTION_ID_DIGAMMA && mstruct.size() == 1) { + MathStructure madd, mmul, mexp; + if(mpow.isOne() && mfac.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { + mstruct.setFunctionId(FUNCTION_ID_GAMMA); + mstruct.transformById(FUNCTION_ID_LOG); + if(!mmul.isOne()) mstruct /= mmul; + return true; + } + } else if(mstruct.function()->id() == FUNCTION_ID_LOGINT && mstruct.size() == 1) { + MathStructure madd, mmul, mexp; + if(mpow.isOne() && integrate_info(mstruct[0], x_var, madd, mmul, mexp) && mexp.isOne()) { + if(mfac.isOne()) { + MathStructure mEi(mstruct); + mstruct *= mEi[0]; + mEi.setFunctionId(FUNCTION_ID_LOG); + mEi *= nr_two; + mEi.transformById(FUNCTION_ID_EXPINT); + mstruct -= mEi; + if(!mmul.isOne()) mstruct /= mmul; + return true; + } else if(madd.isZero() && mfac.isPower() && mfac[0] == x_var && mfac[1].isMinusOne()) { + MathStructure mln(mstruct); + mln.setFunctionId(FUNCTION_ID_LOG); + mstruct *= mln; + mstruct -= mln[0]; + return true; + } + } + } else if(mstruct.function()->id() == FUNCTION_ID_DIFFERENTIATE && (mstruct.size() == 3 || (mstruct.size() == 4 && mstruct[3].isUndefined())) && mstruct[1] == x_var) { + if(!mpow.isOne() || !mfac.isOne()) return false; + if(mstruct[2].isOne()) { + mstruct.setToChild(1, true); + } else { + mstruct[2] += m_minus_one; + } + return true; + } else if(mstruct.function()->id() == FUNCTION_ID_DIFFERENTIATE && mstruct.size() == 2 && mstruct[1] == x_var) { + if(!mpow.isOne() || !mfac.isOne()) return false; + mstruct.setToChild(1, true); + return true; + } else { + return false; + } + if(mstruct.size() == 0) return false; + bool by_parts_tested = false; + + if(mfac.isOne() && (mstruct.function()->id() == FUNCTION_ID_LOG || mstruct.function()->id() == FUNCTION_ID_ASIN || mstruct.function()->id() == FUNCTION_ID_ACOS || mstruct.function()->id() == FUNCTION_ID_ATAN || mstruct.function()->id() == FUNCTION_ID_ASINH || mstruct.function()->id() == FUNCTION_ID_ACOSH || mstruct.function()->id() == FUNCTION_ID_ATANH)) { + by_parts_tested = true; + //integrate by parts + if(max_part_depth > 0) { + MathStructure minteg(mstruct); + if(!mpow.isOne()) minteg ^= mpow; + CALCULATOR->beginTemporaryStopMessages(); + if(minteg.differentiate(x_var, eo) && minteg.containsFunctionId(FUNCTION_ID_DIFFERENTIATE, true) <= 0 && (!definite_integral || check_zero_div(minteg, x_var, eo))) { + minteg *= x_var; + EvaluationOptions eo2 = eo; + eo2.expand = true; + eo2.combine_divisions = false; + eo2.sync_units = false; + minteg.evalSort(true); + minteg.calculateFunctions(eo); + minteg.calculatesub(eo2, eo2, true); + combine_ln(minteg, x_var, eo2); + do_simplification(minteg, eo2, true, false, false, true, true); + if(minteg.integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth - 1, parent_parts) > 0 && minteg.containsFunctionId(FUNCTION_ID_INTEGRATE, true) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + if(!mpow.isOne()) mstruct ^= mpow; + mstruct.multiply(x_var); + mstruct.subtract(minteg); + return true; + } + } + CALCULATOR->endTemporaryStopMessages(); + } + } + + MathStructure madd, mmul, mexp; + if(integrate_info(mstruct[0], x_var, madd, mmul, mexp, false, false, true) && !mexp.isZero()) { + if(mexp.isPower() && (mexp[1] == x_var || (mexp[1].isMultiplication() && mexp[1].size() >= 2 && mexp[1].last() == x_var)) && mfac.isPower() && (mfac[1] == x_var || (mfac[1].isMultiplication() && mfac[1].size() >= 2 && mfac[1].last() == x_var)) && (mfac[0] == mexp[0] || (mfac[0].isNumber() && mfac[0].number().isRational() && mexp[0].isNumber() && mexp[0].number().isRational() && mexp[1] == mfac[1])) && mexp[0].containsRepresentativeOf(x_var, true, true) == 0) { + Number pow1(1, 1), pow2; + MathStructure morig(mexp); + bool b = true; + if(mfac[1].isMultiplication()) { + if(!mexp[1].isMultiplication()) { + if(mfac[1].size() != 2 || !mfac[1][0].isNumber()) b = false; + else {pow2 = mfac[1][0].number(); pow2--;} + } else { + for(size_t i = 0; i < mexp[1].size() - 1; i++) { + if(i == 0 && mexp[1][i].isNumber()) { + pow1 = mexp[1][i].number(); + } else if(mfac[1][i].containsRepresentativeOf(x_var, true, true) != 0) { + b = false; + break; + } + } + if(b) { + if(mexp[1] == mfac[1]) { + pow1.set(1, 1); + } else if(mfac[1].size() - (mfac[1][0].isNumber() ? 1 : 0) != mexp[1].size() - (mexp[1][0].isNumber() ? 1 : 0)) { + b = false; + } else if(b) { + for(size_t i = 0; i < mfac[1].size() - 1; i++) { + if(i == 0 && mfac[1][i].isNumber()) { + pow2 = mfac[1][i].number(); + pow2--; + } else if(mfac[1][i] != mexp[1][i + (mexp[1][0].isNumber() ? 1 : 0) - (mfac[1][0].isNumber() ? 1 : 0)]) { + b = false; + break; + } + } + } + } + } + } else if(mexp[1].isMultiplication()) { + if(mexp[1].size() != 2 || !mexp[1][0].isNumber()) b = false; + else pow1 = mexp[1][0].number(); + } + if(b && !pow1.isOne()) morig[1].delChild(1, true); + if(b && mfac[0] != mexp[0]) { + bool b1 = mfac[0].number() < mexp[0].number(); + if(mfac[0].number().isFraction() || mexp[0].number().isFraction()) b1 = !b1; + Number nlog(b1 ? mexp[0].number() : mfac[0].number()); + nlog.log(b1 ? mfac[0].number() : mexp[0].number()); + if(!nlog.isInteger()) { + nlog.round(); + b = nlog.isInteger() && (b1 ? ((mfac[0].number() ^ nlog) == mexp[0].number()) : ((mfac[0].number() ^ nlog) == mexp[0].number())); + } + if(b) { + if(b1) { + pow1 = nlog; + morig = mfac; + } else { + pow2 = nlog; + pow2--; + } + } + } + if(b) { + UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(morig) + RIGHT_PARENTHESIS); + MathStructure mtest(var); + if(!pow1.isOne()) mtest ^= pow1; + if(!mmul.isOne()) mtest *= mmul; + if(!madd.isZero()) mtest += madd; + mtest.transform(mstruct.function()); + if(!mpow.isOne()) mtest ^= mpow; + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(morig); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(morig); + } + if(!pow2.isZero()) { + mtest *= var; + if(!pow2.isOne()) mtest.last() ^= pow2; + mtest.swapChildren(1, 2); + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mstruct.set(mtest, true); + mstruct.replace(var, morig); + if(!morig[0].isVariable() || morig[0].variable()->id() != VARIABLE_ID_E) mstruct.divide_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &morig[0], NULL)); + if(morig[1].isMultiplication()) { + morig[1].delChild(morig[1].size(), true); + mstruct /= morig[1]; + } + var->destroy(); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } + } else if(mexp == x_var && !madd.isZero() && (mfac.isOne() || mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].isInteger()))) { + MathStructure morig(x_var); + if(!mmul.isOne()) morig *= mmul; + morig += madd; + UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(morig) + RIGHT_PARENTHESIS); + MathStructure mtest(var); + mtest.transform(mstruct.function()); + if(!mpow.isOne()) mtest ^= mpow; + if(!mfac.isOne()) { + MathStructure mrepl(var); + mrepl -= madd; + mrepl /= mmul; + MathStructure mfacnew(mfac); + mfacnew.replace(x_var, mrepl); + mtest *= mfacnew; + } + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(morig); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(morig); + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mstruct.set(mtest, true); + mstruct.replace(var, morig); + if(!mmul.isOne()) mstruct /= mmul; + var->destroy(); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } else if(mfac.isOne() && (mexp.isPower() && mexp[0] == x_var && mexp[1].isNumber() && !mexp[1].number().isInteger() && mexp[1].number().isRational())) { + Number num(mexp[1].number().numerator()); + Number den(mexp[1].number().denominator()); + if(num.isPositive() || num.isMinusOne()) { + MathStructure morig(x_var); + if(num.isNegative()) den.negate(); + Number den_inv(den); + den_inv.recip(); + morig ^= den_inv; + UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(morig) + RIGHT_PARENTHESIS); + Number den_m1(den); + den_m1--; + MathStructure mtest(var); + if(!num.isOne() && !num.isMinusOne()) mtest ^= num; + if(!mmul.isOne()) mtest *= mmul; + if(!madd.isZero()) mtest += madd; + mtest.transform(mstruct.function()); + if(!mpow.isOne()) mtest ^= mpow; + mtest *= var; + if(!den_m1.isOne()) { + mtest.last() ^= den_m1; + mtest.childUpdated(mtest.size()); + } + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(morig); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(morig); + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mstruct.set(mtest, true); + mstruct.replace(var, morig); + mstruct.multiply(den); + var->destroy(); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } + } else if((mfac.isOne() || mfac == x_var || (mfac.isPower() && mfac[0] == x_var && mfac[1].isInteger())) && (mexp.isPower() && mexp[0] != x_var && mexp[1].isNumber())) { + MathStructure madd2, mmul2, mexp2; + if(integrate_info(mexp[0], x_var, madd2, mmul2, mexp2) && (!madd.isZero() || mexp != x_var) && mexp2.isOne()) { + UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(mexp[0]) + RIGHT_PARENTHESIS); + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(mexp[0]); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(mexp[0]); + } + MathStructure mtest(var); + mtest ^= mexp[1]; + if(!mmul.isOne()) mtest *= mmul; + if(!madd.isZero()) mtest += madd; + mtest.transform(mstruct.function()); + if(!mpow.isOne()) mtest ^= mpow; + if(!mfac.isOne()) { + mtest *= var; + if(!madd2.isZero()) { + mtest.last() -= madd2; + mtest.childUpdated(mtest.size()); + } + if(mfac.isPower()) { + mtest.last() ^= mfac[1]; + mtest.childUpdated(mtest.size()); + } + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mstruct.set(mtest, true); + mstruct.replace(var, mexp[0]); + if(!mmul2.isOne()) { + mstruct /= mmul2; + if(!mfac.isOne()) { + if(mfac.isPower()) mmul2 ^= mfac[1]; + mstruct /= mmul2; + } + } + var->destroy(); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } + } + } + if(mstruct[0].isAddition()) { + bool b = true; + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].containsType(STRUCT_ADDITION, true) == 1) { + b = false; + break; + } + } + if(b) { + MathStructure mtest(mstruct); + if(mtest[0].factorize(eo, false, 0, 0, false, false, NULL, x_var, true, true)) { + if(integrate_function(mtest, x_var, eo, mpow, mfac, mpowadd, mpowmul, use_abs, definite_integral, max_part_depth, parent_parts)) { + mstruct = mtest; + return true; + } + } + } + } + + if(!mfac.isOne()) return false; + MathStructure *m_func = NULL, *m_pow = NULL; + if(mstruct[0].isFunction() && mstruct[0].contains(x_var, true) > 0) { + m_func = &mstruct[0]; + } else if(mstruct[0].isPower() && mstruct[0][0].isFunction() && mstruct[0][0].contains(x_var, true) > 0) { + m_func = &mstruct[0][0]; + } else if(mstruct[0].isPower() && mstruct[0][1].contains(x_var, true) > 0) { + m_pow = &mstruct[0]; + } else if(mstruct[0].isMultiplication()) { + for(size_t i = 0; i < mstruct[0].size(); i++) { + if(mstruct[0][i].isFunction() && mstruct[0][i].contains(x_var, true) > 0) { + m_func = &mstruct[0][i]; + } else if(mstruct[0][i].isPower() && mstruct[0][i][0].isFunction() && mstruct[0][i][0].contains(x_var, true) > 0) { + m_func = &mstruct[0][i][0]; + } else if(mstruct[0][i].isPower() && mstruct[0][i][1].contains(x_var, true) > 0) { + m_pow = &mstruct[0][i]; + } + } + } else if(mstruct[0].isAddition()) { + for(size_t i2 = 0; i2 < mstruct[0].size(); i2++) { + if(mstruct[0][i2].isFunction() && mstruct[0][i2].contains(x_var, true) > 0) { + m_func = &mstruct[0][i2]; + } else if(mstruct[0][i2].isPower() && mstruct[0][i2][0].isFunction() && mstruct[0][i2][0].contains(x_var, true) > 0) { + m_func = &mstruct[0][i2][0]; + } else if(mstruct[0][i2].isPower() && mstruct[0][i2][1].contains(x_var, true) > 0) { + m_pow = &mstruct[0][i2]; + } else if(mstruct[0][i2].isMultiplication()) { + for(size_t i = 0; i < mstruct[0][i2].size(); i++) { + if(mstruct[0][i2][i].isFunction() && mstruct[0][i2][i].contains(x_var, true) > 0) { + m_func = &mstruct[0][i2][i]; + } else if(mstruct[0][i2][i].isPower() && mstruct[0][i2][i][0].isFunction() && mstruct[0][i2][i][0].contains(x_var, true) > 0) { + m_func = &mstruct[0][i2][i][0]; + } else if(mstruct[0][i2][i].isPower() && mstruct[0][i2][i][1].contains(x_var, true) > 0) { + m_pow = &mstruct[0][i2][i]; + } + } + } + } + } + if(m_func && m_pow) return false; + if(m_func) { + if((m_func->function()->id() == FUNCTION_ID_LOG || m_func->function()->id() == FUNCTION_ID_ASIN || m_func->function()->id() == FUNCTION_ID_ACOS || m_func->function()->id() == FUNCTION_ID_ASINH || m_func->function()->id() == FUNCTION_ID_ACOSH) && m_func->size() == 1 && integrate_info((*m_func)[0], x_var, madd, mmul, mexp) && mexp.isOne()) { + MathStructure m_orig(*m_func); + UnknownVariable *var = new UnknownVariable("", format_and_print(m_orig)); + MathStructure mtest(mstruct); + if(!mpow.isOne()) mtest ^= mpow; + mtest[0].replace(m_orig, var, (*m_func)[0].containsInterval()); + if(mtest[0].containsRepresentativeOf(x_var, true, true) == 0) { + if(m_func->function()->id() == FUNCTION_ID_LOG) { + MathStructure m_epow(CALCULATOR->getVariableById(VARIABLE_ID_E)); + m_epow ^= var; + mtest *= m_epow; + } else if(m_func->function()->id() == FUNCTION_ID_ASIN) { + MathStructure m_cos(var); + if(CALCULATOR->getRadUnit()) m_cos *= CALCULATOR->getRadUnit(); + m_cos.transformById(FUNCTION_ID_COS); + mtest *= m_cos; + } else if(m_func->function()->id() == FUNCTION_ID_ACOS) { + MathStructure m_sin(var); + if(CALCULATOR->getRadUnit()) m_sin *= CALCULATOR->getRadUnit(); + m_sin.transformById(FUNCTION_ID_SIN); + mtest *= m_sin; + mmul.negate(); + } else if(m_func->function()->id() == FUNCTION_ID_ASINH) { + MathStructure m_cos(var); + m_cos.transformById(FUNCTION_ID_COSH); + mtest *= m_cos; + } else if(m_func->function()->id() == FUNCTION_ID_ACOSH) { + MathStructure m_sin(var); + m_sin.transformById(FUNCTION_ID_SINH); + mtest *= m_sin; + } + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(m_orig); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(m_orig); + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mstruct.set(mtest, true); + mstruct.replace(var, m_orig); + if(!mmul.isOne()) mstruct /= mmul; + var->destroy(); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + } + var->destroy(); + } + } + if(m_pow) { + if((*m_pow)[0].containsRepresentativeOf(x_var, true, true) == 0 && integrate_info((*m_pow)[1], x_var, madd, mmul, mexp) && mexp.isOne()) { + if(definite_integral && ((*m_pow)[0].compare(m_zero) != COMPARISON_RESULT_LESS)) return false; + MathStructure m_orig(*m_pow); + UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(m_orig) + RIGHT_PARENTHESIS); + MathStructure mtest(mstruct); + mtest[0].replace(m_orig, var, m_pow->containsInterval()); + if(mtest[0].containsRepresentativeOf(x_var, true, true) == 0) { + if(!mpow.isOne()) mtest ^= mpow; + mtest /= var; + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(m_orig); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(m_orig); + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mstruct.set(mtest, true); + mstruct.replace(var, m_orig); + MathStructure m_ln(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &m_orig[0], NULL); + mstruct /= m_ln; + if(!mmul.isOne()) mstruct /= mmul; + var->destroy(); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + } + var->destroy(); + } + } + + if(!by_parts_tested && mstruct.function()->id() != FUNCTION_ID_SIN && mstruct.function()->id() != FUNCTION_ID_COS && mstruct.function()->id() != FUNCTION_ID_TAN && mstruct.function()->id() != FUNCTION_ID_SINH && mstruct.function()->id() != FUNCTION_ID_COSH && mstruct.function()->id() != FUNCTION_ID_TANH) { + //integrate by parts + if(max_part_depth > 0) { + MathStructure minteg(mstruct); + if(!mpow.isOne()) minteg ^= mpow; + CALCULATOR->beginTemporaryStopMessages(); + if(minteg.differentiate(x_var, eo) && minteg.containsFunctionId(FUNCTION_ID_DIFFERENTIATE, true) <= 0 && (!definite_integral || check_zero_div(minteg, x_var, eo))) { + minteg *= x_var; + EvaluationOptions eo2 = eo; + eo2.expand = true; + eo2.combine_divisions = false; + eo2.sync_units = false; + minteg.evalSort(true); + minteg.calculateFunctions(eo); + minteg.calculatesub(eo2, eo2, true); + combine_ln(minteg, x_var, eo2); + do_simplification(minteg, eo2, true, false, false, true, true); + if(minteg.integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth - 1, parent_parts) > 0 && minteg.containsFunctionId(FUNCTION_ID_INTEGRATE, true) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + if(!mpow.isOne()) mstruct ^= mpow; + mstruct.multiply(x_var); + mstruct.subtract(minteg); + return true; + } + } + CALCULATOR->endTemporaryStopMessages(); + } + } + return false; +} + +#define CANNOT_INTEGRATE {MathStructure minteg(CALCULATOR->getFunctionById(FUNCTION_ID_INTEGRATE), this, &m_undefined, &m_undefined, &x_var, &m_zero, NULL); set(minteg); return false;} +#define CANNOT_INTEGRATE_INTERVAL {MathStructure minteg(CALCULATOR->getFunctionById(FUNCTION_ID_INTEGRATE), this, &m_undefined, &m_undefined, &x_var, &m_zero, NULL); set(minteg); return -1;} + +int contains_unsolved_integrate(const MathStructure &mstruct, MathStructure *this_mstruct, vector *parent_parts) { + if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_INTEGRATE) { + if(this_mstruct->equals(mstruct[0], true)) return 3; + for(size_t i = 0; i < parent_parts->size(); i++) { + if(mstruct[0].equals(*(*parent_parts)[i], true)) return 2; + } + return 1; + } + int ret = 0; + for(size_t i = 0; i < mstruct.size(); i++) { + int ret_i = contains_unsolved_integrate(mstruct[i], this_mstruct, parent_parts); + if(ret_i == 1) { + return 1; + } else if(ret_i > ret) { + ret = ret_i; + } + } + return ret; +} + +// remove abs() when possible +bool fix_abs_x(MathStructure &mstruct, const MathStructure &x_var, const EvaluationOptions &eo, bool definite_integral) { + bool b = false; + if(mstruct.isFunction() && mstruct.size() == 1 && mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ABS && mstruct[0].size() == 1) { + if(!definite_integral && (mstruct.function()->id() == FUNCTION_ID_SIN || mstruct.function()->id() == FUNCTION_ID_TAN || mstruct.function()->id() == FUNCTION_ID_SINH || mstruct.function()->id() == FUNCTION_ID_TANH || mstruct.function()->id() == FUNCTION_ID_ASIN || mstruct.function()->id() == FUNCTION_ID_ATAN || mstruct.function()->id() == FUNCTION_ID_ASINH || mstruct.function()->id() == FUNCTION_ID_ATANH) && mstruct[0][0].representsNonComplex(true)) { + // sin(abs(f(x)))=sgn(f(x))*sin(f(x)) if not f(x) is complex + mstruct[0].setToChild(1, true); + mstruct.multiply_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SIGNUM), &mstruct[0], &m_zero, NULL)); + mstruct.evalSort(false); + b = true; + } else if((mstruct.function()->id() == FUNCTION_ID_COS || mstruct.function()->id() == FUNCTION_ID_COSH) && mstruct[0][0].representsNonComplex(true)) { + // cos(abs(f(x)))=cos(f(x)) if not f(x) is complex + mstruct[0].setToChild(1, true); + b = true; + } else if(mstruct.function()->id() == FUNCTION_ID_LOG) { + // ln(abs(f(x)))=ln(f(x)^2)/2 if not f(x) is complex + if(mstruct[0][0].representsNonComplex(true)) { + b = true; + } else { + MathStructure mtest(mstruct[0][0]); + transform_absln(mtest, -1, false, x_var, eo); + b = !mtest.isFunction() || mtest.function()->id() != FUNCTION_ID_LOG || (mtest.size() >= 0 && mtest[0].isFunction() && mtest[0].function()->id() == FUNCTION_ID_ABS); + } + if(b) { + mstruct[0].setToChild(1, true); + mstruct[0] ^= nr_two; + mstruct /= nr_two; + } + } + } + for(size_t i = 0; i < mstruct.size(); i++) { + if(fix_abs_x(mstruct[i], x_var, eo, definite_integral)) b = true; + } + return b; +} + +MathStructure *find_abs_x2(MathStructure &mstruct, const MathStructure &x_var, const MathStructure *parent = NULL, int level = 0) { + if(mstruct.isFunction()) { + if(((mstruct.function()->id() == FUNCTION_ID_ABS && mstruct.size() == 1) || (mstruct.function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(mstruct) && mstruct[1].number().isOdd())) && mstruct[0].contains(x_var, true) > 0 && mstruct[0].representsNonComplex(true)) { + return &mstruct[0]; + } + if((!parent || parent->isMultiplication() || parent->isAddition()) && level <= 2 && mstruct.function()->id() == FUNCTION_ID_LOG && mstruct.size() == 1) { + if((mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ROOT) || (mstruct[0].isPower() && mstruct[0][1].isInteger() && mstruct[0][0].isFunction() && mstruct[0][0].function()->id() == FUNCTION_ID_ROOT)) return NULL; + if(mstruct[0].isMultiplication() && mstruct[0].size() == 2 && ((mstruct[0][1].isFunction() && mstruct[0][1].function()->id() == FUNCTION_ID_ROOT) || (mstruct[0][1].isPower() && mstruct[0][1][1].isInteger() && mstruct[0][1][0].isFunction() && mstruct[0][1][0].function()->id() == FUNCTION_ID_ROOT))) return NULL; + } + } + for(size_t i = 0; i < mstruct.size(); i++) { + MathStructure *m = find_abs_x2(mstruct[i], x_var, &mstruct, level + 1); + if(m) return m; + } + return NULL; +} +bool fix_sgn_x(MathStructure &mstruct, const MathStructure &x_var, const EvaluationOptions &eo) { + if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2) { + MathStructure mtest(mstruct); + KnownVariable *var = new KnownVariable("", format_and_print(x_var), ((UnknownVariable*) x_var.variable())->interval()); + mtest.replace(x_var, var); + CALCULATOR->beginTemporaryStopMessages(); + mtest.eval(eo); + var->destroy(); + if(!CALCULATOR->endTemporaryStopMessages() && !mtest.isFunction()) { + mstruct.set(mtest); + return true; + } + } + bool b = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(fix_sgn_x(mstruct[i], x_var, eo)) b = true; + } + return b; +} +bool replace_abs_x(MathStructure &mstruct, const MathStructure &marg, bool b_minus, const MathStructure *parent = NULL, int level = 0) { + if(mstruct.isFunction()) { + if(mstruct.function()->id() == FUNCTION_ID_ABS && mstruct.size() == 1 && mstruct[0].equals(marg, true)) { + mstruct.setToChild(1); + if(b_minus) mstruct.negate(); + return true; + } else if(mstruct.function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(mstruct) && mstruct[1].number().isOdd() && mstruct[0].equals(marg, true)) { + if(b_minus) mstruct[0].negate(); + mstruct[1].number().recip(); + mstruct.setType(STRUCT_POWER); + mstruct.childrenUpdated(); + if(b_minus) mstruct.negate(); + return true; + } + if((!parent || parent->isMultiplication() || parent->isAddition()) && level <= 2 && mstruct.function()->id() == FUNCTION_ID_LOG && mstruct.size() == 1) { + if((mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ROOT) || (mstruct[0].isPower() && mstruct[0][1].isInteger() && mstruct[0][0].isFunction() && mstruct[0][0].function()->id() == FUNCTION_ID_ROOT)) return false; + if(mstruct[0].isMultiplication() && mstruct[0].size() == 2 && ((mstruct[0][1].isFunction() && mstruct[0][1].function()->id() == FUNCTION_ID_ROOT) || (mstruct[0][1].isPower() && mstruct[0][1][1].isInteger() && mstruct[0][1][0].isFunction() && mstruct[0][1][0].function()->id() == FUNCTION_ID_ROOT))) return false; + } + } + if(mstruct.isPower() && mstruct[1].isInteger() && mstruct[1].number().isOdd() && mstruct[0].isFunction() && mstruct[0].function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(mstruct[0]) && mstruct[0][1].number().isOdd() && mstruct[0][0].equals(marg, true)) { + mstruct[1].number().divide(mstruct[0][1].number()); + mstruct[0].setToChild(1, true); + if(mstruct[1].number().isOne()) mstruct.setToChild(1, true); + if(b_minus) mstruct[0].negate(); + mstruct.childrenUpdated(); + if(b_minus) mstruct.negate(); + return true; + } + bool b = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(replace_abs_x(mstruct[i], marg, b_minus, &mstruct, level + 1)) { + mstruct.childUpdated(i + 1); + b = true; + } + } + return b; +} + +bool test_sign_zero(const MathStructure &m, const MathStructure &x_var, const MathStructure &mzero, const EvaluationOptions &eo) { + if(m.contains(x_var, true) <= 0) return false; + if(m.isMultiplication()) { + for(size_t i = 0; i < m.size(); i++) { + if(m[i].isPower() && m[i][1].representsNegative() && test_sign_zero(m[i][0], x_var, mzero, eo)) return true; + } + } + CALCULATOR->beginTemporaryStopMessages(); + MathStructure mtest(m); + mtest.replace(x_var, mzero); + mtest.transform(COMPARISON_EQUALS, m_zero); + mtest.eval(eo); + return !CALCULATOR->endTemporaryStopMessages() && mtest.isOne(); +} + +void do_signum(MathStructure &m1, const MathStructure &marg) { + /*m1 *= marg; + m1 *= marg; + m1.last().transformById(FUNCTION_ID_ABS); + m1.last().inverse();*/ + m1 *= MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SIGNUM), &marg, &m_zero, NULL); +} +bool try_sign(MathStructure &m1, MathStructure &m2, const MathStructure &marg, const MathStructure &x_var, const MathStructure &mzero, const EvaluationOptions &eo, bool *test_zero = NULL) { + if(m1.equals(m2, true)) return true; + if(m1.isNumber() && m1.number().isReal() && m2.isNumber() && m2.number().isReal()) { + m2.number().negate(); + if(m1.number().equals(m2.number(), true)) { + m2.number().negate(); + if(!test_sign_zero(m1, x_var, mzero, eo)) { + if(!test_zero) return false; + *test_zero = true; + } + if(!test_zero || !(*test_zero)) do_signum(m1, marg); + return true; + } + m2.number().negate(); + return false; + } + if(m1.type() != m2.type()) { + if((m1.isMultiplication() && m1.size() == 2 && m1[0].isMinusOne() && try_sign(m1[1], m2, marg, x_var, mzero, eo)) || (m2.isMultiplication() && m2.size() == 2 && m2[0].isMinusOne() && try_sign(m1, m2[1], marg, x_var, mzero, eo))) { + if(!test_sign_zero(m1, x_var, mzero, eo)) { + if(!test_zero) return false; + *test_zero = true; + } + if(!test_zero || !(*test_zero)) do_signum(m1, marg); + return true; + } + return false; + } + if(m1.size() == 0) return false; + if(m1.size() != m2.size()) { + if(m1.isMultiplication() && ((m1.size() == m2.size() + 1 && m1[0].isMinusOne()) || (m2.size() == m1.size() + 1 && m2[0].isMinusOne()))) { + if(m1.size() > m2.size()) { + for(size_t i = 0; i < m2.size(); i++) { + if(!try_sign(m1[i + 1], m2[i], marg, x_var, mzero, eo)) return false; + } + } else { + for(size_t i = 0; i < m1.size(); i++) { + if(!try_sign(m1[i], m2[i + 1], marg, x_var, mzero, eo)) return false; + } + } + if(!test_sign_zero(m1, x_var, mzero, eo)) { + if(!test_zero) return false; + *test_zero = true; + } + if(!test_zero || !(*test_zero)) do_signum(m1, marg); + return true; + } + return false; + } + if(m1.isFunction() && m1.function() != m2.function()) return false; + if(m1.isComparison() && m1.comparisonType() != m2.comparisonType()) return false; + if(m1.isMultiplication() && m1.size() > 1 && m1[0].isNumber() && !m1[0].equals(m2[0], true)) { + if(!m1[0].isNumber()) return false; + m2[0].number().negate(); + if(m1[0].number().equals(m2[0].number(), true)) { + m2[0].number().negate(); + for(size_t i = 1; i < m1.size(); i++) { + if(!try_sign(m1[i], m2[i], marg, x_var, mzero, eo)) return false; + } + if(!test_sign_zero(m1, x_var, mzero, eo)) { + if(!test_zero) return false; + *test_zero = true; + } + if(!test_zero || !(*test_zero)) do_signum(m1, marg); + return true; + } + m2[0].number().negate(); + return false; + }/* else if(m1.isPower()) { + bool b_tz = false; + if(!try_sign(m1[0], m2[0], marg, x_var, mzero, eo, &b_tz) || b_tz) return false; + if(!try_sign(m1[1], m2[1], marg, x_var, mzero, eo, &b_tz)) return false; + if(b_tz && (test_sign_zero(m1[1], x_var, mzero, eo) || !test_sign_zero(m1[0], x_var, mzero, eo))) return false; + return true; + }*/ + bool b_tz = false; + bool b_equal = false; + for(size_t i = 0; i < m1.size(); i++) { + if(!b_equal && m1.isAddition() && m1[i].equals(m2[i], true)) b_equal = true; + else if(!try_sign(m1[i], m2[i], marg, x_var, mzero, eo, m1.isAddition() ? &b_tz : NULL)) return false; + if(b_tz && b_equal) break; + } + if(b_tz) { + if(!test_sign_zero(m1, x_var, mzero, eo)) { + if(!test_zero) return false; + *test_zero = true; + } + if(!test_zero || !(*test_zero)) do_signum(m1, marg); + } + return true; +} +bool contains_imaginary(const MathStructure &m) { + if(m.isNumber()) return m.number().hasImaginaryPart(); + if(m.isVariable() && m.variable()->isKnown()) return contains_imaginary(((KnownVariable*) m.variable())->get()); + for(size_t i = 0; i < m.size(); i++) { + if(contains_imaginary(m[i])) return true; + } + return false; +} + +int MathStructure::integrate(const MathStructure &x_var, const EvaluationOptions &eo_pre, bool simplify_first, int use_abs, bool definite_integral, bool try_abs, int max_part_depth, vector *parent_parts) { + + if(CALCULATOR->aborted()) CANNOT_INTEGRATE + + EvaluationOptions eo = eo_pre; + eo.protected_function = CALCULATOR->getFunctionById(FUNCTION_ID_INTEGRATE); + EvaluationOptions eo2 = eo; + eo2.expand = true; + eo2.combine_divisions = false; + eo2.sync_units = false; + EvaluationOptions eo_t = eo; + eo_t.approximation = APPROXIMATION_TRY_EXACT; + eo_t.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; + + if(simplify_first) { + unformat(eo_pre); + calculateFunctions(eo2); + calculatesub(eo2, eo2); + combine_ln(*this, x_var, eo2); + if(CALCULATOR->aborted()) CANNOT_INTEGRATE + } + bool recalc = false; + + // Try to remove abs() and sgn() + + if(fix_abs_x(*this, x_var, eo, definite_integral)) recalc = true; + + MathStructure *mfound = NULL; + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + if(fix_sgn_x(*this, x_var, eo_t)) recalc = true; + while(true) { + mfound = find_abs_x2(*this, x_var); + if(mfound) { + MathStructure m_interval(*mfound); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + CALCULATOR->beginTemporaryStopMessages(); + m_interval.eval(eo_t); + if(!CALCULATOR->endTemporaryStopMessages()) break; + if(m_interval.representsNonNegative(true)) { + replace_abs_x(*this, MathStructure(*mfound), false); + recalc = true; + } else if(m_interval.representsNegative(true)) { + replace_abs_x(*this, MathStructure(*mfound), true); + recalc = true; + } else { + break; + } + } else { + break; + } + } + } + if(recalc) { + calculatesub(eo2, eo2); + combine_ln(*this, x_var, eo2); + } + + // x: x^2/2 + if(equals(x_var)) { + raise(2); + multiply(MathStructure(1, 2, 0)); + return true; + } + + // a: a*x + if(containsRepresentativeOf(x_var, true, true) == 0) { + multiply(x_var); + return true; + } + + if(m_type == STRUCT_ADDITION) { + // f(x)+g(x): integral of f(x) + integral of g(x) + bool b = false; + MathStructure mbak(*this); + for(size_t i = 0; i < SIZE; i++) { + int bint = CHILD(i).integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts); + if(bint < 0) { + set(mbak); + CANNOT_INTEGRATE_INTERVAL + } + if(bint > 0) b = true; + CHILD_UPDATED(i); + } + if(!b) return false; + return true; + } else if(m_type == STRUCT_MULTIPLICATION) { + // a*f(x): a * integral of f(x) + MathStructure mstruct; + bool b = false; + for(size_t i = 0; i < SIZE;) { + if(CHILD(i).containsRepresentativeOf(x_var, true, true) == 0) { + if(b) { + mstruct *= CHILD(i); + } else { + mstruct = CHILD(i); + b = true; + } + ERASE(i); + } else { + i++; + } + } + if(b) { + if(SIZE == 1) { + setToChild(1, true); + } else if(SIZE == 0) { + set(mstruct, true); + return true; + } + if(integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) { + multiply(mstruct); + CANNOT_INTEGRATE_INTERVAL + } + multiply(mstruct); + return true; + } + + for(size_t i = 0; i < SIZE; i++) { + if((CHILD(i).isFunction() && CHILD(i).function()->id() == FUNCTION_ID_ABS && CHILD(i).size() == 1) || (CHILD(i).isPower() && CHILD(i)[0].isFunction() && CHILD(i)[0].function()->id() == FUNCTION_ID_ABS && CHILD(i)[0].size() == 1 && CHILD(i)[1].representsOdd())) { + if(definite_integral) CANNOT_INTEGRATE + bool b = (m_type == STRUCT_POWER ? CHILD(0)[0].representsNonComplex(true) : CHILD(0).representsNonComplex(true)); + if(!b && !(m_type == STRUCT_POWER ? CHILD(0)[0].representsComplex(true) : CHILD(0).representsComplex(true))) { + MathStructure mtest(m_type == STRUCT_POWER ? CHILD(0)[0] : CHILD(0)); + CALCULATOR->beginTemporaryStopMessages(); + mtest.eval(eo_t); + CALCULATOR->endTemporaryStopMessages(); + b = mtest.representsNonComplex(true); + if(!b && !mtest.representsComplex(true)) { + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + CALCULATOR->beginTemporaryStopMessages(); + mtest.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + mtest.eval(eo_t); + CALCULATOR->endTemporaryStopMessages(); + b = mtest.representsNonComplex(true); + if(!b && !mtest.representsComplex(true) && !contains_imaginary(mtest) && !contains_imaginary(((UnknownVariable*) x_var.variable())->interval())) { + CALCULATOR->error(false, "Integral assumed real", NULL); + b = true; + } + } else if(!contains_imaginary(mtest)) { + CALCULATOR->error(false, "Integral assumed real", NULL); + b = true; + } + } + } + if(b) { + MathStructure mmul(CHILD(i).isPower() ? CHILD(i)[0] : CHILD(i)); + if(CHILD(i).isPower()) CHILD(i)[0].setToChild(1, true); + else CHILD(i).setToChild(1, true); + mmul.inverse(); + mmul *= CHILD(i).isPower() ? CHILD(i)[0] : CHILD(i); + if(integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) { + multiply(mmul); + CANNOT_INTEGRATE_INTERVAL + } + multiply(mmul); + return true; + } + } + } + } else if((m_type == STRUCT_FUNCTION && o_function->id() == FUNCTION_ID_ABS && SIZE == 1) || (m_type == STRUCT_POWER && CHILD(0).isFunction() && CHILD(0).function()->id() == FUNCTION_ID_ABS && CHILD(0).size() == 1 && CHILD(1).representsOdd())) { + bool b = (m_type == STRUCT_POWER ? CHILD(0)[0].representsNonComplex(true) : CHILD(0).representsNonComplex(true)); + if(!b && !(m_type == STRUCT_POWER ? CHILD(0)[0].representsComplex(true) : CHILD(0).representsComplex(true))) { + MathStructure mtest(m_type == STRUCT_POWER ? CHILD(0)[0] : CHILD(0)); + CALCULATOR->beginTemporaryStopMessages(); + mtest.eval(eo_t); + CALCULATOR->endTemporaryStopMessages(); + b = mtest.representsNonComplex(true); + if(!b && !mtest.representsComplex(true)) { + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + CALCULATOR->beginTemporaryStopMessages(); + mtest.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + mtest.eval(eo_t); + CALCULATOR->endTemporaryStopMessages(); + b = mtest.representsNonComplex(true); + if(!b && !mtest.representsComplex(true) && !contains_imaginary(mtest) && !contains_imaginary(((UnknownVariable*) x_var.variable())->interval())) { + CALCULATOR->error(false, "Integral assumed real", NULL); + b = true; + } + } else if(!contains_imaginary(mtest)) { + CALCULATOR->error(false, "Integral assumed real", NULL); + b = true; + } + } + } + if(b) { + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + if(fix_sgn_x(*this, x_var, eo_t)) recalc = true; + while(true) { + mfound = find_abs_x2(*this, x_var); + if(mfound) { + MathStructure m_interval(*mfound); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + CALCULATOR->beginTemporaryStopMessages(); + m_interval.eval(eo_t); + if(!CALCULATOR->endTemporaryStopMessages()) break; + if(m_interval.representsNonNegative(true)) { + replace_abs_x(*this, MathStructure(*mfound), false); + recalc = true; + } else if(m_interval.representsNegative(true)) { + replace_abs_x(*this, MathStructure(*mfound), true); + recalc = true; + } else { + break; + } + } else { + break; + } + } + } + if(m_type == STRUCT_FUNCTION && CHILD(0).isFunction() && (CHILD(0).function()->id() == FUNCTION_ID_SIN || CHILD(0).function()->id() == FUNCTION_ID_COS) && CHILD(0).size() == 1) { + MathStructure madd, mmul, mexp; + if(integrate_info(CHILD(0)[0], x_var, madd, mmul, mexp, true) && mexp.isOne() && madd.isZero()) { + // abs(sin(ax)): 2/a*floor(ax/pi)-1/a*cos(ax-floor(ax/pi)*pi) + // abs(cos(ax)): 2/a*floor(ax/pi+1/2)+1/a*sin(ax-floor(ax/pi+1/2)*pi) + setToChild(1, true); + MathStructure mdivpi(x_var); + if(!mmul.isOne()) mdivpi *= mmul; + mdivpi /= CALCULATOR->getVariableById(VARIABLE_ID_PI); + if(o_function->id() == FUNCTION_ID_COS) mdivpi += nr_half; + mdivpi.transformById(FUNCTION_ID_FLOOR); + if(o_function->id() == FUNCTION_ID_SIN) setFunctionId(FUNCTION_ID_COS); + else setFunctionId(FUNCTION_ID_SIN); + CHILD(0) += mdivpi; + CHILD(0).last() *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + CHILD(0).last() *= CALCULATOR->getRadUnit(); + CHILD(0).last().negate(); + CHILD(0).childUpdated(CHILD(0).size()); + CHILD_UPDATED(0) + if(o_function->id() == FUNCTION_ID_COS) negate(); + if(!mmul.isOne()) divide(mmul); + add(mdivpi); + LAST *= nr_two; + if(!mmul.isOne()) LAST /= mmul; + CHILD_UPDATED(SIZE - 1) + return true; + } + } + MathStructure mstruct(m_type == STRUCT_POWER ? CHILD(0) : *this); + if(m_type != STRUCT_POWER || (CHILD(1).isInteger() && !CHILD(1).number().isMinusOne() && CHILD(1).number().isOdd())) { + MathStructure mexp, mmul, madd; + if(integrate_info(m_type == STRUCT_POWER ? CHILD(0)[0] : CHILD(0), x_var, madd, mmul, mexp) && mexp.isOne()) { + MathStructure mpowp1(m_type == STRUCT_POWER ? CHILD(1) : nr_two); + if(m_type == STRUCT_POWER) { + mpowp1 += m_one; + setToChild(1, true); + } + MathStructure msgn(*this); + msgn.setFunctionId(FUNCTION_ID_SIGNUM); + setToChild(1, true); + raise(mpowp1); + divide(mmul); + divide(mpowp1); + multiply(msgn); + return true; + } + } + if(definite_integral) CANNOT_INTEGRATE + MathStructure mmul; + MathStructure mbak(*this); + if(isPower()) { + mmul = CHILD(0); + CHILD(0).setToChild(1, true); + mmul.inverse(); + mmul *= CHILD(0); + } else { + mmul = *this; + setToChild(1, true); + mmul.inverse(); + mmul *= *this; + } + int b_int = integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts); + if(b_int <= 0) { + set(mbak); + if(b_int < 0) CANNOT_INTEGRATE_INTERVAL + CANNOT_INTEGRATE + } + multiply(mmul); + return true; + } + } + mfound = try_abs ? find_abs_x2(*this, x_var) : NULL; + if(mfound) { + MathStructure mtest(*this); + MathStructure mtest_m(mtest); + if(!replace_abs_x(mtest, *mfound, false) || !replace_abs_x(mtest_m, *mfound, true)) CANNOT_INTEGRATE + eo_t.isolate_x = true; + eo_t.isolate_var = &x_var; + CALCULATOR->beginTemporaryStopMessages(); + MathStructure mpos(*mfound); + mpos.transform(COMPARISON_EQUALS_GREATER, m_zero); + mpos.eval(eo_t); + UnknownVariable *var_p = NULL, *var_m = NULL; + if(!CALCULATOR->endTemporaryStopMessages() && mpos.isComparison() && (mpos.comparisonType() == COMPARISON_EQUALS_GREATER || mpos.comparisonType() == COMPARISON_EQUALS_LESS) && mpos[0] == x_var && mpos[1].isNumber()) { + var_p = new UnknownVariable("", format_and_print(x_var)); + var_m = new UnknownVariable("", format_and_print(x_var)); + Number nr_interval_p, nr_interval_m; + if(x_var.isVariable() && !x_var.variable()->isKnown() && ((UnknownVariable*) x_var.variable())->interval().isNumber() && ((UnknownVariable*) x_var.variable())->interval().number().isInterval() && ((UnknownVariable*) x_var.variable())->interval().number().isReal() && ((UnknownVariable*) x_var.variable())->interval().number().upperEndPoint().isGreaterThanOrEqualTo(mpos[1].number()) && ((UnknownVariable*) x_var.variable())->interval().number().lowerEndPoint().isLessThanOrEqualTo(mpos[1].number())) { + if(mpos.comparisonType() == COMPARISON_EQUALS_GREATER) { + nr_interval_p.setInterval(mpos[1].number(), ((UnknownVariable*) x_var.variable())->interval().number().upperEndPoint()); + nr_interval_m.setInterval(((UnknownVariable*) x_var.variable())->interval().number().lowerEndPoint(), mpos[1].number()); + } else { + nr_interval_m.setInterval(mpos[1].number(), ((UnknownVariable*) x_var.variable())->interval().number().upperEndPoint()); + nr_interval_p.setInterval(((UnknownVariable*) x_var.variable())->interval().number().lowerEndPoint(), mpos[1].number()); + } + } else { + + if(mpos.comparisonType() == COMPARISON_EQUALS_GREATER) { + nr_interval_p.setInterval(mpos[1].number(), nr_plus_inf); + nr_interval_m.setInterval(nr_minus_inf, mpos[1].number()); + } else { + nr_interval_m.setInterval(mpos[1].number(), nr_plus_inf); + nr_interval_p.setInterval(nr_minus_inf, mpos[1].number()); + } + } + var_p->setInterval(nr_interval_p); + var_m->setInterval(nr_interval_m); + mtest.replace(x_var, var_p); + mtest_m.replace(x_var, var_m); + } + int bint1 = mtest.integrate(var_p ? var_p : x_var, eo, true, use_abs, true, definite_integral, max_part_depth, parent_parts); + if(var_p) { + mtest.replace(var_p, x_var); + var_p->destroy(); + } + if(bint1 <= 0 || mtest.containsFunctionId(FUNCTION_ID_INTEGRATE, true) > 0) { + if(var_m) var_m->destroy(); + if(bint1 < 0) CANNOT_INTEGRATE_INTERVAL + CANNOT_INTEGRATE; + } + int bint2 = mtest_m.integrate(var_m ? var_m : x_var, eo, true, use_abs, false, definite_integral, max_part_depth, parent_parts); + if(var_m) { + mtest_m.replace(var_m, x_var); + var_m->destroy(); + } + if(bint2 < 0) CANNOT_INTEGRATE_INTERVAL + if(bint2 == 0 || mtest_m.containsFunctionId(FUNCTION_ID_INTEGRATE, true) > 0) CANNOT_INTEGRATE; + MathStructure m1(mtest), m2(mtest_m); + CALCULATOR->beginTemporaryStopMessages(); + MathStructure mzero(*mfound); + mzero.transform(COMPARISON_EQUALS, m_zero); + mzero.eval(eo_t); + if(!CALCULATOR->endTemporaryStopMessages() && mzero.isComparison() && mzero.comparisonType() == COMPARISON_EQUALS && mzero[0] == x_var) { + mzero.setToChild(2); + CALCULATOR->beginTemporaryStopMessages(); + m1.calculatesub(eo2, eo2, true); + m2.calculatesub(eo2, eo2, true); + m1.evalSort(true, true); + m2.evalSort(true, true); + eo_t.test_comparisons = true; + eo_t.isolate_x = false; + eo_t.isolate_var = NULL; + if((definite_integral && m1.equals(m2, true)) || (!definite_integral && try_sign(m1, m2, *mfound, x_var, mzero, eo_t))) { + set(m1, true); + CALCULATOR->endTemporaryStopMessages(true); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + } + /*MathStructure mcmp(*mfound); + mcmp.transform(COMPARISON_EQUALS_GREATER, m_zero); + set(mtest); + multiply(mcmp); + mcmp.setComparisonType(COMPARISON_LESS); + mtest_m *= mcmp; + add(mtest_m);*/ + /*eo2.test_comparisons = true; + calculatesub(eo2, eo2, true);*/ + + ///return true; + } + + switch(m_type) { + case STRUCT_UNIT: {} + case STRUCT_NUMBER: { + // a: a*x + multiply(x_var); + break; + } + case STRUCT_POWER: { + if(CHILD(1).isNumber() || CHILD(1).containsRepresentativeOf(x_var, true, true) == 0) { + bool b_minusone = (CHILD(1).isNumber() && CHILD(1).number().isMinusOne()); + MathStructure madd, mmul, mmul2, mexp; + if(CHILD(0).isFunction()) { + MathStructure mbase(CHILD(0)); + int bint = integrate_function(mbase, x_var, eo, CHILD(1), m_one, m_zero, m_one, use_abs, definite_integral, max_part_depth, parent_parts); + if(bint < 0) CANNOT_INTEGRATE_INTERVAL + if(bint) { + set(mbase, true); + return true; + } + } else if(integrate_info(CHILD(0), x_var, madd, mmul, mmul2, false, true)) { + if(mmul2.isZero()) { + if(madd.isZero() && mmul.isOne()) { + if(b_minusone) { + // x^-1: ln(x) + if(!transform_absln(CHILD(0), use_abs, definite_integral, x_var, eo)) CANNOT_INTEGRATE_INTERVAL + SET_CHILD_MAP(0); + } else { + // x^a: x^(a+1)/(a+1) + CHILD(1) += m_one; + MathStructure mstruct(CHILD(1)); + divide(mstruct); + } + return true; + } else if(b_minusone) { + // (ax+b)^-1: ln(ax+b)/a + if(!transform_absln(CHILD(0), use_abs, definite_integral, x_var, eo)) CANNOT_INTEGRATE_INTERVAL + SET_CHILD_MAP(0); + if(!mmul.isOne()) divide(mmul); + return true; + } else { + if(definite_integral && !madd.isZero() && (!x_var.representsNonComplex(true) || !mmul.representsNonComplex(true)) && !CHILD(1).representsInteger() && COMPARISON_MIGHT_BE_EQUAL(x_var.compare(m_zero)) && !COMPARISON_IS_EQUAL_OR_LESS(madd.compare(m_zero))) CANNOT_INTEGRATE + // (ax+b)^c: (ax+b)^(c+1)/(a(c+1)) + mexp = CHILD(1); + mexp += m_one; + SET_CHILD_MAP(0); + raise(mexp); + if(!mmul.isOne()) mexp *= mmul; + divide(mexp); + return true; + } + } else if(mmul.isZero() && !madd.isZero() && CHILD(1).number().denominatorIsTwo()) { + MathStructure mmulsqrt2(mmul2); + if(!mmul2.isOne()) mmulsqrt2 ^= nr_half; + Number num(CHILD(1).number().numerator()); + if(num.isOne()) { + // sqrt(ax^2+b): (ln(sqrt(ax^2+b)+x*sqrt(a))*b+sqrt(a)*b*sqrt(ax^2+b))/(2*sqrt(a)) + MathStructure mthis(*this); + add(x_var); + if(!mmul2.isOne()) LAST *= mmulsqrt2; + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mthis); CANNOT_INTEGRATE_INTERVAL} + multiply(madd); + mthis *= x_var; + if(!mmul2.isOne()) mthis *= mmulsqrt2; + add(mthis); + multiply(nr_half); + if(!mmul2.isOne()) divide(mmulsqrt2); + childrenUpdated(true); + return true; + } else if(num == 3) { + // (ax^2+b)^(3/2): + // (ln(sqrt(ax^2+b)+x*sqrt(a))*b^2*3/8+(ax^2+b)^(3/2)*x*sqrt(a)/4+sqrt(ax^2+b)*x*sqrt(a)*b*3/8)/sqrt(a) + MathStructure mterm3(*this); + CHILD(1).number().set(1, 2, 0, true); + MathStructure mterm2(*this); + add(x_var); + if(!mmul2.isOne()) LAST *= mmulsqrt2; + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mterm3); CANNOT_INTEGRATE_INTERVAL} + multiply(madd); + LAST ^= nr_two; + multiply(Number(3, 8, 0), true); + mterm2 *= x_var; + if(!mmul2.isOne()) mterm2 *= mmulsqrt2; + mterm2 *= madd; + mterm2 *= Number(3, 8, 0); + mterm3 *= x_var; + if(!mmul2.isOne()) mterm3 *= mmulsqrt2; + mterm3 *= Number(1, 4, 0); + add(mterm2); + add(mterm3); + if(!mmul2.isOne()) divide(mmulsqrt2); + return true; + } else if(num == 5) { + // (ax^2+b)^(5/2): + // sqrt(ax^2+b)*x^5*a^2/6+ln(sqrt(ax^2+b)*sqrt(a)+ax)*b^3/sqrt(a)*5/16+sqrt(ax^2+b)*x*b^2*11/16+sqrt(ax^2+b)*x^3*b*a*13/24 + CHILD(1).number().set(1, 2, 0, true); + MathStructure mterm2(*this); + MathStructure mterm3(*this); + MathStructure mterm4(*this); + multiply(x_var); + LAST ^= Number(5, 1); + if(!mmul2.isOne()) { + multiply(mmul2, true); + LAST ^= nr_two; + } + multiply(Number(1, 6), true); + if(!mmul2.isOne()) mterm2 *= mmulsqrt2; + mterm2 += x_var; + if(!mmul2.isOne()) mterm2.last() *= mmul2; + if(!transform_absln(mterm2, use_abs, definite_integral, x_var, eo)) {set(mterm3); CANNOT_INTEGRATE_INTERVAL} + mterm2 *= madd; + mterm2.last() ^= nr_three; + if(!mmul2.isOne()) mterm2 /= mmulsqrt2; + mterm2 *= Number(5, 16); + mterm3 *= x_var; + mterm3 *= madd; + mterm3.last() ^= nr_two; + mterm3 *= Number(11, 16); + mterm4 *= x_var; + mterm4.last() ^= nr_three; + mterm4 *= madd; + if(!mmul2.isOne()) mterm4 *= mmul2; + mterm4 *= Number(13, 24); + add(mterm2); + add(mterm3); + add(mterm4); + childrenUpdated(true); + return true; + } else if(num.isMinusOne()) { + // 1/sqrt(ax^2+b): ln(sqrt(ax^2+b)*sqrt(a)+ax)/sqrt(a) + MathStructure mbak(*this); + CHILD(1).number().set(1, 2, 0, true); + if(!mmul2.isOne()) multiply(mmulsqrt2); + add(x_var); + if(!mmul2.isOne()) LAST.multiply(mmul2); + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + if(!mmul2.isOne()) divide(mmulsqrt2); + return true; + } else if(num == -3) { + // (ax^2+b)^(-3/2): x/(b*sqrt(ax^2+b)) + CHILD(1).number().set(-1, 2, 0, true); + madd.inverse(); + multiply(madd); + multiply(x_var); + return true; + } else if(num == -5) { + // (ax^2+b)^(-5/2): (x(2ax^2+3b)/(3b^2*(ax^2+b)^(3/2)) + CHILD(1).number().set(-3, 2, 0, true); + mmul = x_var; + mmul ^= nr_two; + if(!mmul2.isOne()) mmul *= mmul2; + mmul *= nr_two; + mmul += madd; + mmul.last() *= nr_three; + multiply(mmul); + multiply(x_var); + multiply(madd); + LAST ^= Number(-2, 1); + multiply(Number(1, 3)); + return true; + } + } else if(b_minusone) { + // 1/(ax^2+bx+c) + // y=4ac-b^2 + MathStructure m4acmb2(madd); + m4acmb2 *= mmul2; + m4acmb2 *= Number(4, 1); + m4acmb2 += mmul; + m4acmb2.last() ^= nr_two; + m4acmb2.last().negate(); + m4acmb2.calculatesub(eo, eo, true); + if(!m4acmb2.representsNonZero(true)) { + if(m4acmb2.isZero()) { + // y=0: -2/(2ax+b) + set(x_var, true); + multiply(mmul2); + multiply(nr_two, true); + add(mmul); + inverse(); + multiply(Number(-2, 1)); + return true; + } else if(!warn_about_denominators_assumed_nonzero(m4acmb2, eo)) { + CANNOT_INTEGRATE + } + } + if(m4acmb2.representsNegative(true)) { + // y<0: ln((2ax+b-sqrt(-4ac+b^2))/(2ax+b+sqrt(-4ac+b^2)))/sqrt(-4ac+b^2) + MathStructure mbak(*this); + MathStructure m2axpb(x_var); + m2axpb *= mmul2; + m2axpb *= nr_two; + m2axpb += mmul; + MathStructure mb2m4ac(madd); + mb2m4ac *= mmul2; + mb2m4ac *= Number(-4, 1); + mb2m4ac += mmul; + mb2m4ac.last() ^= nr_two; + mb2m4ac ^= nr_half; + set(m2axpb); + subtract(mb2m4ac); + multiply(m2axpb); + LAST += mb2m4ac; + LAST ^= nr_minus_one; + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + divide(mb2m4ac); + return true; + } + // y!=0: 2y*atan((2ax+b)/y^2) + m4acmb2 ^= Number(-1, 2); + set(x_var, true); + multiply(mmul2); + multiply(nr_two, true); + add(mmul); + multiply(m4acmb2); + transformById(FUNCTION_ID_ATAN); + multiply(nr_two); + multiply(m4acmb2, true); + return true; + } else if(CHILD(1).isInteger() && CHILD(1).number().isNegative()) { + // (ax^2+bx+c)^(-n): integral of (ax^2+bx+c)^(-n+1)*(-2a*(-2n+3)*c*a*4+1/(b^(2)*(n-1)))+(2ax+b)*c*a*4+1/b^(2)(ax^2+bx+c)^(-n+1)/(n-1) + MathStructure m2nm3(CHILD(1)); + m2nm3 *= nr_two; + m2nm3 += Number(3, 1); + CHILD(1).number()++; + MathStructure mnp1(CHILD(1)); + mnp1.number().negate(); + mnp1.number().recip(); + MathStructure mthis(*this); + if(integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) CANNOT_INTEGRATE_INTERVAL + MathStructure m4acmb2(madd); + m4acmb2 *= mmul2; + m4acmb2 *= Number(4, 1); + m4acmb2 += mmul; + m4acmb2.last() ^= nr_two; + m4acmb2.last().negate(); + m4acmb2.inverse(); + MathStructure mfac1(mmul2); + mfac1 *= Number(-2, 1); + mfac1 *= m2nm3; + mfac1 *= mnp1; + mfac1 *= m4acmb2; + multiply(mfac1); + MathStructure mterm2(x_var); + mterm2 *= mmul2; + mterm2 *= nr_two; + mterm2 += mmul; + mterm2 *= m4acmb2; + mterm2 *= mthis; + mterm2 *= mnp1; + add(mterm2); + return true; + } + } else if(integrate_info(CHILD(0), x_var, madd, mmul, mexp, false, false)) { + if(madd.isZero() && !b_minusone) { + // (ax^b)^n (n != -1): (ax^b)^n*x/(b*n+1) + MathStructure mden(mexp); + mden *= CHILD(1); + mden += m_one; + multiply(x_var); + divide(mden); + return true; + } else if(b_minusone && mexp.isNumber() && mexp.number().isNegative() && mexp.number().isInteger()) { + if(!madd.isZero()) { + // 1/(ax^(-n)+b): integral of 1/(x^n*b+a)*x^n + Number nexp(mexp.number()); + nexp.negate(); + MathStructure mtest(x_var); + mtest ^= nexp; + mtest *= madd; + mtest += mmul; + mtest.inverse(); + mtest *= x_var; + mtest.last() ^= nexp; + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + set(mtest, true); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + } + } else if(mexp.isNumber() && mexp.number().isRational() && !mexp.number().isInteger()) { + // (ax^(n/d)+b)^c: + // integral of (ay^(n=-1?1:n)+b)^c*(y^(sgn(n)/d))^(sgn(n)*d-1) where y=x^(sgn(n)/d) and divide with sgn(n)*d + Number num(mexp.number().numerator()); + Number den(mexp.number().denominator()); + MathStructure morig(x_var); + if(num.isNegative()) den.negate(); + Number den_inv(den); + den_inv.recip(); + morig ^= den_inv; + UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(morig) + RIGHT_PARENTHESIS); + Number den_m1(den); + den_m1--; + MathStructure mtest(var); + if(!num.isOne() && !num.isMinusOne()) mtest ^= num; + if(!mmul.isOne()) mtest *= mmul; + if(!madd.isZero()) mtest += madd; + mtest ^= CHILD(1); + mtest *= var; + if(!den_m1.isOne()) { + mtest.last() ^= den_m1; + mtest.childUpdated(mtest.size()); + } + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(morig); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(morig); + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + set(mtest, true); + replace(var, morig); + multiply(den); + var->destroy(); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } + } else if(integrate_info(CHILD(0), x_var, madd, mmul, mexp, false, false, true) && !madd.isZero()) { + if(mexp.isFunction()) { + // (a*f(x)+b)^c + MathStructure mfunc(mexp); + int bint = integrate_function(mfunc, x_var, eo, CHILD(1), m_one, madd, mmul, use_abs, definite_integral, max_part_depth, parent_parts); + if(bint < 0) CANNOT_INTEGRATE_INTERVAL + if(bint) { + set(mfunc, true); + return true; + } + } else if(mexp.isPower() && mexp[1].containsRepresentativeOf(x_var, true, true) == 0) { + MathStructure mbase(mexp[0]); + if(integrate_info(mbase, x_var, madd, mmul, mexp, false, false) && mexp.isOne() && (!madd.isZero() || !mmul.isOne())) { + // ((ax^c1+b)^c2+b2)^c3: integral of (y^c2+b^2)^c3 where y=ax^c1+b and divide with a + MathStructure mtest(*this); + + UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(mbase) + RIGHT_PARENTHESIS); + mtest.replace(mbase, var, mbase.containsInterval()); + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(mbase); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(mbase); + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + set(mtest, true); + replace(var, mbase); + if(!mmul.isOne()) divide(mmul); + var->destroy(); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } + } + } + if(CHILD(0).isAddition()) { + MathStructure mtest(*this); + // factor base + if(mtest[0].factorize(eo, false, 0, 0, false, false, NULL, x_var)) { + mmul = m_one; + while(mtest[0].isMultiplication() && mtest[0].size() >= 2 && mtest[0][0].containsRepresentativeOf(x_var, true, true) == 0) { + MathStructure *mchild = &mtest[0][0]; + mchild->ref(); + mtest[0].delChild(1, true); + if(mtest[1].representsInteger(true) || COMPARISON_IS_EQUAL_OR_LESS(mchild->compare(m_zero)) || COMPARISON_IS_EQUAL_OR_LESS(mtest[0].compare(m_zero))) { + if(mmul.isOne()) mmul = *mchild; + else mmul *= *mchild; + mchild->unref(); + } else { + mtest[0].multiply_nocopy(mchild, true); + } + } + if(!mmul.isOne()) { + mmul ^= mtest[1]; + } + MathStructure mtest2(mtest); + if(mtest2.decomposeFractions(x_var, eo) && mtest2.isAddition()) { + bool b = true; + CALCULATOR->beginTemporaryStopMessages(); + for(size_t i = 0; i < mtest2.size(); i++) { + if(mtest2[i].integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) <= 0) { + b = false; + break; + } + } + CALCULATOR->endTemporaryStopMessages(b); + if(b) { + set(mtest2, true); + if(!mmul.isOne()) multiply(mmul); + return true; + } + } + MathStructure mmul2(1, 1, 0); + if(mtest[0].isMultiplication() && mtest[0].size() >= 2 && !mtest[0][0].isAddition()) { + MathStructure *mchild = &mtest[0][0]; + mchild->ref(); + mtest[0].delChild(1, true); + if(mtest[1].representsInteger(true) || COMPARISON_IS_EQUAL_OR_LESS(mchild->compare(m_zero)) || COMPARISON_IS_EQUAL_OR_LESS(mtest[0].compare(m_zero))) { + mmul2 = *mchild; + mmul2.calculateRaise(mtest[1], eo2); + mchild->unref(); + } else { + mtest[0].multiply_nocopy(mchild, true); + } + } + if(mtest[0].isPower()) { + if(mtest[1].representsInteger() || mtest[0][1].representsFraction() || COMPARISON_IS_EQUAL_OR_LESS(mtest[0][0].compare(m_zero))) { + mtest[1].calculateMultiply(mtest[0][1], eo2); + mtest[0].setToChild(1); + } else if(mtest[0][1].representsEven()) { + if(COMPARISON_IS_EQUAL_OR_GREATER(mtest[0][0].compare(m_zero))) { + mtest[1].calculateMultiply(mtest[0][1], eo2); + mtest[0].setToChild(1); + mtest[0].calculateNegate(eo2); + } else if(!definite_integral && mtest[0][0].representsReal(true)) { + mtest[1].calculateMultiply(mtest[0][1], eo2); + mtest[0].setToChild(1); + mtest[0].transformById(FUNCTION_ID_ABS); + } + } + } + mtest[0].evalSort(false); + if(!mmul2.isOne()) { + mtest *= mmul2; + mtest.evalSort(false); + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0) { + CALCULATOR->endTemporaryStopMessages(true); + set(mtest, true); + if(!mmul.isOne()) multiply(mmul); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + } + } + } else if((CHILD(0).isNumber() && !CHILD(0).number().isOne()) || (!CHILD(0).isNumber() && CHILD(0).containsRepresentativeOf(x_var, true, true) == 0)) { + MathStructure madd, mmul, mmul2, mexp; + if(integrate_info(CHILD(1), x_var, madd, mmul, mexp)) { + if(mexp.isOne()) { + if(CHILD(0).isVariable() && CHILD(0).variable()->id() == VARIABLE_ID_E) { + // e^(ax+b): e^(ax+b)/a + if(!mmul.isOne()) divide(mmul); + return true; + } else if(CHILD(0).isNumber() || warn_about_assumed_not_value(CHILD(0), m_one, eo)) { + // c^(ax+b): c^(ax+b)/(a*ln(c)) + MathStructure mmulfac(CHILD(0)); + mmulfac.transformById(FUNCTION_ID_LOG); + if(!mmul.isOne()) mmulfac *= mmul; + divide(mmulfac); + return true; + } + } else if(madd.isZero() || COMPARISON_IS_NOT_EQUAL(madd.compare(m_zero))) { + if(mmul.representsPositive(true) && COMPARISON_IS_EQUAL_OR_GREATER(CHILD(0).compare(m_one)) && CHILD(0).compare(m_zero) == COMPARISON_RESULT_LESS) { + madd.negate(); + mmul.negate(); + CHILD(0).inverse(); + } + if(mexp == nr_two) { + if(!madd.isZero()) {madd ^= CHILD(0); madd.swapChildren(1, 2);} + bool mmul_neg = mmul.representsNegative(true); + if(mmul_neg) mmul.negate(); + if(CHILD(0).isVariable() && CHILD(0).variable()->id() == VARIABLE_ID_E) { + set(mmul); + if(!mmul.isOne()) raise(nr_half); + multiply(x_var); + if(!mmul_neg) multiply(nr_one_i); + transformById(FUNCTION_ID_ERF); + if(!mmul.isOne()) { + mmul ^= Number(-1, 2); + multiply(mmul); + } + multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + LAST ^= nr_half; + multiply(nr_half); + if(!mmul_neg) multiply(nr_minus_i); + } else { + MathStructure mlog(CHILD(0)); + mlog.transformById(FUNCTION_ID_LOG); + mlog ^= nr_half; + set(mmul); + if(!mmul.isOne()) raise(nr_half); + multiply(x_var); + multiply(mlog); + if(!mmul_neg) multiply(nr_one_i); + transformById(FUNCTION_ID_ERF); + if(!mmul.isOne()) { + mmul ^= Number(-1, 2); + multiply(mmul); + } + multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + LAST ^= nr_half; + multiply(nr_half); + if(!mmul_neg) multiply(nr_minus_i); + divide(mlog); + } + if(!madd.isZero()) multiply(madd); + return true; + } else if(mexp.isNumber() && mexp.number().isRational() && !mexp.isInteger()) { + Number num(mexp.number().numerator()); + Number den(mexp.number().denominator()); + MathStructure morig(x_var); + Number den_inv(den); + den_inv.recip(); + morig ^= den_inv; + + UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(morig) + RIGHT_PARENTHESIS); + MathStructure mvar(var); + if(!num.isOne()) mvar ^= num; + MathStructure mtest(CHILD(0)); + mtest ^= mvar; + if(!mmul.isOne()) mtest.last() *= mmul; + if(!madd.isZero()) mtest.last() += madd; + mtest.childUpdated(mtest.size()); + Number npow(den); + npow--; + mtest *= var; + if(!npow.isOne()) mtest.last() ^= npow; + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(morig); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(morig); + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + set(mtest, true); + replace(var, morig); + multiply(den); + var->destroy(); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } + // a^(b+cx^d): -x*a^b*(-c*x^d*ln(a))^(-1/d)*igamma(1/d, -c*x^d*ln(a))/d + if(definite_integral) CANNOT_INTEGRATE + if(!madd.isZero()) {madd ^= CHILD(0); madd.swapChildren(1, 2);} + MathStructure mexpinv(mexp); + mexpinv.inverse(); + MathStructure marg2(CHILD(0)); + marg2.transformById(FUNCTION_ID_LOG); + marg2 *= x_var; + marg2.last() ^= mexp; + marg2 *= mmul; + marg2.negate(); + set(CALCULATOR->getFunctionById(FUNCTION_ID_I_GAMMA), &mexpinv, &marg2, NULL); + if(!madd.isZero()) multiply(madd); + multiply(x_var); + multiply(mexpinv); + mexpinv.negate(); + multiply(marg2); + LAST ^= mexpinv; + negate(); + return true; + } + } else if(integrate_info(CHILD(1), x_var, madd, mmul, mmul2, false, true)) { + // a^(bx-cx^2+d): sqrt(pi)*a^(b^2/(4c)+d)*erf(sqrt(ln(a))*(2cx-b)/(2*sqrt(c)))/(2*sqrt(c)*sqrt(ln(a)) + MathStructure sqrt2(1, 1, 0); + if(mmul2.isMinusOne()) { + mmul2 = m_one; + } else { + mmul2.negate(); + sqrt2 = mmul2; + sqrt2 ^= Number(-1, 2); + } + MathStructure loga(1, 1, 0); + if(CHILD(0) != CALCULATOR->getVariableById(VARIABLE_ID_E)) {loga = CHILD(0); loga.transformById(FUNCTION_ID_LOG);} + loga ^= nr_half; + MathStructure merf(x_var); + if(!mmul2.isOne()) merf *= mmul2; + merf *= nr_two; + merf -= mmul; + if(!loga.isOne()) merf *= loga; + merf *= nr_half; + if(!sqrt2.isOne()) merf *= sqrt2; + merf.transformById(FUNCTION_ID_ERF); + MathStructure mapow(mmul); + if(!mapow.isOne()) mapow ^= nr_two; + mapow *= Number(1, 4); + if(!mmul2.isOne()) mapow /= mmul2; + if(!madd.isZero()) mapow += madd; + SET_CHILD_MAP(0) + raise(mapow); + multiply(merf); + multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + LAST ^= nr_half; + if(!sqrt2.isOne()) multiply(sqrt2); + if(!loga.isOne()) divide(loga); + multiply(nr_half); + return true; + } + } + CANNOT_INTEGRATE + } + case STRUCT_FUNCTION: { + MathStructure mfunc(*this); + int bint = integrate_function(mfunc, x_var, eo, m_one, m_one, m_zero, m_one, use_abs, definite_integral, max_part_depth, parent_parts); + if(bint < 0) CANNOT_INTEGRATE_INTERVAL + if(!bint) CANNOT_INTEGRATE + set(mfunc, true); + break; + } + case STRUCT_MULTIPLICATION: { + if(combine_powers(*this, x_var, eo2) && m_type != STRUCT_MULTIPLICATION) return integrate(x_var, eo, false, use_abs, definite_integral, try_abs, max_part_depth, parent_parts); + if(SIZE == 2) { + if(CHILD(0) != x_var && (CHILD(1) == x_var || (CHILD(1).isPower() && CHILD(1)[0] == x_var))) SWAP_CHILDREN(0, 1); + if(CHILD(1).isPower() && CHILD(1)[1].containsRepresentativeOf(x_var, true, true) == 0) { + MathStructure madd, mmul, mmul2; + MathStructure mexp(CHILD(1)[1]); + if(integrate_info(CHILD(1)[0], x_var, madd, mmul, mmul2, false, true)) { + if(mmul2.isZero() && mexp.isNumber()) { + if(CHILD(0) == x_var) { + MathStructure mbak(*this); + SET_CHILD_MAP(1) + SET_CHILD_MAP(0) + if(mexp.number().isMinusOne()) { + MathStructure mterm(x_var); + if(!mmul.isOne()) mterm /= mmul; + if(!madd.isZero()) { + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + multiply(madd); + if(!mmul.isOne()) { + MathStructure a2(mmul); + a2 ^= nr_two; + divide(a2); + } + negate(); + add(mterm); + } else { + set(mterm, true); + } + } else if(mexp.number() == -2) { + MathStructure mterm(*this); + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + MathStructure a2(mmul); + if(!mmul.isOne()) { + a2 ^= nr_two; + divide(a2); + } + if(!madd.isZero()) { + if(!mmul.isOne()) mterm *= a2; + mterm.inverse(); + mterm *= madd; + } + add(mterm); + } else if(mexp.number().isNegative()) { + MathStructure onemn(1, 1, 0); + onemn += mexp; + MathStructure nm1(mexp); + nm1.negate(); + MathStructure nm2(nm1); + nm1 += nr_minus_one; + nm2 += Number(-2, 1); + raise(nm1); + multiply(nm2); + multiply(nm1); + if(!mmul.isOne()) { + MathStructure a2(mmul); + a2 ^= nr_two; + multiply(a2); + } + inverse(); + MathStructure mnum(x_var); + mnum *= onemn; + if(!mmul.isOne()) mnum *= mmul; + if(!madd.isZero()) mnum -= madd; + multiply(mnum); + } else { + MathStructure nm1(mexp); + nm1 += m_one; + raise(nm1); + MathStructure mnum(x_var); + mnum *= nm1; + if(!mmul.isOne()) mnum *= mmul; + mnum -= madd; + MathStructure mden(mexp); + mden += nr_two; + mden *= nm1; + if(!mmul.isOne()) { + mden *= mmul; + mden.last() ^= nr_two; + } + multiply(mnum); + divide(mden); + return true; + } + return true; + } else if(CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1] == nr_two) { + MathStructure mbak(*this); + SET_CHILD_MAP(1) + SET_CHILD_MAP(0) + if(mexp.number().isMinusOne()) { + MathStructure mterm(x_var); + mterm ^= nr_two; + if(!mmul.isOne()) mterm *= mmul; + if(!madd.isZero()) { + MathStructure mtwobx(-2 ,1, 0); + mtwobx *= madd; + mtwobx *= x_var; + mterm += mtwobx; + } + if(!mmul.isOne()) { + MathStructure a2(mmul); + a2 ^= nr_two; + a2 *= nr_two; + mterm /= a2; + } else { + mterm /= nr_two; + } + if(!madd.isZero()) { + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + MathStructure b2(madd); + b2 ^= nr_two; + multiply(b2); + if(!mmul.isOne()) { + MathStructure a3(mmul); + a3 ^= nr_three; + divide(a3); + } + add(mterm); + } else { + set(mterm, true); + } + } else if(mexp.number() == -2) { + MathStructure mterm1(x_var); + if(!mmul.isOne()) mterm1 *= mmul; + if(!madd.isZero()) { + MathStructure mterm2(*this); + if(!transform_absln(mterm2, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + mterm2 *= madd; + mterm2 *= -2; + MathStructure mterm3(*this); + mterm3.inverse(); + madd ^= nr_two; + mterm3 *= madd; + mterm3.negate(); + set(mterm1); + add(mterm2); + add(mterm3); + } else { + set(mterm1); + } + if(!mmul.isOne()) { + MathStructure a3(mmul); + a3 ^= nr_three; + divide(a3); + } + } else if(mexp.number() == -3) { + if(!madd.isZero()) { + MathStructure mterm2(*this); + mterm2.inverse(); + mterm2 *= madd; + mterm2 *= nr_two; + MathStructure mterm3(*this); + mterm3 ^= nr_two; + mterm3 *= nr_two; + mterm3.inverse(); + madd ^= nr_two; + mterm3 *= madd; + mterm3.negate(); + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + add(mterm2); + add(mterm3); + } else { + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + } + if(!mmul.isOne()) { + MathStructure a3(mmul); + a3 ^= nr_three; + divide(a3); + } + } else { + MathStructure mterm2(*this); + MathStructure mterm3(*this); + raise(nr_three); + CHILD(1) += mexp; + MathStructure mden(mexp); + mden += nr_three; + divide(mden); + if(!madd.isZero()) { + mterm2 ^= nr_two; + mterm2[1] += mexp; + mterm2 *= madd; + mterm2 *= -2; + mden = mexp; + mden += nr_two; + mterm2 /= mden; + mterm3 ^= m_one; + mterm3[1] += mexp; + madd ^= nr_two; + mterm3 *= madd; + mden = mexp; + mden += m_one; + mterm3 /= mden; + add(mterm2); + add(mterm3); + } + if(!mmul.isOne()) { + MathStructure a3(mmul); + a3 ^= nr_three; + divide(a3); + } + } + return true; + } else if(CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1] == nr_minus_one && !madd.isZero()) { + if(mexp.number().isMinusOne()) { + MathStructure mbak(*this); + SET_CHILD_MAP(1) + SET_CHILD_MAP(0) + divide(x_var); + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + divide(madd); + negate(); + return true; + } + } else if(CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1] == -2 && !madd.isZero()) { + if(mexp.number().isMinusOne()) { + MathStructure mbak(*this); + SET_CHILD_MAP(1) + SET_CHILD_MAP(0) + divide(x_var); + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + MathStructure madd2(madd); + madd2 ^= nr_two; + divide(madd2); + if(!mmul.isOne()) multiply(mmul); + madd *= x_var; + madd.inverse(); + subtract(madd); + return true; + } else if(mexp.number() == -2) { + MathStructure mbak(*this); + SET_CHILD_MAP(1) + SET_CHILD_MAP(0) + MathStructure mterm2(madd); + mterm2 ^= nr_two; + MathStructure mterm3(mterm2); + mterm2 *= *this; + mterm2.inverse(); + divide(x_var); + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + MathStructure madd3(madd); + madd3 ^= nr_three; + divide(madd3); + multiply(Number(-2, 1, 0)); + mterm3 *= x_var; + if(!mmul.isOne()) mterm3 *= mmul; + mterm3.inverse(); + add(mterm2); + add(mterm3); + mmul.negate(); + multiply(mmul); + return true; + } + } + } else if(mmul.isZero() && !madd.isZero() && mexp.isNumber() && mexp.number().denominatorIsTwo()) { + Number num(mexp.number()); + if(CHILD(0) == x_var) { + num.add(1); + SET_CHILD_MAP(1) + SET_CHILD_MAP(0) + raise(num); + num.multiply(2); + num.recip(); + multiply(num); + if(!mmul2.isOne()) divide(mmul2); + return true; + } else if(CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isInteger()) { + if(CHILD(0)[1].number() == 2) { + if(num == nr_half) { + MathStructure mbak(*this); + SET_CHILD_MAP(1) + MathStructure mterm2(*this); + if(!mmul2.isOne()) { + mterm2 *= mmul2; + mterm2.last() ^= nr_half; + } + mterm2 += x_var; + if(!mmul2.isOne()) mterm2.last() *= mmul2; + if(!transform_absln(mterm2, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + mterm2.multiply(madd); + mterm2.last() ^= nr_two; + multiply(x_var); + if(!mmul2.isOne()) { + multiply(mmul2); + LAST ^= nr_half; + } + multiply(x_var); + LAST ^= nr_two; + if(!mmul2.isOne()) LAST *= mmul2; + LAST *= nr_two; + LAST += madd; + subtract(mterm2); + multiply(Number(1, 8)); + if(!mmul2.isOne()) { + multiply(mmul2); + LAST ^= Number(-3, 2); + } + return true; + } + } else if(CHILD(0)[1].number() == -1) { + if(num == nr_minus_half) { + MathStructure mbak(*this); + SET_CHILD_MAP(1) + SET_CHILD_MAP(0) + raise(nr_half); + multiply(madd); + LAST ^= nr_half; + add(madd); + transformById(FUNCTION_ID_LOG); + negate(); + add(x_var); + if(!transform_absln(LAST, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + multiply(madd); + LAST ^= nr_minus_half; + return true; + } else if(num == nr_half) { + MathStructure mbak(*this); + SET_CHILD_MAP(1) + MathStructure mterm2(*this); + mterm2 *= madd; + mterm2.last() ^= nr_half; + mterm2 += madd; + mterm2.transformById(FUNCTION_ID_LOG); + mterm2 *= madd; + mterm2.last() ^= nr_half; + MathStructure mterm3(x_var); + if(!transform_absln(mterm3, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + mterm3 *= madd; + mterm3.last() ^= nr_half; + subtract(mterm2); + add(mterm3); + return true; + } + } + } + } else if(mmul2.isZero()) { + if(CHILD(0) == x_var) { + SET_CHILD_MAP(1) + CHILD(1) += m_one; + MathStructure mnum(x_var); + mnum *= CHILD(1); + if(!mmul.isOne()) mnum *= mmul; + mnum -= madd; + MathStructure mden(CHILD(1)[0]); + mden += nr_two; + mden *= CHILD(1); + if(!mmul.isOne()) { + mden *= mmul; + mden[mden.size() - 1] ^= nr_two; + } + multiply(mnum); + divide(mden); + return true; + } + } else if(mexp.isMinusOne() && CHILD(0) == x_var) { + MathStructure mbak(*this); + SET_CHILD_MAP(1) + MathStructure mterm2(CHILD(0)); + if(integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) CANNOT_INTEGRATE_INTERVAL + multiply(mmul); + divide(mmul2); + multiply(Number(-1, 2)); + if(!transform_absln(mterm2, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + mterm2 /= mmul2; + mterm2 *= nr_half; + add(mterm2); + return true; + } else if(mexp.isMinusOne() && CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1].isMinusOne()) { + MathStructure mbak(*this); + SET_CHILD_MAP(1) + MathStructure mterm2(CHILD(0)); + if(integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) CANNOT_INTEGRATE_INTERVAL + multiply(mmul); + divide(madd); + multiply(Number(-1, 2)); + mterm2.inverse(); + mterm2 *= x_var; + mterm2.last() ^= nr_two; + if(!transform_absln(mterm2, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + mterm2 /= madd; + mterm2 *= nr_half; + add(mterm2); + return true; + } else if(mexp.isInteger() && mexp.number().isNegative() && CHILD(0) == x_var) { + MathStructure mbak(*this); + SET_CHILD_MAP(1) + MathStructure m2nm3(CHILD(1)); + m2nm3 *= nr_two; + m2nm3 += Number(3, 1); + CHILD(1).number()++; + MathStructure mnp1(CHILD(1)); + mnp1.number().negate(); + mnp1.number().recip(); + MathStructure mthis(*this); + if(integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + MathStructure m4acmb2(madd); + m4acmb2 *= mmul2; + m4acmb2 *= Number(4, 1); + m4acmb2 += mmul; + m4acmb2.last() ^= nr_two; + m4acmb2.last().negate(); + m4acmb2.inverse(); + MathStructure mfac1(mmul); + mfac1 *= m2nm3; + mfac1 *= mnp1; + mfac1 *= m4acmb2; + multiply(mfac1); + MathStructure mterm2(x_var); + mterm2 *= mmul; + mterm2 += madd; + mterm2.last() *= nr_two; + mterm2 *= m4acmb2; + mterm2 *= mthis; + mterm2 *= mnp1; + subtract(mterm2); + return true; + } + } + + if(CHILD(0) == x_var || (CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isRational())) { + Number nexp(1, 1, 0); + if(CHILD(0).isPower()) nexp = CHILD(0)[1].number(); + MathStructure madd, mmul, mpow; + if(integrate_info(CHILD(1)[0], x_var, madd, mmul, mpow, false, false, true)) { + if(mpow.isPower() && mpow[0] == x_var) { + mpow.setToChild(2); + if(mpow.isNumber() && mpow.number().isRational() & !mpow.number().isOne()) { + if(!nexp.isOne() && mpow.isInteger()) { + if(mexp.isMinusOne() && nexp.isMinusOne()) { + MathStructure mbak(*this); + if(mpow.number().isNegative()) { + set(x_var, true); + mpow.number().negate(); + raise(mpow); + if(!madd.isOne()) multiply(madd); + add(mmul); + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + divide(mpow); + if(!madd.isOne()) divide(madd); + } else { + SET_CHILD_MAP(1) + SET_CHILD_MAP(0) + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + add(x_var); + if(!transform_absln(LAST, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + LAST *= mpow; + LAST.negate(); + negate(); + divide(mpow); + if(!madd.isOne()) divide(madd); + } + return true; + } + Number mpowmexp(mpow.number()); + mpowmexp -= nexp; + if(mpowmexp.isOne()) { + if(mexp.isMinusOne()) { + MathStructure mbak(*this); + if(mpow.number().isNegative()) { + set(x_var, true); + mpow.number().negate(); + raise(mpow); + if(!madd.isOne()) multiply(madd); + add(mmul); + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + divide(mpow); + divide(madd); + add(x_var); + if(!transform_absln(LAST, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + LAST.negate(); + divide(mpow); + divide(madd); + negate(); + } else { + SET_CHILD_MAP(1) + SET_CHILD_MAP(0) + if(!transform_absln(*this, use_abs, definite_integral, x_var, eo)) {set(mbak); CANNOT_INTEGRATE_INTERVAL} + divide(mpow); + if(!mmul.isOne()) divide(mmul); + } + } else { + SET_CHILD_MAP(1) + MathStructure mden(CHILD(1)); + CHILD(1) += m_one; + mden *= mpow; + if(!mmul.isOne()) mden *= mmul; + mden += mpow; + if(!mmul.isOne()) mden.last() *= mmul; + divide(mden); + } + return true; + } + } + if(x_var.representsNonNegative(true) || mpow.number().isEven() || mpow.number().isFraction()) { + for(int i = 1; i <= 3; i++) { + if(i > 1 && (!mpow.isInteger() || !mpow.number().isIntegerDivisible(i) || mpow.number() == i)) break; + UnknownVariable *var = NULL; + MathStructure m_replace(x_var); + MathStructure mtest(CHILD(1)); + Number new_pow(nexp); + bool b = false; + if(i == 1) { + m_replace ^= mpow; + var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(m_replace) + RIGHT_PARENTHESIS); + mtest.replace(m_replace, var); + new_pow++; + new_pow -= mpow.number(); + new_pow /= mpow.number(); + b = true; + } else if(i == 2) { + new_pow = nexp; + new_pow++; + new_pow -= 2; + new_pow /= 2; + if(new_pow.isInteger()) { + b = true; + m_replace ^= nr_two; + var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(m_replace) + RIGHT_PARENTHESIS); + MathStructure m_prev(x_var), m_new(var); + m_prev ^= mpow; + m_new ^= mpow; + m_new[1].number() /= 2; + mtest.replace(m_prev, m_new); + } + } else if(i == 3) { + new_pow++; + new_pow -= 3; + new_pow /= 3; + if(new_pow.isInteger()) { + b = true; + m_replace ^= nr_three; + var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(m_replace) + RIGHT_PARENTHESIS); + MathStructure m_prev(x_var), m_new(var); + m_prev ^= mpow; + m_new ^= mpow; + m_new[1].number() /= 3; + mtest.replace(m_prev, m_new); + } + } + if(b) { + if(!new_pow.isZero()) { + mtest *= var; + mtest.swapChildren(1, mtest.size()); + if(!new_pow.isOne()) mtest[0] ^= new_pow; + } + CALCULATOR->beginTemporaryStopMessages(); + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(m_replace); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(m_replace); + } + if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0) { + CALCULATOR->endTemporaryStopMessages(true); + mtest.replace(var, m_replace); + set(mtest, true); + divide(m_replace[1]); + var->destroy(); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } + } + } + } + } else if(mpow.isPower() && nexp.isInteger() && !madd.isZero() && mpow[1].containsRepresentativeOf(x_var, true, true) == 0) { + MathStructure mbase(mpow[0]); + if(integrate_info(mbase, x_var, madd, mmul, mpow, false, false) && mpow.isOne() && (!madd.isZero() || !mmul.isOne())) { + MathStructure mtest(CHILD(1)); + + UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(mbase) + RIGHT_PARENTHESIS); + mtest.replace(mbase, var, mbase.containsInterval()); + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(mbase); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(mbase); + } + mtest *= var; + if(!madd.isZero()) { + mtest.last() -= madd; + mtest.childUpdated(mtest.size()); + } + if(!nexp.isOne()) { + mtest.last() ^= nexp; + mtest.childUpdated(mtest.size()); + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + set(mtest, true); + replace(var, mbase); + if(!mmul.isOne()) { + nexp++; + if(!nexp.isOne()) mmul ^= nexp; + divide(mmul); + } + var->destroy(); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } + } /*else if(mpow.isFunction() && mpow.function()->id() == FUNCTION_ID_LOG && mpow.size() == 1 && mpow[0] == x_var) { + MathStructure mtest(CHILD(1)); + UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(mpow) + RIGHT_PARENTHESIS); + mtest.replace(mpow, var, mpow.containsInterval()); + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(mpow); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(mpow); + } + nexp++; + mtest *= CALCULATOR->getVariableById(VARIABLE_ID_E); + mtest.last() ^= nexp; + mtest.last().last() *= var; + mmul = CALCULATOR->getVariableById(VARIABLE_ID_E); + mmul ^= nexp; + mmul.last() *= Number(-2, 1); + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + set(mtest, true); + replace(var, mpow); + multiply(mmul); + var->destroy(); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + }*/ + } + } + if(CHILD(0).isPower() && (CHILD(0)[1] == x_var || (CHILD(0)[1].isMultiplication() && CHILD(0)[1].size() >= 2 && CHILD(0)[1].last() == x_var)) && CHILD(0)[0].containsRepresentativeOf(x_var, true, true) == 0) { + MathStructure mpow, madd, mmul; + if(integrate_info(CHILD(1)[0], x_var, madd, mmul, mpow, false, false, true) && mpow.isPower() && (mpow[1] == x_var || (mpow[1].isMultiplication() && mpow[1].size() >= 2 && mpow[1].last() == x_var)) && (CHILD(0)[0] == mpow[0] || (CHILD(0)[0].isNumber() && CHILD(0)[0].number().isRational() && mpow[0].isNumber() && mpow[0].number().isRational() && mpow[1] == CHILD(0)[1]))) { + Number pow1(1, 1), pow2; + MathStructure morig(mpow); + bool b = true; + if(CHILD(0)[1].isMultiplication()) { + if(!mpow[1].isMultiplication()) { + if(CHILD(0)[1].size() != 2 || !CHILD(0)[1][0].isNumber()) b = false; + else {pow2 = CHILD(0)[1][0].number(); pow2--;} + } else { + for(size_t i = 0; i < mpow[1].size() - 1; i++) { + if(i == 0 && mpow[1][i].isNumber()) { + pow1 = mpow[1][i].number(); + } else if(CHILD(0)[1][i].containsRepresentativeOf(x_var, true, true) != 0) { + b = false; + break; + } + } + if(b) { + if(mpow[1] == CHILD(0)[1]) { + pow1.set(1, 1); + } else if(CHILD(0)[1].size() - (CHILD(0)[1][0].isNumber() ? 1 : 0) != mpow[1].size() - (mpow[1][0].isNumber() ? 1 : 0)) { + b = false; + } else if(b) { + for(size_t i = 0; i < CHILD(0)[1].size() - 1; i++) { + if(i == 0 && CHILD(0)[1][i].isNumber()) { + pow2 = CHILD(0)[1][i].number(); + pow2--; + } else if(CHILD(0)[1][i] != mpow[1][i + (mpow[1][0].isNumber() ? 1 : 0) - (CHILD(0)[1][0].isNumber() ? 1 : 0)]) { + b = false; + break; + } + } + } + } + } + } else if(mpow[1].isMultiplication()) { + if(mpow[1].size() != 2 || !mpow[1][0].isNumber()) b = false; + else pow1 = mpow[1][0].number(); + } + if(b && !pow1.isOne()) morig[1].delChild(1, true); + if(b && CHILD(0)[0] != mpow[0]) { + bool b1 = CHILD(0)[0].number() < mpow[0].number(); + if(mpow[0].number().isFraction() || CHILD(0)[0].number().isFraction()) b1 = !b1; + Number nlog(b1 ? mpow[0].number() : CHILD(0)[0].number()); + nlog.log(b1 ? CHILD(0)[0].number() : mpow[0].number()); + if(!nlog.isInteger()) { + nlog.round(); + b = nlog.isInteger() && (b1 ? ((CHILD(0)[0].number() ^ nlog) == mpow[0].number()) : ((mpow[0].number() ^ nlog) == CHILD(0)[0].number())); + } + if(b) { + if(b1) { + pow1 = nlog; + morig = CHILD(0); + } else { + pow2 = nlog; + pow2--; + } + } + } + if(b) { + UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(morig) + RIGHT_PARENTHESIS); + MathStructure mtest(var); + if(!pow1.isOne()) mtest ^= pow1; + if(!mmul.isOne()) mtest *= mmul; + if(!madd.isZero()) mtest += madd; + if(!mexp.isOne()) mtest ^= mexp; + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(morig); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(morig); + } + if(!pow2.isZero()) { + mtest *= var; + if(!pow2.isOne()) mtest.last() ^= pow2; + mtest.swapChildren(1, 2); + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + set(mtest, true); + replace(var, morig); + if(!morig[0].isVariable() || morig[0].variable()->id() != VARIABLE_ID_E) divide_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &morig[0], NULL)); + if(morig[1].isMultiplication()) { + morig[1].delChild(morig[1].size(), true); + divide(morig[1]); + } + var->destroy(); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } + } + } + if(CHILD(1)[1].number().isMinusOne() && CHILD(1)[0].isMultiplication() && CHILD(1)[0].size() == 2 && CHILD(1)[0][0].isAddition() && CHILD(1)[0][1].isAddition() && (CHILD(0) == x_var || (CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isTwo()))) { + MathStructure madd1, mmul1, mexp1; + if(integrate_info(CHILD(1)[0][0], x_var, madd1, mmul1, mexp1) && mexp1.isOne()) { + MathStructure madd2, mexp2; + if(integrate_info(CHILD(1)[0][1], x_var, madd2, mmul2, mexp2) && mexp2.isOne()) { + MathStructure mnum1, mnum2, mx1(madd2), mx2(madd1); + mx1.negate(); + if(!mmul2.isOne()) mx1 /= mmul2; + mnum1 = mx1; + if(!mmul1.isOne()) mx1 *= mmul1; + mx1 += madd1; + mnum1 /= mx1; + mx2.negate(); + if(!mmul1.isOne()) mx2 /= mmul1; + mnum2 = mx2; + if(!mmul2.isOne()) mx2 *= mmul2; + mx2 += madd2; + mnum2 /= mx2; + mnum2 /= CHILD(1)[0][0]; + mnum1 /= CHILD(1)[0][1]; + if(CHILD(0) != x_var) { + mnum1 *= x_var; + mnum2 *= x_var; + } + mnum2 += mnum1; + CALCULATOR->beginTemporaryStopMessages(); + if(mnum2.integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0) { + CALCULATOR->endTemporaryStopMessages(true); + set(mnum2, true); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + } + } + } + if(CHILD(1)[0].isAddition()) { + bool b_poly = false; + if(CHILD(1)[1].isMinusOne()) { + MathStructure mquo, mrem; + b_poly = polynomial_long_division(CHILD(0), CHILD(1)[0], x_var, mquo, mrem, eo, true); + if(b_poly && !mquo.isZero()) { + MathStructure mtest(mquo); + if(!mrem.isZero()) { + mtest += mrem; + mtest.last() *= CHILD(1); + mtest.childrenUpdated(); + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0) { + CALCULATOR->endTemporaryStopMessages(true); + set(mtest, true); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + } + } + MathStructure mtest(*this); + if(mtest[1][0].factorize(eo, false, 0, 0, false, false, NULL, x_var)) { + mmul = m_one; + while(mtest[1][0].isMultiplication() && mtest[1][0].size() >= 2 && mtest[1][0][0].containsRepresentativeOf(x_var, true, true) == 0) { + MathStructure *mchild = &mtest[1][0][0]; + mchild->ref(); + mtest[1][0].delChild(1, true); + if(CHILD(1)[1].representsInteger(true) || COMPARISON_IS_EQUAL_OR_LESS(mchild->compare(m_zero)) || COMPARISON_IS_EQUAL_OR_LESS(mtest[1][0].compare(m_zero))) { + if(mmul.isOne()) mmul = *mchild; + else mmul *= *mchild; + mchild->unref(); + } else { + mtest[1][0].multiply_nocopy(mchild, true); + } + } + if(!mmul.isOne()) { + mmul ^= CHILD(1)[1]; + } + if(b_poly) { + MathStructure mtest2(mtest); + if(mtest2.decomposeFractions(x_var, eo)) { + if(mtest2.isAddition()) { + bool b = true; + CALCULATOR->beginTemporaryStopMessages(); + for(size_t i = 0; i < mtest2.size(); i++) { + if(mtest2[i].integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) <= 0) { + b = false; + break; + } + } + CALCULATOR->endTemporaryStopMessages(b); + if(b) { + set(mtest2, true); + if(!mmul.isOne()) multiply(mmul); + return true; + } + } + } else { + mtest2 = mtest[1]; + if(mtest2.decomposeFractions(x_var, eo) && mtest2.isAddition()) { + if(mtest2.isAddition()) { + bool b = true; + CALCULATOR->beginTemporaryStopMessages(); + for(size_t i = 0; i < mtest2.size(); i++) { + mtest2[i] *= mtest[0]; + if(mtest2[i].integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) <= 0) { + b = false; + break; + } + } + CALCULATOR->endTemporaryStopMessages(b); + if(b) { + set(mtest2, true); + if(!mmul.isOne()) multiply(mmul); + return true; + } + } + } + } + } + mmul2 = m_one; + if(mtest[1][0].isMultiplication() && mtest[1][0].size() >= 2 && !mtest[1][0][0].isAddition()) { + MathStructure *mchild = &mtest[1][0][0]; + mchild->ref(); + mtest[1][0].delChild(1, true); + if(CHILD(1)[1].representsInteger(true) || COMPARISON_IS_EQUAL_OR_LESS(mchild->compare(m_zero)) || COMPARISON_IS_EQUAL_OR_LESS(mtest[1][0].compare(m_zero))) { + mmul2 = *mchild; + mmul2.calculateRaise(CHILD(1)[1], eo2); + mchild->unref(); + } else { + mtest[1][0].multiply_nocopy(mchild, true); + } + } + if(mtest[1][0].isPower()) { + if(mtest[1][1].representsInteger() || mtest[1][0][1].representsFraction() || COMPARISON_IS_EQUAL_OR_LESS(mtest[1][0][0].compare(m_zero))) { + mtest[1][1].calculateMultiply(mtest[1][0][1], eo2); + mtest[1][0].setToChild(1); + } else if(mtest[1][0][1].representsEven()) { + if(COMPARISON_IS_EQUAL_OR_GREATER(mtest[1][0][0].compare(m_zero))) { + mtest[1][1].calculateMultiply(mtest[1][0][1], eo2); + mtest[1][0].setToChild(1); + mtest[1][0].calculateNegate(eo2); + } else if(!definite_integral && mtest[1][0][0].representsReal(true)) { + mtest[1][1].calculateMultiply(mtest[1][0][1], eo2); + mtest[1][0].setToChild(1); + mtest[1][0].transformById(FUNCTION_ID_ABS); + } + } + } + mtest[1][0].evalSort(false); + if(!mmul2.isOne()) { + mtest *= mmul2; + mtest.evalSort(false); + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest.integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0) { + CALCULATOR->endTemporaryStopMessages(true); + set(mtest); + if(!mmul.isOne()) multiply(mmul); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + } + if(CHILD(1)[1].number().isMinusOne() && CHILD(0) == x_var) { + if(integrate_info(CHILD(1)[0], x_var, madd, mmul, mmul2, false, true) && !mmul2.isZero() && mmul.isZero() && !madd.isZero()) { + SET_CHILD_MAP(1) + SET_CHILD_MAP(0) + transformById(FUNCTION_ID_LOG); + mmul2 *= Number(-2, 1); + multiply(mmul2); + return true; + } + } + } + } else if(CHILD(1).isPower() && ((CHILD(1)[0].isNumber() && !CHILD(1)[0].number().isOne()) || (!CHILD(1)[0].isNumber() && CHILD(1)[0].containsRepresentativeOf(x_var, true, true) == 0))) { + MathStructure mexp(1, 1, 0); + if(CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1].isInteger()) mexp = CHILD(0)[1]; + else if(CHILD(0) != x_var) CANNOT_INTEGRATE; + MathStructure madd, mmul, mpow; + if(mexp.number() < 100 && mexp.number() > -100 && integrate_info(CHILD(1)[1], x_var, madd, mmul, mpow, false, false) && mpow.isInteger()) { + bool b_e = CHILD(1)[0].isVariable() && CHILD(1)[0].variable()->id() == VARIABLE_ID_E; + if(b_e || CHILD(1)[0].isNumber() || warn_about_assumed_not_value(CHILD(1)[0], m_one, eo)) { + if(mpow.isOne()) { + SET_CHILD_MAP(1) + if(!b_e) { + if(mmul.isOne()) { + mmul = CHILD(0); + mmul.transformById(FUNCTION_ID_LOG); + } else { + MathStructure lnbase(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &CHILD(0), NULL); + mmul *= lnbase; + } + } + if(mexp.isOne()) { + MathStructure mmulfac(x_var); + if(!mmul.isOne()) mmulfac *= mmul; + mmulfac += nr_minus_one; + multiply(mmulfac); + if(!mmul.isOne()) { + mmul ^= Number(-2, 1);; + multiply(mmul); + } + } else if(mexp.number().isTwo()) { + MathStructure mmulfac(x_var); + mmulfac ^= nr_two; + if(!mmul.isOne()) mmulfac /= mmul; + mmulfac += x_var; + mmulfac.last() *= Number(-2, 1); + if(!mmul.isOne()) { + mmulfac.last() *= mmul; + mmulfac.last().last() ^= Number(-2, 1); + } + mmulfac += nr_two; + if(!mmul.isOne()) { + mmulfac.last() *= mmul; + mmulfac.last().last() ^= Number(-3, 1); + } + mmulfac.childrenUpdated(true); + multiply(mmulfac); + } else if(mexp.isMinusOne()) { + if(!madd.isZero()) { + madd.raise(CHILD(0)); + madd.swapChildren(1, 2); + } + set(x_var, true); + if(!mmul.isOne()) multiply(mmul); + transformById(FUNCTION_ID_EXPINT); + if(!madd.isZero()) multiply(madd); + } else if(mexp.number().isNegative()) { + MathStructure mterm2(*this); + mexp += m_one; + multiply(x_var); + LAST ^= mexp; + CHILDREN_UPDATED + if(integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) CANNOT_INTEGRATE_INTERVAL + if(!mmul.isOne()) multiply(mmul); + mterm2 *= x_var; + mterm2.last() ^= mexp; + mterm2.childrenUpdated(); + subtract(mterm2); + mexp.negate(); + divide(mexp); + } else { + MathStructure mterm2(*this); + multiply(x_var); + LAST ^= mexp; + LAST[1] += nr_minus_one; + LAST.childUpdated(2); + CHILDREN_UPDATED + if(integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts) < 0) CANNOT_INTEGRATE_INTERVAL + multiply(mexp); + if(!mmul.isOne()) divide(mmul); + negate(); + mterm2 *= x_var; + mterm2.last() ^= mexp; + mterm2.childrenUpdated(); + if(!mmul.isOne()) mterm2.divide(mmul); + add(mterm2); + } + return true; + } else { + Number mpowmexp(mpow.number()); + mpowmexp -= mexp.number(); + if(mpowmexp.isOne()) { + SET_CHILD_MAP(1) + MathStructure malog(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &CHILD(0), NULL); + divide(mpow); + if(!mmul.isOne()) divide(mmul); + if(!b_e) divide(malog); + return true; + } else if(mexp.isMinusOne() && mpow.number().isPositive()) { + MathStructure malog; + if(b_e) { + malog = x_var; + malog ^= mpow; + } else { + malog.set(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &CHILD(1)[0], NULL); + malog *= x_var; + malog.last() ^= mpow; + } + if(!mmul.isOne()) malog *= mmul; + malog.transformById(FUNCTION_ID_EXPINT); + if(madd.isZero()) { + set(malog, true); + } else { + SET_CHILD_MAP(1) + SET_CHILD_MAP(0) + raise(madd); + multiply(malog); + } + divide(mpow); + return true; + } + } + } + } + } + } + if(SIZE >= 2) { + for(size_t i = 0; i < SIZE; i++) { + if((CHILD(i).isFunction() && CHILD(i).function()->id() == FUNCTION_ID_SIGNUM) || (CHILD(i).isPower() && CHILD(i)[0].isFunction() && CHILD(i)[0].function()->id() == FUNCTION_ID_SIGNUM)) { + MathStructure mfunc(CHILD(i).isPower() ? CHILD(i)[0] : CHILD(i)); + MathStructure mmul(*this); + mmul.delChild(i + 1, true); + CALCULATOR->beginTemporaryStopMessages(); + int bint = integrate_function(mfunc, x_var, eo, CHILD(i).isPower() ? CHILD(i)[1] : m_one, mmul, m_zero, m_one, use_abs, definite_integral, max_part_depth, parent_parts); + CALCULATOR->endTemporaryStopMessages(bint > 0); + if(bint < 0) CANNOT_INTEGRATE_INTERVAL + if(bint) { + set(mfunc, true); + return true; + } + } + } + for(size_t i = 0; i < SIZE; i++) { + if((CHILD(i).isFunction() && CHILD(i).function()->id() != FUNCTION_ID_SIGNUM) || (CHILD(i).isPower() && CHILD(i)[0].isFunction() && CHILD(i)[0].function()->id() != FUNCTION_ID_SIGNUM)) { + MathStructure mfunc(CHILD(i).isPower() ? CHILD(i)[0] : CHILD(i)); + MathStructure mmul(*this); + mmul.delChild(i + 1, true); + CALCULATOR->beginTemporaryStopMessages(); + int bint = integrate_function(mfunc, x_var, eo, CHILD(i).isPower() ? CHILD(i)[1] : m_one, mmul, m_zero, m_one, use_abs, definite_integral, max_part_depth, parent_parts); + CALCULATOR->endTemporaryStopMessages(bint > 0); + if(bint < 0) CANNOT_INTEGRATE_INTERVAL + if(bint) { + set(mfunc, true); + return true; + } + } + } + MathStructure mbak(*this); + if(CHILD(0) == x_var || (CHILD(0).isPower() && CHILD(0)[0] == x_var && CHILD(0)[1].isNumber() && CHILD(0)[1].number().isRational())) { + Number nexp(1, 1, 0); + if(CHILD(0).isPower()) nexp = CHILD(0)[1].number(); + MathStructure mpow(1, 1, 0); + bool b = true; + MathStructure madd, mmul, mpown; + for(size_t i = 1; i < SIZE; i++) { + if(CHILD(i).isFunction() && CHILD(i).size() >= 1) { + if(!integrate_info(CHILD(i)[0], x_var, madd, mmul, mpown, false, false) || !mpown.isNumber() || !mpown.number().isRational() || mpown.number().isOne() || (!mpow.isOne() && mpow != mpown)) { + b = false; + break; + } + mpow = mpown; + } else if(CHILD(i).isPower() && CHILD(i)[1].containsRepresentativeOf(x_var, true, true) == 0) { + if((CHILD(i)[0].isFunction() && CHILD(i)[0].size() == 1)) { + if(!integrate_info(CHILD(i)[0][0], x_var, madd, mmul, mpown, false, false)) {b = false; break;} + } else if(integrate_info(CHILD(i)[0], x_var, madd, mmul, mpown, false, false, true)) { + if(mpown.isPower() && mpown[0] == x_var) { + mpown.setToChild(2); + if(SIZE == 2 && mpown.isInteger()) {b = false; break;} + } else if(mpown.isFunction() && mpown.size() >= 1) { + MathStructure marg(mpown[0]); + if(!integrate_info(marg, x_var, madd, mmul, mpown, false, false)) {b = false; break; } + } else { + b = false; break; + } + } else { + b = false; break; + } + if(!mpown.isNumber() || !mpown.number().isRational() || mpown.number().isOne() || (!mpow.isOne() && mpow != mpown)) { + b = false; + break; + } + mpow = mpown; + } else if(CHILD(i).isPower() && CHILD(i)[0].containsRepresentativeOf(x_var, true, true) == 0) { + if(!integrate_info(CHILD(i)[1], x_var, madd, mmul, mpown, false, false) || !mpown.isNumber() || !mpown.number().isRational() || mpown.number().isOne() || (!mpow.isOne() && mpow != mpown)) { + b = false; + break; + } + mpow = mpown; + } else { + b = false; + break; + } + } + if(b && (x_var.representsNonNegative(true) || mpow.number().isEven() || mpow.number().isFraction())) { + for(int i = 1; i <= 3; i++) { + if(!mpow.isInteger()) { + if(i > 2) break; + } else if(i > 1 && (!mpow.number().isIntegerDivisible(i) || mpow.number() == i)) { + break; + } + if(CALCULATOR->aborted()) CANNOT_INTEGRATE + UnknownVariable *var = NULL; + MathStructure m_replace(x_var); + MathStructure mtest(*this); + mtest.delChild(1, true); + Number new_pow(nexp); + b = false; + if(i == 1) { + m_replace ^= mpow; + var = new UnknownVariable("", ""); + mtest.replace(m_replace, var); + new_pow++; + new_pow -= mpow.number(); + new_pow /= mpow.number(); + b = true; + } else if(i == 2) { + if(!mpow.number().isInteger()) { + Number nden = mpow.number().denominator(); + nden.recip(); + nden--; + nden.negate(); + new_pow = nexp; + new_pow += nden; + new_pow *= mpow.number().denominator(); + if(new_pow.isInteger()) { + b = true; + m_replace ^= mpow.number().denominator(); + m_replace[1].number().recip(); + var = new UnknownVariable("", ""); + MathStructure m_prev(x_var), m_new(var); + m_prev ^= mpow; + if(!mpow.number().numeratorIsOne()) m_new ^= mpow.number().numerator(); + mtest.replace(m_prev, m_new); + } + } else if((mpow.number() / 2).isEven()) { + new_pow = nexp; + new_pow++; + new_pow -= 2; + new_pow /= 2; + if(new_pow.isInteger()) { + b = true; + m_replace ^= nr_two; + var = new UnknownVariable("", ""); + MathStructure m_prev(x_var), m_new(var); + m_prev ^= mpow; + m_new ^= mpow; + m_new[1].number() /= 2; + mtest.replace(m_prev, m_new); + } + } + } else if(i == 3) { + new_pow++; + new_pow -= 3; + new_pow /= 3; + if(new_pow.isInteger()) { + b = true; + m_replace ^= nr_three; + var = new UnknownVariable("", ""); + MathStructure m_prev(x_var), m_new(var); + m_prev ^= mpow; + m_new ^= mpow; + m_new[1].number() /= 3; + mtest.replace(m_prev, m_new); + } + } + if(b) { + if(!new_pow.isZero()) { + mtest *= var; + mtest.swapChildren(1, mtest.size()); + if(!new_pow.isOne()) mtest[0] ^= new_pow; + } + CALCULATOR->beginTemporaryStopMessages(); + var->setName(string(LEFT_PARENTHESIS) + format_and_print(m_replace) + RIGHT_PARENTHESIS); + if(x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined()) { + MathStructure m_interval(m_replace); + m_interval.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + var->setInterval(m_interval); + } else { + var->setInterval(m_replace); + } + if(mtest.integrate(var, eo, false, use_abs, definite_integral, true, max_part_depth, parent_parts) > 0 && mtest.containsFunctionId(FUNCTION_ID_INTEGRATE) <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + mtest.replace(var, m_replace); + set(mtest, true); + if(m_replace.isPower()) divide(m_replace[1]); + var->destroy(); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + var->destroy(); + } + } + } + } + + vector parent_parts_pre; + if(parent_parts) { + for(size_t i = 0; i < parent_parts->size(); i++) { + if(equals(*(*parent_parts)[i], true)) CANNOT_INTEGRATE + } + } else { + parent_parts = &parent_parts_pre; + } + size_t pp_size = parent_parts->size(); + bool b = false; + + // integration by parts: u(x)*v(x): u*integral of(v) - integral of (u'(x) * integral of v(x)) + for(size_t i = 0; !b && max_part_depth > 0 && (i < SIZE || (SIZE == 3 && i < SIZE * 2)) && SIZE < 10; i++) { + if(CALCULATOR->aborted()) CANNOT_INTEGRATE + CALCULATOR->beginTemporaryStopMessages(); + MathStructure mstruct_u; + MathStructure mstruct_v; + MathStructure minteg_v; + + // select two parts + if(SIZE == 3 && i >= 3) { + mstruct_v = CHILD(i - 3); + mstruct_u = *this; + mstruct_u.delChild(i - 2); + } else { + mstruct_u = CHILD(i); + if(SIZE == 2 && i == 0) mstruct_v = CHILD(1); + else if(SIZE == 2 && i == 1) mstruct_v = CHILD(0); + else {mstruct_v = *this; mstruct_v.delChild(i + 1);} + } + + MathStructure mdiff_u(mstruct_u); + if(mdiff_u.differentiate(x_var, eo2) && mdiff_u.containsFunctionId(FUNCTION_ID_DIFFERENTIATE, true) <= 0 && (!definite_integral || check_zero_div(mdiff_u, x_var, eo))) { + minteg_v = mstruct_v; + if(minteg_v.integrate(x_var, eo, false, use_abs, definite_integral, true, 0, parent_parts) > 0) { + parent_parts->push_back(this); + MathStructure minteg_2(minteg_v); + if(!mdiff_u.isOne()) minteg_2 *= mdiff_u; + if(minteg_2.countTotalChildren() < 1000) { + minteg_2.evalSort(true); + minteg_2.calculateFunctions(eo2); + minteg_2.calculatesub(eo2, eo2, true); + combine_ln(minteg_2, x_var, eo2); + do_simplification(minteg_2, eo2, true, false, false, true, true); + } + if(minteg_2.countTotalChildren() < 100 && minteg_2.integrate(x_var, eo, false, use_abs, definite_integral, true, max_part_depth - 1, parent_parts) > 0) { + int cui = contains_unsolved_integrate(minteg_2, this, parent_parts); + if(cui == 3) { + MathStructure mfunc(CALCULATOR->getFunctionById(FUNCTION_ID_INTEGRATE), this, &m_undefined, &m_undefined, &x_var, &m_zero, NULL); + UnknownVariable *var = new UnknownVariable("", format_and_print(mfunc)); + var->setAssumptions(mfunc); + MathStructure mvar(var); + minteg_2.replace(mfunc, mvar); + MathStructure msolve(mstruct_u); + msolve.multiply(minteg_v); + msolve.evalSort(false); + msolve.calculatesub(eo2, eo2, true); + msolve.subtract(minteg_2); + msolve.evalSort(false); + msolve.calculatesub(eo2, eo2, true); + MathStructure msolve_d(msolve); + if(msolve_d.differentiate(mvar, eo2) && COMPARISON_IS_NOT_EQUAL(msolve_d.compare(m_one))) { + msolve.transform(COMPARISON_EQUALS, mvar); + msolve.isolate_x(eo2, mvar); + if(msolve.isComparison() && msolve.comparisonType() == COMPARISON_EQUALS && msolve[0] == mvar && msolve[1].contains(mvar, true) <= 0) { + b = true; + set(msolve[1], true); + } + } + var->destroy(); + } else if(cui != 1) { + set(mstruct_u); + multiply(minteg_v); + subtract(minteg_2); + b = true; + } + } + parent_parts->pop_back(); + } + } + CALCULATOR->endTemporaryStopMessages(b); + } + while(parent_parts->size() > pp_size) parent_parts->pop_back(); + if(b) return true; + } + CANNOT_INTEGRATE + break; + } + case STRUCT_SYMBOLIC: { + if(representsNumber(true)) { + // y: x*y + multiply(x_var); + } else { + CANNOT_INTEGRATE + } + break; + } + case STRUCT_VARIABLE: { + if(eo.calculate_variables && o_variable->isKnown()) { + if(eo.approximation != APPROXIMATION_EXACT || !o_variable->isApproximate()) { + set(((KnownVariable*) o_variable)->get(), true); + unformat(eo); + return integrate(x_var, eo, true, use_abs, definite_integral, true, max_part_depth, parent_parts); + } else if(containsRepresentativeOf(x_var, true, true) != 0) { + CANNOT_INTEGRATE + } + } + // y: x*y + if(representsNumber(true)) { + multiply(x_var); + break; + } + } + default: { + CANNOT_INTEGRATE + } + } + return true; +} + +// Type 0: Simpson's rule, 1: trapezoid, 2: Simpson's 3/8, 3: Boole's + +bool numerical_integration(const MathStructure &mstruct, Number &nvalue, const MathStructure &x_var, const EvaluationOptions &eo2, const Number &nr_begin, const Number &nr_end, int i_samples, int type = 0) { + if((type == 0 && i_samples % 2 == 1) || (type == 2 && i_samples % 3 == 2) || (type == 3 && i_samples % 4 == 3)) { + i_samples++; + } else if((type == 2 && i_samples % 3 == 1) || (type == 3 && i_samples % 4 == 2)) { + i_samples += 2; + } else if(type == 3 && i_samples % 4 == 1) { + i_samples += 3; + } + Number nr_step(nr_end); + nr_step -= nr_begin; + nr_step /= i_samples; + MathStructure m_a = mstruct; + m_a.replace(x_var, nr_begin); + m_a.eval(eo2); + if(!m_a.isNumber()) return false; + nvalue = m_a.number(); + m_a = mstruct; + m_a.replace(x_var, nr_end); + m_a.eval(eo2); + if(!m_a.isNumber()) return false; + if(!nvalue.add(m_a.number())) return false; + if(type == 1 && !nvalue.multiply(nr_half)) return false; + if(type == 3 && !nvalue.multiply(7)) return false; + for(int i = 1; i < i_samples; i++) { + if(CALCULATOR->aborted()) { + return false; + } + Number nr(nr_step); + nr *= i; + nr += nr_begin; + MathStructure m_a(mstruct); + m_a.replace(x_var, nr); + m_a.eval(eo2); + if(!m_a.isNumber()) return false; + if((type == 0 && i % 2 == 0) || (type == 2 && i % 3 == 0)) { + if(!m_a.number().multiply(nr_two)) return false; + } else if(type == 0) { + if(!m_a.number().multiply(4)) return false; + } else if(type == 2) { + if(!m_a.number().multiply(nr_three)) return false; + } else if(type == 3 && i % 4 == 0) { + if(!m_a.number().multiply(14)) return false; + } else if(type == 3 && i % 2 == 0) { + if(!m_a.number().multiply(12)) return false; + } else if(type == 3) { + if(!m_a.number().multiply(32)) return false; + } + if(!nvalue.add(m_a.number())) return false; + } + if(!nvalue.multiply(nr_step)) return false; + if(type == 0 && !nvalue.multiply(Number(1, 3))) return false; + if(type == 2 && !nvalue.multiply(Number(3, 8))) return false; + if(type == 3 && !nvalue.multiply(Number(2, 45))) return false; + return true; +} +bool montecarlo(const MathStructure &minteg, Number &nvalue, const MathStructure &x_var, const EvaluationOptions &eo, Number a, Number b, Number n) { + Number range(b); range -= a; + MathStructure m; + Number u; + nvalue.clear(); + vector v; + Number i(1, 1); + while(i <= n) { + if(CALCULATOR->aborted()) { + n = i; + break; + } + u.rand(); + u *= range; + u += a; + m = minteg; + m.replace(x_var, u); + m.eval(eo); + if(!m.isNumber() || m.number().includesInfinity()) return false; + if(!m.number().multiply(range)) return false; + if(!nvalue.add(m.number())) return false; + v.push_back(m.number()); + i++; + } + if(!nvalue.divide(n)) return false; + Number var; + for(size_t i = 0; i < v.size(); i++) { + if(!v[i].subtract(nvalue) || !v[i].square() || !var.add(v[i])) return false; + } + if(!var.divide(n) || !var.sqrt()) return false; + Number nsqrt(n); if(!nsqrt.sqrt() || !var.divide(nsqrt)) return false; + nvalue.setUncertainty(var); + return true; +} +bool has_wide_trig_interval(const MathStructure &m, const MathStructure &x_var, const EvaluationOptions &eo, Number a, Number b) { + for(size_t i = 0; i < m.size(); i++) { + if(has_wide_trig_interval(m[i], x_var, eo, a, b)) return true; + } + if(m.isFunction() && m.size() == 1 && (m.function()->id() == FUNCTION_ID_SINC || m.function()->id() == FUNCTION_ID_SIN || m.function()->id() == FUNCTION_ID_COS)) { + Number nr_interval; + nr_interval.setInterval(a, b); + MathStructure mtest(m[0]); + mtest.replace(x_var, nr_interval); + CALCULATOR->beginTemporaryStopMessages(); + mtest.eval(eo); + CALCULATOR->endTemporaryStopMessages(); + return mtest.isMultiplication() && mtest.size() >= 1 && mtest[0].isNumber() && (mtest[0].number().uncertainty().realPart() > 100 || mtest[0].number().uncertainty().imaginaryPart() > 100); + } + return false; +} +bool romberg(const MathStructure &minteg, Number &nvalue, const MathStructure &x_var, const EvaluationOptions &eo, Number a, Number b, long int max_steps, long int min_steps, bool safety_measures) { + + bool auto_max = max_steps <= 0; + if(auto_max) max_steps = 22; + if(min_steps > max_steps) max_steps = min_steps; + + Number R1[max_steps], R2[max_steps]; + Number *Rp = &R1[0], *Rc = &R2[0]; + Number h(b); h -= a; + Number acc, acc_i, c, ntmp, prevunc, prevunc_i, nunc, nunc_i; + + nvalue.clear(); + + MathStructure mf(minteg); + mf.replace(x_var, a); + mf.eval(eo); + if(!mf.isNumber() || mf.number().includesInfinity()) { + if(!a.setToFloatingPoint()) return false; + mpfr_nextabove(a.internalLowerFloat()); + mpfr_nextabove(a.internalUpperFloat()); + mf = minteg; + mf.replace(x_var, a); + mf.eval(eo); + } + if(!mf.isNumber()) return false; + Rp[0] = mf.number(); + + mf = minteg; + mf.replace(x_var, b); + mf.eval(eo); + if(!mf.isNumber() || mf.number().includesInfinity()) { + if(!b.setToFloatingPoint()) return false; + mpfr_nextbelow(b.internalLowerFloat()); + mpfr_nextbelow(b.internalUpperFloat()); + mf = minteg; + mf.replace(x_var, a); + mf.eval(eo); + } + if(!mf.isNumber()) return false; + + if(!Rp[0].add(mf.number()) || !Rp[0].multiply(nr_half) || !Rp[0].multiply(h)) return false; + + if(safety_measures && min_steps < 15 && has_wide_trig_interval(minteg, x_var, eo, a, b)) min_steps = (max_steps < 15 ? max_steps : 15); + + for(long int i = 1; i < max_steps; i++) { + + if(CALCULATOR->aborted()) break; + + if(!h.multiply(nr_half)) return false; + + c.clear(); + + long int ep = 1 << (i - 1); + ntmp = a; ntmp += h; + for(long int j = 1; j <= ep; j++){ + if(CALCULATOR->aborted()) break; + mf = minteg; + mf.replace(x_var, ntmp); + mf.eval(eo); + if(CALCULATOR->aborted()) break; + if(!mf.isNumber() || mf.number().includesInfinity()) { + Number ntmp2(ntmp); + if(ntmp2.setToFloatingPoint()) return false; + if(j % 2 == 0) {mpfr_nextabove(ntmp2.internalLowerFloat()); mpfr_nextabove(ntmp2.internalUpperFloat());} + else {mpfr_nextbelow(ntmp2.internalLowerFloat()); mpfr_nextbelow(ntmp2.internalUpperFloat());} + mf = minteg; + mf.replace(x_var, ntmp2); + mf.eval(eo); + if(CALCULATOR->aborted()) break; + } + if(!mf.isNumber() || !c.add(mf.number())) return false; + ntmp += h; ntmp += h; + } + if(CALCULATOR->aborted()) break; + + Rc[0] = h; + ntmp = Rp[0]; + if(!ntmp.multiply(nr_half) || !Rc[0].multiply(c) || !Rc[0].add(ntmp)) return false; + + for(long int j = 1; j <= i; ++j){ + if(CALCULATOR->aborted()) break; + ntmp = 4; + ntmp ^= j; + Rc[j] = ntmp; + ntmp--; ntmp.recip(); + if(!Rc[j].multiply(Rc[j - 1]) || !Rc[j].subtract(Rp[j - 1]) || !Rc[j].multiply(ntmp)) return false; + } + if(CALCULATOR->aborted()) break; + + if(i >= min_steps - 1 && !Rp[i - 1].includesInfinity() && !Rc[i].includesInfinity()) { + if(Rp[i - 1].hasImaginaryPart()) nunc = Rp[i - 1].realPart(); + else nunc = Rp[i - 1]; + if(Rc[i].hasImaginaryPart()) nunc -= Rc[i].realPart(); + else nunc -= Rc[i]; + nunc.abs(); + if(safety_measures) nunc *= 10; + nunc.intervalToMidValue(); + if(Rp[i - 1].hasImaginaryPart() || Rc[i].hasImaginaryPart()) { + nunc_i = Rp[i - 1].imaginaryPart(); + nunc_i -= Rc[i].imaginaryPart(); + nunc_i.abs(); + } else { + nunc_i.clear(); + } + if(safety_measures) nunc_i *= 10; + nunc_i.intervalToMidValue(); + long int prec = PRECISION + (auto_max ? 3 : 1); + if(auto_max) { + if(i > 10) prec += 10 - ((!prevunc.isZero() || !prevunc_i.isZero()) ? i - 1 : i); + if(prec < 4) prec = 4; + } + acc.set(1, 1, -prec); + ntmp = Rc[i - 1]; + ntmp.intervalToMidValue(); + if(ntmp.hasImaginaryPart()) { + if(ntmp.hasRealPart()) acc *= ntmp.realPart(); + } else { + if(!ntmp.isZero()) acc *= ntmp; + } + acc.abs(); + acc.intervalToMidValue(); + nvalue = Rc[i - 1]; + if(nunc <= acc) { + if(!nunc_i.isZero()) { + acc_i.set(1, 1, -prec); + if(ntmp.hasImaginaryPart()) acc_i *= ntmp.imaginaryPart(); + acc_i.abs(); + acc_i.intervalToMidValue(); + if(nunc_i <= acc_i) { + if(!safety_measures) { + nunc.setImaginaryPart(nunc_i); + nvalue.setUncertainty(nunc); + return true; + } + if(!prevunc.isZero() || !prevunc_i.isZero() || (nunc.isZero() && nunc_i.isZero())) { + if(nunc <= prevunc && nunc_i <= prevunc_i) { + if(!ntmp.hasRealPart()) prevunc = acc; + if(!ntmp.hasImaginaryPart()) prevunc.setImaginaryPart(acc_i); + else prevunc.setImaginaryPart(prevunc_i); + nvalue.setUncertainty(prevunc); + } else { + acc.setImaginaryPart(acc_i); + nvalue.setUncertainty(acc); + } + return true; + } + prevunc = nunc; + prevunc_i = nunc_i; + } else { + prevunc.clear(); + prevunc_i.clear(); + } + } else { + if(!safety_measures) { + nvalue.setUncertainty(nunc); + return true; + } + if(!prevunc.isZero() || nunc.isZero()) { + if(!prevunc_i.isZero()) nunc.setImaginaryPart(prevunc_i); + if(!ntmp.isZero() && nunc <= prevunc) nvalue.setUncertainty(prevunc); + else nvalue.setUncertainty(acc); + return true; + } + prevunc = nunc; + prevunc_i = nunc_i; + } + } else { + prevunc.clear(); + prevunc_i.clear(); + } + } + + Number *rt = Rp; + Rp = Rc; + Rc = rt; + } + if(!nunc.isZero() || !nunc_i.isZero()) { + acc.set(1, 1, auto_max ? -3 : -2); + ntmp = nvalue; + ntmp.intervalToMidValue(); + if(ntmp.hasImaginaryPart()) { + if(ntmp.hasRealPart()) acc *= ntmp.realPart(); + } else { + if(!ntmp.isZero()) acc *= ntmp; + } + acc.abs(); + acc.intervalToMidValue(); + if(nunc > acc) return false; + if(!ntmp.hasRealPart()) nunc = acc; + if(!nunc_i.isZero()) { + acc.set(1, 1, -3); + if(ntmp.hasImaginaryPart()) acc *= ntmp.imaginaryPart(); + acc.abs(); + acc.intervalToMidValue(); + if(nunc_i > acc) return false; + if(ntmp.hasImaginaryPart()) nunc.setImaginaryPart(nunc_i); + else nunc.setImaginaryPart(acc); + } + if(safety_measures) nunc *= 10; + nvalue.setUncertainty(nunc); + return true; + } + return false; +} +int numerical_integration_part(const MathStructure &minteg, const MathStructure &x_var, const MathStructure &merr_pre, const MathStructure &merr_diff, KnownVariable *v, Number &nvalue, EvaluationOptions &eo, const Number &nr, int type = 0, int depth = 0, bool nzerodiff = false) { + if(CALCULATOR->aborted()) return 0; + eo.interval_calculation = INTERVAL_CALCULATION_NONE; + MathStructure merr(merr_pre); + int i_ret = 1; + v->set(nr); + bool do_parts = true; + /*if(nzerodiff) { + v->set(nr.lowerEndPoint()); + MathStructure mlow(merr); + mlow.eval(eo); + v->set(nr.upperEndPoint()); + merr.eval(eo); + if(!merr.isNumber() || !mlow.isNumber() || merr.number().includesInfinity() || mlow.number().includesInfinity()) return 0; + merr.number().setInterval(mlow.number(), merr.number()); + do_parts = false; + } else if(depth > 1 && !merr_diff.isUndefined()) { + CALCULATOR->beginTemporaryStopMessages(); + MathStructure mzero(merr_diff); + mzero.eval(eo); + if(CALCULATOR->endTemporaryStopMessages() == 0 && mzero.isNumber() && mzero.number().isNonZero() && (!mzero.number().hasImaginaryPart() || mzero.number().internalImaginary()->isNonZero())) { + v->set(nr.lowerEndPoint()); + MathStructure mlow(merr); + mlow.eval(eo); + v->set(nr.upperEndPoint()); + merr.eval(eo); + if(!merr.isNumber() || !mlow.isNumber() || merr.number().includesInfinity() || mlow.number().includesInfinity()) return 0; + merr.number().setInterval(mlow.number(), merr.number()); + do_parts = false; + nzerodiff = true; + } + }*/ + if(depth > 0 && do_parts) { + CALCULATOR->beginTemporaryStopMessages(); + merr.eval(eo); + do_parts = (CALCULATOR->endTemporaryStopMessages() > 0 || !merr.isNumber() || merr.number().includesInfinity()); + } + if(do_parts) { + integrate_parts: + if(depth > 4) { + if(numerical_integration(minteg, nvalue, x_var, eo, nr.lowerEndPoint(), nr.upperEndPoint(), 1002, type)) {nvalue.setApproximate(); return -1;} + return 0; + } + vector parts; + nr.splitInterval(depth == 0 ? 5 : 5, parts); + nvalue.clear(); + Number n_i; + for(size_t i = 0; i < parts.size(); i++) { + int i_reti = numerical_integration_part(minteg, x_var, merr_pre, merr_diff, v, n_i, eo, parts[i], type, depth + 1, nzerodiff); + if(i_reti != 0) { + if(i_reti < i_ret) i_ret = i_reti; + if(!nvalue.add(n_i)) return false; + } else { + return 0; + } + } + return i_ret; + } else { + CALCULATOR->beginTemporaryStopIntervalArithmetic(); + eo.interval_calculation = INTERVAL_CALCULATION_NONE; + Number nr_interval(merr.number()); + Number nr_interval_abs; + Number nr1(nr_interval.upperEndPoint(true)); + Number nr2(nr_interval.lowerEndPoint(true)); + nr1.abs(); + nr2.abs(); + if(nr1.isGreaterThan(nr2)) nr_interval_abs = nr1; + else nr_interval_abs = nr2; + if(merr.number().hasImaginaryPart()) { + if(merr.number().hasRealPart()) { + nr1 = merr.number().realPart().upperEndPoint(); + nr2 = merr.number().realPart().lowerEndPoint(); + nr1.abs(); + nr2.abs(); + if(nr1.isGreaterThan(nr2)) nr_interval = nr1; + else nr_interval = nr2; + nr1 = merr.number().imaginaryPart().upperEndPoint(); + nr2 = merr.number().imaginaryPart().lowerEndPoint(); + nr1.abs(); + nr2.abs(); + if(nr1.isGreaterThan(nr2)) nr_interval.setImaginaryPart(nr1); + else nr_interval.setImaginaryPart(nr2); + } else { + nr_interval.setImaginaryPart(nr_interval_abs); + } + } else { + nr_interval = nr_interval_abs; + } + Number nr_samples(6, 1); + Number nr_range(nr.upperEndPoint()); + nr_range -= nr.lowerEndPoint(); + int i_run = 0; + while(true) { + if(CALCULATOR->aborted()) {CALCULATOR->endTemporaryStopIntervalArithmetic(); return 0;} + if(numerical_integration(minteg, nvalue, x_var, eo, nr.lowerEndPoint(), nr.upperEndPoint(), nr_samples.intValue(), type)) { + if(nr.includesInfinity()) { + CALCULATOR->endTemporaryStopIntervalArithmetic(); + return 0; + } + Number nr_prec(nr_range); + if(type == 0 || type == 2) { + nr_prec /= nr_samples; + nr_prec ^= 4; + nr_prec *= nr_range; + nr_prec /= (type == 2 ? 80 : 180); + } else if(type == 1) { + nr_prec /= nr_samples; + nr_prec ^= 2; + nr_prec *= nr_range; + nr_prec /= 12; + } else if(type == 3) { + nr_prec ^= 7; + //nr_prec *= Number(8, 945); ? + nr_prec /= (nr_samples ^ 6); + } + nr_prec *= nr_interval; + Number nr_prec_abs(nr_prec); + nr_prec_abs.abs(); + Number mabs(nvalue); + mabs.abs(); + Number max_error(1, 1, -(PRECISION + 1 - (i_run * 2))); + max_error *= mabs; + if(nr_prec_abs >= max_error) { + for(int i = 0; ; i++) { + if(type == 0 || type == 2) { + nr_samples = nr_range; + nr_samples ^= 5; + nr_samples /= (type == 2 ? 80 : 180); + nr_samples *= nr_interval_abs; + nr_samples /= max_error; + nr_samples.root(4); + } else if(type == 3) { + nr_samples = nr_range; + nr_samples ^= 7; + //nr_samples *= Number(8, 945); ? + nr_samples *= nr_interval_abs; + nr_samples /= max_error; + nr_samples.root(6); + } else { + nr_samples = nr_range; + nr_samples ^= 3; + nr_samples /= 12; + nr_samples *= nr_interval_abs; + nr_samples /= max_error; + nr_samples.sqrt(); + } + nr_samples.ceil(); + if(type == 0 && nr_samples.isOdd()) { + nr_samples++; + } else if(type == 2 && !nr_samples.isIntegerDivisible(3)) { + Number nmod(nr_samples); + nmod.mod(3); + if(nmod == 1) nr_samples += 2; + else nr_samples += 1; + } else if(type == 3 && !nr_samples.isIntegerDivisible(4)) { + Number nmod(nr_samples); + nmod.mod(4); + if(nmod == 1) nr_samples += 3; + if(nmod == 2) nr_samples += 2; + else nr_samples += 1; + } + if(nr_samples < 10000) break; + i_run++; + if(depth <= 3 && PRECISION + 1 - (i_run * 2) < (PRECISION > 10 ? 10 : PRECISION) - depth) goto integrate_parts; + if(PRECISION + 1 - (i_run * 2) < 5) { + if(nr_samples < 50000) break; + if(PRECISION + 1 - (i_run * 2) < 2 - depth) { + if(numerical_integration(minteg, nvalue, x_var, eo, nr.lowerEndPoint(), nr.upperEndPoint(), 1002, type)) {nvalue.setApproximate(); return -1;} + return 0; + } + } + max_error *= Number(1, 1, (PRECISION + 1 - ((i_run - 1) * 2))); + max_error *= Number(1, 1, -(PRECISION + 1 - (i_run * 2))); + } + } else { + CALCULATOR->endTemporaryStopIntervalArithmetic(); + nvalue.setUncertainty(nr_prec); + return 1; + } + } else { + CALCULATOR->endTemporaryStopIntervalArithmetic(); + return 0; + } + i_run++; + } + } + return 0; +} +bool contains_complex(const MathStructure &mstruct) { + if(mstruct.isNumber()) return mstruct.number().isComplex(); + if(mstruct.isVariable() && mstruct.variable()->isKnown()) return contains_complex(((KnownVariable*) mstruct.variable())->get()); + for(size_t i = 0; i < mstruct.size(); i++) { + if(contains_complex(mstruct[i])) return true; + } + return false; +} + +bool check_denominators(const MathStructure &m, const MathStructure &mi, const MathStructure &mx, const EvaluationOptions &eo) { + if(m.contains(mx, false, true, true) == 0) return true; + for(size_t i = 0; i < m.size(); i++) { + if(!check_denominators(m[i], mi, mx, eo)) return false; + } + if(m.isPower()) { + bool b_neg = m[1].representsNegative(); + if(!m[1].representsNonNegative()) { + if(!m[0].representsNonZero()) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + eo2.interval_calculation = INTERVAL_CALCULATION_INTERVAL_ARITHMETIC; + CALCULATOR->beginTemporaryStopMessages(); + KnownVariable *v = new KnownVariable("", "v", mi); + MathStructure mpow(m[1]); + mpow.replace(mx, v, true); + mpow.eval(eo2); + b_neg = mpow.representsNegative(); + CALCULATOR->endTemporaryStopMessages(); + v->destroy(); + } + } + if(b_neg && !m[0].representsNonZero()) { + if(m[0].isZero()) return false; + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; + CALCULATOR->beginTemporaryStopMessages(); + MathStructure mbase(m[0]); + KnownVariable *v = new KnownVariable("", "v", mi); + mbase.replace(mx, v, true); + bool b_multiple = mbase.contains(mx, true) > 0; + if(b_multiple) mbase.replace(mx, v); + mbase.eval(eo2); + CALCULATOR->endTemporaryStopMessages(); + /*if(mbase.isZero()) { + v->destroy(); return false; + } else if(!b_multiple && mbase.isNumber()) { + if(!mbase.number().isNonZero()) {v->destroy(); return false;} + } else if(!mbase.isNumber() || !mbase.number().isNonZero()) { + CALCULATOR->beginTemporaryStopMessages(); + eo2.interval_calculation = INTERVAL_CALCULATION_INTERVAL_ARITHMETIC; + mbase = m[0]; + mbase.replace(mx, v); + mbase.eval(eo2); + CALCULATOR->endTemporaryStopMessages(); + }*/ + if(mbase.isZero()) { + v->destroy(); return false; + } else if(!b_multiple && mbase.isNumber()) { + if(!mbase.number().isNonZero()) {v->destroy(); return false;} + } else if(!mbase.isNumber() || !mbase.number().isNonZero()) { + CALCULATOR->beginTemporaryStopMessages(); + mbase = m[0]; + eo2.isolate_x = true; + eo2.isolate_var = &mx; + eo2.test_comparisons = true; + eo2.approximation = APPROXIMATION_EXACT; + mbase.transform(COMPARISON_NOT_EQUALS, m_zero); + mbase.eval(eo2); + eo2.approximation = APPROXIMATION_APPROXIMATE; + eo2.isolate_x = false; + eo2.isolate_var = NULL; + if(!mbase.isNumber()) { + MathStructure mtest(mbase); + mtest.replace(mx, v); + mtest.eval(eo2); + if(mtest.isNumber()) mbase = mtest; + } + CALCULATOR->endTemporaryStopMessages(); + if(!mbase.isOne()) { + if(mbase.isZero()) {v->destroy(); return false;} + bool b = false; + if(mbase.isComparison()) { + CALCULATOR->beginTemporaryStopMessages(); + mbase[0].eval(eo2); mbase[1].eval(eo2); + CALCULATOR->endTemporaryStopMessages(); + } + if(mbase.isComparison() && mbase.comparisonType() == COMPARISON_NOT_EQUALS && (mbase[0] == mx || mbase[0].isFunction()) && mbase[1].isNumber() && mi.isNumber()) { + ComparisonResult cr = COMPARISON_RESULT_UNKNOWN; + if(mbase[0].isFunction()) { + MathStructure mfunc(mbase[0]); + mfunc.replace(mx, v); + mfunc.eval(eo2); + if(mfunc.isNumber()) cr = mbase[1].number().compare(mfunc.number()); + } else { + cr = mbase[1].number().compare(mi.number()); + } + b = COMPARISON_IS_NOT_EQUAL(cr); + if(!b && cr != COMPARISON_RESULT_UNKNOWN) {v->destroy(); return false;} + } else if(mbase.isLogicalAnd()) { + for(size_t i = 0; i < mbase.size(); i++) { + if(mbase[i].isComparison()) {mbase[i][0].eval(eo2); mbase[i][1].eval(eo2);} + if(mbase[i].isComparison() && mbase[i].comparisonType() == COMPARISON_NOT_EQUALS && (mbase[i][0] == mx || mbase[i][0].isFunction()) && mbase[i][1].isNumber() && mi.isNumber()) { + ComparisonResult cr = COMPARISON_RESULT_UNKNOWN; + if(mbase[i][0].isFunction()) { + MathStructure mfunc(mbase[i][0]); + mfunc.replace(mx, v); + mfunc.eval(eo2); + if(mfunc.isNumber()) cr = mbase[i][1].number().compare(mfunc.number()); + } else { + cr = mbase[i][1].number().compare(mi.number()); + } + b = COMPARISON_IS_NOT_EQUAL(cr); + if(!b && cr != COMPARISON_RESULT_UNKNOWN) {v->destroy(); return false;} + } + } + } + if(!b) { + CALCULATOR->endTemporaryStopMessages(); + CALCULATOR->endTemporaryStopMessages(); + CALCULATOR->error(false, _("To avoid division by zero, the following must be true: %s."), format_and_print(mbase).c_str(), NULL); + CALCULATOR->beginTemporaryStopMessages(); + CALCULATOR->beginTemporaryStopMessages(); + } + } + } + v->destroy(); + } + } else if(m.isVariable()) { + if(m.variable()->isKnown() && !check_denominators(((KnownVariable*) m.variable())->get(), mi, mx, eo)) return false; + } else if(m.isFunction() && (m.function()->id() == FUNCTION_ID_TAN || m.function()->id() == FUNCTION_ID_TANH || !m.representsNumber(true))) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + eo2.assume_denominators_nonzero = false; + MathStructure mfunc(m); + bool b = mfunc.calculateFunctions(eo2); + if(b && !check_denominators(mfunc, mi, mx, eo)) return false; + if(mfunc.isFunction() && (mfunc.function()->id() == FUNCTION_ID_TAN || mfunc.function()->id() == FUNCTION_ID_TANH)) { + mfunc.replace(mx, mi); + eo2.interval_calculation = INTERVAL_CALCULATION_INTERVAL_ARITHMETIC; + CALCULATOR->beginTemporaryStopMessages(); + b = mfunc.calculateFunctions(eo2); + CALCULATOR->endTemporaryStopMessages(); + if(!b) return false; + } + } + return true; +} +bool replace_atanh(MathStructure &m, const MathStructure &x_var, const MathStructure &m1, const MathStructure &m2, const EvaluationOptions &eo) { + bool b = false; + if(m.isFunction() && m.function()->id() == FUNCTION_ID_ATANH && m.size() == 1 && m[0].contains(x_var, true)) { + /*MathStructure mtest(m[0]); + mtest.replace(x_var, m1); + b = (mtest.compare(m_one) == COMPARISON_RESULT_EQUAL) || (mtest.compare(m_minus_one) == COMPARISON_RESULT_EQUAL); + if(!b) { + mtest = m[0]; + mtest.replace(x_var, m2); + b = (mtest.compare(m_one) == COMPARISON_RESULT_EQUAL) || (mtest.compare(m_minus_one) == COMPARISON_RESULT_EQUAL); + }*/ + b = true; + if(b) { + MathStructure marg(m[0]); + m = marg; + m += m_one; + m.transformById(FUNCTION_ID_LOG); + m *= nr_half; + m += marg; + m.last().negate(); + m.last() += m_one; + m.last().transformById(FUNCTION_ID_LOG); + m.last() *= Number(-1, 2); + return true; + } + } + if(m.isPower() && m[1].isInteger() && (m[1].number() > 10 || m[1].number() < -10)) return false; + for(size_t i = 0; i < m.size(); i++) { + if(replace_atanh(m[i], x_var, m1, m2, eo)) b = true; + } + if(b) { + m.childrenUpdated(); + m.calculatesub(eo, eo, false); + } + return b; +} +MathStructure *find_abs_x(MathStructure &mstruct, const MathStructure &x_var) { + for(size_t i = 0; i < mstruct.size(); i++) { + MathStructure *m = find_abs_x(mstruct[i], x_var); + if(m) return m; + } + if(mstruct.isFunction() && ((mstruct.function()->id() == FUNCTION_ID_ABS && mstruct.size() == 1) || (mstruct.function()->id() == FUNCTION_ID_ROOT && mstruct.size() == 2 && mstruct[1].isInteger() && mstruct[1].number().isOdd()))) { + return &mstruct; + } + return NULL; +} +bool replace_abs(MathStructure &mstruct, const MathStructure &mabs, bool neg) { + if(mstruct.equals(mabs, true, true)) { + if(mabs.function()->id() == FUNCTION_ID_ROOT) { + mstruct[1].inverse(); + mstruct.setType(STRUCT_POWER); + if(neg) { + mstruct[0].negate(); + mstruct.negate(); + } + } else { + mstruct.setToChild(1, true); + if(neg) mstruct.negate(); + } + return true; + } + bool b_ret = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(replace_abs(mstruct[i], mabs, neg)) b_ret = true; + } + return b_ret; +} + +// Check definite integral for functions that cannot be calculated +bool contains_incalc_function(const MathStructure &mstruct, const EvaluationOptions &eo) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(contains_incalc_function(mstruct[i], eo)) return true; + } + if(mstruct.isFunction()) { + if((mstruct.function()->id() == FUNCTION_ID_FRESNEL_S || mstruct.function()->id() == FUNCTION_ID_FRESNEL_C) && mstruct.size() == 1) { + if(mstruct[0].representsComplex()) return true; + MathStructure mtest(mstruct[0]); + mtest.eval(eo); + return !mtest.isNumber() || !(mtest.number() >= -6) || !(mtest.number() <= 6); + } else if(mstruct.function()->id() == FUNCTION_ID_POLYLOG || ((mstruct.function()->id() == FUNCTION_ID_EXPINT || mstruct.function()->id() == FUNCTION_ID_ERF || mstruct.function()->id() == FUNCTION_ID_ERFI) && mstruct.size() == 1 && !mstruct[0].representsReal())) { + MathStructure mtest(mstruct); + mtest.eval(eo); + return !mtest.isNumber(); + } else if(mstruct.function()->id() == FUNCTION_ID_I_GAMMA && mstruct.size() == 2) { +#if MPFR_VERSION_MAJOR < 4 + return true; +#else + return !COMPARISON_IS_EQUAL_OR_LESS(mstruct[1].compare(m_zero)); +#endif + } + } + return false; +} + +bool test_definite_ln(const MathStructure &m, const MathStructure &mi, const MathStructure &mx, const EvaluationOptions &eo) { + for(size_t i = 0; i < m.size(); i++) { + if(!test_definite_ln(m[i], mi, mx, eo)) return false; + } + if(m.isFunction() && m.function()->id() == FUNCTION_ID_LOG && m.size() == 1 && m[0].contains(mx, true) > 0 && !m[0].representsNonComplex(true)) { + MathStructure mtest(m[0]); + mtest.replace(mx, mi); + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; + CALCULATOR->beginTemporaryStopMessages(); + mtest.eval(eo2); + CALCULATOR->endTemporaryStopMessages(); + if(mtest.isNumber() && mtest.number().hasImaginaryPart() && !mtest.number().imaginaryPartIsNonZero() && !mtest.number().realPart().isNonNegative()) return false; + } + return true; +} + +void replace_intervals(MathStructure &m, vector vars) { + if(m.isNumber() && m.number().isInterval()) { + KnownVariable *v = new KnownVariable("", format_and_print(m), m); + m.set(v, true); + vars.push_back(v); + return; + } + for(size_t i = 0; i < m.size(); i++) { + replace_intervals(m[i], vars); + } +} +void restore_intervals(MathStructure &m, MathStructure &m2, vector vars, const EvaluationOptions &eo) { + for(size_t i = 0; i < vars.size(); i++) { + if(eo.approximation == APPROXIMATION_EXACT) { + m.replace(vars[i], vars[i]->get()); + m2.replace(vars[i], vars[i]->get()); + } + vars[i]->destroy(); + } +} + +bool MathStructure::integrate(const MathStructure &lower_limit, const MathStructure &upper_limit, const MathStructure &x_var_pre, const EvaluationOptions &eo, bool force_numerical, bool simplify_first) { + + if(!lower_limit.isUndefined() && lower_limit == upper_limit) { + clear(); + return true; + } + + MathStructure m1(lower_limit), m2(upper_limit); + MathStructure x_var = x_var_pre; + if(m1.isUndefined() != m2.isUndefined()) { + if(m1.isUndefined()) m1.set(nr_minus_inf); + else m2.set(nr_plus_inf); + } + m1.eval(eo); + m2.eval(eo); + int definite_integral = 0; + if(!m1.isUndefined() && !m2.isUndefined()) definite_integral = -1; + if(definite_integral < 0 && (!m1.isNumber() || !m1.number().isMinusInfinity()) && (!m2.isNumber() || !m2.number().isPlusInfinity())) definite_integral = 1; + if(definite_integral > 0 && m1 == m2) { + clear(); + return true; + } + + CALCULATOR->beginTemporaryStopMessages(); + EvaluationOptions eo2 = eo; + if(simplify_first) eo2.approximation = APPROXIMATION_EXACT; + CALCULATOR->beginTemporaryStopMessages(); + MathStructure mstruct_pre(*this); + MathStructure m_interval; + if(!m1.isUndefined()) { + m_interval.set(CALCULATOR->getFunctionById(FUNCTION_ID_INTERVAL), &m1, &m2, NULL); + CALCULATOR->beginTemporaryStopMessages(); + EvaluationOptions eo3 = eo; + eo3.approximation = APPROXIMATION_APPROXIMATE; + m_interval.calculateFunctions(eo3); + CALCULATOR->endTemporaryStopMessages(); + UnknownVariable *var = new UnknownVariable("", format_and_print(x_var_pre)); + var->setInterval(m_interval); + x_var.set(var); + mstruct_pre.replace(x_var_pre, x_var); + var->destroy(); + if(definite_integral && !check_denominators(mstruct_pre, m_interval, x_var, eo)) { + if(definite_integral < 0) { + definite_integral = 0; + } else { + CALCULATOR->endTemporaryStopMessages(); + CALCULATOR->endTemporaryStopMessages(true); + CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); + return false; + } + } + } + MathStructure mstruct(mstruct_pre); + vector vars; + replace_intervals(mstruct, vars); + eo2.do_polynomial_division = false; + + if(simplify_first) mstruct.eval(eo2); + + if(definite_integral > 0 && mstruct.isAddition() && m1.isNumber() && m1.number().isReal() && m2.isNumber() && m2.number().isReal()) { + mstruct.replace(x_var, x_var_pre); + MathStructure mbak(mstruct); + Number nr; + for(size_t i = 0; i < mstruct.size();) { + if(!mstruct[i].integrate(lower_limit, upper_limit, x_var_pre, eo, force_numerical, simplify_first)) { + CALCULATOR->endTemporaryStopMessages(); + CALCULATOR->endTemporaryStopMessages(); + CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); + if(simplify_first) set(mbak); + return false; + } + if(mstruct[i].isNumber()) { + if(nr.add(mstruct[i].number())) mstruct.delChild(i + 1); + else i++; + } else i++; + } + mstruct.childrenUpdated(); + if(mstruct.size() == 0) mstruct.set(nr, true); + else if(!nr.isZero() || nr.isApproximate()) mstruct.addChild(nr); + CALCULATOR->endTemporaryStopMessages(true); + CALCULATOR->endTemporaryStopMessages(true); + set(mstruct); + return true; + } + if(simplify_first) do_simplification(mstruct, eo2, true, false, false, true, true); + eo2.do_polynomial_division = eo.do_polynomial_division; + MathStructure mbak(mstruct); + + if(!force_numerical || definite_integral == 0) { + int use_abs = -1; + /*if(m1.isUndefined() && x_var.representsReal() && !contains_complex(mstruct)) { + use_abs = 1; + }*/ + if(definite_integral) replace_atanh(mstruct, x_var, lower_limit, upper_limit, eo2); + if(definite_integral && !simplify_first) combine_ln(mstruct, x_var, eo2); + + int b = mstruct.integrate(x_var, eo2, simplify_first, use_abs, definite_integral, true, (definite_integral && eo.approximation != APPROXIMATION_EXACT && PRECISION < 20) ? 2 : 4); + + if(b < 0) { + restore_intervals(mstruct, mbak, vars, eo); + CALCULATOR->endTemporaryStopMessages(true); + CALCULATOR->endTemporaryStopMessages(true); + CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); + if(simplify_first) { + set(mbak); + if(definite_integral != 0) replace(x_var, x_var_pre); + } + return false; + } + if(simplify_first && eo.approximation != APPROXIMATION_EXACT && (!b || mstruct.containsFunctionId(FUNCTION_ID_INTEGRATE, true) > 0)) { + vector blocked_messages; + CALCULATOR->endTemporaryStopMessages(false, &blocked_messages); + CALCULATOR->beginTemporaryStopMessages(); + MathStructure mbak_integ(mstruct); + eo2.approximation = eo.approximation; + eo2.do_polynomial_division = false; + mstruct = mstruct_pre; + if(definite_integral) replace_atanh(mstruct, x_var, lower_limit, upper_limit, eo2); + mstruct.eval(eo2); + do_simplification(mstruct, eo2, true, false, false, true, true); + eo2.do_polynomial_division = eo.do_polynomial_division; + int b2 = mstruct.integrate(x_var, eo2, true, use_abs, definite_integral, true, (definite_integral && eo.approximation != APPROXIMATION_EXACT && PRECISION < 20) ? 2 : 4); + if(b2 < 0) { + restore_intervals(mstruct, mbak, vars, eo); + CALCULATOR->endTemporaryStopMessages(true); + CALCULATOR->endTemporaryStopMessages(true); + CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); + if(simplify_first) { + set(mbak); + if(definite_integral != 0) replace(x_var, x_var_pre); + } + return false; + } + if(b2 && (!b || mstruct.containsFunctionId(FUNCTION_ID_INTEGRATE, true) <= 0)) { + CALCULATOR->endTemporaryStopMessages(true); + b = true; + } else { + CALCULATOR->endTemporaryStopMessages(false); + if(b) { + CALCULATOR->addMessages(&blocked_messages); + mstruct = mbak_integ; + } + } + } else { + restore_intervals(mstruct, mbak, vars, eo); + CALCULATOR->endTemporaryStopMessages(true); + } + eo2.approximation = eo.approximation; + if(b) { + if(definite_integral && mstruct.containsFunctionId(FUNCTION_ID_INTEGRATE, true) <= 0 && test_definite_ln(mstruct, m_interval, x_var, eo)) { + CALCULATOR->endTemporaryStopMessages(true); + MathStructure mstruct_lower(mstruct); + if(m1.isInfinite() || m2.isInfinite()) { + CALCULATOR->beginTemporaryStopMessages(); + EvaluationOptions eo3 = eo; + eo3.approximation = APPROXIMATION_EXACT; + if(m1.isInfinite()) { + b = mstruct_lower.calculateLimit(x_var, m1, eo3) && !mstruct_lower.isInfinite(); + } else { + mstruct_lower.replace(x_var, lower_limit); + b = eo.approximation == APPROXIMATION_EXACT || !contains_incalc_function(mstruct_lower, eo); + } + MathStructure mstruct_upper(mstruct); + if(m2.isInfinite()) { + b = mstruct_upper.calculateLimit(x_var, m2, eo3) && !mstruct_upper.isInfinite(); + } else { + mstruct_upper.replace(x_var, upper_limit); + b = eo.approximation == APPROXIMATION_EXACT || !contains_incalc_function(mstruct_upper, eo); + } + if(b) { + set(mstruct_upper); + subtract(mstruct_lower); + return true; + } else { + if(definite_integral > 0) { + CALCULATOR->endTemporaryStopMessages(true); + CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); + if(simplify_first) { + set(mbak); + replace(x_var, x_var_pre); + } + return false; + } else { + definite_integral = 0; + } + } + } else { + mstruct_lower.replace(x_var, lower_limit); + if(eo.approximation == APPROXIMATION_EXACT || !m1.isNumber() || !m1.number().isReal() || !contains_incalc_function(mstruct_lower, eo)) { + mstruct.replace(x_var, upper_limit); + if(eo.approximation != APPROXIMATION_EXACT && m2.isNumber() && m2.number().isReal() && contains_incalc_function(mstruct, eo)) { + mstruct = mbak; + } else { + set(mstruct); + subtract(mstruct_lower); + return true; + } + } + } + } else if(definite_integral < 0) { + definite_integral = 0; + } else if(definite_integral > 0) { + mstruct = mbak; + } + if(!definite_integral) { + set(mstruct); + if(!m1.isUndefined()) replace(x_var, x_var_pre); + CALCULATOR->endTemporaryStopMessages(true); + add(CALCULATOR->getVariableById(VARIABLE_ID_C)); + return true; + } + } + if(!b) { + if(definite_integral <= 0) { + CALCULATOR->endTemporaryStopMessages(true); + CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); + if(simplify_first) { + set(mbak); + replace(x_var, x_var_pre); + } + return false; + } else { + mstruct = mbak; + } + } + + // Calculate definite integral with abs() or root() with appropriate intervals + MathStructure *mabs = find_abs_x(mbak, x_var); + if(mabs && !is_differentiable((*mabs)[0])) mabs = NULL; + if(mabs && !(*mabs)[0].representsNonComplex(true)) { + MathStructure mtest((*mabs)[0]); + mtest.transformById(FUNCTION_ID_IM); + if(mtest.compare(m_zero) != COMPARISON_RESULT_EQUAL) mabs = NULL; + } + if(mabs) { + bool b_reversed = COMPARISON_IS_EQUAL_OR_GREATER(m2.compare(m1)); + MathStructure m0((*mabs)[0]); + m0.transform(COMPARISON_EQUALS, m_zero); + EvaluationOptions eo3 = eo; + eo3.approximation = APPROXIMATION_EXACT; + eo3.isolate_x = true; + eo3.isolate_var = &x_var; + m0.eval(eo3); + bool b_exit = false; + if(m0.isZero()) { + m0 = (*mabs)[0]; + m0.replace(x_var, lower_limit); + ComparisonResult cr1 = m0.compare(m_zero); + if(COMPARISON_IS_EQUAL_OR_LESS(cr1)) { + if(replace_abs(mbak, *mabs, false)) { + mbak.replace(x_var, x_var_pre); + CALCULATOR->endTemporaryStopMessages(true); + if(mbak.integrate(lower_limit, upper_limit, x_var_pre, eo, false, true)) { + set(mbak); + return true; + } + if(simplify_first) set(mbak); + return false; + } + } else if(COMPARISON_IS_EQUAL_OR_GREATER(cr1)) { + if(replace_abs(mbak, *mabs, true)) { + mbak.replace(x_var, x_var_pre); + CALCULATOR->endTemporaryStopMessages(true); + if(mbak.integrate(lower_limit, upper_limit, x_var_pre, eo, false, true)) { + set(mbak); + return true; + } + if(simplify_first) set(mbak); + return false; + } + } + } else if(m0.isComparison() && m0.comparisonType() == COMPARISON_EQUALS && m0[0] == x_var && m0[1].contains(x_var, true) == 0) { + CALCULATOR->endTemporaryStopMessages(); + CALCULATOR->beginTemporaryStopMessages(); + m0.setToChild(2, true); + ComparisonResult cr1 = m0.compare(b_reversed ? m2 : m1); + ComparisonResult cr2 = m0.compare(b_reversed ? m1 : m2); + if(COMPARISON_IS_EQUAL_OR_GREATER(cr1) || COMPARISON_IS_EQUAL_OR_LESS(cr2)) { + MathStructure mtest((*mabs)[0]); + if(b_reversed) mtest.replace(x_var, COMPARISON_IS_EQUAL_OR_GREATER(cr1) ? lower_limit : upper_limit); + else mtest.replace(x_var, COMPARISON_IS_EQUAL_OR_GREATER(cr1) ? upper_limit : lower_limit); + ComparisonResult cr = mtest.compare(m_zero); + if(COMPARISON_IS_EQUAL_OR_LESS(cr)) { + if(replace_abs(mbak, *mabs, false)) { + mbak.replace(x_var, x_var_pre); + CALCULATOR->endTemporaryStopMessages(true); + if(mbak.integrate(lower_limit, upper_limit, x_var_pre, eo, false, true)) { + set(mbak); + return true; + } + if(simplify_first) set(mbak); + return false; + } + } else if(COMPARISON_IS_EQUAL_OR_GREATER(cr)) { + if(replace_abs(mbak, *mabs, true)) { + mbak.replace(x_var, x_var_pre); + CALCULATOR->endTemporaryStopMessages(true); + if(mbak.integrate(lower_limit, upper_limit, x_var_pre, eo, false, true)) { + set(mbak); + return true; + } + if(simplify_first) set(mbak); + return false; + } + } + } else if(cr1 == COMPARISON_RESULT_LESS && cr2 == COMPARISON_RESULT_GREATER) { + MathStructure mtest((*mabs)[0]); + mtest.replace(x_var, lower_limit); + ComparisonResult cr = mtest.compare(m_zero); + MathStructure minteg1(mbak), minteg2; + b = false; + if(COMPARISON_IS_EQUAL_OR_LESS(cr)) { + if(replace_abs(minteg1, *mabs, false)) b = true; + } else if(COMPARISON_IS_EQUAL_OR_GREATER(cr)) { + if(replace_abs(minteg1, *mabs, true)) b = true; + } + if(b) { + minteg1.replace(x_var, x_var_pre); + CALCULATOR->beginTemporaryStopMessages(); + b = minteg1.integrate(lower_limit, m0, x_var_pre, eo, false, true); + b_exit = CALCULATOR->endTemporaryStopMessages(NULL, NULL, MESSAGE_ERROR) == 0; + if(!b_exit) b = false; + } + if(b) { + mtest = (*mabs)[0]; + mtest.replace(x_var, upper_limit); + cr = mtest.compare(m_zero); + minteg2 = mbak; + b = false; + if(COMPARISON_IS_EQUAL_OR_LESS(cr)) { + if(replace_abs(minteg2, *mabs, false)) b = true; + } else if(COMPARISON_IS_EQUAL_OR_GREATER(cr)) { + if(replace_abs(minteg2, *mabs, true)) b = true; + } + } + if(b) { + minteg2.replace(x_var, x_var_pre); + CALCULATOR->beginTemporaryStopMessages(); + b = minteg2.integrate(m0, upper_limit, x_var_pre, eo, false, true); + b_exit = CALCULATOR->endTemporaryStopMessages(NULL, NULL, MESSAGE_ERROR) == 0; + if(!b_exit) b = false; + } + if(b) { + CALCULATOR->endTemporaryStopMessages(true); + set(minteg1); + add(minteg2); + return true; + } + } + } else if(m0.isLogicalOr() && m0.size() <= 10) { + vector zeroes; + bool b = true; + for(size_t i = 0; i < m0.size(); i++) { + if(!m0[i].isComparison() || m0[i].comparisonType() != COMPARISON_EQUALS || m0[i][0] != x_var) { + b = false; + break; + } else { + for(size_t i2 = 0; i2 < zeroes.size(); i2++) { + ComparisonResult cr = m0[i][1].compare(zeroes[i2]); + if(cr == COMPARISON_RESULT_GREATER) {zeroes.insert(zeroes.begin() + i2, m0[i][1]); break;} + else if(cr != COMPARISON_RESULT_LESS) {b = false; break;} + } + if(!b) break; + if(zeroes.size() == i) zeroes.push_back(m0[i][1]); + } + } + if(b) { + vector integs; + for(size_t i = 0; i <= zeroes.size(); i++) { + MathStructure mtest((*mabs)[0]); + if(i == 0) { + mtest.replace(x_var, b_reversed ? upper_limit : lower_limit); + } else if(i == zeroes.size()) { + mtest.replace(x_var, b_reversed ? lower_limit : upper_limit); + } else { + MathStructure mrepl(zeroes[i - 1]); + mrepl += zeroes[i]; + mrepl *= nr_half; + mtest.replace(x_var, mrepl); + } + ComparisonResult cr = mtest.compare(m_zero); + MathStructure minteg(mbak); + b = false; + if(COMPARISON_IS_EQUAL_OR_LESS(cr)) { + if(replace_abs(minteg, *mabs, false)) b = true; + } else if(COMPARISON_IS_EQUAL_OR_GREATER(cr)) { + if(replace_abs(minteg, *mabs, true)) b = true; + } + if(b) { + minteg.replace(x_var, x_var_pre); + CALCULATOR->beginTemporaryStopMessages(); + b = minteg.integrate(i == 0 ? (b_reversed ? upper_limit : lower_limit) : zeroes[i - 1], i == zeroes.size() ? (b_reversed ? lower_limit : upper_limit) : zeroes[i], x_var_pre, eo, false, true); + b_exit = CALCULATOR->endTemporaryStopMessages(NULL, NULL, MESSAGE_ERROR) == 0; + if(!b_exit) b = false; + if(b_reversed) minteg.negate(); + } + if(!b) break; + integs.push_back(minteg); + } + if(b) { + for(size_t i = 0; i < integs.size(); i++) { + if(i == 0) set(integs[i]); + else add(integs[i], true); + } + CALCULATOR->endTemporaryStopMessages(true); + return true; + } + } + } + if(b_exit) { + CALCULATOR->endTemporaryStopMessages(); + CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); + if(simplify_first) { + set(mbak); + replace(x_var, x_var_pre); + } + return false; + } + } + CALCULATOR->endTemporaryStopMessages(); + if(mstruct.containsInterval() && eo.approximation == APPROXIMATION_EXACT) { + CALCULATOR->error(false, _("Unable to integrate the expression exact."), NULL); + if(simplify_first) { + set(mstruct); + replace(x_var, x_var_pre); + } + return false; + } + } else { + CALCULATOR->endTemporaryStopMessages(); + CALCULATOR->endTemporaryStopMessages(); + restore_intervals(mstruct, mbak, vars, eo); + } + + if(m1.isNumber() && m1.number().isReal() && m2.isNumber() && m2.number().isReal()) { + + if(eo.approximation != APPROXIMATION_EXACT) eo2.approximation = APPROXIMATION_APPROXIMATE; + + mstruct = mstruct_pre; + mstruct.eval(eo2); + + eo2.interval_calculation = INTERVAL_CALCULATION_SIMPLE_INTERVAL_ARITHMETIC; + eo2.warn_about_denominators_assumed_nonzero = false; + + Number nr_begin, nr_end; + bool b_reversed = false; + if(m1.number().isGreaterThan(m2.number())) { + nr_begin = m2.number(); + nr_end = m1.number(); + b_reversed = true; + } else { + nr_begin = m1.number(); + nr_end = m2.number(); + } + if(eo.approximation != APPROXIMATION_EXACT) { + Number nr; + CALCULATOR->beginTemporaryStopMessages(); + if(romberg(mstruct, nr, x_var, eo2, nr_begin, nr_end)) { + CALCULATOR->endTemporaryStopMessages(); + if(b_reversed) nr.negate(); + if(!force_numerical) CALCULATOR->error(false, _("Definite integral was approximated."), NULL); + set(nr); + return true; + } + CALCULATOR->endTemporaryStopMessages(); + CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); + if(simplify_first) { + set(mbak); + replace(x_var, x_var_pre); + } + return false; + } + Number nr_range(nr_end); + nr_range -= nr_begin; + MathStructure merr(mstruct); + CALCULATOR->beginTemporaryStopMessages(); + eo2.expand = false; + for(size_t i = 0; i < 4; i++) { + if(merr.containsFunctionId(FUNCTION_ID_DIFFERENTIATE, true) > 0 || !merr.differentiate(x_var, eo2)) { + break; + } + merr.calculatesub(eo2, eo2, true); + if(CALCULATOR->aborted() || merr.countTotalChildren() > 200) { + break; + } + } + eo2.expand = eo.expand; + CALCULATOR->endTemporaryStopMessages(); + if(merr.isZero()) { + Number nr; + if(numerical_integration(mstruct, nr, x_var, eo2, nr_begin, nr_end, 12, 0)) { + if(b_reversed) nr.negate(); + set(nr); + return true; + } + } + CALCULATOR->error(false, _("Unable to integrate the expression exact."), NULL); + if(simplify_first) { + set(mbak); + replace(x_var, x_var_pre); + } + return false; + } + if(simplify_first) { + set(mbak); + replace(x_var, x_var_pre); + } + CALCULATOR->error(false, _("Unable to integrate the expression."), NULL); + return false; +} + + + diff -Nru libqalculate-3.6.0/libqalculate/MathStructure-isolatex.cc libqalculate-3.7.0/libqalculate/MathStructure-isolatex.cc --- libqalculate-3.6.0/libqalculate/MathStructure-isolatex.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure-isolatex.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,5600 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "BuiltinFunctions.h" +#include "MathStructure.h" +#include "Calculator.h" +#include "Number.h" +#include "Function.h" +#include "Variable.h" +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +bool combine_powers(MathStructure &m, const MathStructure &x_var, const EvaluationOptions &eo) { + bool b_ret = false; + if(!m.isMultiplication()) { + for(size_t i = 0; i < m.size(); i++) { + if(combine_powers(m[i], x_var, eo)) { + m.childUpdated(i + 1); + b_ret = true; + } + } + return b_ret; + } + for(size_t i = 0; i < m.size() - 1; i++) { + if(m[i].isPower() && !m[i][0].contains(x_var, true) && m[i][1].contains(x_var, true)) { + for(size_t i2 = i + 1; i2 < m.size(); i2++) { + // a^(f(x))*b^(g(x))=e^(f(x)/ln(a)+g(x)/ln(b)) + if(m[i2].isPower() && !m[i2][0].contains(x_var, true) && m[i2][1].contains(x_var, true)) { + if(m[i2][0] != m[i][0]) { + if(!m[i2][0].isVariable() || m[i2][0].variable()->id() != VARIABLE_ID_E) { + MathStructure mln(m[i2][0]); + mln.transformById(FUNCTION_ID_LOG); + m[i2][1].calculateMultiply(mln, eo); + } + if(!m[i][0].isVariable() || m[i][0].variable()->id() != VARIABLE_ID_E) { + MathStructure mln(m[i][0]); + mln.transformById(FUNCTION_ID_LOG); + m[i][1].calculateMultiply(mln, eo); + m[i][0] = CALCULATOR->getVariableById(VARIABLE_ID_E); + m[i].childrenUpdated(); + } + } + m[i2][1].ref(); + m[i][1].add_nocopy(&m[i2][1], true); + m[i][1].calculateAddLast(eo); + m[i].childUpdated(2); + m.childUpdated(i + 1); + m.delChild(i2 + 1); + b_ret = true; + } else { + i2++; + } + } + if(b_ret && m.size() == 1) { + m.setToChild(1, true); + } + return b_ret; + } + } + return false; +} + +bool isUnit_multi(const MathStructure &mstruct) { + if(!mstruct.isMultiplication() || mstruct.size() == 0) return false; + for(size_t i = 0; i < mstruct.size(); i++) { + if((i > 0 || !mstruct[i].isNumber()) && !mstruct[i].isUnit_exp()) return false; + } + return true; +} + +MathStructure *find_mvar(MathStructure &m, const MathStructure &x_var, MathStructure &mcoeff) { + if(m.isAddition()) { + MathStructure *mvar = find_mvar(m[0], x_var, mcoeff); + if(!mvar) return NULL; + for(size_t i = 1; i < m.size(); i++) { + MathStructure mcoeffi; + MathStructure *mvari = find_mvar(m[i], x_var, mcoeffi); + if(!mvari || !mvari->equals(*mvar)) return NULL; + mcoeff.add(mcoeffi, true); + } + mcoeff.evalSort(false); + return mvar; + } + if(m.isMultiplication()) { + MathStructure *mvar = NULL; + size_t i_x = 0; + for(size_t i = 0; i < m.size(); i++) { + if(m[i].contains(x_var, true)) { + if(mvar) return NULL; + mvar = &m[i]; + i_x = i; + } + } + mcoeff = m; + mcoeff.delChild(i_x + 1, true); + return mvar; + } + mcoeff = m_one; + return &m; +} + +bool get_multiplier(const MathStructure &mstruct, const MathStructure &xvar, MathStructure &mcoeff, size_t exclude_i = (size_t) -1) { + const MathStructure *mcur = NULL; + mcoeff.clear(); + for(size_t i = 0; ; i++) { + if(mstruct.isAddition()) { + if(i == exclude_i) i++; + if(i >= mstruct.size()) break; + mcur = &mstruct[i]; + } else { + mcur = &mstruct; + } + if((*mcur) == xvar) { + if(mcoeff.isZero()) mcoeff.set(1, 1, 0); + else mcoeff.add(m_one, true); + } else if(mcur->isMultiplication()) { + bool b = false; + for(size_t i2 = 0; i2 < mcur->size(); i2++) { + if((*mcur)[i2] == xvar) { + b = true; + if(mcoeff.isZero()) { + if(mcur->size() == 1) { + mcoeff.set(1, 1, 0); + } else { + for(size_t i3 = 0; i3 < mcur->size(); i3++) { + if(i3 != i2) { + if(mcoeff.isZero()) mcoeff = (*mcur)[i3]; + else mcoeff.multiply((*mcur)[i3], true); + } + } + } + } else if(mcur->size() == 1) { + mcoeff.add(m_one, true); + } else { + mcoeff.add(m_zero, true); + for(size_t i3 = 0; i3 < mcur->size(); i3++) { + if(i3 != i2) { + if(mcoeff[mcoeff.size() - 1].isZero()) mcoeff[mcoeff.size() - 1] = (*mcur)[i3]; + else mcoeff[mcoeff.size() - 1].multiply((*mcur)[i3], true); + } + } + } + break; + } else if(xvar.isMultiplication() && xvar.size() > 0 && (*mcur)[i2] == xvar[0]) { + if(mcur->size() - i2 < xvar.size()) break; + b = true; + for(size_t i3 = 1; i3 < xvar.size(); i3++) { + if((*mcur)[i2 + i3] != xvar[i3]) {b = false; break;} + } + if(!b) break; + if(mcoeff.isZero()) { + if(mcur->size() == xvar.size()) { + mcoeff.set(1, 1, 0); + } else { + for(size_t i3 = 0; i3 < mcur->size(); i3++) { + if(i3 < i2 || i3 >= i2 + xvar.size()) { + if(mcoeff.isZero()) mcoeff = (*mcur)[i3]; + else mcoeff.multiply((*mcur)[i3], true); + } + } + } + } else if(mcur->size() == xvar.size()) { + mcoeff.add(m_one, true); + } else { + mcoeff.add(m_zero, true); + for(size_t i3 = 0; i3 < mcur->size(); i3++) { + if(i3 < i2 || i3 >= i2 + xvar.size()) { + if(mcoeff[mcoeff.size() - 1].isZero()) mcoeff[mcoeff.size() - 1] = (*mcur)[i3]; + else mcoeff[mcoeff.size() - 1].multiply((*mcur)[i3], true); + } + } + } + break; + } + } + if(!b) { + mcoeff.clear(); + return false; + } + } else { + mcoeff.clear(); + return false; + } + if(!mstruct.isAddition()) break; + } + if(mcoeff.isZero()) return false; + mcoeff.evalSort(); + return true; +} +bool get_power(const MathStructure &mstruct, const MathStructure &xvar, MathStructure &mpow) { + if(mstruct == xvar) { + mpow = m_one; + return true; + } + if(mstruct.isPower() && mstruct[0] == xvar) { + mpow = mstruct[1]; + return true; + } + for(size_t i = 0; i < mstruct.size(); i++) { + if(get_power(mstruct[i], xvar, mpow)) return true; + } + return false; +} +const MathStructure *get_power_term(const MathStructure &mstruct, const MathStructure &xvar) { + if(mstruct == xvar) { + return &mstruct; + } + if(mstruct.isPower() && mstruct[0] == xvar) { + return &mstruct; + } + for(size_t i = 0; i < mstruct.size(); i++) { + const MathStructure *mterm = get_power_term(mstruct[i], xvar); + if(mterm) return mterm; + } + return NULL; +} + +int test_comparisons(const MathStructure &msave, MathStructure &mthis, const MathStructure &x_var, const EvaluationOptions &eo, bool sub, int alt) { + if(mthis.isComparison() && mthis[0] == x_var) { + if(mthis.comparisonType() != COMPARISON_EQUALS && mthis.comparisonType() != COMPARISON_NOT_EQUALS) return 1; + MathStructure mtest; + EvaluationOptions eo2 = eo; + eo2.calculate_functions = false; + eo2.isolate_x = false; + eo2.test_comparisons = true; + eo2.warn_about_denominators_assumed_nonzero = false; + eo2.assume_denominators_nonzero = false; + eo2.approximation = APPROXIMATION_APPROXIMATE; + mtest = mthis; + mtest.eval(eo2); + if(mtest.isComparison()) { + eo2.calculate_functions = true; + mtest = msave; + mtest.replace(x_var, mthis[1]); + if(CALCULATOR->usesIntervalArithmetic()) { + MathStructure mtest2(mtest[0]); + if(!mtest[1].isZero()) { + mtest2.subtract(mtest[1]); + } + CALCULATOR->beginTemporaryStopMessages(); + mtest2.eval(eo2); + if(CALCULATOR->endTemporaryStopMessages() > 0) { + if(!sub) mthis = msave; + return -1; + } + if(mtest2.isNumber()) { + if(mtest.comparisonType() == COMPARISON_LESS || mtest.comparisonType() == COMPARISON_EQUALS_LESS) { + if(!mtest2.number().hasImaginaryPart() && mtest2.number().lowerEndPoint().isNonPositive()) return 1; + } else if(mtest.comparisonType() == COMPARISON_GREATER || mtest.comparisonType() == COMPARISON_EQUALS_GREATER) { + if(!mtest2.number().hasImaginaryPart() && mtest2.number().upperEndPoint().isNonNegative()) return 1; + } else if(mtest.comparisonType() == COMPARISON_NOT_EQUALS) { + if(!mtest2.number().isNonZero()) return 1; + else if(mtest2.number().isInterval() || mtest2.number().isRational()) {mthis = m_one; return 0;} + } else { + if(!mtest2.number().isNonZero()) return 1; + else if(mtest2.number().isInterval() || mtest2.number().isRational()) {mthis.clear(); return 0;} + } + } else if(mtest2.isUnit_exp()) { + if(mtest.comparisonType() == COMPARISON_GREATER || mtest.comparisonType() == COMPARISON_EQUALS_GREATER) return 1; + else if(mtest.comparisonType() == COMPARISON_EQUALS) {mthis.clear(); return 0;} + else if(mtest.comparisonType() == COMPARISON_NOT_EQUALS) {mthis = m_one; return 0;} + } else if(isUnit_multi(mtest2)) { + if(mtest.comparisonType() == COMPARISON_LESS || mtest.comparisonType() == COMPARISON_EQUALS_LESS) { + if(mtest2[0].isNumber() && !mtest2[0].number().hasImaginaryPart() && mtest2[0].number().lowerEndPoint().isNonPositive()) return 1; + } else if(mtest.comparisonType() == COMPARISON_GREATER || mtest.comparisonType() == COMPARISON_EQUALS_GREATER) { + if(!mtest2[0].isNumber() || (!mtest2[0].number().hasImaginaryPart() && mtest2.number().upperEndPoint().isNonNegative())) return 1; + + } else if(mtest.comparisonType() == COMPARISON_NOT_EQUALS) { + if(!mtest2[0].isNumber()) {mthis = m_one; return 0;} + if(!mtest2[0].number().isNonZero()) return 1; + else if(mtest2[0].number().isInterval() || mtest2[0].number().isRational()) {mthis = m_one; return 0;} + } else { + if(!mtest2[0].isNumber()) {mthis.clear(); return 0;} + if(!mtest2[0].number().isNonZero()) return 1; + else if(mtest2[0].number().isInterval() || mtest2[0].number().isRational()) {mthis.clear(); return 0;} + } + } + + } + CALCULATOR->beginTemporaryStopMessages(); + if(mtest[1].isZero() && mtest[0].isAddition() && mtest[0].size() > 1) { + mtest[1].subtract(mtest[0][0]); + mtest[0].delChild(1, true); + } + mtest.eval(eo2); + if(CALCULATOR->endTemporaryStopMessages() > 0) { + if(!sub) mthis = msave; + return -1; + } + if(mtest.isNumber()) { + if(mtest.number().getBoolean() == 1) { + return 1; + } else if(mtest.number().getBoolean() == 0) { + if(mtest.isApproximate() && mtest.comparisonType() != COMPARISON_EQUALS && mtest.comparisonType() != COMPARISON_NOT_EQUALS) return -1; + if(mtest.comparisonType() == COMPARISON_EQUALS) mthis.clear(); + else if(mtest.comparisonType() == COMPARISON_NOT_EQUALS) mthis = m_one; + return 0; + } + } + } else { + mthis = mtest; + if(mtest.isNumber()) { + if(mtest.number().getBoolean() == 0) { + return 0; + } + } + return 1; + } + if(!sub) mthis = msave; + return -1; + } + if(alt && mthis.isComparison()) { + if(!sub && alt != 1) mthis = msave; + return -1; + } + if(mthis.isLogicalOr() || mthis.isLogicalAnd()) { + int i_ret = 1; + for(size_t i = 0; i < mthis.size(); i++) { + if(test_comparisons(msave, mthis[i], x_var, eo, true, alt) < 0) { + if(alt != 1) { + mthis = msave; + return -1; + } + i_ret = -1; + } + } + return i_ret; + } + if(sub) return 1; + else return -1; +} + +bool isx_deabsify(MathStructure &mstruct) { + switch(mstruct.type()) { + case STRUCT_FUNCTION: { + if(mstruct.function()->id() == FUNCTION_ID_ABS && mstruct.size() == 1 && mstruct[0].representsNonComplex(true)) { + mstruct.setToChild(1, true); + return true; + } + break; + } + case STRUCT_POWER: { + if(mstruct[1].isMinusOne()) { + return isx_deabsify(mstruct[0]); + } + break; + } + case STRUCT_MULTIPLICATION: { + bool b = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(isx_deabsify(mstruct[i])) b = true; + } + return b; + } + default: {} + } + return false; +} + +int newton_raphson(const MathStructure &mstruct, MathStructure &x_value, const MathStructure &x_var, const EvaluationOptions &eo) { + if(mstruct == x_var) { + x_value = m_zero; + return 1; + } + + if(!mstruct.isAddition()) return -1; + if(mstruct.size() == 2) { + if(mstruct[1] == x_var && mstruct[0].isNumber() && mstruct[0].number().isReal()) { + x_value = mstruct[0]; + x_value.number().negate(); + return 1; + } + if(mstruct[0] == x_var && mstruct[1].isNumber() && mstruct[1].number().isReal()) { + x_value = mstruct[1]; + x_value.number().negate(); + return 1; + } + } + + Number nr; + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i] != x_var) { + switch(mstruct[i].type()) { + case STRUCT_NUMBER: {nr = mstruct[i].number(); break;} + case STRUCT_MULTIPLICATION: { + if(mstruct[i].size() == 2 && mstruct[i][0].isNumber() && (mstruct[i][1] == x_var || (mstruct[i][1].isPower() && mstruct[i][1][0] == x_var && mstruct[i][1][1].isNumber() && mstruct[i][1][1].number().isInteger() && mstruct[i][1][1].number().isPositive()))) { + break; + } + return -1; + } + case STRUCT_POWER: { + if(mstruct[i][0] == x_var && mstruct[i][1].isNumber() && mstruct[i][1].number().isInteger() && mstruct[i][1].number().isPositive()) { + break; + } + } + default: {return -1;} + } + } + } + + MathStructure mdiff(mstruct); + if(!mdiff.differentiate(x_var, eo)) return -1; + MathStructure minit(mstruct); + minit.divide(mdiff); + minit.negate(); + minit.add(x_var); + minit.eval(eo); + + Number nr_target_high(1, 1, -(PRECISION) - 10); + Number nr_target_low(1, 1, 0); + nr_target_low -= nr_target_high; + nr_target_high++; + MathStructure mguess(2, 1, 0); + Number ndeg(mstruct.degree(x_var)); + bool overflow = false; + int ideg = ndeg.intValue(&overflow); + if(overflow || ideg > 100) return -1; + nr.negate(); + if(!nr.isZero()) { + bool b_neg = nr.isNegative(); + if(b_neg) nr.negate(); + if(nr.root(ndeg)) { + if(ndeg.isOdd() && b_neg) nr.negate(); + mguess = nr; + } else { + nr = mguess.number(); + } + } else { + nr = mguess.number(); + } + + for(int i = 0; i < 100 + PRECISION + ideg * 2; i++) { + + mguess.number().setToFloatingPoint(); + if(mguess.number().hasImaginaryPart()) mguess.number().internalImaginary()->setToFloatingPoint(); + + if(CALCULATOR->aborted()) return -1; + + MathStructure mtest(minit); + mtest.replace(x_var, mguess); + mtest.eval(eo); + + Number nrdiv(mguess.number()); + if(!mtest.isNumber() || !nrdiv.divide(mtest.number())) { + return -1; + } + + if(nrdiv.isLessThan(nr_target_high) && nrdiv.isGreaterThan(nr_target_low)) { + if(CALCULATOR->usesIntervalArithmetic()) { + if(!x_value.number().setInterval(mguess.number(), mtest.number())) return -1; + } else { + x_value = mtest; + if(x_value.number().precision() < 0 || x_value.number().precision() > PRECISION + 10) x_value.number().setPrecision(PRECISION + 10); + } + x_value.numberUpdated(); + return 1; + } + mguess = mtest; + } + + nr.negate(); + mguess = nr; + for(int i = 0; i < 100 + PRECISION + ideg * 2; i++) { + + mguess.number().setToFloatingPoint(); + if(mguess.number().hasImaginaryPart()) mguess.number().internalImaginary()->setToFloatingPoint(); + + if(CALCULATOR->aborted()) return -1; + + MathStructure mtest(minit); + mtest.replace(x_var, mguess); + mtest.eval(eo); + + Number nrdiv(mguess.number()); + if(!mtest.isNumber() || !nrdiv.divide(mtest.number())) { + return -1; + } + if(nrdiv.isLessThan(nr_target_high) && nrdiv.isGreaterThan(nr_target_low)) { + if(CALCULATOR->usesIntervalArithmetic()) { + if(!x_value.number().setInterval(mguess.number(), mtest.number())) return -1; + } else { + x_value = mtest; + if(x_value.number().precision() < 0 || x_value.number().precision() > PRECISION + 10) x_value.number().setPrecision(PRECISION + 10); + } + x_value.numberUpdated(); + return 1; + } + mguess = mtest; + } + + return 0; + +} + +int find_interval_precision(const MathStructure &mstruct); + +int find_interval_precision(const MathStructure &mstruct) { + if(mstruct.isNumber()) { + return mstruct.number().precision(1); + } + int iv_prec = -1; + for(size_t i = 0; i < mstruct.size(); i++) { + if(iv_prec > -1) { + if(find_interval_precision(mstruct[i]) > -1) return 0; + } else { + iv_prec = find_interval_precision(mstruct[i]); + } + } + return iv_prec; +} + +MathStructure *find_abs_sgn(MathStructure &mstruct, const MathStructure &x_var); +MathStructure *find_abs_sgn(MathStructure &mstruct, const MathStructure &x_var) { + switch(mstruct.type()) { + case STRUCT_FUNCTION: { + if(((mstruct.function()->id() == FUNCTION_ID_ABS && mstruct.size() == 1) || (mstruct.function()->id() == FUNCTION_ID_SIGNUM && mstruct.size() == 2)) && mstruct[0].contains(x_var, false) && mstruct[0].representsNonComplex()) { + return &mstruct; + } + break; + } + case STRUCT_POWER: { + return find_abs_sgn(mstruct[0], x_var); + } + case STRUCT_ADDITION: {} + case STRUCT_MULTIPLICATION: { + for(size_t i = 0; i < mstruct.size(); i++) { + MathStructure *m = find_abs_sgn(mstruct[i], x_var); + if(m) return m; + } + break; + } + default: {break;} + } + return NULL; +} + +bool is_units_with_multiplier(const MathStructure &mstruct) { + if(!mstruct.isMultiplication() || mstruct.size() == 0 || !mstruct[0].isNumber()) return false; + for(size_t i = 1; i < mstruct.size(); i++) { + if(!mstruct[i].isUnit_exp()) return false; + } + return true; +} + +bool fix_n_multiple(MathStructure &mstruct, const EvaluationOptions &eo, const EvaluationOptions &feo, const MathStructure &x_var) { + bool b_ret = false; + if(mstruct.isComparison()) { + if(mstruct.comparisonType() == COMPARISON_EQUALS && x_var.isVariable() && !x_var.variable()->isKnown() && !((UnknownVariable*) x_var.variable())->interval().isUndefined() && mstruct[1].contains(CALCULATOR->getVariableById(VARIABLE_ID_N))) { + MathStructure mtest(mstruct); + mtest.replace(x_var, ((UnknownVariable*) x_var.variable())->interval()); + EvaluationOptions eo2 = eo; + EvaluationOptions feo2 = feo; + if(eo.approximation == APPROXIMATION_EXACT) { + eo2.approximation = APPROXIMATION_TRY_EXACT; + feo2.approximation = APPROXIMATION_TRY_EXACT; + } + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(CALCULATOR->usesIntervalArithmetic()) { + CALCULATOR->beginTemporaryStopMessages(); + mtest.calculateFunctions(feo2); + if(mtest.isolate_x(eo2, feo2, CALCULATOR->getVariableById(VARIABLE_ID_N))) { + if(CALCULATOR->endTemporaryStopMessages() == 0) { + if(mtest.isZero()) { + mstruct.clear(true); + b_ret = true; + } else if(mtest.isComparison() && mtest.comparisonType() == COMPARISON_EQUALS && mtest[0].isVariable() && mtest[0].variable() == CALCULATOR->getVariableById(VARIABLE_ID_N) && mtest[1].isNumber()) { + if(mtest[1].number().isInteger()) { + mstruct.calculateReplace(CALCULATOR->getVariableById(VARIABLE_ID_N), mtest[1], eo); + b_ret = true; + } else if(mtest[1].number().isInterval()) { + Number nr_int; bool b_multiple = false; + if(mtest[1].number().getCentralInteger(nr_int, &b_multiple)) { + mstruct.calculateReplace(CALCULATOR->getVariableById(VARIABLE_ID_N), nr_int, eo); + b_ret = true; + } else if(!b_multiple) { + mstruct.clear(true); + b_ret = true; + } + } else { + mstruct.clear(true); + b_ret = true; + } + } + } + } else { + CALCULATOR->endTemporaryStopMessages(); + } + } + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + } + } else { + for(size_t i = 0; i < mstruct.size(); i++) { + if(fix_n_multiple(mstruct[i], eo, feo, x_var)) { + mstruct.childUpdated(i + 1); + b_ret = true; + } + } + if(b_ret) mstruct.calculatesub(eo, feo, false); + } + return b_ret; +} + +bool MathStructure::isolate_x_sub(const EvaluationOptions &eo, EvaluationOptions &eo2, const MathStructure &x_var, MathStructure *morig) { + if(!isComparison()) { + cout << "isolate_x_sub: " << *this << " is not a comparison." << endl; + return false; + } + + if(CHILD(0) == x_var) return false; + if(contains(x_var, true) <= 0) return false; + + if(CALCULATOR->aborted()) return false; + + switch(CHILD(0).type()) { + case STRUCT_ADDITION: { + bool b = false; + // x+y=z => x=z-y + for(size_t i = 0; i < CHILD(0).size();) { + if(!CHILD(0)[i].contains(x_var)) { + CHILD(0)[i].calculateNegate(eo2); + CHILD(0)[i].ref(); + CHILD(1).add_nocopy(&CHILD(0)[i], true); + CHILD(1).calculateAddLast(eo2); + CHILD(0).delChild(i + 1); + b = true; + } else { + i++; + } + } + if(b) { + CHILD_UPDATED(0); + CHILD_UPDATED(1); + if(CHILD(0).size() == 1) { + CHILD(0).setToChild(1, true); + } else if(CHILD(0).size() == 0) { + CHILD(0).clear(true); + } + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } + if(CALCULATOR->aborted()) return false; + + // ax^(2n)+bx^n=c + if(CHILD(0).size() >= 2 && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { + bool sqpow = false, nopow = false; + MathStructure mstruct_a, mstruct_b, mpow_a, mpow_b; + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CHILD(0)[i] == x_var || (CHILD(0)[i].isPower() && CHILD(0)[i][0] == x_var)) { + b = false; + const MathStructure *mexp = &m_one; + if(CHILD(0)[i] != x_var) mexp = &CHILD(0)[i][1]; + if(nopow) { + if(*mexp == mpow_b) { + mstruct_b.add(m_one, true); + b = true; + } else if(!sqpow) { + MathStructure mtest(*mexp); + mtest.calculateMultiply(nr_half, eo); + if(mtest == mpow_b) { + mpow_a = *mexp; + mstruct_a.set(m_one, true); + b = true; + } else { + mtest = *mexp; + mtest.calculateMultiply(nr_two, eo); + if(mtest == mpow_b) { + mpow_a = mpow_b; + mpow_b = *mexp; + mstruct_a = mstruct_b; + mstruct_b.set(m_one, true); + b = true; + } + } + if(b) sqpow = true; + } else if(*mexp == mpow_a) { + mstruct_a.add(m_one, true); + b = true; + } + } else if(sqpow) { + if(*mexp == mpow_a) { + mstruct_a.add(m_one, true); + b = true; + } else { + MathStructure mtest(*mexp); + mtest.calculateMultiply(nr_two, eo); + if(mtest == mpow_a) { + mpow_b = *mexp; + mstruct_b.set(m_one, true); + b = true; + } else { + mtest = *mexp; + mtest.calculateMultiply(nr_half, eo); + if(mtest == mpow_a) { + mpow_b = mpow_a; + mpow_a = *mexp; + mstruct_b = mstruct_a; + mstruct_a.set(m_one, true); + b = true; + } + } + if(b) nopow = true; + } + } else { + if(mexp->isOne()) { + mpow_b = *mexp; + nopow = true; + mstruct_b.set(m_one); + } else { + mpow_a = *mexp; + sqpow = true; + mstruct_a.set(m_one); + } + b = true; + } + if(!b) { + sqpow = false; + nopow = false; + break; + } + } else if(CHILD(0)[i].isMultiplication()) { + for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { + if(CHILD(0)[i][i2] == x_var || (CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][0] == x_var)) { + b = false; + const MathStructure *mexp = &m_one; + if(CHILD(0)[i][i2] != x_var) mexp = &CHILD(0)[i][i2][1]; + if(nopow) { + if(*mexp == mpow_b) { + MathStructure *madd = new MathStructure(CHILD(0)[i]); + madd->delChild(i2 + 1, true); + mstruct_b.add_nocopy(madd, true); + b = true; + } else if(!sqpow) { + MathStructure mtest(*mexp); + mtest.calculateMultiply(nr_half, eo); + if(mtest == mpow_b) { + mpow_a = *mexp; + mstruct_a = CHILD(0)[i]; + mstruct_a.delChild(i2 + 1, true); + b = true; + } else { + mtest = *mexp; + mtest.calculateMultiply(nr_two, eo); + if(mtest == mpow_b) { + mpow_a = mpow_b; + mpow_b = *mexp; + mstruct_a = mstruct_b; + mstruct_b = CHILD(0)[i]; + mstruct_b.delChild(i2 + 1, true); + b = true; + } + } + if(b) sqpow = true; + } else if(*mexp == mpow_a) { + MathStructure *madd = new MathStructure(CHILD(0)[i]); + madd->delChild(i2 + 1, true); + mstruct_a.add_nocopy(madd, true); + b = true; + } + } else if(sqpow) { + if(*mexp == mpow_a) { + MathStructure *madd = new MathStructure(CHILD(0)[i]); + madd->delChild(i2 + 1, true); + mstruct_a.add_nocopy(madd, true); + b = true; + } else { + MathStructure mtest(*mexp); + mtest.calculateMultiply(nr_two, eo); + if(mtest == mpow_a) { + mpow_b = *mexp; + mstruct_b.add(m_one, true); + mstruct_b = CHILD(0)[i]; + mstruct_b.delChild(i2 + 1, true); + b = true; + } else { + mtest = *mexp; + mtest.calculateMultiply(nr_half, eo); + if(mtest == mpow_a) { + mpow_b = mpow_a; + mpow_a = *mexp; + mstruct_b = mstruct_a; + mstruct_a = CHILD(0)[i]; + mstruct_a.delChild(i2 + 1, true); + b = true; + } + } + if(b) nopow = true; + } + } else { + if(mexp->isOne()) { + mpow_b = *mexp; + nopow = true; + mstruct_b = CHILD(0)[i]; + mstruct_b.delChild(i2 + 1, true); + } else { + mpow_a = *mexp; + sqpow = true; + mstruct_a = CHILD(0)[i]; + mstruct_a.delChild(i2 + 1, true); + } + b = true; + } + if(!b) { + sqpow = false; + nopow = false; + break; + } + } else if(CHILD(0)[i][i2].contains(x_var)) { + sqpow = false; + nopow = false; + break; + } + } + if(!sqpow && !nopow) break; + } else { + sqpow = false; + nopow = false; + break; + } + } + b = false; + if(sqpow && nopow && !mstruct_a.representsZero(true)) { + b = mstruct_a.representsNonZero(true); + if(!b && eo2.approximation == APPROXIMATION_EXACT) { + MathStructure mtest(mstruct_a); + mtest.add(m_zero, OPERATION_NOT_EQUALS); + EvaluationOptions eo3 = eo2; + eo3.test_comparisons = true; + mtest.calculatesub(eo3, eo, false); + b = mtest.isOne(); + } + } + + if(b) { + int a_iv = find_interval_precision(mstruct_a); + int b_iv = find_interval_precision(mstruct_b); + int c_iv = find_interval_precision(CHILD(1)); + if(a_iv >= 0 && (c_iv < 0 || c_iv > a_iv) && CHILD(1).representsNonZero()) { + //x=(-2c)/(b+/-sqrt(b^2-4ac)) + MathStructure mbak(*this); + bool stop_iv = false; + if(c_iv >= 0 && c_iv <= PRECISION) { + stop_iv = true; + } else if(b_iv >= 0) { + MathStructure mstruct_bl; + MathStructure mstruct_bu; + stop_iv = true; + if(mstruct_b.isNumber() && mstruct_b.number().isNonZero() && !mstruct_b.number().hasImaginaryPart()) { + mstruct_bl = mstruct_b.number().lowerEndPoint(); + mstruct_bu = mstruct_b.number().upperEndPoint(); + stop_iv = false; + } else if(is_units_with_multiplier(mstruct_b) && mstruct_b[0].number().isNonZero() && !mstruct_b[0].number().hasImaginaryPart()) { + mstruct_bl = mstruct_b; + mstruct_bl[0].number() = mstruct_b[0].number().lowerEndPoint(); + mstruct_bu = mstruct_b; + mstruct_bu[0].number() = mstruct_b[0].number().upperEndPoint(); + stop_iv = false; + } + if(!stop_iv) { + // Lower b+sqrt(b^2-4ac) + MathStructure b2l(mstruct_bl); + b2l.calculateRaise(nr_two, eo2); + MathStructure ac(4, 1); + ac.calculateMultiply(mstruct_a, eo2); + ac.calculateMultiply(CHILD(1), eo2); + b2l.calculateAdd(ac, eo2); + + b2l.calculateRaise(nr_half, eo2); + MathStructure mstruct_1l(mstruct_bl); + mstruct_1l.calculateAdd(b2l, eo2); + + // Upper -b+sqrt(b^2-4ac) + MathStructure b2u(mstruct_bu); + b2u.calculateRaise(nr_two, eo2); + b2u.calculateAdd(ac, eo2); + + b2u.calculateRaise(nr_half, eo2); + MathStructure mstruct_1u(mstruct_bu); + mstruct_1u.calculateAdd(b2u, eo2); + + MathStructure mstruct_1(mstruct_1l); + mstruct_1.transform(STRUCT_FUNCTION, mstruct_1u); + mstruct_1.setFunctionId(FUNCTION_ID_INTERVAL); + mstruct_1.calculateFunctions(eo, false); + + // Lower -b-sqrt(b^2-4ac) + MathStructure mstruct_2l(mstruct_bl); + mstruct_2l.calculateSubtract(b2l, eo2); + + // Upper -b-sqrt(b^2-4ac) + MathStructure mstruct_2u(mstruct_bu); + mstruct_2u.calculateSubtract(b2u, eo2); + + MathStructure mstruct_2(mstruct_2l); + mstruct_2.transform(STRUCT_FUNCTION, mstruct_2u); + mstruct_2.setFunctionId(FUNCTION_ID_INTERVAL); + mstruct_2.calculateFunctions(eo, false); + + MathStructure mstruct_c(CHILD(1)); + mstruct_c.calculateMultiply(nr_two, eo2); + + mstruct_1.calculateInverse(eo2); + mstruct_2.calculateInverse(eo2); + mstruct_1.calculateMultiply(mstruct_c, eo2); + mstruct_2.calculateMultiply(mstruct_c, eo2); + + CHILD(0) = x_var; + if(!mpow_b.isOne()) {CHILD(0) ^= mpow_b; CHILD_UPDATED(0);} + if(mstruct_1 == mstruct_2) { + CHILD(1) = mstruct_1; + isolate_x_sub(eo, eo2, x_var, morig); + } else { + CHILD(1) = mstruct_1; + MathStructure *mchild2 = new MathStructure(CHILD(0)); + isolate_x_sub(eo, eo2, x_var, morig); + mchild2->transform(STRUCT_COMPARISON, mstruct_2); + mchild2->setComparisonType(ct_comp); + mchild2->isolate_x_sub(eo, eo2, x_var, morig); + if(ct_comp == COMPARISON_NOT_EQUALS) { + transform_nocopy(STRUCT_LOGICAL_AND, mchild2); + } else { + transform_nocopy(STRUCT_LOGICAL_OR, mchild2); + } + calculatesub(eo2, eo, false); + } + CHILDREN_UPDATED + return true; + } + } + EvaluationOptions eo3 = eo2; + if(b && stop_iv) { + CALCULATOR->beginTemporaryStopIntervalArithmetic(); + eo3.interval_calculation = INTERVAL_CALCULATION_NONE; + bool failed = false; + fix_intervals(*this, eo3, &failed); + if(failed) { + set(mbak); + CALCULATOR->endTemporaryStopIntervalArithmetic(); + b = false; + } + } + if(b) { + MathStructure b2(mstruct_b); + b2.calculateRaise(nr_two, eo3); + MathStructure ac(4, 1); + ac.calculateMultiply(mstruct_a, eo3); + ac.calculateMultiply(CHILD(1), eo3); + b2.calculateAdd(ac, eo3); + + b2.calculateRaise(nr_half, eo3); + MathStructure mstruct_1(mstruct_b); + mstruct_1.calculateAdd(b2, eo3); + MathStructure mstruct_2(mstruct_b); + mstruct_2.calculateSubtract(b2, eo3); + + MathStructure mstruct_c(CHILD(1)); + mstruct_c.calculateMultiply(nr_two, eo3); + + mstruct_1.calculateInverse(eo3); + mstruct_2.calculateInverse(eo3); + mstruct_1.calculateMultiply(mstruct_c, eo3); + mstruct_2.calculateMultiply(mstruct_c, eo3); + + CHILD(0) = x_var; + if(!mpow_b.isOne()) {CHILD(0) ^= mpow_b; CHILD_UPDATED(0);} + if(mstruct_1 == mstruct_2) { + CHILD(1) = mstruct_1; + isolate_x_sub(eo, eo3, x_var, morig); + } else { + CHILD(1) = mstruct_1; + MathStructure *mchild2 = new MathStructure(CHILD(0)); + isolate_x_sub(eo, eo3, x_var, morig); + mchild2->transform(STRUCT_COMPARISON, mstruct_2); + mchild2->setComparisonType(ct_comp); + mchild2->isolate_x_sub(eo, eo3, x_var, morig); + if(ct_comp == COMPARISON_NOT_EQUALS) { + transform_nocopy(STRUCT_LOGICAL_AND, mchild2); + } else { + transform_nocopy(STRUCT_LOGICAL_OR, mchild2); + } + calculatesub(eo3, eo, false); + } + CHILDREN_UPDATED; + if(stop_iv) { + CALCULATOR->endTemporaryStopIntervalArithmetic(); + CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); + fix_intervals(*this, eo2); + } + return true; + } + } else if(CHILD(1).isZero()) { + // x=0 || x=-a/b || (a=0 && b=0) + ComparisonType ct = ct_comp; + CHILD(0) = x_var; + if(!mpow_b.isOne()) {CHILD(0) ^= mpow_b; CHILD_UPDATED(0);} + MathStructure *mchild2 = new MathStructure(CHILD(0)); + CHILD(1) = mstruct_b; + CHILD(1).calculateDivide(mstruct_a, eo2); + CHILD(1).calculateNegate(eo2); + isolate_x_sub(eo, eo2, x_var, morig); + if(!mstruct_a.representsNonZero()) { + MathStructure *mtest = new MathStructure(mstruct_a); + mtest->transform(ct == COMPARISON_NOT_EQUALS ? COMPARISON_EQUALS : COMPARISON_NOT_EQUALS, m_zero); + mtest->calculatesub(eo2, eo, false); + transform_nocopy(ct == COMPARISON_NOT_EQUALS ? STRUCT_LOGICAL_OR : STRUCT_LOGICAL_AND, mtest); + calculatesub(eo2, eo, false); + } + mchild2->transform(ct, m_zero); + mchild2->isolate_x_sub(eo, eo2, x_var, morig); + transform_nocopy(ct == COMPARISON_NOT_EQUALS ? STRUCT_LOGICAL_AND : STRUCT_LOGICAL_OR, mchild2); + if(!mstruct_b.representsNonZero() && !mstruct_a.representsNonZero()) { + MathStructure *mchild3a = new MathStructure(mstruct_a); + mchild3a->transform(ct, m_zero); + MathStructure *mchild3b = new MathStructure(mstruct_b); + mchild3b->transform(ct, m_zero); + mchild3a->transform_nocopy(ct == COMPARISON_NOT_EQUALS ? STRUCT_LOGICAL_OR : STRUCT_LOGICAL_AND, mchild3b); + mchild3a->calculatesub(eo2, eo, false); + add_nocopy(mchild3a, ct == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); + } + calculatesub(eo2, eo, false); + return true; + } else { + // x=(-b+/-sqrt(b^2-4ac))/(2a) + MathStructure mbak(*this); + bool stop_iv = false; + if(a_iv >= 0 && a_iv <= PRECISION) { + stop_iv = true; + } else if(b_iv >= 0) { + MathStructure mstruct_bl; + MathStructure mstruct_bu; + stop_iv = true; + if(mstruct_b.isNumber() && mstruct_b.number().isNonZero() && !mstruct_b.number().hasImaginaryPart()) { + mstruct_bl = mstruct_b.number().lowerEndPoint(); + mstruct_bu = mstruct_b.number().upperEndPoint(); + stop_iv = false; + } else if(is_units_with_multiplier(mstruct_b) && mstruct_b[0].number().isNonZero() && !mstruct_b[0].number().hasImaginaryPart()) { + mstruct_bl = mstruct_b; + mstruct_bl[0].number() = mstruct_b[0].number().lowerEndPoint(); + mstruct_bu = mstruct_b; + mstruct_bu[0].number() = mstruct_b[0].number().upperEndPoint(); + stop_iv = false; + } + if(!stop_iv) { + // Lower -b+sqrt(b^2-4ac) + MathStructure b2l(mstruct_bl); + b2l.calculateRaise(nr_two, eo2); + MathStructure ac(4, 1); + ac.calculateMultiply(mstruct_a, eo2); + ac.calculateMultiply(CHILD(1), eo2); + b2l.calculateAdd(ac, eo2); + + b2l.calculateRaise(nr_half, eo2); + mstruct_bl.calculateNegate(eo2); + MathStructure mstruct_1l(mstruct_bl); + mstruct_1l.calculateAdd(b2l, eo2); + + // Upper -b+sqrt(b^2-4ac) + MathStructure b2u(mstruct_bu); + b2u.calculateRaise(nr_two, eo2); + b2u.calculateAdd(ac, eo2); + + b2u.calculateRaise(nr_half, eo2); + mstruct_bu.calculateNegate(eo2); + MathStructure mstruct_1u(mstruct_bu); + mstruct_1u.calculateAdd(b2u, eo2); + + MathStructure mstruct_1(mstruct_1l); + mstruct_1.transform(STRUCT_FUNCTION, mstruct_1u); + mstruct_1.setFunctionId(FUNCTION_ID_INTERVAL); + mstruct_1.calculateFunctions(eo, false); + + // Lower -b-sqrt(b^2-4ac) + MathStructure mstruct_2l(mstruct_bl); + mstruct_2l.calculateSubtract(b2l, eo2); + + // Upper -b-sqrt(b^2-4ac) + MathStructure mstruct_2u(mstruct_bu); + mstruct_2u.calculateSubtract(b2u, eo2); + + MathStructure mstruct_2(mstruct_2l); + mstruct_2.transform(STRUCT_FUNCTION, mstruct_2u); + mstruct_2.setFunctionId(FUNCTION_ID_INTERVAL); + mstruct_2.calculateFunctions(eo, false); + + mstruct_a.calculateMultiply(nr_two, eo2); + mstruct_a.calculateInverse(eo2); + mstruct_1.calculateMultiply(mstruct_a, eo2); + mstruct_2.calculateMultiply(mstruct_a, eo2); + CHILD(0) = x_var; + if(!mpow_b.isOne()) {CHILD(0) ^= mpow_b; CHILD_UPDATED(0);} + if(mstruct_1 == mstruct_2) { + CHILD(1) = mstruct_1; + isolate_x_sub(eo, eo2, x_var, morig); + } else { + CHILD(1) = mstruct_1; + MathStructure *mchild2 = new MathStructure(CHILD(0)); + isolate_x_sub(eo, eo2, x_var, morig); + mchild2->transform(STRUCT_COMPARISON, mstruct_2); + mchild2->setComparisonType(ct_comp); + mchild2->isolate_x_sub(eo, eo2, x_var, morig); + if(ct_comp == COMPARISON_NOT_EQUALS) { + transform_nocopy(STRUCT_LOGICAL_AND, mchild2); + } else { + transform_nocopy(STRUCT_LOGICAL_OR, mchild2); + } + calculatesub(eo2, eo, false); + } + CHILDREN_UPDATED + return true; + } + } + EvaluationOptions eo3 = eo2; + if(b && stop_iv) { + CALCULATOR->beginTemporaryStopIntervalArithmetic(); + eo3.interval_calculation = INTERVAL_CALCULATION_NONE; + bool failed = false; + fix_intervals(*this, eo3, &failed); + if(failed) { + set(mbak); + CALCULATOR->endTemporaryStopIntervalArithmetic(); + b = false; + } + } + if(b) { + MathStructure b2(mstruct_b); + b2.calculateRaise(nr_two, eo3); + MathStructure ac(4, 1); + ac.calculateMultiply(mstruct_a, eo3); + ac.calculateMultiply(CHILD(1), eo3); + b2.calculateAdd(ac, eo3); + b2.calculateRaise(nr_half, eo3); + mstruct_b.calculateNegate(eo3); + MathStructure mstruct_1(mstruct_b); + mstruct_1.calculateAdd(b2, eo3); + MathStructure mstruct_2(mstruct_b); + mstruct_2.calculateSubtract(b2, eo3); + mstruct_a.calculateMultiply(nr_two, eo3); + mstruct_a.calculateInverse(eo3); + mstruct_1.calculateMultiply(mstruct_a, eo3); + mstruct_2.calculateMultiply(mstruct_a, eo3); + CHILD(0) = x_var; + if(!mpow_b.isOne()) {CHILD(0) ^= mpow_b; CHILD_UPDATED(0);} + if(mstruct_1 == mstruct_2) { + CHILD(1) = mstruct_1; + isolate_x_sub(eo, eo3, x_var, morig); + } else { + CHILD(1) = mstruct_1; + MathStructure *mchild2 = new MathStructure(CHILD(0)); + isolate_x_sub(eo, eo3, x_var, morig); + mchild2->transform(STRUCT_COMPARISON, mstruct_2); + mchild2->setComparisonType(ct_comp); + mchild2->isolate_x_sub(eo, eo3, x_var, morig); + if(ct_comp == COMPARISON_NOT_EQUALS) { + transform_nocopy(STRUCT_LOGICAL_AND, mchild2); + } else { + transform_nocopy(STRUCT_LOGICAL_OR, mchild2); + } + calculatesub(eo3, eo, false); + } + CHILDREN_UPDATED; + if(stop_iv) { + CALCULATOR->endTemporaryStopIntervalArithmetic(); + CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); + fix_intervals(*this, eo2); + } + return true; + } + } + } + } + + if(CALCULATOR->aborted()) return false; + + // a*b^(dx)+cx=0 => -lambertw(a*d*log(b)/c)/(d*log(b)) + // a*b^(dx)+cx=y => (y*d*log(b)-c*lambertw(a*b^(y*d/c)*log(b)/c))/(c*d*log(b)) + if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && CHILD(0).size() > 1) { + combine_powers(*this, x_var, eo2); + size_t i_px = 0, i_mpx = 0; + MathStructure mbak(*this); + MathStructure *mvar = NULL, *m_b_p; + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CHILD(0)[i].isMultiplication()) { + for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { + if(CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][1].contains(x_var) && !CHILD(0)[i][i2][0].contains(x_var)) { + mvar = &CHILD(0)[i][i2][1]; + m_b_p = &CHILD(0)[i][i2][0]; + i_px = i; + i_mpx = i2; + break; + } + } + if(mvar) break; + } else if(CHILD(0)[i].isPower() && CHILD(0)[i][1].contains(x_var) && !CHILD(0)[i][0].contains(x_var)) { + mvar = &CHILD(0)[i][1]; + m_b_p = &CHILD(0)[i][0]; + i_px = i; + break; + } + } + if(mvar) { + MathStructure m_b(*m_b_p); + if((mvar->isAddition() || mvar->isMultiplication()) && m_b.representsPositive()) { + MathStructure *mvar2 = NULL; + if(mvar->isMultiplication()) { + for(size_t i = 0; i < mvar->size(); i++) { + if((*mvar)[i].contains(x_var)) {mvar2 = &(*mvar)[i]; break;} + } + } else if(mvar->isAddition()) { + for(size_t i = 0; i < mvar->size(); i++) { + if((*mvar)[i].contains(x_var)) { + mvar2 = &(*mvar)[i]; + if(mvar2->isMultiplication()) { + for(size_t i2 = 0; i2 < mvar2->size(); i2++) { + if((*mvar2)[i2].contains(x_var)) {mvar2 = &(*mvar2)[i2]; break;} + } + } + break; + } + } + } + if(mvar2) { + MathStructure m_b_exp; + if(get_multiplier(*mvar, *mvar2, m_b_exp) && m_b.representsReal() && !m_b.contains(x_var)) { + m_b ^= m_b_exp; + mvar = mvar2; + } else { + mvar = NULL; + } + } + } + MathStructure m_c; + if(mvar && get_multiplier(CHILD(0), *mvar, m_c, i_px) && m_c.representsNonZero() && m_c.contains(x_var) == 0) { + MathStructure mlogb(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &m_b, NULL); + if(mlogb.calculateFunctions(eo)) mlogb.calculatesub(eo2, eo, true); + MathStructure *marg = NULL; + if(mlogb.representsNonZero()) { + marg = new MathStructure(mlogb); + if(CHILD(0)[i_px].isMultiplication()) { + marg->multiply(CHILD(0)[i_px]); + marg->last().delChild(i_mpx + 1, true); + if(!marg->last().representsNonZero()) {marg->unref(); marg = NULL;} + else marg->calculateMultiplyLast(eo2); + } + } + if(marg) { + if(!CHILD(1).isZero()) { + marg->multiply(m_b); + marg->last().raise(CHILD(1)); + if(!m_c.isOne()) marg->last().last().calculateDivide(m_c, eo2); + marg->last().calculateRaiseExponent(eo2); + marg->calculateMultiplyLast(eo2); + } + if(!m_c.isOne()) marg->calculateDivide(m_c, eo2); + } + if(marg && mvar->representsNonComplex() && m_b.representsPositive()) { + if(marg->representsComplex()) { + marg->unref(); + if(ct_comp == COMPARISON_EQUALS) clear(true); + else set(1, 1, 0, true); + return true; + } + MathStructure *mreq1 = NULL; + MathStructure *marg2 = NULL; + MathStructure *mreq2 = NULL; + if(!marg->representsNonNegative()) { + mreq1 = new MathStructure(*marg); + mreq2 = new MathStructure(*marg); + marg2 = new MathStructure(*marg); + marg2->transformById(FUNCTION_ID_LAMBERT_W); + marg2->addChild(m_minus_one); + if(marg2->calculateFunctions(eo)) marg2->calculatesub(eo2, eo, true); + marg2->calculateNegate(eo2); + if(CHILD(1).isZero()) { + marg2->calculateDivide(mlogb, eo2); + } else { + if(!m_c.isOne()) marg->calculateMultiply(m_c, eo2); + marg2->add(CHILD(1)); + marg2->last().calculateMultiply(mlogb, eo); + marg2->calculateAddLast(eo2); + marg2->calculateDivide(mlogb, eo2); + if(!m_c.isOne()) marg->calculateDivide(m_c, eo2); + } + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->getVariableById(VARIABLE_ID_E)); + mreq1->last().calculateRaise(m_minus_one, eo2); + mreq1->last().calculateNegate(eo2); + mreq1->childUpdated(2); + mreq1->isolate_x(eo2, eo); + mreq2->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, m_zero); + mreq2->isolate_x(eo2, eo); + marg2->transform(ct_comp, *mvar); + marg2->swapChildren(1, 2); + marg2->isolate_x_sub(eo, eo2, x_var, morig); + marg2->add(*mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + marg2->add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + marg2->calculatesub(eo2, eo, false); + } + marg->transformById(FUNCTION_ID_LAMBERT_W); + marg->addChild(m_zero); + if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); + marg->calculateNegate(eo2); + if(CHILD(1).isZero()) { + marg->calculateDivide(mlogb, eo2); + } else { + if(!m_c.isOne()) marg->calculateMultiply(m_c, eo2); + marg->add(CHILD(1)); + marg->last().calculateMultiply(mlogb, eo); + marg->calculateAddLast(eo2); + marg->calculateDivide(mlogb, eo2); + if(!m_c.isOne()) marg->calculateDivide(m_c, eo2); + } + setChild_nocopy(marg, 2, true); + mvar->ref(); + CHILD(0).clear(true); + setChild_nocopy(mvar, 1, true); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + if(mreq1) { + add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + if(marg2) { + add_nocopy(marg2, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + return true; + } else if(marg) { + marg->transformById(FUNCTION_ID_LAMBERT_W); + marg->addChild(CALCULATOR->getVariableById(VARIABLE_ID_N)); + if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); + marg->calculateNegate(eo2); + if(CHILD(1).isZero()) { + marg->calculateDivide(mlogb, eo2); + } else { + if(!m_c.isOne()) marg->calculateMultiply(m_c, eo2); + marg->add(CHILD(1)); + marg->last().calculateMultiply(mlogb, eo); + marg->calculateAddLast(eo2); + marg->calculateDivide(mlogb, eo2); + if(!m_c.isOne()) marg->calculateDivide(m_c, eo2); + } + setChild_nocopy(marg, 2, true); + mvar->ref(); + CHILD(0).clear(true); + setChild_nocopy(mvar, 1, true); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } + } + } + if(i_px == 0) { + // a^(2x)+a^x, a^(-x)+a^x + MathStructure *mvar1 = NULL, *mvar2 = NULL; + b = true; + for(size_t i = 0; i < CHILD(0).size() && b; i++) { + b = false; + if(CHILD(0)[i].isMultiplication()) { + for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { + if(!b && CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][1].contains(x_var) && !CHILD(0)[i][i2][0].contains(x_var)) { + if(mvar2) { + if(mvar1->equals(CHILD(0)[i][i2]) || mvar2->equals(CHILD(0)[i][i2])) { + b = true; + } + } else if(mvar1) { + if(!mvar1->equals(CHILD(0)[i][i2])) { + mvar2 = &CHILD(0)[i][i2]; + } + b = true; + } else { + mvar1 = &CHILD(0)[i][i2]; + b = true; + } + if(!b) break; + } else if(CHILD(0)[i][i2].contains(x_var)) { + b = false; + break; + } + } + } else if(CHILD(0)[i].isPower() && CHILD(0)[i][1].contains(x_var) && !CHILD(0)[i][0].contains(x_var)) { + if(mvar2) { + if(mvar1->equals(CHILD(0)[i]) || mvar2->equals(CHILD(0)[i])) { + b = true; + } + } else if(mvar1) { + if(!mvar1->equals(CHILD(0)[i])) { + mvar2 = &CHILD(0)[i]; + } + b = true; + } else { + mvar1 = &CHILD(0)[i]; + b = true; + } + } + } + if(b && mvar2 && mvar1->base()->representsPositive()) { + bool b_two = false, b_m_one = false; + if(mvar1->base()->equals(*mvar2->base())) { + MathStructure m1m2((*mvar1)[1]); + m1m2.calculateMultiply(nr_two, eo2); + if(m1m2.equals((*mvar2)[1])) { + b_two = true; + MathStructure *mtmp = mvar2; + mvar2 = mvar1; + mvar1 = mtmp; + } + if(!b_two && !b_m_one) { + MathStructure m1mm1((*mvar1)[1]); + m1mm1.calculateMultiply(nr_minus_one, eo2); + if(m1mm1.equals((*mvar2)[1])) { + b_m_one = true; + MathStructure *mtmp = mvar2; + mvar2 = mvar1; + mvar1 = mtmp; + } + } + if(!b_two && !b_m_one) { + MathStructure m2m2((*mvar2)[1]); + m2m2.calculateMultiply(nr_two, eo2); + if(m2m2.equals((*mvar1)[1])) { + b_two = true; + } + } + if(!b_two && !b_m_one) { + MathStructure m2mm1((*mvar2)[1]); + m2mm1.calculateMultiply(nr_minus_one, eo2); + if(m2mm1.equals((*mvar1)[1])) { + b_m_one = true; + } + } + } else if(mvar1->base()->isNumber() && mvar2->base()->isNumber() && !mvar1->base()->number().isInterval() && !mvar2->base()->number().isInterval()) { + if(mvar1->base()->number() < mvar2->base()->number()) { + if(mvar2->base()->number() == (mvar1->base()->number() ^ 2)) { + b_two = true; + } else if(mvar1->base()->number() == (mvar2->base()->number() ^ -1)) { + b_m_one = true; + MathStructure *mtmp = mvar2; + mvar2 = mvar1; + mvar1 = mtmp; + } + } else { + if(mvar1->base()->number() == (mvar2->base()->number() ^ 2)) { + b_two = true; + MathStructure *mtmp = mvar2; + mvar2 = mvar1; + mvar1 = mtmp; + } else if(mvar2->base()->number() == (mvar1->base()->number() ^ -1)) { + b_m_one = true; + } + } + } + if(b_two || b_m_one) { + MathStructure mv(*mvar1); + MathStructure mv2(*mvar2); + UnknownVariable *var = new UnknownVariable("", format_and_print(mv)); + var->setInterval(mv); + MathStructure u_var(var); + replace(mv, u_var); + MathStructure u_var2(var); + u_var2.raise(b_two ? nr_two : nr_minus_one); + replace(mv2, u_var2); + b = isolate_x_sub(eo, eo2, u_var); + calculateReplace(u_var, mv, eo2); + var->destroy(); + if(b) isolate_x(eo, eo2, x_var); + return b; + } + } + } + if(CHILD(0).containsFunctionId(FUNCTION_ID_LOG)) { + // x+ln(x)=lambertw(x) + MathStructure *mln = NULL; + mvar = NULL; + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CHILD(0)[i].isMultiplication()) { + MathStructure *mln2 = NULL; + for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { + if(CHILD(0)[i][i2].contains(x_var)) { + if(!mln2 && CHILD(0)[i][i2].isFunction() && CHILD(0)[i][i2].function()->id() == FUNCTION_ID_LOG && CHILD(0)[i][i2].size() == 1) { + mln2 = &CHILD(0)[i][i2]; + } else { + mln2 = NULL; + break; + } + } + } + if(mln2) { + if(mln) { + if(*mln2 != *mln) { + if(!mvar) mvar = &CHILD(0)[i]; + } + } else { + mln = mln2; + } + } else if(!mvar) { + mvar = &CHILD(0)[i]; + } + } else if(!mln && CHILD(0)[i].isFunction() && CHILD(0)[i].function()->id() == FUNCTION_ID_LOG && CHILD(0)[i].size() == 1) { + mln = &CHILD(0)[i]; + } else if(!mvar) { + mvar = &CHILD(0)[i]; + } + } + if(mvar && mln) { + MathStructure mx(1, 1, 0); + MathStructure mmul2; + if(mvar->isMultiplication()) { + for(size_t i = 0; i < mvar->size(); i++) { + if((*mvar)[i].contains(x_var)) { + if(mx.isOne()) mx = (*mvar)[i]; + else mx.multiply((*mvar)[i], true); + } + } + } else { + mx = *mvar; + } + if(!mx.isOne() && !get_multiplier((*mln)[0], mx, mmul2)) { + mx = m_one; + } + if(!mx.isOne()) { + MathStructure mbak(*this); + MathStructure mlns; + MathStructure mmul1; + mlns.setType(STRUCT_ADDITION); + bool b_mul = false; + for(size_t i = 0; i < CHILD(0).size();) { + if(&CHILD(0)[i] == mln || CHILD(0)[i] == *mln) { + if(&CHILD(0)[i] != mln) b_mul = true; + CHILD(0)[i].ref(); + mlns.addChild_nocopy(&CHILD(0)[i]); + CHILD(0).delChild(i + 1); + } else if(CHILD(0)[i].isMultiplication()) { + b = false; + for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { + if(CHILD(0)[i][i2] == *mln) { + CHILD(0)[i].ref(); + mlns.addChild_nocopy(&CHILD(0)[i]); + CHILD(0).delChild(i + 1); + b = true; + b_mul = true; + break; + } + } + if(!b) i++; + } else { + i++; + } + } + if(CHILD(0).size() == 1) CHILD(0).setToChild(1, true); + if(!get_multiplier(CHILD(0), mx, mmul1)) { + mx = m_one; + } + if(!mx.isOne()) { + if(mlns.size() == 0) { + mx = m_one; + } else if(b_mul) { + MathStructure mmul3; + MathStructure mln2(*mln); + if(!get_multiplier(mlns, mln2, mmul3)) { + mx = m_one; + } else if(!mmul3.isOne()) { + mmul1.calculateDivide(mmul3, eo2); + CHILD(1).calculateDivide(mmul3, eo2); + } + } + } + if(!mx.isOne() && mmul1.representsNonZero() && mmul2.representsNonZero() && !mmul2.contains(x_var)) { + MathStructure *marg; + if(!CHILD(1).isZero()) { + marg = new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_E)); + marg->calculateRaise(CHILD(1), eo2); + if(!mmul1.isOne()) marg->calculateMultiply(mmul1, eo2); + } else { + marg = new MathStructure(mmul1); + } + if(!mmul2.isOne()) marg->calculateDivide(mmul2, eo2); + MathStructure *mreq1 = NULL; + if(mx.representsNonComplex() && !marg->representsNonNegative()) { + mreq1 = new MathStructure(*marg); + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->getVariableById(VARIABLE_ID_E)); + mreq1->last().calculateRaise(m_minus_one, eo2); + mreq1->last().calculateNegate(eo2); + mreq1->childUpdated(2); + mreq1->isolate_x(eo2, eo); + } + marg->transformById(FUNCTION_ID_LAMBERT_W); + marg->addChild(m_zero); + if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); + CHILD(0).set(mx, true); + setChild_nocopy(marg, 2); + if(!mmul1.isOne()) CHILD(1).calculateDivide(mmul1, eo2); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + if(mreq1) { + add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + return true; + } + set(mbak); + } + } + } + if(CHILD(0).containsFunctionId(FUNCTION_ID_COSH) && CHILD(0).containsFunctionId(FUNCTION_ID_SINH)) { + // a*cosh(x) + b*cosh(x) + MathStructure *marg = NULL, *m_cosh = NULL, *m_sinh = NULL; + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CHILD(0)[i].isMultiplication()) { + bool b_found = false; + for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { + if(CHILD(0)[i][i2].contains(x_var)) { + if(!b_found && CHILD(0)[i][i2].isFunction() && (CHILD(0)[i][i2].function()->id() == FUNCTION_ID_COSH || CHILD(0)[i][i2].function()->id() == FUNCTION_ID_SINH) && CHILD(0)[i][i2].size() == 1 && (!marg || marg->equals(CHILD(0)[i][i2][0]))) { + if(!marg) marg = &CHILD(0)[i][i2][0]; + if(CHILD(0)[i][i2].function()->id() == FUNCTION_ID_COSH) m_cosh = &CHILD(0)[i][i2]; + else m_sinh = &CHILD(0)[i][i2]; + b_found = true; + } else { + b_found = false; + break; + } + } + } + if(!b_found) { + marg = NULL; + break; + } + } else if(CHILD(0)[i].isFunction() && (CHILD(0)[i].function()->id() == FUNCTION_ID_COSH || CHILD(0)[i].function()->id() == FUNCTION_ID_SINH) && CHILD(0)[i].size() == 1 && (!marg || marg->equals(CHILD(0)[i][0]))) { + if(!marg) marg = &CHILD(0)[i][0]; + if(CHILD(0)[i].function()->id() == FUNCTION_ID_COSH) m_cosh = &CHILD(0)[i]; + else m_sinh = &CHILD(0)[i]; + } else { + marg = NULL; + break; + } + } + if(marg && m_cosh && m_sinh) { + MathStructure mtest(*this); + EvaluationOptions eo3 = eo; + eo3.approximation = APPROXIMATION_EXACT; + MathStructure m_ex(CALCULATOR->getVariableById(VARIABLE_ID_E)); + m_ex.raise(*marg); + MathStructure m_emx(m_ex); + m_emx.last().calculateMultiply(nr_minus_one, eo2); + m_ex *= nr_half; + m_emx *= nr_half; + m_ex.swapChildren(1, 2); + m_emx.swapChildren(1, 2); + MathStructure mr_sinh(m_ex); + mr_sinh.calculateSubtract(m_emx, eo3); + MathStructure mr_cosh(m_ex); + mr_cosh.calculateAdd(m_emx, eo3); + mtest[0].calculateReplace(*m_sinh, mr_sinh, eo3); + mtest[0].calculateReplace(*m_cosh, mr_cosh, eo3); + if(mtest.isolate_x_sub(eo, eo3, x_var, morig)) { + if(eo2.approximation != APPROXIMATION_EXACT) mtest.calculatesub(eo2, eo, true); + set(mtest); + return true; + } + } + } + } + + // x+x^(1/a)=b => x=(b-x)^a + if(eo2.expand && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && CHILD(0).size() <= 10 && CHILD(0).size() > 1) { + int i_root = 0; + size_t root_index = 0; + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CALCULATOR->aborted()) return false; + if(CHILD(0)[i].isPower()) { + if(CHILD(0)[i][1].isNumber() && !CHILD(0)[i][1].isInteger() && CHILD(0)[i][1].number().numeratorIsOne() && CHILD(0)[i][1].number().denominatorIsLessThan(10)) { + if(i_root) { + if(i_root != CHILD(0)[i][1].number().denominator().intValue()) { + i_root = 0; + break; + } + } else { + i_root = CHILD(0)[i][1].number().denominator().intValue(); + root_index = i; + } + } else if(!CHILD(0)[i][1].isNumber() || !CHILD(0)[i][1].number().isInteger()) { + i_root = 0; + break; + } + } else if(CHILD(0)[i].isFunction() && CHILD(0)[i].function()->id() == FUNCTION_ID_ROOT) { + if(VALID_ROOT(CHILD(0)[i]) && CHILD(0)[i][1].number().isLessThan(10)) { + if(i_root) { + if(i_root != CHILD(0)[i][1].number().intValue()) { + i_root = 0; + break; + } + } else { + i_root = CHILD(0)[i][1].number().intValue(); + root_index = i; + } + } else { + i_root = 0; + break; + } + } else if(CHILD(0)[i].isMultiplication()) { + bool b_break = false; + for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { + if(CHILD(0)[i][i2].contains(x_var)) { + if(CHILD(0)[i][i2].isPower()) { + if(CHILD(0)[i][i2][1].isNumber() && !CHILD(0)[i][i2][1].number().isInteger() && CHILD(0)[i][i2][1].number().numeratorIsOne() && CHILD(0)[i][i2][1].number().denominatorIsLessThan(10)) { + if(i_root) { + if(i_root != CHILD(0)[i][i2][1].number().denominator().intValue()) { + i_root = 0; + b_break = true; + break; + } + } else { + i_root = CHILD(0)[i][i2][1].number().denominator().intValue(); + root_index = i; + } + } else if(!CHILD(0)[i][i2][1].isNumber() || !CHILD(0)[i][i2][1].number().isInteger()) { + i_root = 0; + b_break = true; + break; + } + } else if(CHILD(0)[i][i2].isFunction() && CHILD(0)[i][i2].function()->id() == FUNCTION_ID_ROOT) { + if(VALID_ROOT(CHILD(0)[i][i2]) && CHILD(0)[i][i2][1].number().isLessThan(10)) { + if(i_root) { + if(i_root != CHILD(0)[i][i2][1].number().intValue()) { + i_root = 0; + b_break = true; + break; + } + } else { + i_root = CHILD(0)[i][i2][1].number().intValue(); + root_index = i; + } + } else { + i_root = 0; + b_break = true; + break; + } + } + } + } + if(b_break) break; + } + } + if(i_root) { + MathStructure mtest(*this); + MathStructure msub; + if(mtest[0].size() == 2) { + msub = mtest[0][root_index == 0 ? 1 : 0]; + } else { + msub = mtest[0]; + msub.delChild(root_index + 1); + } + mtest[0].setToChild(root_index + 1); + mtest[1].calculateSubtract(msub, eo2); + if(mtest[0].calculateRaise(i_root, eo2) && mtest[1].calculateRaise(i_root, eo2)) { + mtest.childrenUpdated(); + if(mtest.isolate_x(eo2, eo, x_var)) { + if((mtest.isLogicalAnd() || mtest.isLogicalOr() || mtest.isComparison()) && test_comparisons(*this, mtest, x_var, eo, false, eo2.expand ? 1 : 2) < 0) { + if(eo2.expand) { + add(mtest, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); + calculatesub(eo2, eo, false); + return true; + } + } else { + set(mtest); + return true; + } + } + } + + } + } + + // x+y/x=z => x*x+y=z*x + MathStructure mdiv; + mdiv.setUndefined(); + MathStructure mdiv_inv; + bool b_multiple_div = false; + for(size_t i = 0; i < CHILD(0).size() && !b_multiple_div; i++) { + if(CALCULATOR->aborted()) return false; + if(CHILD(0)[i].isMultiplication()) { + for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { + if(CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][1].isNumber() && CHILD(0)[i][i2][1].number().isReal() && CHILD(0)[i][i2][1].number().isNegative()) { + if(!mdiv.isUndefined()) b_multiple_div = true; + else mdiv = CHILD(0)[i][i2]; + break; + } + } + } else if(CHILD(0)[i].isPower() && CHILD(0)[i][1].isNumber() && CHILD(0)[i][1].number().isReal() && CHILD(0)[i][1].number().isNegative()) { + if(!mdiv.isUndefined()) b_multiple_div = true; + else mdiv = CHILD(0)[i]; + } + } + if(!mdiv.isUndefined() && countTotalChildren() > 200) mdiv.setUndefined(); + if(!mdiv.isUndefined() && b_multiple_div && mdiv.containsInterval()) { + MathStructure mbak(*this); + CALCULATOR->beginTemporaryStopIntervalArithmetic(); + bool failed = false; + EvaluationOptions eo3 = eo2; + eo3.interval_calculation = INTERVAL_CALCULATION_NONE; + fix_intervals(*this, eo3, &failed); + if(!failed && isolate_x_sub(eo, eo3, x_var, morig)) { + CALCULATOR->endTemporaryStopIntervalArithmetic(); + if((CALCULATOR->usesIntervalArithmetic() && eo.approximation != APPROXIMATION_EXACT) || mbak.containsInterval()) CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); + fix_intervals(*this, eo2); + return true; + } + CALCULATOR->endTemporaryStopIntervalArithmetic(); + set(mbak); + } else if(!mdiv.isUndefined()) { + if(mdiv[1].isMinusOne()) { + mdiv_inv = mdiv[0]; + } else { + mdiv_inv = mdiv; + mdiv_inv[1].number().negate(); + } + EvaluationOptions eo3 = eo2; + eo3.expand = true; + bool b2 = false; + for(size_t i3 = 0; i3 < CHILD(0).size(); i3++) { + bool b = false; + if(!b2 || !mdiv.containsInterval()) { + if(CHILD(0)[i3].isPower() && CHILD(0)[i3].equals(mdiv, true)) { + CHILD(0)[i3].set(1, 1, 0, true); + b = true; + } else if(CHILD(0)[i3].isMultiplication()) { + for(size_t i4 = 0; i4 < CHILD(0)[i3].size(); i4++) { + if(CHILD(0)[i3][i4].isPower() && CHILD(0)[i3][i4].equals(mdiv, true)) { + b = true; + CHILD(0)[i3].delChild(i4 + 1); + if(CHILD(0)[i3].size() == 0) CHILD(0)[i3].set(1, 1, 0, true); + else if(CHILD(0)[i3].size() == 1) CHILD(0)[i3].setToChild(1, true); + break; + } + } + } + } + if(!b) { + CHILD(0)[i3].calculateMultiply(mdiv_inv, eo3); + } else { + b2 = true; + } + } + CHILD(0).childrenUpdated(); + CHILD(0).evalSort(); + CHILD(0).calculatesub(eo2, eo, false); + CHILD(1).calculateMultiply(mdiv_inv, eo3); + CHILDREN_UPDATED + if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { + bool not_equals = ct_comp == COMPARISON_NOT_EQUALS; + isolate_x(eo, eo2, x_var, morig); + if(!mdiv[0].representsNonZero(true)) { + MathStructure *mtest = new MathStructure(mdiv[0]); + mtest->add(m_zero, not_equals ? OPERATION_EQUALS : OPERATION_NOT_EQUALS); + mtest->isolate_x_sub(eo, eo2, x_var); + add_nocopy(mtest, not_equals ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + } else { + MathStructure *malt = new MathStructure(*this); + if(ct_comp == COMPARISON_EQUALS_GREATER) { + ct_comp = COMPARISON_EQUALS_LESS; + } else if(ct_comp == COMPARISON_GREATER) { + ct_comp = COMPARISON_LESS; + } else if(ct_comp == COMPARISON_EQUALS_LESS) { + ct_comp = COMPARISON_EQUALS_GREATER; + } else if(ct_comp == COMPARISON_LESS) { + ct_comp = COMPARISON_GREATER; + } + isolate_x(eo, eo2, x_var, morig); + MathStructure *mtest = new MathStructure(mdiv); + mtest->add(m_zero, OPERATION_LESS); + MathStructure *mtest_alt = new MathStructure(*mtest); + mtest_alt->setComparisonType(COMPARISON_GREATER); + mtest->isolate_x_sub(eo, eo2, x_var); + add_nocopy(mtest, OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + malt->isolate_x(eo, eo2, x_var, morig); + mtest_alt->isolate_x_sub(eo, eo2, x_var); + malt->add_nocopy(mtest_alt, OPERATION_LOGICAL_AND); + malt->calculatesub(eo2, eo, false); + add_nocopy(malt, OPERATION_LOGICAL_OR); + calculatesub(eo2, eo, false); + return true; + } + return true; + } + + // x^a+x^(b/c)=d => x^(1/c)^(a*c)+x^(1/c)^b=d; f(x)^a+f(x)^b=c => u^a+u^b=c + MathStructure mbase; + b = true; + Number nr_root; + bool b_f_root = false; + + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CALCULATOR->aborted()) return false; + if(!mbase.isZero() && CHILD(0)[i] == mbase) { + } else if(CHILD(0)[i].isPower() && CHILD(0)[i][1].isNumber() && CHILD(0)[i][1].number().isPositive() && CHILD(0)[i][1].number().isRational()) { + if(CHILD(0)[i][0].isFunction() && CHILD(0)[i][0].function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(CHILD(0)[i][0])) { + if(mbase.isZero()) mbase = CHILD(0)[i][0][0]; + else if(mbase != CHILD(0)[i][0][0]) {b = false; break;} + if(!nr_root.isZero()) { + if(!b_f_root) {b = false; break;} + nr_root.lcm(CHILD(0)[i][0][1].number()); + } else { + nr_root = CHILD(0)[i][0][1].number(); + } + b_f_root = true; + } else { + if(mbase.isZero()) mbase = CHILD(0)[i][0]; + else if(mbase != CHILD(0)[i][0]) {b = false; break;} + if(!CHILD(0)[i][1].number().isInteger()) { + if(b_f_root) {b = false; break;} + if(!nr_root.isZero()) { + nr_root.lcm(CHILD(0)[i][1].number().denominator()); + } else { + nr_root = CHILD(0)[i][1].number().denominator(); + } + } + } + } else if(CHILD(0)[i].isMultiplication()) { + for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { + if(!mbase.isZero() && CHILD(0)[i][i2] == mbase) { + } else if(CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][1].isNumber() && CHILD(0)[i][i2][1].number().isPositive() && CHILD(0)[i][i2][1].number().isRational()) { + if(CHILD(0)[i][i2][0].isFunction() && CHILD(0)[i][i2][0].function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(CHILD(0)[i][i2][0])) { + if(mbase.isZero()) mbase = CHILD(0)[i][i2][0][0]; + else if(mbase != CHILD(0)[i][i2][0][0]) {b = false; break;} + if(!nr_root.isZero()) { + if(!b_f_root) {b = false; break;} + nr_root.lcm(CHILD(0)[i][i2][0][1].number()); + } else { + nr_root = CHILD(0)[i][i2][0][1].number(); + } + b_f_root = true; + } else { + if(mbase.isZero()) mbase = CHILD(0)[i][i2][0]; + else if(mbase != CHILD(0)[i][i2][0]) {b = false; break;} + if(!CHILD(0)[i][i2][1].number().isInteger()) { + if(b_f_root) {b = false; break;} + if(!nr_root.isZero()) { + nr_root.lcm(CHILD(0)[i][i2][1].number().denominator()); + } else { + nr_root = CHILD(0)[i][i2][1].number().denominator(); + } + } + } + } else if(CHILD(0)[i][i2].isFunction() && CHILD(0)[i][i2].function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(CHILD(0)[i][i2])) { + if(mbase.isZero()) mbase = CHILD(0)[i][i2][0]; + else if(mbase != CHILD(0)[i][i2][0]) {b = false; break;} + if(!nr_root.isZero()) { + if(!b_f_root) {b = false; break;} + nr_root.lcm(CHILD(0)[i][i2][1].number()); + } else { + nr_root = CHILD(0)[i][i2][1].number(); + } + b_f_root = true; + } else if(CHILD(0)[i][i2].isNumber() && !CHILD(0)[i][i2].number().isZero()) { + } else if(mbase.isZero()) { + mbase = CHILD(0)[i][i2]; + } else { + b = false; break; + } + } + if(!b) break; + } else if(CHILD(0)[i].isFunction() && CHILD(0)[i].function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(CHILD(0)[i])) { + if(mbase.isZero()) mbase = CHILD(0)[i][0]; + else if(mbase != CHILD(0)[i][0]) {b = false; break;} + if(!nr_root.isZero()) { + if(!b_f_root) {b = false; break;} + nr_root.lcm(CHILD(0)[i][1].number()); + } else { + nr_root = CHILD(0)[i][1].number(); + } + b_f_root = true; + } else if(mbase.isZero()) { + mbase = CHILD(0)[i]; + } else { + b = false; break; + } + } + if(b && !mbase.isZero() && nr_root.isLessThan(100)) { + MathStructure mvar(mbase); + if(!nr_root.isZero()) { + if(b_f_root) { + MathStructure mroot(nr_root); + mvar.set(CALCULATOR->getFunctionById(FUNCTION_ID_ROOT), &mbase, &mroot, NULL); + } else { + Number nr_pow(nr_root); + nr_pow.recip(); + mvar.raise(nr_pow); + } + } + UnknownVariable *var = NULL; + if(mvar != x_var) { + var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(mvar) + RIGHT_PARENTHESIS); + var->setInterval(mvar); + } + if(!nr_root.isZero()) { + MathStructure mbak(*this); + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CALCULATOR->aborted()) {set(mbak); return false;} + if(CHILD(0)[i] == mbase) { + CHILD(0)[i] = var; + CHILD(0)[i].raise(nr_root); + } else if(CHILD(0)[i].isPower() && CHILD(0)[i][1].isNumber()) { + if(CHILD(0)[i][0].isFunction() && CHILD(0)[i][0].function()->id() == FUNCTION_ID_ROOT && CHILD(0)[i][0] != mbase) { + CHILD(0)[i][1].number().multiply(nr_root); + CHILD(0)[i][1].number().divide(CHILD(0)[i][0][1].number()); + if(CHILD(0)[i][1].isOne()) CHILD(0)[i] = var; + else CHILD(0)[i][0] = var; + } else if(CHILD(0)[i][0] == mbase) { + CHILD(0)[i][1].number().multiply(nr_root); + if(CHILD(0)[i][1].isOne()) CHILD(0)[i] = var; + else CHILD(0)[i][0] = var; + } else { + // should not happen + } + } else if(CHILD(0)[i].isMultiplication()) { + for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { + if(CHILD(0)[i][i2] == mbase) { + CHILD(0)[i][i2] = var; + CHILD(0)[i][i2].raise(nr_root); + } else if(CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][1].isNumber()) { + if(CHILD(0)[i][i2][0].isFunction() && CHILD(0)[i][i2][0].function()->id() == FUNCTION_ID_ROOT && CHILD(0)[i][i2][0] != mbase) { + CHILD(0)[i][i2][1].number().multiply(nr_root); + CHILD(0)[i][i2][1].number().divide(CHILD(0)[i][i2][0][1].number()); + if(CHILD(0)[i][i2][1].isOne()) CHILD(0)[i][i2] = var; + else CHILD(0)[i][i2][0] = var; + } else if(CHILD(0)[i][i2][0] == mbase) { + CHILD(0)[i][i2][1].number().multiply(nr_root); + if(CHILD(0)[i][i2][1].isOne()) CHILD(0)[i][i2] = var; + else CHILD(0)[i][i2][0] = var; + } else { + // should not happen + } + } else if(CHILD(0)[i][i2].isFunction() && CHILD(0)[i][i2].function()->id() == FUNCTION_ID_ROOT) { + Number nr_pow(nr_root); + nr_pow.divide(CHILD(0)[i][i2][1].number()); + CHILD(0)[i][i2][1] = nr_pow; + CHILD(0)[i][i2][0] = var; + CHILD(0)[i][i2].setType(STRUCT_POWER); + } else if(CHILD(0)[i][i2].isNumber() && !CHILD(0)[i][i2].number().isZero()) { + } else { + // should not happen + } + } + } else if(CHILD(0)[i].isFunction() && CHILD(0)[i].function()->id() == FUNCTION_ID_ROOT) { + Number nr_pow(nr_root); + nr_pow.divide(CHILD(0)[i][1].number()); + CHILD(0)[i][1] = nr_pow; + CHILD(0)[i][0] = var; + CHILD(0)[i].setType(STRUCT_POWER); + } else { + // should not happen + } + } + MathStructure u_var(var); + replace(mvar, u_var); + CHILD(0).calculatesub(eo2, eo2, true); + CHILD_UPDATED(0) + b = isolate_x_sub(eo, eo2, u_var); + calculateReplace(u_var, mvar, eo2); + var->destroy(); + if(b) isolate_x(eo, eo2, x_var); + return b; + } else if(mvar != x_var) { + MathStructure u_var(var); + replace(mvar, u_var); + CHILD(0).calculatesub(eo2, eo2, true); + CHILD_UPDATED(0) + b = isolate_x_sub(eo, eo2, u_var); + calculateReplace(u_var, mvar, eo2); + var->destroy(); + if(b) isolate_x(eo, eo2, x_var); + return b; + } + } + + if(!eo2.expand) break; + + // Try factorization + if(!morig || !equals(*morig)) { + MathStructure mtest(*this); + if(!mtest[1].isZero()) { + mtest[0].calculateSubtract(CHILD(1), eo2); + mtest[1].clear(); + mtest.childrenUpdated(); + } + b = eo2.do_polynomial_division && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && do_simplification(mtest[0], eo, true, true, false, false, true); + if(b && mtest[0].isMultiplication() && mtest[0].size() == 2 && mtest[0][1].isPower() && mtest[0][1][1].representsNegative()) { + MathStructure mreq(mtest); + mtest[0].setToChild(1, true); + mtest.childUpdated(1); + eo2.do_polynomial_division = false; + if(mtest.isolate_x_sub(eo, eo2, x_var, this)) { + mreq.setComparisonType(ct_comp == COMPARISON_EQUALS ? COMPARISON_NOT_EQUALS : COMPARISON_EQUALS); + mreq[0].setToChild(2, true); + mreq[0][1].calculateNegate(eo2); + mreq[0].calculateRaiseExponent(eo2); + mreq.childUpdated(1); + mreq.isolate_x_sub(eo, eo2, x_var, this); + mtest.add(mreq, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); + mtest.calculatesub(eo2, eo, false); + set_nocopy(mtest); + return true; + } + } else { + if(b) { + mtest = *this; + if(!mtest[1].isZero()) { + mtest[0].calculateSubtract(CHILD(1), eo2); + mtest[1].clear(); + mtest.childrenUpdated(); + } + } + if(mtest[0].factorize(eo2, false, false, 0, false, false, NULL, m_undefined, false, false, 3) && !(mtest[0].isMultiplication() && mtest[0].size() == 2 && ((mtest[0][0].isNumber() && mtest[0][1].isAddition()) || mtest[0][0] == CHILD(1) || mtest[0][1] == CHILD(1)))) { + mtest.childUpdated(1); + if(mtest.isolate_x_sub(eo, eo2, x_var, this)) { + set_nocopy(mtest); + return true; + } + } + } + } + + // ax^3+bx^2+cx=d + if(CHILD(0).size() >= 2 && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { + bool cbpow = false, sqpow = false, nopow = false; + MathStructure mstruct_a, mstruct_b, mstruct_c; + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CALCULATOR->aborted()) return false; + if(CHILD(0)[i].isPower() && CHILD(0)[i][0] == x_var && CHILD(0)[i][1].isNumber() && CHILD(0)[i][1].number() == 3) { + if(cbpow) mstruct_a.add(m_one, true); + else {cbpow = true; mstruct_a.set(m_one);} + } else if(CHILD(0)[i].isPower() && CHILD(0)[i][0] == x_var && CHILD(0)[i][1].isNumber() && CHILD(0)[i][1].number() == 2) { + if(sqpow) mstruct_b.add(m_one, true); + else {sqpow = true; mstruct_b.set(m_one);} + } else if(CHILD(0)[i] == x_var) { + if(nopow) mstruct_c.add(m_one, true); + else {nopow = true; mstruct_c.set(m_one);} + } else if(CHILD(0)[i].isMultiplication()) { + for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { + if(CHILD(0)[i][i2] == x_var) { + if(nopow) { + MathStructure *madd = new MathStructure(CHILD(0)[i]); + madd->delChild(i2 + 1, true); + mstruct_c.add_nocopy(madd, true); + } else { + nopow = true; + mstruct_c = CHILD(0)[i]; + mstruct_c.delChild(i2 + 1, true); + } + } else if(CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][0] == x_var && CHILD(0)[i][i2][1].isNumber() && CHILD(0)[i][i2][1].number() == 2) { + if(sqpow) { + MathStructure *madd = new MathStructure(CHILD(0)[i]); + madd->delChild(i2 + 1, true); + mstruct_b.add_nocopy(madd, true); + } else { + sqpow = true; + mstruct_b = CHILD(0)[i]; + mstruct_b.delChild(i2 + 1, true); + } + } else if(CHILD(0)[i][i2].isPower() && CHILD(0)[i][i2][0] == x_var && CHILD(0)[i][i2][1].isNumber() && CHILD(0)[i][i2][1].number() == 3) { + if(cbpow) { + MathStructure *madd = new MathStructure(CHILD(0)[i]); + madd->delChild(i2 + 1, true); + mstruct_a.add_nocopy(madd, true); + } else { + cbpow = true; + mstruct_a = CHILD(0)[i]; + mstruct_a.delChild(i2 + 1, true); + } + } else if(CHILD(0)[i][i2].contains(x_var)) { + cbpow = false; + sqpow = false; + nopow = false; + break; + } + } + if(!cbpow && !sqpow && !nopow) break; + } else { + cbpow = false; + sqpow = false; + nopow = false; + break; + } + } + bool b = false; + if(cbpow && (nopow || sqpow) && !mstruct_a.representsZero(true)) { + b = mstruct_a.representsNonZero(true); + if(!b && eo2.approximation == APPROXIMATION_EXACT) { + MathStructure mtest(mstruct_a); + mtest.add(m_zero, OPERATION_NOT_EQUALS); + EvaluationOptions eo3 = eo2; + eo3.test_comparisons = true; + mtest.calculatesub(eo3, eo, false); + b = mtest.isOne(); + } + } + if(b) { + + MathStructure mbak(*this); + + bool stop_iv = containsInterval(true, false, false, -2, false); + + cube_eq_stop_iv: + + CALCULATOR->beginTemporaryStopMessages(); + + EvaluationOptions eo3 = eo2; + bool failed = false; + if(stop_iv) { + CALCULATOR->beginTemporaryStopIntervalArithmetic(); + eo3.interval_calculation = INTERVAL_CALCULATION_NONE; + fix_intervals(*this, eo3, &failed); + } + if(failed) { + set(mbak); + CALCULATOR->endTemporaryStopIntervalArithmetic(); + CALCULATOR->endTemporaryStopMessages(); + } else { + eo3.keep_zero_units = false; + + MathStructure mstruct_d(CHILD(1)); + mstruct_d.calculateNegate(eo3); + + // 18abcd - 4b^3*d + b^2*c^2 - 4a*c^3 - 27a^2*d^2 + MathStructure mdelta(18, 1, 0); + mdelta.multiply(mstruct_a); + mdelta.multiply(mstruct_b, true); + mdelta.multiply(mstruct_c, true); + mdelta.multiply(mstruct_d, true); + MathStructure *mdelta_b = new MathStructure(mstruct_b); + mdelta_b->raise(nr_three); + mdelta_b->multiply(Number(-4, 1, 0)); + mdelta_b->multiply(mstruct_d); + MathStructure *mdelta_c = new MathStructure(mstruct_b); + mdelta_c->raise(nr_two); + MathStructure *mdelta_c2 = new MathStructure(mstruct_c); + mdelta_c2->raise(nr_two); + mdelta_c->multiply_nocopy(mdelta_c2); + MathStructure *mdelta_d = new MathStructure(mstruct_c); + mdelta_d->raise(nr_three); + mdelta_d->multiply(Number(-4, 1, 0)); + mdelta_d->multiply(mstruct_a, true); + MathStructure *mdelta_e = new MathStructure(mstruct_a); + mdelta_e->raise(nr_two); + MathStructure *mdelta_e2 = new MathStructure(mstruct_d); + mdelta_e2->raise(nr_two); + mdelta_e->multiply_nocopy(mdelta_e2); + mdelta_e->multiply(Number(-27, 1, 0)); + mdelta.add_nocopy(mdelta_b); + mdelta.add_nocopy(mdelta_c, true); + mdelta.add_nocopy(mdelta_d, true); + mdelta.add_nocopy(mdelta_e, true); + mdelta.calculatesub(eo3, eo); + + if(CALCULATOR->aborted()) {CALCULATOR->endTemporaryStopMessages(); if(stop_iv) CALCULATOR->endTemporaryStopIntervalArithmetic(); set(mbak); return false;} + + int b_zero = -1; + int b_real = -1; + if(mdelta.representsNonZero(true)) b_zero = 0; + else if(mdelta.representsZero(true)) b_zero = 1; + + if(b_zero == 0) { + if(mdelta.representsPositive(true)) { + b_real = 1; + } else if(mdelta.representsNegative(true)) { + b_real = 0; + } + } else if(b_zero < 0) { + ComparisonResult cr = mdelta.compare(m_zero); + if(cr == COMPARISON_RESULT_EQUAL) { + b_zero = 1; + } else if(COMPARISON_IS_NOT_EQUAL(cr)) { + if(cr == COMPARISON_RESULT_GREATER) b_real = 0; + else if(cr == COMPARISON_RESULT_LESS) b_real = 1; + b_zero = 0; + } + } + if(b_real < 0 && mdelta.representsComplex(true)) b_real = -2; + if(b_real == -1) b_zero = -1; + + if(b_real > 0 && (!mstruct_a.representsNonComplex() || !mstruct_b.representsNonComplex() || !mstruct_c.representsNonComplex() || !mstruct_d.representsNonComplex())) b_real = -2; + + MathStructure mdelta0; + int b0_zero = -1; + + if(CALCULATOR->aborted()) {CALCULATOR->endTemporaryStopMessages(); if(stop_iv) CALCULATOR->endTemporaryStopIntervalArithmetic(); set(mbak); return false;} + + if(b_zero >= 0) { + // b^2 - 3ac + mdelta0 = mstruct_b; + mdelta0.raise(nr_two); + MathStructure *mdelta0_b = new MathStructure(-3, 1, 0); + mdelta0_b->multiply(mstruct_a); + mdelta0_b->multiply(mstruct_c, true); + mdelta0.add_nocopy(mdelta0_b); + mdelta0.calculatesub(eo3, eo, true); + if(mdelta0.representsNonZero(true)) b0_zero = 0; + else if(mdelta0.representsZero(true)) b0_zero = 1; + else { + ComparisonResult cr = mdelta0.compare(m_zero); + if(cr == COMPARISON_RESULT_EQUAL) { + b0_zero = 1; + } else if(COMPARISON_IS_NOT_EQUAL(cr)) { + b0_zero = 0; + } + } + } + + if(CALCULATOR->aborted()) {CALCULATOR->endTemporaryStopMessages(); if(stop_iv) CALCULATOR->endTemporaryStopIntervalArithmetic(); set(mbak); return false;} + + if(b_zero == 1) { + if(b0_zero == 1) { + // -b/(3a) + CHILD(0) = x_var; + CHILD(1).set(-1, 3); + CHILD(1).calculateMultiply(mstruct_b, eo3); + CHILD(1).calculateDivide(mstruct_a, eo3); + CHILDREN_UPDATED; + if(stop_iv) { + CALCULATOR->endTemporaryStopIntervalArithmetic(); + CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); + fix_intervals(*this, eo2); + } else if(containsInterval(true, false, false, -2, false)) { + set(mbak); + stop_iv = true; + CALCULATOR->endTemporaryStopMessages(); + goto cube_eq_stop_iv; + } + CALCULATOR->endTemporaryStopMessages(true); + return true; + } else if(b0_zero == 0) { + + MathStructure *malt1 = new MathStructure(x_var); + malt1->transform(STRUCT_COMPARISON, m_zero); + malt1->setComparisonType(comparisonType()); + MathStructure *malt2 = new MathStructure(*malt1); + + // (9ad - bc) / (2*delta0) + (*malt1)[1].set(9, 1, 0); + (*malt1)[1].calculateMultiply(mstruct_a, eo3); + (*malt1)[1].calculateMultiply(mstruct_d, eo3); + MathStructure *malt1_2b = new MathStructure(-1, 1, 0); + malt1_2b->calculateMultiply(mstruct_b, eo3); + malt1_2b->calculateMultiply(mstruct_c, eo3); + (*malt1)[1].add_nocopy(malt1_2b); + (*malt1)[1].calculateAddLast(eo3); + (*malt1)[1].calculateDivide(nr_two, eo3); + (*malt1)[1].calculateDivide(mdelta0, eo3); + + // (4abc - 9a^2*d - b^3) / (a*delta0) + (*malt2)[1].set(4, 1, 0); + (*malt2)[1].calculateMultiply(mstruct_a, eo3); + (*malt2)[1].calculateMultiply(mstruct_b, eo3); + (*malt2)[1].calculateMultiply(mstruct_c, eo3); + MathStructure *malt2_2b = new MathStructure(mstruct_a); + malt2_2b->calculateRaise(nr_two, eo3); + malt2_2b->calculateMultiply(Number(-9, 1, 0), eo3); + malt2_2b->calculateMultiply(mstruct_d, eo3); + (*malt2)[1].add_nocopy(malt2_2b); + (*malt2)[1].calculateAddLast(eo3); + MathStructure *malt2_2c = new MathStructure(mstruct_b); + malt2_2c->calculateRaise(nr_three, eo3); + malt2_2c->calculateNegate(eo3); + (*malt2)[1].add_nocopy(malt2_2c); + (*malt2)[1].calculateAddLast(eo3); + (*malt2)[1].calculateDivide(mstruct_a, eo3); + (*malt2)[1].calculateDivide(mdelta0, eo3); + + if(ct_comp == COMPARISON_NOT_EQUALS) { + clear(true); + setType(STRUCT_LOGICAL_AND); + } else { + clear(true); + setType(STRUCT_LOGICAL_OR); + } + + malt1->childUpdated(2); + malt2->childUpdated(2); + + addChild_nocopy(malt1); + addChild_nocopy(malt2); + + calculatesub(eo3, eo, false); + + if(stop_iv) { + CALCULATOR->endTemporaryStopIntervalArithmetic(); + CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); + fix_intervals(*this, eo2); + } else if(containsInterval(true, false, false, -2, false)) { + set(mbak); + stop_iv = true; + CALCULATOR->endTemporaryStopMessages(); + goto cube_eq_stop_iv; + } + CALCULATOR->endTemporaryStopMessages(true); + return true; + } + } + + if(CALCULATOR->aborted()) {CALCULATOR->endTemporaryStopMessages(); if(stop_iv) CALCULATOR->endTemporaryStopIntervalArithmetic(); return false;} + + MathStructure mdelta1; + bool b_neg = false; + + if(b_zero == 0 && b0_zero >= 0) { + + // 2b^3 - 9abc + 27a^2*d + mdelta1 = mstruct_b; + mdelta1.raise(nr_three); + mdelta1.multiply(nr_two); + MathStructure *mdelta1_b = new MathStructure(-9, 1, 0); + mdelta1_b->multiply(mstruct_a); + mdelta1_b->multiply(mstruct_b, true); + mdelta1_b->multiply(mstruct_c, true); + MathStructure *mdelta1_c = new MathStructure(mstruct_a); + mdelta1_c->raise(nr_two); + mdelta1_c->multiply(Number(27, 1, 0)); + mdelta1_c->multiply(mstruct_d, true); + mdelta1.add_nocopy(mdelta1_b); + mdelta1.add_nocopy(mdelta1_c, true); + mdelta1.calculatesub(eo3, eo, true); + + if(b0_zero == 1) { + + if(mdelta1.representsNegative(true)) { + b_neg = true; + } else if(!mdelta1.representsPositive(true)) { + if(mdelta1.representsZero(true)) { + // -b/(3a) + CHILD(0) = x_var; + CHILD(1).set(-1, 3); + CHILD(1).calculateMultiply(mstruct_b, eo3); + CHILD(1).calculateDivide(mstruct_a, eo3); + CHILDREN_UPDATED; + if(stop_iv) { + CALCULATOR->endTemporaryStopIntervalArithmetic(); + CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); + fix_intervals(*this, eo2); + } else if(containsInterval(true, false, false, -2, false)) { + set(mbak); + stop_iv = true; + CALCULATOR->endTemporaryStopMessages(); + goto cube_eq_stop_iv; + } + CALCULATOR->endTemporaryStopMessages(true); + return true; + } + ComparisonResult cr = mdelta1.compare(m_zero); + if(cr == COMPARISON_RESULT_EQUAL) { + // -b/(3a) + CHILD(0) = x_var; + CHILD(1).set(-1, 3); + CHILD(1).calculateMultiply(mstruct_b, eo3); + CHILD(1).calculateDivide(mstruct_a, eo3); + CHILDREN_UPDATED; + if(stop_iv) { + CALCULATOR->endTemporaryStopIntervalArithmetic(); + CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); + fix_intervals(*this, eo2); + } else if(containsInterval(true, false, false, -2, false)) { + set(mbak); + stop_iv = true; + CALCULATOR->endTemporaryStopMessages(); + goto cube_eq_stop_iv; + } + CALCULATOR->endTemporaryStopMessages(true); + return true; + } else if(cr == COMPARISON_RESULT_GREATER) { + b_neg = true; + } else if(cr != COMPARISON_RESULT_LESS) { + b_zero = -1; + } + } + } + } + + if(b_zero == 0 && b0_zero == 0) { + + // ((delta1 +-sqrt(delta1^2-4*delta0^3))/2)^(1/3) + MathStructure mC; + MathStructure *md0_43 = new MathStructure(mdelta0); + md0_43->raise(nr_three); + md0_43->multiply(Number(-4, 1, 0)); + MathStructure *md1_2 = new MathStructure(mdelta1); + md1_2->raise(nr_two); + md1_2->add_nocopy(md0_43); + md1_2->raise(nr_half); + if(b_neg) md1_2->calculateNegate(eo3); + md1_2->calculatesub(eo3, eo, true); + + if(CALCULATOR->aborted()) {CALCULATOR->endTemporaryStopMessages(); if(stop_iv) CALCULATOR->endTemporaryStopIntervalArithmetic(); set(mbak); return false;} + + mC = mdelta1; + mC.add_nocopy(md1_2); + mC.calculateAddLast(eo3); + mC.calculateDivide(nr_two, eo3); + if(b_real == 0 && x_var.representsReal(true)) { + if(!mC.representsComplex(true)) { + mC.transform(STRUCT_FUNCTION); + mC.addChild(nr_three); + mC.setFunctionId(FUNCTION_ID_ROOT); + if(mC.calculateFunctions(eo)) mC.calculatesub(eo3, eo, true); + // x = -1/(3a)*(b + C + delta0/C) + CHILD(0) = x_var; + CHILD(1).set(-1, 3, 0); + CHILD(1).calculateDivide(mstruct_a, eo3); + MathStructure *malt1_2b = new MathStructure(mdelta0); + malt1_2b->calculateDivide(mC, eo3); + malt1_2b->calculateAdd(mC, eo3); + malt1_2b->calculateAdd(mstruct_b, eo3); + CHILD(1).multiply_nocopy(malt1_2b); + CHILD(1).calculateMultiplyLast(eo3); + CHILDREN_UPDATED; + if(stop_iv) { + CALCULATOR->endTemporaryStopIntervalArithmetic(); + CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); + fix_intervals(*this, eo2); + } else if(containsInterval(true, false, false, -2, false)) { + set(mbak); + stop_iv = true; + CALCULATOR->endTemporaryStopMessages(); + goto cube_eq_stop_iv; + } + CALCULATOR->endTemporaryStopMessages(true); + return true; + } + } else if(eo3.allow_complex) { + + if(mC.representsNegative(true)) { + mC.calculateNegate(eo3); + mC.calculateRaise(Number(1, 3, 0), eo3); + mC.calculateNegate(eo3); + } else { + mC.calculateRaise(Number(1, 3, 0), eo3); + } + + // x = -1/(3a)*(b + C + delta0/C) + + MathStructure *malt1 = new MathStructure(x_var); + malt1->transform(STRUCT_COMPARISON, Number(-1, 3, 0)); + malt1->setComparisonType(comparisonType()); + (*malt1)[1].calculateDivide(mstruct_a, eo3); + + MathStructure *malt2 = new MathStructure(*malt1); + MathStructure *malt3 = new MathStructure(*malt1); + + MathStructure *malt1_2b = new MathStructure(mdelta0); + malt1_2b->calculateDivide(mC, eo3); + malt1_2b->calculateAdd(mC, eo3); + malt1_2b->calculateAdd(mstruct_b, eo3); + (*malt1)[1].multiply_nocopy(malt1_2b); + (*malt1)[1].calculateMultiplyLast(eo3); + + MathStructure cbrt_mul(nr_three); + cbrt_mul.calculateRaise(nr_half, eo3); + cbrt_mul.calculateMultiply(nr_one_i, eo3); + MathStructure cbrt_mul2(cbrt_mul); + cbrt_mul.calculateMultiply(nr_half, eo3); + cbrt_mul.calculateAdd(Number(-1, 2, 0), eo3); + cbrt_mul2.calculateMultiply(Number(-1, 2, 0), eo3); + cbrt_mul2.calculateAdd(Number(-1, 2, 0), eo3); + + MathStructure mC2(mC); + mC2.calculateMultiply(cbrt_mul, eo3); + MathStructure mC3(mC); + mC3.calculateMultiply(cbrt_mul2, eo3); + + MathStructure *malt2_2b = new MathStructure(mdelta0); + malt2_2b->calculateDivide(mC2, eo3); + malt2_2b->calculateAdd(mC2, eo3); + malt2_2b->calculateAdd(mstruct_b, eo3); + (*malt2)[1].multiply_nocopy(malt2_2b); + (*malt2)[1].calculateMultiplyLast(eo3); + + MathStructure *malt3_2b = new MathStructure(mdelta0); + malt3_2b->calculateDivide(mC3, eo3); + malt3_2b->calculateAdd(mC3, eo3); + malt3_2b->calculateAdd(mstruct_b, eo3); + (*malt3)[1].multiply_nocopy(malt3_2b); + (*malt3)[1].calculateMultiplyLast(eo3); + + if(b_real == 1) { + if((*malt1)[1].isNumber()) { + (*malt1)[1].number().clearImaginary(); + } else if((*malt1)[1].isMultiplication() && (*malt1)[1][0].isNumber()) { + bool b = true; + for(size_t i = 1; i < (*malt1)[1].size(); i++) { + if(!(*malt1)[1][i].representsReal(true)) { + b = false; + break; + } + } + if(b) (*malt1)[1][0].number().clearImaginary(); + } + if((*malt2)[1].isNumber()) { + (*malt2)[1].number().clearImaginary(); + } else if((*malt2)[1].isMultiplication() && (*malt2)[1][0].isNumber()) { + bool b = true; + for(size_t i = 1; i < (*malt2)[1].size(); i++) { + if(!(*malt2)[1][i].representsReal(true)) { + b = false; + break; + } + } + if(b) (*malt2)[1][0].number().clearImaginary(); + } + if((*malt3)[1].isNumber()) { + (*malt3)[1].number().clearImaginary(); + } else if((*malt3)[1].isMultiplication() && (*malt3)[1][0].isNumber()) { + bool b = true; + for(size_t i = 1; i < (*malt3)[1].size(); i++) { + if(!(*malt3)[1][i].representsReal(true)) { + b = false; + break; + } + } + if(b) (*malt3)[1][0].number().clearImaginary(); + } + } + + if(b_real < 1 || !x_var.representsReal(true) || (!(*malt1)[1].representsComplex(true) && !(*malt2)[1].representsComplex(true) && !(*malt3)[1].representsComplex(true))) { + + if(ct_comp == COMPARISON_NOT_EQUALS) { + clear(true); + setType(STRUCT_LOGICAL_AND); + } else { + clear(true); + setType(STRUCT_LOGICAL_OR); + } + + malt1->childUpdated(2); + malt2->childUpdated(2); + malt3->childUpdated(2); + + addChild_nocopy(malt1); + addChild_nocopy(malt2); + addChild_nocopy(malt3); + + calculatesub(eo3, eo, false); + if(stop_iv) { + CALCULATOR->endTemporaryStopIntervalArithmetic(); + CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); + fix_intervals(*this, eo2); + } else if(containsInterval(true, false, false, -2, false)) { + set(mbak); + stop_iv = true; + goto cube_eq_stop_iv; + CALCULATOR->endTemporaryStopMessages(); + } + CALCULATOR->endTemporaryStopMessages(true); + return true; + } + } + } + CALCULATOR->endTemporaryStopMessages(); + if(stop_iv) CALCULATOR->endTemporaryStopIntervalArithmetic(); + } + } + } + + + // abs(x)+x=a => -x+x=a || x+x=a; sgn(x)+x=a => -1+x=a || 0+x=a || 1+x=a + if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { + MathStructure *m = find_abs_sgn(CHILD(0), x_var); + if(m && m->function()->id() == FUNCTION_ID_ABS) { + + MathStructure mabs(*m); + + ComparisonType cmp_type = ct_comp; + MathStructure *malt = new MathStructure(*this); + MathStructure mabs_minus(mabs[0]); + mabs_minus.calculateNegate(eo2); + (*malt)[0].replace(mabs, mabs_minus, mabs.containsInterval()); + (*malt)[0].calculatesub(eo2, eo, true); + malt->childUpdated(1); + MathStructure *mcheck = new MathStructure(mabs[0]); + mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_EQUALS_GREATER : OPERATION_LESS); + mcheck->isolate_x_sub(eo, eo2, x_var); + malt->isolate_x_sub(eo, eo2, x_var); + malt->add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + malt->calculatesub(eo2, eo, false); + + mcheck = new MathStructure(mabs[0]); + CHILD(0).replace(mabs, mabs[0], mabs.containsInterval()); + CHILD(0).calculatesub(eo2, eo, true); + CHILD_UPDATED(0) + mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LESS : OPERATION_EQUALS_GREATER); + mcheck->isolate_x_sub(eo, eo2, x_var); + isolate_x_sub(eo, eo2, x_var); + add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + calculatesub(eo2, eo, false); + add_nocopy(malt, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); + calculatesub(eo2, eo, false); + + return true; + } else if(m && m->function()->id() == FUNCTION_ID_SIGNUM) { + MathStructure mabs(*m); + + ComparisonType cmp_type = ct_comp; + MathStructure *malt = new MathStructure(*this); + (*malt)[0].replace(mabs, m_minus_one, mabs.containsInterval()); + (*malt)[0].calculatesub(eo2, eo, true); + malt->childUpdated(1); + MathStructure *mcheck = new MathStructure(mabs[0]); + mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? ((*m)[1].isMinusOne() ? OPERATION_GREATER : OPERATION_EQUALS_GREATER) : ((*m)[1].isMinusOne() ? OPERATION_EQUALS_LESS : OPERATION_LESS)); + mcheck->isolate_x_sub(eo, eo2, x_var); + malt->isolate_x_sub(eo, eo2, x_var); + malt->add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + malt->calculatesub(eo2, eo, false); + + MathStructure *malt0 = NULL; + if(!(*m)[1].isOne() && !(*m)[1].isMinusOne()) { + malt0 = new MathStructure(*this); + (*malt0)[0].replace(mabs, (*m)[1], mabs.containsInterval()); + (*malt0)[0].calculatesub(eo2, eo, true); + malt0->childUpdated(1); + mcheck = new MathStructure(mabs[0]); + mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_NOT_EQUALS : OPERATION_EQUALS); + mcheck->isolate_x_sub(eo, eo2, x_var); + malt0->isolate_x_sub(eo, eo2, x_var); + malt0->add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + malt0->calculatesub(eo2, eo, false); + } + + mcheck = new MathStructure(mabs[0]); + CHILD(0).replace(mabs, m_one, mabs.containsInterval()); + CHILD(0).calculatesub(eo2, eo, true); + CHILD_UPDATED(0) + mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? ((*m)[1].isOne() ? OPERATION_LESS : OPERATION_EQUALS_LESS) : ((*m)[1].isOne() ? OPERATION_EQUALS_GREATER : OPERATION_GREATER)); + mcheck->isolate_x_sub(eo, eo2, x_var); + isolate_x_sub(eo, eo2, x_var); + add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + calculatesub(eo2, eo, false); + add_nocopy(malt, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); + if(malt0) add_nocopy(malt0, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); + calculatesub(eo2, eo, false); + return true; + } + } + + // Use newton raphson to calculate approximate solution for polynomial + MathStructure x_value; + if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && CHILD(1).isNumber() && eo.approximation != APPROXIMATION_EXACT && !x_var.representsComplex(true)) { + MathStructure mtest(CHILD(0)); + if(!CHILD(0).isZero()) mtest.calculateSubtract(CHILD(1), eo2); + CALCULATOR->beginTemporaryStopIntervalArithmetic(); + EvaluationOptions eo3 = eo2; + eo3.interval_calculation = INTERVAL_CALCULATION_NONE; + bool failed = false; + if(CALCULATOR->usesIntervalArithmetic()) failed = true; + else fix_intervals(mtest, eo3, &failed); + if(failed) { + CALCULATOR->endTemporaryStopIntervalArithmetic(); + } else { + MathStructure mbak(*this); + int ret = -1; + eo3.approximation = APPROXIMATION_APPROXIMATE; + if(ct_comp == COMPARISON_EQUALS) clear(true); + else set(1, 1, 0, true); + while((ret = newton_raphson(mtest, x_value, x_var, eo3)) > 0) { + if(isNumber()) { + set(x_var, true); + transform(STRUCT_COMPARISON, x_value); + setComparisonType(mbak.comparisonType()); + } else { + if(isComparison()) transform(mbak.comparisonType() == COMPARISON_NOT_EQUALS ? STRUCT_LOGICAL_AND : STRUCT_LOGICAL_OR); + MathStructure *mnew = new MathStructure(x_var); + mnew->transform(STRUCT_COMPARISON, x_value); + mnew->setComparisonType(mbak.comparisonType()); + addChild_nocopy(mnew); + } + MathStructure mdiv(x_var); + mdiv.calculateSubtract(x_value, eo3); + MathStructure mtestcopy(mtest); + MathStructure mrem; + if(!polynomial_long_division(mtestcopy, mdiv, x_var, mtest, mrem, eo3, false, true) || !mrem.isNumber()) { + ret = -1; + break; + } + if(!mtest.contains(x_var)) break; + } + CALCULATOR->endTemporaryStopIntervalArithmetic(); + if(ret < 0) { + set(mbak); + } else { + if(!x_var.representsReal()) CALCULATOR->error(false, _("Not all complex roots were calculated for %s."), format_and_print(mbak).c_str(), NULL); + if((CALCULATOR->usesIntervalArithmetic() && eo.approximation != APPROXIMATION_EXACT) || mbak.containsInterval()) CALCULATOR->error(false, _("Interval arithmetic was disabled during calculation of %s."), format_and_print(mbak).c_str(), NULL); + fix_intervals(*this, eo2); + return true; + } + } + } + + // Try factorization + if((!morig || !equals(*morig)) && !CHILD(1).isZero()) { + MathStructure mtest(*this); + if(mtest[0].factorize(eo2, false, false, 0, false, false, NULL, m_undefined, false, false, 3) && !(mtest[0].isMultiplication() && mtest[0].size() == 2 && (mtest[0][0].isNumber() || mtest[0][0] == CHILD(1) || mtest[0][1] == CHILD(1)))) { + mtest.childUpdated(1); + if(mtest.isolate_x_sub(eo, eo2, x_var, this)) { + set_nocopy(mtest); + return true; + } + } + } + + break; + } + case STRUCT_MULTIPLICATION: { + if(!representsNonMatrix()) return false; + //x*y=0 => x=0 || y=0 + if(CHILD(1).isZero()) { + if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { + vector checktype; + bool bdoit = false; + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CALCULATOR->aborted()) return false; + if(CHILD(0)[i].isPower() && !CHILD(0)[i][1].representsNonNegative()) { + if(CHILD(0)[i][1].representsNegative()) { + checktype.push_back(1); + } else { + checktype.push_back(2); + bdoit = true; + } + } else { + checktype.push_back(0); + bdoit = true; + } + } + if(!bdoit) break; + MathStructure *mcheckpowers = NULL; + ComparisonType ct = ct_comp; + setToChild(1); + if(ct == COMPARISON_NOT_EQUALS) { + setType(STRUCT_LOGICAL_AND); + } else { + setType(STRUCT_LOGICAL_OR); + } + MathStructure mbak(*this); + for(size_t i = 0; i < SIZE;) { + if(CALCULATOR->aborted()) { + set(mbak); + if(mcheckpowers) mcheckpowers->unref(); + return false; + } + if(checktype[i] > 0) { + MathStructure *mcheck = new MathStructure(CHILD(i)[0]); + if(ct_comp == COMPARISON_NOT_EQUALS) mcheck->add(m_zero, OPERATION_EQUALS); + else mcheck->add(m_zero, OPERATION_NOT_EQUALS); + mcheck->isolate_x_sub(eo, eo2, x_var); + if(checktype[i] == 2) { + MathStructure *mexpcheck = new MathStructure(CHILD(i)[1]); + if(ct_comp == COMPARISON_NOT_EQUALS) mexpcheck->add(m_zero, OPERATION_LESS); + else mexpcheck->add(m_zero, OPERATION_EQUALS_GREATER); + mexpcheck->isolate_x_sub(eo, eo2, x_var); + if(ct_comp == COMPARISON_NOT_EQUALS) mexpcheck->add_nocopy(mcheck, OPERATION_LOGICAL_AND, true); + else mexpcheck->add_nocopy(mcheck, OPERATION_LOGICAL_OR, true); + mexpcheck->calculatesub(eo2, eo, false); + mcheck = mexpcheck; + } + if(mcheckpowers) { + if(ct_comp == COMPARISON_NOT_EQUALS) mcheckpowers->add_nocopy(mcheck, OPERATION_LOGICAL_OR, true); + else mcheckpowers->add_nocopy(mcheck, OPERATION_LOGICAL_AND, true); + } else { + mcheckpowers = mcheck; + } + } + if(checktype[i] == 1) { + ERASE(i) + checktype.erase(checktype.begin() + i); + } else { + CHILD(i).transform(STRUCT_COMPARISON, m_zero); + CHILD(i).setComparisonType(ct); + CHILD(i).isolate_x_sub(eo, eo2, x_var); + CHILD_UPDATED(i) + i++; + } + } + if(SIZE == 1) setToChild(1); + else if(SIZE == 0) clear(true); + else calculatesub(eo2, eo, false); + if(mcheckpowers) { + mcheckpowers->calculatesub(eo2, eo, false); + if(ct_comp == COMPARISON_NOT_EQUALS) add_nocopy(mcheckpowers, OPERATION_LOGICAL_OR, true); + else add_nocopy(mcheckpowers, OPERATION_LOGICAL_AND, true); + SWAP_CHILDREN(0, SIZE - 1) + calculatesub(eo2, eo, false); + } + return true; + } else if(CHILD(0).size() >= 2) { + MathStructure mless1(CHILD(0)[0]); + MathStructure mless2; + if(CHILD(0).size() == 2) { + mless2 = CHILD(0)[1]; + } else { + mless2 = CHILD(0); + mless2.delChild(1); + } + + int checktype1 = 0, checktype2 = 0; + MathStructure *mcheck1 = NULL, *mcheck2 = NULL; + if(mless1.isPower() && !mless1[1].representsNonNegative()) { + if(mless1[1].representsNegative()) { + checktype1 = 1; + } else if(ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER) { + checktype1 = 2; + mcheck1 = new MathStructure(mless1[1]); + mcheck1->add(m_zero, OPERATION_EQUALS_GREATER); + mcheck1->isolate_x_sub(eo, eo2, x_var); + MathStructure *mcheck = new MathStructure(mless1[0]); + mcheck->add(m_zero, OPERATION_NOT_EQUALS); + mcheck->isolate_x_sub(eo, eo2, x_var); + mcheck1->add_nocopy(mcheck, OPERATION_LOGICAL_OR); + mcheck1->calculatesub(eo2, eo, false); + } + } + if(mless2.isPower() && !mless2[1].representsNonNegative()) { + if(mless2[1].representsNegative()) { + checktype2 = 1; + } else if(ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER) { + checktype2 = 2; + mcheck2 = new MathStructure(mless2[1]); + mcheck2->add(m_zero, OPERATION_EQUALS_GREATER); + mcheck2->isolate_x_sub(eo, eo2, x_var); + MathStructure *mcheck = new MathStructure(mless2[0]); + mcheck->add(m_zero, OPERATION_NOT_EQUALS); + mcheck->isolate_x_sub(eo, eo2, x_var); + mcheck2->add_nocopy(mcheck, OPERATION_LOGICAL_OR); + mcheck2->calculatesub(eo2, eo, false); + } + } + + mless1.transform(STRUCT_COMPARISON, m_zero); + if(checktype1 != 1 && (ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER)) { + mless1.setComparisonType(COMPARISON_EQUALS_LESS); + } else { + mless1.setComparisonType(COMPARISON_LESS); + } + mless1.isolate_x_sub(eo, eo2, x_var); + mless2.transform(STRUCT_COMPARISON, m_zero); + mless2.setComparisonType(COMPARISON_LESS); + if(checktype2 != 1 && (ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER)) { + mless2.setComparisonType(COMPARISON_EQUALS_LESS); + } else { + mless2.setComparisonType(COMPARISON_LESS); + } + mless2.isolate_x_sub(eo, eo2, x_var); + MathStructure mgreater1(CHILD(0)[0]); + mgreater1.transform(STRUCT_COMPARISON, m_zero); + if(checktype1 != 1 && (ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER)) { + mgreater1.setComparisonType(COMPARISON_EQUALS_GREATER); + } else { + mgreater1.setComparisonType(COMPARISON_GREATER); + } + mgreater1.isolate_x_sub(eo, eo2, x_var); + MathStructure mgreater2; + if(CHILD(0).size() == 2) { + mgreater2 = CHILD(0)[1]; + } else { + mgreater2 = CHILD(0); + mgreater2.delChild(1); + } + mgreater2.transform(STRUCT_COMPARISON, m_zero); + if(checktype2 != 1 && (ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_EQUALS_GREATER)) { + mgreater2.setComparisonType(COMPARISON_EQUALS_GREATER); + } else { + mgreater2.setComparisonType(COMPARISON_GREATER); + } + mgreater2.isolate_x_sub(eo, eo2, x_var); + clear(); + + if(ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) { + set(mless1); + transform(STRUCT_LOGICAL_AND, mgreater2); + calculatesub(eo2, eo, false); + transform(STRUCT_LOGICAL_OR, mless2); + CHILD(1).transform(STRUCT_LOGICAL_AND, mgreater1); + CHILD(1).calculatesub(eo2, eo, false); + CHILD_UPDATED(1) + calculatesub(eo2, eo, false); + } else { + set(mless1); + transform(STRUCT_LOGICAL_AND, mless2); + calculatesub(eo2, eo, false); + transform(STRUCT_LOGICAL_OR, mgreater1); + CHILD(1).transform(STRUCT_LOGICAL_AND, mgreater2); + CHILD(1).calculatesub(eo2, eo, false); + CHILD_UPDATED(1) + calculatesub(eo2, eo, false); + } + if(checktype1 == 2) { + add_nocopy(mcheck1, OPERATION_LOGICAL_AND, true); + calculatesub(eo2, eo, false); + } + if(checktype2 == 2) { + add_nocopy(mcheck2, OPERATION_LOGICAL_AND, true); + calculatesub(eo2, eo, false); + } + return true; + + } + } + // x/(x+a)=b => x=b(x+a) + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CALCULATOR->aborted()) return false; + if(CHILD(0)[i].isPower() && CHILD(0)[i][1].isNumber() && CHILD(0)[i][1].number().isNegative() && CHILD(0)[i][1].number().isReal()) { + MathStructure *mtest; + if(CHILD(0)[i][1].number().isMinusOne()) { + CHILD(1).multiply(CHILD(0)[i][0]); + mtest = new MathStructure(CHILD(0)[i][0]); + } else { + CHILD(0)[i][1].number().negate(); + CHILD(1).multiply(CHILD(0)[i]); + mtest = new MathStructure(CHILD(0)[i]); + } + CHILD(0).delChild(i + 1); + if(CHILD(0).size() == 1) CHILD(0).setToChild(1); + CHILD(0).calculateSubtract(CHILD(1), eo); + ComparisonType cmp_type = ct_comp; + CHILD(1).clear(); + CHILDREN_UPDATED + if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { + isolate_x_sub(eo, eo2, x_var, morig); + mtest->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_EQUALS : OPERATION_NOT_EQUALS); + mtest->isolate_x_sub(eo, eo2, x_var); + add_nocopy(mtest, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + calculatesub(eo2, eo, false); + return true; + } else { + MathStructure *malt = new MathStructure(*this); + if(ct_comp == COMPARISON_EQUALS_GREATER) { + ct_comp = COMPARISON_EQUALS_LESS; + } else if(ct_comp == COMPARISON_GREATER) { + ct_comp = COMPARISON_LESS; + } else if(ct_comp == COMPARISON_EQUALS_LESS) { + ct_comp = COMPARISON_EQUALS_GREATER; + } else if(ct_comp == COMPARISON_LESS) { + ct_comp = COMPARISON_GREATER; + } + isolate_x_sub(eo, eo2, x_var, morig); + mtest->add(m_zero, OPERATION_LESS); + MathStructure *mtest_alt = new MathStructure(*mtest); + mtest_alt->setComparisonType(COMPARISON_GREATER); + mtest->isolate_x_sub(eo, eo2, x_var); + add_nocopy(mtest, OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + malt->isolate_x_sub(eo, eo2, x_var, morig); + mtest_alt->isolate_x_sub(eo, eo2, x_var); + malt->add_nocopy(mtest_alt, OPERATION_LOGICAL_AND); + malt->calculatesub(eo2, eo, false); + add_nocopy(malt, OPERATION_LOGICAL_OR); + calculatesub(eo2, eo, false); + return true; + } + } + } + bool b = false; + int zero1; + if(CHILD(1).isZero()) zero1 = 1; + else if(CHILD(1).representsNonZero(true)) zero1 = 0; + else zero1 = 2; + MathStructure *mcheckmulti = NULL, *mtryzero = NULL, *mchecknegative = NULL, *mchecknonzeropow = NULL; + MathStructure mchild2(CHILD(1)); + MathStructure mbak(*this); + ComparisonType ct_orig = ct_comp; + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CALCULATOR->aborted()) { + set(mbak); + if(mcheckmulti) mcheckmulti->unref(); + if(mtryzero) mcheckmulti->unref(); + if(mchecknegative) mcheckmulti->unref(); + if(mchecknonzeropow) mcheckmulti->unref(); + return false; + } + if(!CHILD(0)[i].contains(x_var)) { + bool nonzero = false; + if(CHILD(0)[i].isPower() && !CHILD(0)[i][1].representsNonNegative(true) && !CHILD(0)[i][0].representsNonZero(true)) { + MathStructure *mcheck = new MathStructure(CHILD(0)[i][0]); + if(ct_comp == COMPARISON_NOT_EQUALS) mcheck->add(m_zero, OPERATION_EQUALS); + else mcheck->add(m_zero, OPERATION_NOT_EQUALS); + mcheck->isolate_x(eo2, eo); + if(CHILD(0)[i][1].representsNegative(true)) { + nonzero = true; + } else { + MathStructure *mcheckor = new MathStructure(CHILD(0)[i][1]); + if(ct_comp == COMPARISON_NOT_EQUALS) mcheckor->add(m_zero, OPERATION_EQUALS_LESS); + else mcheckor->add(m_zero, OPERATION_EQUALS_GREATER); + mcheckor->isolate_x(eo2, eo); + if(ct_comp == COMPARISON_NOT_EQUALS) mcheck->add_nocopy(mcheckor, OPERATION_LOGICAL_AND); + else mcheck->add_nocopy(mcheckor, OPERATION_LOGICAL_OR); + mcheck->calculatesub(eo2, eo, false); + } + if(mchecknonzeropow) { + if(ct_comp == COMPARISON_NOT_EQUALS) mchecknonzeropow->add_nocopy(mcheck, OPERATION_LOGICAL_OR); + else mchecknonzeropow->add_nocopy(mcheck, OPERATION_LOGICAL_AND); + } else { + mchecknonzeropow = mcheck; + } + } + if(!nonzero && !CHILD(0)[i].representsNonZero(true)) { + if(zero1 != 1 && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { + MathStructure *mcheck = new MathStructure(CHILD(0)[i]); + if(ct_comp == COMPARISON_NOT_EQUALS) mcheck->add(m_zero, OPERATION_EQUALS); + else mcheck->add(m_zero, OPERATION_NOT_EQUALS); + mcheck->isolate_x(eo2, eo); + if(mcheckmulti) { + if(ct_comp == COMPARISON_NOT_EQUALS) mcheckmulti->add_nocopy(mcheck, OPERATION_LOGICAL_OR); + else mcheckmulti->add_nocopy(mcheck, OPERATION_LOGICAL_AND); + } else { + mcheckmulti = mcheck; + } + } + if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { + if(!mtryzero) { + mtryzero = new MathStructure(CHILD(0)[i]); + mtryzero->add(m_zero, OPERATION_EQUALS); + mtryzero->isolate_x(eo2, eo); + MathStructure *mcheck = new MathStructure(mchild2); + switch(ct_orig) { + case COMPARISON_LESS: {mcheck->add(m_zero, OPERATION_GREATER); break;} + case COMPARISON_GREATER: {mcheck->add(m_zero, OPERATION_LESS); break;} + case COMPARISON_EQUALS_LESS: {mcheck->add(m_zero, OPERATION_EQUALS_GREATER); break;} + case COMPARISON_EQUALS_GREATER: {mcheck->add(m_zero, OPERATION_EQUALS_LESS); break;} + default: {} + } + mcheck->isolate_x(eo2, eo); + mtryzero->add_nocopy(mcheck, OPERATION_LOGICAL_AND); + } else { + MathStructure *mcheck = new MathStructure(CHILD(0)[i]); + mcheck->add(m_zero, OPERATION_EQUALS); + mcheck->isolate_x(eo2, eo); + (*mtryzero)[0].add_nocopy(mcheck, OPERATION_LOGICAL_OR); + mtryzero[0].calculateLogicalOrLast(eo2); + } + } else if(zero1 > 0) { + MathStructure *mcheck = new MathStructure(CHILD(0)[i]); + if(ct_comp == COMPARISON_NOT_EQUALS) mcheck->add(m_zero, OPERATION_NOT_EQUALS); + else mcheck->add(m_zero, OPERATION_EQUALS); + mcheck->isolate_x(eo2, eo); + if(zero1 == 2) { + MathStructure *mcheck2 = new MathStructure(mchild2); + if(ct_comp == COMPARISON_NOT_EQUALS) mcheck2->add(m_zero, OPERATION_NOT_EQUALS); + else mcheck2->add(m_zero, OPERATION_EQUALS); + mcheck2->isolate_x(eo2, eo); + if(ct_comp == COMPARISON_NOT_EQUALS) mcheck2->add_nocopy(mcheck, OPERATION_LOGICAL_OR); + else mcheck2->add_nocopy(mcheck, OPERATION_LOGICAL_AND); + mcheck2->calculatesub(eo2, eo, false); + mcheck = mcheck2; + } + if(mtryzero) { + if(ct_comp == COMPARISON_NOT_EQUALS) mtryzero->add_nocopy(mcheck, OPERATION_LOGICAL_AND); + else mtryzero->add_nocopy(mcheck, OPERATION_LOGICAL_OR); + } else { + mtryzero = mcheck; + } + } + } + if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { + if(CHILD(0)[i].representsNegative()) { + switch(ct_comp) { + case COMPARISON_LESS: {ct_comp = COMPARISON_GREATER; break;} + case COMPARISON_GREATER: {ct_comp = COMPARISON_LESS; break;} + case COMPARISON_EQUALS_LESS: {ct_comp = COMPARISON_EQUALS_GREATER; break;} + case COMPARISON_EQUALS_GREATER: {ct_comp = COMPARISON_EQUALS_LESS; break;} + default: {} + } + } else if(!CHILD(0)[i].representsNonNegative()) { + if(mchecknegative) { + mchecknegative->multiply(CHILD(0)[i]); + } else { + mchecknegative = new MathStructure(CHILD(0)[i]); + } + } + } + if(zero1 != 1) { + CHILD(1).calculateDivide(CHILD(0)[i], eo2); + CHILD_UPDATED(1); + } + CHILD(0).delChild(i + 1); + b = true; + } + } + if(combine_powers(*this, x_var, eo2) && m_type != STRUCT_MULTIPLICATION) return isolate_x_sub(eo, eo2, x_var, morig); + if(!b && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && CHILD(0).size() >= 2) { + // (x+a)*b^(c*x)=d => x=(lambertw(b^(a*c)*c*d*ln(b))-a*c*ln(b)))/(c*ln(b)) + if(CALCULATOR->aborted()) { + set(mbak); + if(mcheckmulti) mcheckmulti->unref(); + if(mtryzero) mcheckmulti->unref(); + if(mchecknegative) mcheckmulti->unref(); + if(mchecknonzeropow) mcheckmulti->unref(); + return false; + } + size_t i_px = 0; + MathStructure *mvar = NULL; + MathStructure m_c; + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CHILD(0)[i].isPower() && CHILD(0)[i][1].contains(x_var) && !CHILD(0)[i][0].contains(x_var)) { + mvar = find_mvar(CHILD(0)[i][1], x_var, m_c); + if(mvar) i_px = i; + else break; + } + } + if(mvar) { + size_t i_x = 0; + bool found_mvar = false; + MathStructure mmul(1, 1, 0), m_a; + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(i != i_px) { + if(CHILD(0)[i].contains(x_var)) { + if(!found_mvar && CHILD(0)[i].equals(*mvar)) { + found_mvar = true; + i_x = i; + } else if(!found_mvar && CHILD(0)[i].isAddition()) { + i_x = i; + for(size_t i2 = 0; i2 < CHILD(0)[i].size(); i2++) { + if(CHILD(0)[i][i2].contains(*mvar)) { + if(!found_mvar && CHILD(0)[i][i2].equals(*mvar)) { + found_mvar = true; + } else if(!found_mvar && CHILD(0)[i][i2].isMultiplication()) { + for(size_t i3 = 0; i3 < CHILD(0)[i][i2].size(); i3++) { + if(CHILD(0)[i][i2][i3].equals(*mvar)) { + mmul = CHILD(0)[i][i2]; + mmul.delChild(i3 + 1, true); + break; + } + } + if(mmul.contains(*mvar)) { + found_mvar = false; + break; + } + } else { + found_mvar = false; + break; + } + m_a = CHILD(0)[i]; + m_a.delChild(i2 + 1, true); + if(!mmul.isOne()) m_a.calculateDivide(mmul, eo2); + } + } + if(!found_mvar) break; + } else { + found_mvar = false; + break; + } + } + } + } + if(found_mvar) { + MathStructure mln(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &CHILD(0)[i_px][0], NULL); + if(mln.calculateFunctions(eo)) mln.calculatesub(eo2, eo, true); + MathStructure *marg = NULL; + if(mln.representsNonZero()) { + marg = new MathStructure(mln); + if(COMPARISON_MIGHT_BE_EQUAL(m_c.compare(m_zero))) {marg->unref(); marg = NULL;} + else if(!m_c.isOne()) marg->calculateMultiply(m_c, eo2); + } + if(marg) { + marg->calculateMultiply(CHILD(1), eo2); + if(CHILD(0).size() > 2) { + marg->multiply(CHILD(0)); + marg->last().delChild(i_x + 1); + marg->last().delChild(i_px + (i_px < i_x ? 1 : 0), true); + if(!marg->last().representsNonZero()) { + marg->unref(); marg = NULL; + } else { + marg->last().calculateRaise(nr_minus_one, eo2); + marg->calculateMultiplyLast(eo2); + } + } + if(!mmul.isOne()) marg->calculateDivide(mmul, eo2); + + } + if(marg && !m_a.isZero()) { + marg->multiply(CHILD(0)[i_px][0]); + marg->last().raise(m_a); + if(!m_c.isOne()) marg->last().last().calculateMultiply(m_c, eo2); + marg->last().calculateRaiseExponent(eo2); + marg->calculateMultiplyLast(eo2); + } + if(marg && mvar->representsNonComplex() && CHILD(0)[i_px][0].representsPositive()) { + if(mcheckmulti) mcheckmulti->unref(); + if(mtryzero) mcheckmulti->unref(); + if(mchecknegative) mcheckmulti->unref(); + if(mchecknonzeropow) mcheckmulti->unref(); + if(marg->representsComplex()) { + marg->unref(); + if(ct_comp == COMPARISON_EQUALS) clear(true); + else set(1, 1, 0, true); + return true; + } + MathStructure *mreq1 = NULL; + MathStructure *marg2 = NULL; + MathStructure *mreq2 = NULL; + + if(m_a == CHILD(1)) { + marg2 = new MathStructure(*mvar); + marg2->transform(ct_comp, m_zero); + marg2->calculatesub(eo2, eo, false); + } + if(!m_a.isZero()) { + if(!m_c.isOne()) m_a.calculateMultiply(m_c, eo2); + m_a.calculateMultiply(mln, eo2); + } + if(!marg2 && !marg->representsNonNegative()) { + mreq1 = new MathStructure(*marg); + mreq2 = new MathStructure(*marg); + marg2 = new MathStructure(*marg); + marg2->transformById(FUNCTION_ID_LAMBERT_W); + marg2->addChild(m_minus_one); + if(marg2->calculateFunctions(eo)) marg2->calculatesub(eo2, eo, true); + if(!m_a.isZero()) marg2->calculateSubtract(m_a, eo2); + if(!m_c.isOne()) marg2->calculateDivide(m_c, eo2); + marg2->calculateDivide(mln, eo2); + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->getVariableById(VARIABLE_ID_E)); + mreq1->last().calculateRaise(m_minus_one, eo2); + mreq1->last().calculateNegate(eo2); + mreq1->childUpdated(2); + mreq1->isolate_x(eo2, eo); + mreq2->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_EQUALS_LESS : COMPARISON_GREATER, m_zero); + mreq2->isolate_x(eo2, eo); + marg2->transform(ct_comp, *mvar); + marg2->swapChildren(1, 2); + marg2->isolate_x_sub(eo, eo2, x_var, morig); + marg2->add(*mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + marg2->add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + marg2->calculatesub(eo2, eo, false); + } + marg->transformById(FUNCTION_ID_LAMBERT_W); + marg->addChild(m_zero); + if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); + if(!m_a.isZero()) marg->calculateSubtract(m_a, eo2); + if(!m_c.isOne()) marg->calculateDivide(m_c, eo2); + marg->calculateDivide(mln, eo2); + setChild_nocopy(marg, 2, true); + mvar->ref(); + CHILD(0).clear(true); + setChild_nocopy(mvar, 1, true); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + if(mreq1) { + add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + if(marg2) { + add_nocopy(marg2, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + return true; + } else if(marg) { + if(mcheckmulti) mcheckmulti->unref(); + if(mtryzero) mcheckmulti->unref(); + if(mchecknegative) mcheckmulti->unref(); + if(mchecknonzeropow) mcheckmulti->unref(); + marg->transformById(FUNCTION_ID_LAMBERT_W); + marg->addChild(CALCULATOR->getVariableById(VARIABLE_ID_N)); + if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); + if(!m_a.isZero()) { + m_a.calculateMultiply(mln, eo2); + marg->calculateSubtract(m_a, eo2); + } + if(!m_c.isOne()) marg->calculateDivide(m_c, eo2); + marg->calculateDivide(mln, eo2); + setChild_nocopy(marg, 2, true); + mvar->ref(); + CHILD(0).clear(true); + setChild_nocopy(mvar, 1, true); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } + } + } + if(CHILD(0).size() == 2) { + // x*ln(x)=a => e^lambertw(a) + bool b_swap = false; + if(CHILD(0)[0].isFunction() && CHILD(0)[0].function()->id() == FUNCTION_ID_LOG && CHILD(0)[0].size() == 1) { + CHILD(0).swapChildren(1, 2); + b_swap = true; + } + if(CHILD(0)[1].isFunction() && CHILD(0)[1].function()->id() == FUNCTION_ID_LOG && CHILD(0)[1].size() == 1) { + MathStructure mmul(1, 1, 0), mexp(1, 1, 0); + mvar = NULL; + if(CHILD(0)[0] == CHILD(0)[1][0]) { + mvar = &CHILD(0)[0]; + } else if(CHILD(0)[0].isPower() && CHILD(0)[0][0] == CHILD(0)[1][0]) { + mexp = CHILD(0)[0][1]; + mvar = &CHILD(0)[0][0]; + } else { + if(get_multiplier(CHILD(0)[1][0], CHILD(0)[0], mmul)) { + mvar = &CHILD(0)[0]; + } else if(CHILD(0)[0].isPower() && get_multiplier(CHILD(0)[1][0], CHILD(0)[0][0], mmul)) { + mexp = CHILD(0)[0][1]; + mvar = &CHILD(0)[0][0]; + } + + } + if(mvar && mexp.isInteger() && (mexp.number().isOne() || mexp.number().isTwo()) && mmul.representsNonZero() && !mmul.contains(x_var)) { + if(mcheckmulti) mcheckmulti->unref(); + if(mtryzero) mcheckmulti->unref(); + if(mchecknegative) mcheckmulti->unref(); + if(mchecknonzeropow) mcheckmulti->unref(); + MathStructure *marg; + if(mexp.isOne() || mmul.isOne()) { + marg = new MathStructure(CHILD(1)); + if(!mmul.isOne()) marg->calculateMultiply(mmul, eo2); + else if(!mexp.isOne()) marg->calculateMultiply(mexp, eo2); + } else { + marg = new MathStructure(mmul); + marg->calculateRaise(mexp, eo2); + marg->calculateMultiply(CHILD(1), eo2); + marg->calculateMultiply(mexp, eo2); + } + if(mvar->representsNonComplex()) { + MathStructure *mreq1 = NULL; + MathStructure *marg2 = NULL; + MathStructure *mreq2 = NULL; + if(!marg->representsPositive()) { + mreq1 = new MathStructure(*marg); + mreq2 = new MathStructure(*marg); + marg2 = new MathStructure(*marg); + marg2->transformById(FUNCTION_ID_LAMBERT_W); + marg2->addChild(m_minus_one); + if(marg2->calculateFunctions(eo)) marg2->calculatesub(eo2, eo, true); + if(!mexp.isOne()) marg2->calculateDivide(mexp, eo2); + marg2->transform(STRUCT_POWER); + marg2->insertChild(CALCULATOR->getVariableById(VARIABLE_ID_E), 1); + (*marg2)[0].calculatesub(eo2, eo, true); + marg2->calculateRaiseExponent(eo2); + if(!mmul.isOne()) marg2->calculateDivide(mmul, eo2); + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->getVariableById(VARIABLE_ID_E)); + mreq1->last().calculateRaise(m_minus_one, eo2); + mreq1->last().calculateNegate(eo2); + mreq1->childUpdated(2); + mreq1->isolate_x(eo2, eo); + mreq2->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_EQUALS_LESS : COMPARISON_GREATER, m_zero); + mreq2->isolate_x(eo2, eo); + marg2->transform(ct_comp, *mvar); + marg2->swapChildren(1, 2); + marg2->isolate_x_sub(eo, eo2, x_var, morig); + marg2->add(*mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + marg2->add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + marg2->calculatesub(eo2, eo, false); + } + marg->transformById(FUNCTION_ID_LAMBERT_W); + marg->addChild(m_zero); + if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); + if(!mexp.isOne()) marg->calculateDivide(mexp, eo2); + CHILD(0).setToChild(1, true); + if(!mexp.isOne()) CHILD(0).setToChild(1, true); + CHILD(1).set(CALCULATOR->getVariableById(VARIABLE_ID_E)); + CHILD(1).raise_nocopy(marg); + CHILD(1).calculateRaiseExponent(eo2); + if(!mmul.isOne()) CHILD(1).calculateDivide(mmul, eo2); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + if(mreq1) { + add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + if(marg2) { + add_nocopy(marg2, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + } else { + if(!mexp.isOne()) marg->calculateMultiply(mexp, eo2); + if(!mmul.isOne()) marg->calculateDivide(mmul, eo2); + MathStructure *marg2 = new MathStructure(*marg); + MathStructure *marg3 = new MathStructure(*marg); + marg2->transformById(FUNCTION_ID_LAMBERT_W); + marg2->addChild(m_minus_one); + if(marg2->calculateFunctions(eo)) marg2->calculatesub(eo2, eo, true); + if(!mexp.isOne()) marg2->calculateDivide(mexp, eo2); + marg2->transform(STRUCT_POWER); + marg2->insertChild(CALCULATOR->getVariableById(VARIABLE_ID_E), 1); + (*marg2)[0].calculatesub(eo2, eo, true); + marg2->calculateRaiseExponent(eo2); + if(!mmul.isOne()) marg2->calculateDivide(mmul, eo2); + marg3->transformById(FUNCTION_ID_LAMBERT_W); + marg3->addChild(m_one); + if(marg3->calculateFunctions(eo)) marg3->calculatesub(eo2, eo, true); + if(!mexp.isOne()) marg3->calculateDivide(mexp, eo2); + marg3->transform(STRUCT_POWER); + marg3->insertChild(CALCULATOR->getVariableById(VARIABLE_ID_E), 1); + (*marg3)[0].calculatesub(eo2, eo, true); + marg3->calculateRaiseExponent(eo2); + if(!mmul.isOne()) marg3->calculateDivide(mmul, eo2); + marg2->transform(ct_comp, *mvar); + marg2->swapChildren(1, 2); + marg2->isolate_x_sub(eo, eo2, x_var, morig); + marg3->transform(ct_comp, *mvar); + marg3->swapChildren(1, 2); + marg3->isolate_x_sub(eo, eo2, x_var, morig); + marg->transformById(FUNCTION_ID_LAMBERT_W); + marg->addChild(m_zero); + if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); + if(!mexp.isOne()) marg->calculateDivide(mexp, eo2); + CHILD(0).setToChild(1, true); + if(!mexp.isOne()) CHILD(0).setToChild(1, true); + CHILD(1).set(CALCULATOR->getVariableById(VARIABLE_ID_E)); + CHILD(1).raise_nocopy(marg); + CHILD(1).calculateRaiseExponent(eo2); + if(!mmul.isOne()) CHILD(1).calculateDivide(mmul, eo2); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + add_nocopy(marg2, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + add_nocopy(marg3, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + calculatesub(eo2, eo, false); + } + return true; + } + } + if(b_swap) CHILD(0).swapChildren(1, 2); + } + } + if(b) { + if(CHILD(0).size() == 1) { + CHILD(0).setToChild(1); + } + if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && CHILD(1).contains(x_var)) { + CHILD(0).calculateSubtract(CHILD(1), eo2); + CHILD(1).clear(); + } + if(mchecknegative) { + MathStructure *mneg = new MathStructure(*this); + switch(ct_comp) { + case COMPARISON_LESS: {mneg->setComparisonType(COMPARISON_GREATER); break;} + case COMPARISON_GREATER: {mneg->setComparisonType(COMPARISON_LESS); break;} + case COMPARISON_EQUALS_LESS: {mneg->setComparisonType(COMPARISON_EQUALS_GREATER); break;} + case COMPARISON_EQUALS_GREATER: {mneg->setComparisonType(COMPARISON_EQUALS_LESS); break;} + default: {} + } + isolate_x_sub(eo, eo2, x_var, morig); + //mneg->isolate_x_sub(eo, eo2, x_var); + mchecknegative->add(m_zero, OPERATION_GREATER); + add(*mchecknegative, OPERATION_LOGICAL_AND, true); + SWAP_CHILDREN(0, SIZE - 1) + calculatesub(eo2, eo, false); + //LAST.isolate_x(eo2, eo); + mchecknegative->setComparisonType(COMPARISON_LESS); + mchecknegative->isolate_x(eo2, eo); + mneg->add_nocopy(mchecknegative, OPERATION_LOGICAL_AND, true); + mneg->calculatesub(eo2, eo, false); + add_nocopy(mneg, OPERATION_LOGICAL_OR, true); + calculatesub(eo2, eo, false); + } else { + isolate_x_sub(eo, eo2, x_var, morig); + } + if(mcheckmulti) { + mcheckmulti->calculatesub(eo2, eo, false); + if(ct_comp == COMPARISON_NOT_EQUALS) { + add_nocopy(mcheckmulti, OPERATION_LOGICAL_OR, true); + } else { + add_nocopy(mcheckmulti, OPERATION_LOGICAL_AND, true); + SWAP_CHILDREN(0, SIZE - 1) + } + calculatesub(eo2, eo, false); + } + if(mchecknonzeropow) { + mchecknonzeropow->calculatesub(eo2, eo, false); + if(ct_comp == COMPARISON_NOT_EQUALS) { + add_nocopy(mchecknonzeropow, OPERATION_LOGICAL_OR, true); + } else { + add_nocopy(mchecknonzeropow, OPERATION_LOGICAL_AND, true); + SWAP_CHILDREN(0, SIZE - 1) + } + calculatesub(eo2, eo, false); + } + if(mtryzero) { + mtryzero->calculatesub(eo2, eo, false); + if(ct_comp == COMPARISON_NOT_EQUALS) { + add_nocopy(mtryzero, OPERATION_LOGICAL_AND, true); + SWAP_CHILDREN(0, SIZE - 1) + } else { + add_nocopy(mtryzero, OPERATION_LOGICAL_OR, true); + } + calculatesub(eo2, eo, false); + } + return true; + } + + if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { + // x*(x+a)^(1/b)=c => (x*(x+a)^(1/b))^b=c^b + Number nrexp; + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CALCULATOR->aborted()) return false; + if(CHILD(0)[i].isPower() && CHILD(0)[i][1].isNumber() && CHILD(0)[i][1].number().isRational()) { + if(!CHILD(0)[i][1].number().isInteger()) { + if(nrexp.isZero()) nrexp = CHILD(0)[i][1].number().denominator(); + else nrexp.lcm(CHILD(0)[i][1].number().denominator()); + } + } else if(CHILD(0)[i].isFunction() && CHILD(0)[i].function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(CHILD(0)[i])) { + if(nrexp.isZero()) nrexp = CHILD(0)[i][1].number(); + else nrexp.lcm(CHILD(0)[i][1].number()); + } else if(CHILD(0)[i] != x_var && !(CHILD(0)[i].isFunction() && CHILD(0)[i].function()->id() == FUNCTION_ID_ABS && CHILD(0)[i].size() == 1 && CHILD(0)[i][0].representsReal(true))) { + nrexp.clear(); + break; + } + } + if(!nrexp.isZero()) { + MathStructure mtest(*this); + if(mtest[0].calculateRaise(nrexp, eo2)) { + mtest[1].calculateRaise(nrexp, eo2); + mtest.childrenUpdated(); + if(mtest.isolate_x(eo2, eo, x_var)) { + if((mtest.isLogicalAnd() || mtest.isLogicalOr() || mtest.isComparison()) && test_comparisons(*this, mtest, x_var, eo, false, eo.expand ? 1 : 2) < 0) { + if(eo.expand) { + add(mtest, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); + calculatesub(eo2, eo, false); + return true; + } + } else { + set(mtest); + return true; + } + } + } + } + } + if(!eo2.expand) break; + // abs(x)*x=a => -x*x=a || x*x=a; sgn(x)*x=a => -1*x=a || 0*x=a || 1*x=a + if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { + MathStructure *m = find_abs_sgn(CHILD(0), x_var); + if(m && m->function()->id() == FUNCTION_ID_ABS) { + + MathStructure mabs(*m); + + ComparisonType cmp_type = ct_comp; + MathStructure *malt = new MathStructure(*this); + MathStructure mabs_minus(mabs[0]); + mabs_minus.calculateNegate(eo2); + (*malt)[0].replace(mabs, mabs_minus, mabs.containsInterval()); + (*malt)[0].calculatesub(eo2, eo, true); + MathStructure *mcheck = new MathStructure(mabs[0]); + mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_EQUALS_GREATER : OPERATION_LESS); + mcheck->isolate_x_sub(eo, eo2, x_var); + malt->isolate_x_sub(eo, eo2, x_var); + malt->add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + malt->calculatesub(eo2, eo, false); + + mcheck = new MathStructure(mabs[0]); + CHILD(0).replace(mabs, mabs[0], mabs.containsInterval()); + CHILD(0).calculatesub(eo2, eo, true); + mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LESS : OPERATION_EQUALS_GREATER); + mcheck->isolate_x_sub(eo, eo2, x_var); + isolate_x_sub(eo, eo2, x_var); + add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + calculatesub(eo2, eo, false); + add_nocopy(malt, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); + calculatesub(eo2, eo, false); + return true; + } else if(m && m->function()->id() == FUNCTION_ID_SIGNUM) { + MathStructure mabs(*m); + + ComparisonType cmp_type = ct_comp; + MathStructure *malt = new MathStructure(*this); + (*malt)[0].replace(mabs, m_minus_one, mabs.containsInterval()); + (*malt)[0].calculatesub(eo2, eo, true); + MathStructure *mcheck = new MathStructure(mabs[0]); + mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_EQUALS_GREATER : OPERATION_LESS); + mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? ((*m)[1].isMinusOne() ? OPERATION_GREATER : OPERATION_EQUALS_GREATER) : ((*m)[1].isMinusOne() ? OPERATION_EQUALS_LESS : OPERATION_LESS)); + mcheck->isolate_x_sub(eo, eo2, x_var); + malt->isolate_x_sub(eo, eo2, x_var); + malt->add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + malt->calculatesub(eo2, eo, false); + + MathStructure *malt0 = NULL; + if(!(*m)[1].isOne() && !(*m)[1].isMinusOne()) { + malt0 = new MathStructure(*this); + (*malt0)[0].replace(mabs, (*m)[1], mabs.containsInterval()); + (*malt0)[0].calculatesub(eo2, eo, true); + mcheck = new MathStructure(mabs[0]); + mcheck->add((*m)[1], cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_NOT_EQUALS : OPERATION_EQUALS); + mcheck->isolate_x_sub(eo, eo2, x_var); + malt0->isolate_x_sub(eo, eo2, x_var); + malt0->add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + malt0->calculatesub(eo2, eo, false); + } + + mcheck = new MathStructure(mabs[0]); + CHILD(0).replace(mabs, m_one, mabs.containsInterval()); + CHILD(0).calculatesub(eo2, eo, true); + mcheck->add(m_zero, cmp_type == COMPARISON_NOT_EQUALS ? ((*m)[1].isOne() ? OPERATION_LESS : OPERATION_EQUALS_LESS) : ((*m)[1].isOne() ? OPERATION_EQUALS_GREATER : OPERATION_GREATER)); + mcheck->isolate_x_sub(eo, eo2, x_var); + isolate_x_sub(eo, eo2, x_var); + add_nocopy(mcheck, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + calculatesub(eo2, eo, false); + add_nocopy(malt, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); + if(malt0) add_nocopy(malt0, cmp_type == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); + calculatesub(eo2, eo, false); + return true; + } + } + // Try factorization + if(!CHILD(1).isZero() && (!morig || !equals(*morig))) { + MathStructure mtest(*this); + mtest[0].calculateSubtract(CHILD(1), eo2); + mtest[1].clear(); + mtest.childrenUpdated(); + if(mtest[0].factorize(eo2, false, false, 0, false, false, NULL, m_undefined, false, false, 3) && !(mtest[0].isMultiplication() && mtest[0].size() == 2 && (mtest[0][0].isNumber() || mtest[0][0] == CHILD(1) || mtest[0][1] == CHILD(1)))) { + mtest.childUpdated(1); + if(mtest.isolate_x_sub(eo, eo2, x_var, this)) { + set_nocopy(mtest); + return true; + } + } + } + break; + } + case STRUCT_POWER: { + if(CHILD(0)[0].contains(x_var)) { + if(CHILD(0)[1].contains(x_var)) { + if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && !CHILD(1).isZero()) { + // x^(a*x)=b => x=e^(lambertw(ln(x)/a)) + MathStructure mmul(1, 1, 0); + const MathStructure *mvar = get_power_term(CHILD(0)[1], CHILD(0)[0]); + if(!mvar || !get_multiplier(CHILD(0)[1], *mvar, mmul) || mmul.contains(x_var) || COMPARISON_MIGHT_BE_EQUAL(mmul.compare(m_zero))) return false; + MathStructure mexp(1, 1, 0); + if(mvar->isPower() && *mvar != CHILD(0)[0]) mexp = (*mvar)[1]; + if(!mexp.representsPositive()) return false; + if(mmul.isOne() && mexp.isOne() && CHILD(1).isNumber() && CHILD(1).number().isRational() && CHILD(0)[0].representsNonComplex()) { + // x is real, a=1, b is rational + if(CHILD(1).number().isInteger()) { + if(CHILD(1).number().isOne()) { + // 1^1=1 + CHILD(0).setToChild(1, true); + return true; + } else if(CHILD(1).number().isMinusOne()) { + // (-1)^(-1)=-1 + CHILD(0).setToChild(1, true); + return true; + } else if(CHILD(1).number() == 4) { + // 2^2=4 + CHILD(1).set(2, 1, 0, true); + CHILD(0).setToChild(1, true); + return true; + } else if(CHILD(1).number() == 27) { + // 3^3=27 + CHILD(1).set(3, 1, 0, true); + CHILD(0).setToChild(1, true); + return true; + } else if(CHILD(1).number() == 256) { + // 4^4=256 + CHILD(1).set(4, 1, 0, true); + CHILD(0).setToChild(1, true); + return true; + } else if(CHILD(1).number() == 3125) { + // 5^5=3125 + CHILD(1).set(5, 1, 0, true); + CHILD(0).setToChild(1, true); + return true; + } else if(CHILD(1).number() == 46656) { + // 6^6=46656 + CHILD(1).set(6, 1, 0, true); + CHILD(0).setToChild(1, true); + return true; + } else if(CHILD(1).number() == 823543L) { + // 7^7=823543 + CHILD(1).set(7, 1, 0, true); + CHILD(0).setToChild(1, true); + return true; + } else if(eo.approximation == APPROXIMATION_EXACT && CHILD(1).number() > 823543L) { + CALCULATOR->beginTemporaryStopMessages(); + Number nr(CHILD(1).number()); + // n=round(e^(lambertw(ln(b)))) + if(nr.ln() && nr.lambertW() && nr.exp() && nr.round()) { + nr.setApproximate(false); + Number nrtest(nr); + nrtest.raise(nr, true); + // if b=n^n, x=n + if(!CALCULATOR->endTemporaryStopMessages() && !nrtest.isApproximate() && CHILD(1).number() == nrtest) { + CHILD(1).set(nr, true); + CHILD(0).setToChild(1, true); + return true; + } + } else { + CALCULATOR->endTemporaryStopMessages(); + } + } + } else if(CHILD(1).number().numeratorIsOne()) { + Number nr_den = CHILD(1).number().denominator(); + if(nr_den == 4) { + // (-2)^(-2)=1/4 + CHILD(1).set(-2, 1, 0, true); + CHILD(0).setToChild(1, true); + return true; + } else if(nr_den == 256) { + // (-4)^(-4)=1/256 + CHILD(1).set(-4, 1, 0, true); + CHILD(0).setToChild(1, true); + return true; + } else if(nr_den == 46656) { + // (-6)^(-6)=1/46656 + CHILD(1).set(-6, 1, 0, true); + CHILD(0).setToChild(1, true); + return true; + } else if(nr_den > 46656) { + CALCULATOR->beginTemporaryStopMessages(); + // n=-round(e^(lambertw(ln(b)))) + if(nr_den.ln() && nr_den.lambertW() && nr_den.exp() && nr_den.round() && nr_den.negate()) { + nr_den.setApproximate(false); + Number nrtest(nr_den); + nrtest.raise(nr_den, true); + // if b=n^n, x=n + if(!CALCULATOR->endTemporaryStopMessages() && !nrtest.isApproximate() && CHILD(1).number() == nrtest) { + CHILD(1).set(nr_den, true); + CHILD(0).setToChild(1, true); + return true; + } + } else { + CALCULATOR->endTemporaryStopMessages(); + } + } + } else if(CHILD(1).number().numeratorIsMinusOne()) { + Number nr_den = CHILD(1).number().denominator(); + if(nr_den == 27) { + // (-3)^(-3)=-1/27 + CHILD(1).set(-3, 1, 0, true); + CHILD(0).setToChild(1, true); + return true; + } else if(nr_den == 3125) { + // (-5)^(-5)=-1/3125 + CHILD(1).set(-5, 1, 0, true); + CHILD(0).setToChild(1, true); + return true; + } else if(nr_den == 823543L) { + // (-7)^(-7)=-1/823543 + CHILD(1).set(-7, 1, 0, true); + CHILD(0).setToChild(1, true); + return true; + } else if(nr_den < 823543L) { + // x^x!=-1/m if x is not integer + if(ct_comp == COMPARISON_NOT_EQUALS) set(1, 1, 0, true); + else clear(true); + return true; + } else { + CALCULATOR->beginTemporaryStopMessages(); + // n=-round(e^(lambertw(ln(b)))) + if(nr_den.ln() && nr_den.lambertW() && nr_den.exp() && nr_den.negate() && nr_den.round()) { + nr_den.setApproximate(false); + Number nrtest(nr_den); + nrtest.raise(nr_den, true); + // if b=n^n, x=n + if(!CALCULATOR->endTemporaryStopMessages() && !nrtest.isApproximate()) { + if(CHILD(1).number() == nrtest) { + CHILD(1).set(nr_den, true); + CHILD(0).setToChild(1, true); + return true; + } + // x^x!=-1/m if x is not integer + if(ct_comp == COMPARISON_NOT_EQUALS) set(1, 1, 0, true); + else clear(true); + return true; + } + } else if(!CALCULATOR->endTemporaryStopMessages()) { + return false; + } + } + } else if(CHILD(1).number().isNegative()) { + // x^x!=-n/m if x is not integer and n is not 1 + if(ct_comp == COMPARISON_NOT_EQUALS) set(1, 1, 0, true); + else clear(true); + return true; + } + } + MathStructure *marg = new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &CHILD(1), NULL); + if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); + if(CHILD(0)[0].representsNonComplex() && CHILD(1).compare(m_zero) == COMPARISON_RESULT_LESS) { + // x is real, b > 0: + // x=e^lambertw(ln(b)/a) if ln(b)/a >= -1/e + // x=e^lambertw(ln(b)/a, -1) if -1/e <= ln(b)/a < 0 + if(!mexp.isOne()) marg->calculateMultiply(mexp, eo2); + if(!mmul.isOne()) marg->calculateDivide(mmul, eo2); + MathStructure *mreq1 = NULL; + MathStructure *marg2 = NULL; + MathStructure *mreq2 = NULL; + if(!marg->representsNonNegative()) { + mreq1 = new MathStructure(*marg); + mreq2 = new MathStructure(*marg); + marg2 = new MathStructure(*marg); + marg2->transformById(FUNCTION_ID_LAMBERT_W); + marg2->addChild(m_minus_one); + if(marg2->calculateFunctions(eo)) marg2->calculatesub(eo2, eo, true); + if(!mexp.isOne()) marg2->calculateDivide(mexp, eo2); + marg2->transform(STRUCT_POWER); + marg2->insertChild(CALCULATOR->getVariableById(VARIABLE_ID_E), 1); + (*marg2)[0].calculatesub(eo2, eo, true); + marg2->calculateRaiseExponent(eo2); + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->getVariableById(VARIABLE_ID_E)); + mreq1->last().calculateRaise(m_minus_one, eo2); + mreq1->last().calculateNegate(eo2); + mreq1->childUpdated(2); + mreq1->isolate_x(eo2, eo); + mreq2->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, m_zero); + mreq2->isolate_x(eo2, eo); + marg2->transform(ct_comp, CHILD(0)[0]); + marg2->swapChildren(1, 2); + marg2->isolate_x_sub(eo, eo2, x_var, morig); + marg2->add(*mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + marg2->add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + marg2->calculatesub(eo2, eo, false); + } + marg->transformById(FUNCTION_ID_LAMBERT_W); + marg->addChild(m_zero); + if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); + if(!mexp.isOne()) marg->calculateDivide(mexp, eo2); + CHILD(0).setToChild(1, true); + CHILD(1).set(CALCULATOR->getVariableById(VARIABLE_ID_E)); + CHILD(1).raise_nocopy(marg); + CHILD(1).calculateRaiseExponent(eo2); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + if(mreq1) { + add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + if(marg2) { + add_nocopy(marg2, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + } else { + // x is not real or b < 0: + // x=e^lambertw(ln(b)+2i*pi*n/a) || x=e^lambertw(ln(b)+2i*pi*n/a, -1) || x=e^lambertw(ln(b)+2i*pi*n/a, 1) + marg->add(nr_one_i); + marg->last().multiply(nr_two); + marg->last().multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI), true); + marg->last().multiply(CALCULATOR->getVariableById(VARIABLE_ID_N), true); + marg->evalSort(true); + MathStructure *mreq2 = NULL; + if(!CHILD(1).representsNonZero()) { + mreq2 = new MathStructure(CHILD(1)); + mreq2->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_NOT_EQUALS : COMPARISON_EQUALS, m_zero); + mreq2->isolate_x(eo2, eo); + } + MathStructure *mreq1 = NULL; + if(!CHILD(1).isNumber() || !CHILD(1).number().isFraction()) { + mreq1 = new MathStructure(*marg); + mreq1->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_NOT_EQUALS : COMPARISON_EQUALS, m_zero); + mreq1->isolate_x(eo2, eo); + EvaluationOptions eo3 = eo2; + eo3.test_comparisons = true; + mreq1->calculatesub(eo3, eo, false); + if(mreq1->isNumber()) { + if(mreq1->number().getBoolean() == (ct_comp == COMPARISON_NOT_EQUALS)) { + clear(true); + return true; + } else { + mreq1->unref(); + mreq1 = NULL; + } + } + } + MathStructure *mreq3a = new MathStructure(*marg); + mreq3a->transformById(FUNCTION_ID_IM); + mreq3a->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, CALCULATOR->getVariableById(VARIABLE_ID_PI)); + mreq3a->last().negate(); + mreq3a->last().calculatesub(eo2, eo, true); + mreq3a->childUpdated(2); + MathStructure *mreq3b = new MathStructure(*marg); + mreq3b->transformById(FUNCTION_ID_IM); + mreq3b->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, CALCULATOR->getVariableById(VARIABLE_ID_PI)); + mreq3b->last().calculatesub(eo2, eo, true); + mreq3b->childUpdated(2); + if(!mexp.isOne()) marg->calculateMultiply(mexp, eo2); + if(!mmul.isOne()) marg->calculateDivide(mmul, eo2); + MathStructure *marg2 = new MathStructure(*marg); + MathStructure *marg3 = new MathStructure(*marg); + marg2->transformById(FUNCTION_ID_LAMBERT_W); + marg2->addChild(m_minus_one); + if(marg2->calculateFunctions(eo)) marg2->calculatesub(eo2, eo, true); + if(!mexp.isOne()) marg2->calculateDivide(mexp, eo2); + marg2->transform(STRUCT_POWER); + marg2->insertChild(CALCULATOR->getVariableById(VARIABLE_ID_E), 1); + (*marg2)[0].calculatesub(eo2, eo, true); + marg2->calculateRaiseExponent(eo2); + marg3->transformById(FUNCTION_ID_LAMBERT_W); + marg3->addChild(m_one); + if(marg3->calculateFunctions(eo)) marg3->calculatesub(eo2, eo, true); + if(!mexp.isOne()) marg3->calculateDivide(mexp, eo2); + marg3->transform(STRUCT_POWER); + marg3->insertChild(CALCULATOR->getVariableById(VARIABLE_ID_E), 1); + (*marg3)[0].calculatesub(eo2, eo, true); + marg3->calculateRaiseExponent(eo2); + marg2->transform(ct_comp, CHILD(0)[0]); + marg2->swapChildren(1, 2); + marg2->isolate_x_sub(eo, eo2, x_var, morig); + marg2->add(*mreq3a, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + if(mreq1) marg2->add(*mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + if(mreq2) marg2->add(*mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + marg2->calculatesub(eo2, eo, false); + marg3->transform(ct_comp, CHILD(0)[0]); + marg3->swapChildren(1, 2); + marg3->isolate_x_sub(eo, eo2, x_var, morig); + marg3->add(*mreq3b, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + if(mreq1) marg3->add(*mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + if(mreq2) marg3->add(*mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + marg3->calculatesub(eo2, eo, false); + marg->transformById(FUNCTION_ID_LAMBERT_W); + marg->addChild(m_zero); + if(marg->calculateFunctions(eo)) marg->calculatesub(eo2, eo, true); + if(!mexp.isOne()) marg->calculateDivide(mexp, eo2); + CHILD(0).setToChild(1, true); + CHILD(1).set(CALCULATOR->getVariableById(VARIABLE_ID_E)); + CHILD(1).raise_nocopy(marg); + CHILD(1).calculateRaiseExponent(eo2); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + if(mreq1) add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + if(mreq2) add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + if(mreq1 || mreq2) calculatesub(eo2, eo, false); + add_nocopy(marg2, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + add_nocopy(marg3, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + calculatesub(eo2, eo, false); + } + return true; + } + } else if(CHILD(0)[1].isNumber() && CHILD(0)[1].number().isRational()) { + // x^a=b + if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && !CHILD(0)[1].number().isInteger() && !CHILD(0)[1].number().isFraction() && !CHILD(0).representsNonComplex(true)) { + MathStructure mvar(CHILD(0)[0]); + mvar.raise(CHILD(0)[1].number().numerator()); + + UnknownVariable *var = new UnknownVariable("", string(LEFT_PARENTHESIS) + format_and_print(mvar) + RIGHT_PARENTHESIS); + var->setInterval(mvar); + MathStructure mu(var); + MathStructure mtest(mu); + mtest.raise(CHILD(0)[1]); + mtest[1].number().divide(CHILD(0)[1].number().numerator()); + mtest.transform(ct_comp, CHILD(1)); + if(mtest.isolate_x_sub(eo, eo2, mu)) { + mtest.replace(mu, mvar); + if((mtest.isLogicalAnd() || mtest.isLogicalOr() || mtest.isComparison()) && test_comparisons(*this, mtest, x_var, eo, false, eo.expand ? 1 : 2) < 0) { + if(eo.expand) { + add(mtest, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); + calculatesub(eo2, eo, false); + var->destroy(); + return true; + } + } else { + set(mtest); + var->destroy(); + return true; + } + } + var->destroy(); + return false; + } + bool b_neg = CHILD(0)[1].number().isNegative(); + bool b_nonzero = !CHILD(1).isZero() && CHILD(1).representsNonZero(true); + if(b_neg && CHILD(1).isZero()) { + if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { + CHILD(0).setToChild(1); + CHILD(1) = nr_plus_inf; + CHILDREN_UPDATED + MathStructure *malt = new MathStructure(*this); + (*malt)[1] = nr_minus_inf; + isolate_x_sub(eo, eo2, x_var, morig); + malt->isolate_x_sub(eo, eo2, x_var, morig); + add_nocopy(malt, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); + calculatesub(eo, eo2, false); + return true; + } + if(CHILD(0)[1].number().isInteger() && CHILD(0)[1].number().isEven()) { + if(ct_comp == COMPARISON_EQUALS_LESS) { + clear(true); + return true; + } + ct_comp = COMPARISON_NOT_EQUALS; + CHILD(1).clear(true); + CHILD(0).setToChild(1); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } + if(ct_comp == COMPARISON_EQUALS_GREATER) { + ct_comp = COMPARISON_GREATER; + } else if(ct_comp == COMPARISON_EQUALS_LESS) { + ct_comp = COMPARISON_LESS; + } + CHILD(1).clear(true); + CHILD(0).setToChild(1); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } else if(CHILD(1).isZero()) { + if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS && CHILD(0)[1].number().isInteger() && CHILD(0)[1].number().isEven()) { + if(ct_comp == COMPARISON_LESS) { + clear(true); + return true; + } + if(ct_comp == COMPARISON_EQUALS_LESS) { + ct_comp = COMPARISON_EQUALS; + CHILD(0).setToChild(1); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } + if(ct_comp == COMPARISON_EQUALS_GREATER) { + set(1, 1, 0, true); + return true; + } + CHILD(0).setToChild(1); + MathStructure *mneg = new MathStructure(*this); + if(ct_comp == COMPARISON_GREATER) mneg->setComparisonType(COMPARISON_LESS); + mneg->isolate_x_sub(eo, eo2, x_var, morig); + add_nocopy(mneg, OPERATION_LOGICAL_OR); + calculatesub(eo2, eo, false); + } else { + if(!CHILD(0)[1].number().isInteger()) { + if(ct_comp == COMPARISON_LESS) { + clear(true); + return true; + } + if(ct_comp == COMPARISON_EQUALS_LESS) { + ct_comp = COMPARISON_EQUALS; + CHILD(0).setToChild(1); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } + } + CHILD(0).setToChild(1); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + } + return true; + } else if(b_neg && ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { + if(CHILD(0)[1].number().isMinusOne()) { + CHILD(0).setToChild(1); + } else { + CHILD(0)[1].number().negate(); + + } + MathStructure *mtest = new MathStructure(CHILD(0)); + CHILD(1).set(1, 1, 0); + CHILDREN_UPDATED + MathStructure *malt = new MathStructure(*this); + if(ct_comp == COMPARISON_EQUALS_GREATER) { + ct_comp = COMPARISON_EQUALS_LESS; + } else if(ct_comp == COMPARISON_GREATER) { + ct_comp = COMPARISON_LESS; + } else if(ct_comp == COMPARISON_EQUALS_LESS) { + ct_comp = COMPARISON_EQUALS_GREATER; + } else if(ct_comp == COMPARISON_LESS) { + ct_comp = COMPARISON_GREATER; + } + isolate_x_sub(eo, eo2, x_var, morig); + mtest->add(m_zero, OPERATION_GREATER); + MathStructure *mtest_alt = new MathStructure(*mtest); + mtest_alt->setComparisonType(COMPARISON_LESS); + mtest->isolate_x_sub(eo, eo2, x_var); + add_nocopy(mtest, OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + malt->isolate_x_sub(eo, eo2, x_var, morig); + mtest_alt->isolate_x_sub(eo, eo2, x_var); + malt->add_nocopy(mtest_alt, OPERATION_LOGICAL_AND); + malt->calculatesub(eo2, eo, false); + add_nocopy(malt, OPERATION_LOGICAL_OR); + calculatesub(eo2, eo, false); + return true; + } + MathStructure mbak(*this); + if(CHILD(0)[1].number().isMinusOne()) { + CHILD(0).setToChild(1, true); + CHILD(1).calculateRaise(m_minus_one, eo2); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + } else if(CHILD(0)[1].number().isInteger()) { + bool b_real = CHILD(0)[0].representsNonComplex(true); + bool b_complex = !b_real && CHILD(0)[0].representsComplex(true); + bool warn_complex = false; + bool check_complex = false; + if(CHILD(0)[1].number().isEven()) { + if(!CHILD(1).representsNonNegative(true)) { + if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { + if(CHILD(1).representsNegative(true)) { + if(ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_LESS) clear(true); + else set(1, 1, 0, true); + return true; + } + return false; + } + if(b_real && (CHILD(1).representsNegative(true) || CHILD(1).representsComplex(true))) { + if(ct_comp == COMPARISON_EQUALS) { + clear(true); + } else if(ct_comp == COMPARISON_NOT_EQUALS) { + set(1, 1, 0, true); + } + return true; + } + } + } + bool b_set = false; + if(b_neg) CHILD(0)[1].number().negate(); + if(CHILD(0)[1].number().isTwo()) { + CHILD(1).raise(CHILD(0)[1].number()); + CHILD(1)[1].number().recip(); + if(b_neg) CHILD(1)[1].number().negate(); + CHILD(1).calculateRaiseExponent(eo2); + CHILDREN_UPDATED + } else if(!b_real && CHILD(0)[1].number() == 4 && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { + CHILD(1).raise(CHILD(0)[1].number()); + CHILD(1)[1].number().recip(); + if(b_neg) CHILD(1)[1].number().negate(); + CHILD(1).calculateRaiseExponent(eo2); + CHILD(0).setToChild(1); + CHILDREN_UPDATED + MathStructure *malt1 = new MathStructure(*this); + MathStructure *malt2 = new MathStructure(*this); + MathStructure *malt3 = new MathStructure(*this); + (*malt1)[1].calculateNegate(eo2); + (*malt2)[1].calculateMultiply(m_one_i, eo2); + (*malt3)[1].calculateMultiply(nr_minus_i, eo2); + malt1->childUpdated(2); + malt2->childUpdated(2); + malt3->childUpdated(2); + malt1->isolate_x_sub(eo, eo2, x_var, morig); + malt2->isolate_x_sub(eo, eo2, x_var, morig); + malt3->isolate_x_sub(eo, eo2, x_var, morig); + isolate_x_sub(eo, eo2, x_var, morig); + add_nocopy(malt1, ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); + add_nocopy(malt2, ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); + add_nocopy(malt3, ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); + calculatesub(eo2, eo, false); + b_set = true; + } else if(!b_real && (ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { + if(CHILD(0)[1].number() > 20) return false; + MathStructure mdeg(CHILD(0)[1]); + Number marg_pi; + MathStructure marg; + if(CHILD(1).representsNegative(true)) { + marg_pi.set(1, 1, 0); + } else if(!CHILD(1).representsNegative(true)) { + if(CHILD(1).isNumber() && !CHILD(1).number().hasRealPart()) { + if(CHILD(1).number().imaginaryPartIsNegative()) marg_pi.set(-1, 2, 0); + else marg_pi.set(1, 2, 0); + } else { + marg.set(CALCULATOR->getFunctionById(FUNCTION_ID_ARG), &CHILD(1), NULL); + marg.calculateFunctions(eo); + switch(eo2.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {marg.multiply(Number(1, 180, 0)); marg.multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;} + case ANGLE_UNIT_GRADIANS: {marg.multiply(Number(1, 200, 0)); marg.multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI)); break;} + case ANGLE_UNIT_RADIANS: {break;} + default: {if(CALCULATOR->getRadUnit()) marg /= CALCULATOR->getRadUnit();} + } + marg.calculatesub(eo2, eo, true); + } + } + MathStructure minv(mdeg); + minv.number().recip(); + MathStructure mmul(CALCULATOR->getFunctionById(FUNCTION_ID_ABS), &CHILD(1), NULL); + mmul.calculateFunctions(eo); + mmul.calculateRaise(minv, eo2); + Number nr_i; + while(nr_i.isLessThan(mdeg.number())) { + MathStructure mroot; + if(CALCULATOR->aborted()) {set(mbak); return false;} + MathStructure mexp; + Number nexp; + if(!nr_i.isZero()) { + nexp.set(2, 1, 0); + if(!nexp.multiply(nr_i)) {set(mbak); return false;} + } + b_set = false; + if(!marg_pi.isZero()) { + if(nexp.isZero()) nexp = marg_pi; + else if(!nexp.add(marg_pi)) {set(mbak); return false;} + if(!nexp.divide(mdeg.number())) {set(mbak); return false;} + if(nexp.isInteger()) { + mroot.set(mmul); + if(nexp.isOdd()) { + mroot.calculateNegate(eo2); + } + b_set = true; + } else if(nexp.isRational() && nexp.denominatorIsTwo()) { + if(!nexp.floor()) {set(mbak); return false;} + mroot.set(mmul); + if(nexp.isEven()) { + mroot.calculateMultiply(nr_one_i, eo2); + } else { + mroot.calculateMultiply(nr_minus_i, eo2); + } + b_set = true; + } + if(!b_set) { + mexp.set(nexp); + mexp.multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + } + } else { + if(nexp.isZero()) { + if(!marg.isZero()) { + mexp.set(marg); + mexp.multiply(minv); + } + } else { + mexp.set(nexp); + mexp.multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI)); + if(!marg.isZero()) mexp.add(marg); + mexp.multiply(minv); + } + } + if(!b_set) { + if(mexp.isZero()) { + mroot.set(mmul); + } else { + mexp.multiply(m_one_i); + mroot.set(CALCULATOR->getVariableById(VARIABLE_ID_E)); + mroot.raise(mexp); + mroot.calculatesub(eo2, eo, true); + mroot.calculateMultiply(mmul, eo2); + } + } + if(b_neg) mroot.calculateRaise(m_minus_one, eo2); + if(nr_i.isZero()) { + CHILD(0).setToChild(1); + CHILD(1) = mroot; + isolate_x_sub(eo, eo2, x_var, morig); + } else { + MathStructure *malt = new MathStructure(mbak[0][0]); + malt->add(mroot, mbak.comparisonType() == COMPARISON_NOT_EQUALS ? OPERATION_NOT_EQUALS : OPERATION_EQUALS); + malt->isolate_x_sub(eo, eo2, x_var, morig); + add_nocopy(malt, mbak.comparisonType() == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR, true); + } + nr_i++; + } + calculatesub(eo2, eo, false); + b_set = true; + } else { + if(b_complex) { + warn_complex = true; + } else if(!b_real) { + check_complex = true; + } + CHILD(1).transform(STRUCT_FUNCTION, CHILD(0)[1]); + CHILD(1).setFunctionId(FUNCTION_ID_ROOT); + if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); + if(b_neg) CHILD(1).calculateRaise(m_minus_one, eo2); + childUpdated(2); + } + if(!b_set) { + if(CHILD(0)[1].number().isEven()) { + CHILD(0).setToChild(1); + MathStructure *mneg = new MathStructure(*this); + (*mneg)[1].calculateNegate(eo2); + mneg->childUpdated(2); + if(ct_comp == COMPARISON_LESS) mneg->setComparisonType(COMPARISON_GREATER); + else if(ct_comp == COMPARISON_GREATER) mneg->setComparisonType(COMPARISON_LESS); + else if(ct_comp == COMPARISON_EQUALS_LESS) mneg->setComparisonType(COMPARISON_EQUALS_GREATER); + else if(ct_comp == COMPARISON_EQUALS_GREATER) mneg->setComparisonType(COMPARISON_EQUALS_LESS); + mneg->isolate_x_sub(eo, eo2, x_var, morig); + isolate_x_sub(eo, eo2, x_var, morig); + add_nocopy(mneg, ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); + calculatesub(eo2, eo, false); + } else { + CHILD(0).setToChild(1); + isolate_x_sub(eo, eo2, x_var, morig); + } + } + if(check_complex) { + if(!isComparison() || CHILD(0) != x_var) { + warn_complex = true; + } + MathStructure mtest(mbak[0][0]); + if(!warn_complex && check_complex) { + mtest.replace(x_var, CHILD(1)); + if(mtest.representsNonComplex(true)) check_complex = false; + if(mtest.representsComplex(true)) { + warn_complex = true; + } + } + if(!warn_complex && check_complex) { + CALCULATOR->beginTemporaryStopMessages(); + EvaluationOptions eo3 = eo; + eo3.approximation = APPROXIMATION_APPROXIMATE; + mtest.eval(eo3); + if(CALCULATOR->endTemporaryStopMessages() || !mtest.representsReal(true)) { + warn_complex = true; + } + } + } + if(warn_complex) CALCULATOR->error(false, _("Only one or two of the roots where calculated for %s."), format_and_print(mbak).c_str(), NULL); + } else { + MathStructure *mposcheck = NULL; + bool b_test = false; + if(!CHILD(1).representsNonNegative(true)) { + if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { + if(CHILD(1).representsNegative(true)) { + if(ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_LESS) clear(true); + else {CHILD(0).setToChild(1, true); CHILD(1).clear(true); CHILDREN_UPDATED} + return true; + } + if(ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_GREATER) { + mposcheck = new MathStructure(CHILD(0)[0]); + mposcheck->add(m_zero, OPERATION_EQUALS_GREATER); + mposcheck->isolate_x_sub(eo, eo2, x_var); + } + } else { + if(CHILD(1).representsNegative(true)) { + if(ct_comp == COMPARISON_EQUALS) { + clear(true); + } else if(ct_comp == COMPARISON_NOT_EQUALS) { + set(1, 1, 0, true); + } + return true; + } + if(CHILD(1).representsNonComplex(true)) { + mposcheck = new MathStructure(CHILD(1)); + mposcheck->add(m_zero, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LESS : OPERATION_EQUALS_GREATER); + mposcheck->isolate_x_sub(eo, eo2, x_var); + } else { + b_test = true; + mposcheck = new MathStructure(*this); + } + } + } + if(ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_LESS) { + mposcheck = new MathStructure(CHILD(0)[0]); + mposcheck->add(m_zero, OPERATION_EQUALS_GREATER); + mposcheck->isolate_x_sub(eo, eo2, x_var); + } + CHILD(0)[1].number().recip(); + CHILD(1).calculateRaise(CHILD(0)[1], eo); + CHILD(0).setToChild(1); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + if(b_test) { + if(test_comparisons(*mposcheck, *this, x_var, eo) < 0) { + mposcheck->unref(); + return false; + } + mposcheck->unref(); + } else if(mposcheck) { + add_nocopy(mposcheck, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + } + if(b_neg && !b_nonzero) { + MathStructure *mtest = new MathStructure(mbak[1]); + mtest->add(m_zero, (mbak.comparisonType() == COMPARISON_NOT_EQUALS) ? OPERATION_EQUALS : OPERATION_NOT_EQUALS); + mtest->isolate_x_sub(eo, eo2, x_var); + add_nocopy(mtest, (mbak.comparisonType() == COMPARISON_NOT_EQUALS) ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + if(mbak.comparisonType() != COMPARISON_NOT_EQUALS && mbak.comparisonType() != COMPARISON_EQUALS) { + MathStructure *malt = new MathStructure(mbak[0]); + if(mbak[0][1].representsInteger() && mbak[0][1].representsEven()) { + malt->add(m_zero, OPERATION_NOT_EQUALS); + } else { + malt->add(m_zero, (ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_GREATER) ? OPERATION_LESS : OPERATION_GREATER); + } + malt->isolate_x_sub(eo, eo2, x_var, morig); + MathStructure *mtest2 = new MathStructure(mbak[1]); + mtest2->add(m_zero, OPERATION_EQUALS); + mtest2->isolate_x_sub(eo, eo2, x_var); + malt->add_nocopy(mtest2, (mbak.comparisonType() == COMPARISON_NOT_EQUALS) ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + malt->calculatesub(eo2, eo, false); + add_nocopy(malt, OPERATION_LOGICAL_OR); + calculatesub(eo2, eo, false); + } + } + return true; + } + } else if(CHILD(0)[1].contains(x_var) && CHILD(0)[0].representsNumber() && (!CHILD(0)[1].representsNonComplex() || (CHILD(0)[0].representsNonNegative() || (CHILD(0)[0].isNumber() && CHILD(0)[0].number().isNegative() && CHILD(1).isNumber())))) { + // a^x=b => x=log(b, a) + MathStructure *mtest = NULL, *m0 = NULL, *m1 = NULL; + if(CHILD(0)[0].isOne()) return false; + if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && !CHILD(0)[0].representsNonZero()) { + if(!CHILD(1).representsNonZero()) { + MathStructure *mtest2 = NULL; + if(!CHILD(1).isZero()) { + mtest2 = new MathStructure(CHILD(1)); + mtest2->transform(ct_comp, m_zero); + mtest2->isolate_x(eo2, eo); + } + m0 = new MathStructure(CHILD(0)[1]); + if(!m0->representsNonComplex(true)) { + m0->transformById(FUNCTION_ID_RE); + if(m0->calculateFunctions(eo)) m0->calculatesub(eo2, eo, true); + } + m0->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, m_zero); + m0->isolate_x_sub(eo, eo2, x_var, morig); + if(mtest2) { + m0->add_nocopy(mtest2, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); + m0->calculatesub(eo2, eo, false); + } + if(CHILD(0)[0].isZero()) { + set_nocopy(*m0, true); + m0->unref(); + return true; + } + MathStructure *mtest3 = new MathStructure(CHILD(0)[0]); + mtest3->transform(ct_comp, m_zero); + mtest3->isolate_x(eo2, eo); + m0->add_nocopy(mtest3, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); + m0->calculatesub(eo2, eo, false); + } + mtest = new MathStructure(CHILD(0)[1]); + mtest->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_NOT_EQUALS : COMPARISON_EQUALS, m_zero); + mtest->isolate_x_sub(eo, eo2, x_var, morig); + if(!CHILD(0)[0].isZero()) { + MathStructure *mtest_b = new MathStructure(CHILD(0)[0]); + mtest_b->transform(ct_comp == COMPARISON_EQUALS ? COMPARISON_NOT_EQUALS : COMPARISON_EQUALS, m_zero); + mtest_b->isolate_x_sub(eo, eo2, x_var, morig); + mtest->add_nocopy(mtest_b, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + mtest->calculatesub(eo2, eo, false); + } + } + ComparisonResult cr1 = COMPARISON_RESULT_NOT_EQUAL; + if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) { + cr1 = CHILD(0)[0].compare(m_one); + if(cr1 == COMPARISON_RESULT_EQUAL) { + ComparisonResult cr2 = CHILD(1).compare(m_one); + if(cr2 == COMPARISON_RESULT_EQUAL) { + if(ct_comp == COMPARISON_EQUALS) set(1, 1, 0, true); + else clear(true); + return true; + } else if(COMPARISON_MIGHT_BE_EQUAL(cr2)) { + m1 = new MathStructure(); + m1->setType(STRUCT_COMPARISON); + m1->setComparisonType(ct_comp); + m1->addChild(CHILD(1)); + m1->addChild(m_one); + m1->isolate_x(eo2, eo); + } + } else if(COMPARISON_MIGHT_BE_EQUAL(cr1)) { + ComparisonResult cr2 = CHILD(1).compare(m_one); + if(cr2 == COMPARISON_RESULT_EQUAL) { + m1 = new MathStructure(); + m1->setType(STRUCT_COMPARISON); + m1->setComparisonType(ct_comp); + m1->addChild(CHILD(0)[0]); + m1->addChild(m_one); + m1->isolate_x(eo2, eo); + } else if(COMPARISON_MIGHT_BE_EQUAL(cr2)) { + m1 = new MathStructure(); + m1->setType(STRUCT_COMPARISON); + m1->setComparisonType(ct_comp); + m1->addChild(CHILD(1)); + m1->addChild(m_one); + m1->isolate_x(eo2, eo); + MathStructure *m1b = new MathStructure(); + m1b->setType(STRUCT_COMPARISON); + m1b->setComparisonType(ct_comp); + m1b->addChild(CHILD(0)[0]); + m1b->addChild(m_one); + m1b->isolate_x(eo2, eo); + m1->add_nocopy(m1b, ct_comp == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + m1->calculatesub(eo2, eo, false); + } + } + } + ComparisonType ct = ct_comp; + + if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS)) { + if(CHILD(0)[0].isMinusOne()) { + if(CHILD(1).isOne() || CHILD(1).isMinusOne()) { + bool b_m1 = CHILD(1).isMinusOne(); + CHILD(0).setToChild(2, true); + CHILD(1).set(2, 1, 0, true); + CHILD(1) *= CALCULATOR->getVariableById(VARIABLE_ID_N); + if(b_m1) CHILD(1) += m_one; + CHILD(1).evalSort(false); + fix_n_multiple(*this, eo2, eo, x_var); + CHILDREN_UPDATED; + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } + } else if(CHILD(1).isOne() && CHILD(0)[1].representsNonComplex()) { + CHILD(0).setToChild(2, true); + CHILD(1).clear(true); + isolate_x_sub(eo, eo2, x_var, morig); + if(m1) { + add_nocopy(m1, ct == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + if(mtest) { + add_nocopy(mtest, ct == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + return true; + } + } + if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { + if(CHILD(0)[0].isNumber() && CHILD(0)[0].number().isReal() && CHILD(0)[0].number().isPositive()) { + if(CHILD(1).representsNegative()) { + if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) { + set(1, 1, 0, true); + } else { + clear(true); + } + return true; + } + if(CHILD(0)[0].number().isFraction()) { + switch(ct_comp) { + case COMPARISON_LESS: {ct_comp = COMPARISON_GREATER; break;} + case COMPARISON_GREATER: {ct_comp = COMPARISON_LESS; break;} + case COMPARISON_EQUALS_LESS: {ct_comp = COMPARISON_EQUALS_GREATER; break;} + case COMPARISON_EQUALS_GREATER: {ct_comp = COMPARISON_EQUALS_LESS; break;} + default: {} + } + } + } else if(CHILD(0)[0].isZero()) { + bool b_clear = false, b_gz = false; + switch(ct_comp) { + case COMPARISON_LESS: {b_gz = CHILD(1).representsPositive(); b_clear = !b_gz && CHILD(1).representsNonPositive(); break;} + case COMPARISON_GREATER: {b_gz = CHILD(1).representsNegative(); b_clear = !b_gz && CHILD(1).representsNonNegative(); break;} + case COMPARISON_EQUALS_LESS: {b_gz = CHILD(1).representsNonNegative(); b_clear = !b_gz && CHILD(1).representsNegative(); break;} + case COMPARISON_EQUALS_GREATER: {b_gz = CHILD(1).representsNonPositive(); b_clear = !b_gz && CHILD(1).representsPositive(); break;} + default: {} + } + if(b_clear) { + clear(true); + return true; + } else if(b_gz) { + ct_comp = COMPARISON_GREATER; + CHILD(1).clear(true); + CHILD(0).setToChild(2, true); + if(!CHILD(0).representsNonComplex(true)) { + CHILD(0).transformById(FUNCTION_ID_RE); + if(CHILD(0).calculateFunctions(eo)) CHILD(0).calculatesub(eo2, eo, true); + } + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } else { + return false; + } + } else { + return false; + } + } + MathStructure msave(CHILD(1)); + if(CHILD(0)[1].representsNonComplex()) { + if(CHILD(0)[0].representsNegative()) { + MathStructure mtest2(CALCULATOR->getFunctionById(FUNCTION_ID_LOGN), &msave, &CHILD(0)[0], NULL); + mtest2[1].calculateNegate(eo2); + mtest2.childUpdated(2); + if(mtest2.calculateFunctions(eo)) mtest2.calculatesub(eo2, eo, true); + if(mtest) mtest->unref(); + if(m0) m0->unref(); + mtest = NULL; + if(!mtest2.isInteger()) return false; + if(mtest2.number().isOdd()) { + if(ct_comp == COMPARISON_NOT_EQUALS) set(1, 1, 0, true); + else clear(true); + return true; + } + CHILD(1).set(mtest2, true); + } else { + CHILD(1).set(CALCULATOR->getFunctionById(FUNCTION_ID_LOGN), &msave, &CHILD(0)[0], NULL); + bool b = CHILD(1).calculateFunctions(eo); + if(b) CHILD(1).calculatesub(eo2, eo, true); + } + } else { + CHILD(1).set(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &msave, NULL); + CHILD(1) += nr_one_i; + CHILD(1)[1] *= nr_two; + CHILD(1)[1].multiply(CALCULATOR->getVariableById(VARIABLE_ID_PI), true); + CHILD(1)[1].multiply(CALCULATOR->getVariableById(VARIABLE_ID_N), true); + CHILD(1).divide_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_LOG), &CHILD(0)[0], NULL)); + CHILD(1).evalSort(true); + bool b = CHILD(1).calculateFunctions(eo); + if(b) CHILD(1).calculatesub(eo2, eo, true); + } + MathStructure *mn1 = NULL; + if(COMPARISON_MIGHT_BE_EQUAL(cr1)) { + mn1 = new MathStructure(); + mn1->setType(STRUCT_COMPARISON); + mn1->setComparisonType(ct == COMPARISON_EQUALS ? COMPARISON_NOT_EQUALS : COMPARISON_EQUALS); + mn1->addChild(CHILD(0)[0]); + mn1->addChild(m_one); + mn1->isolate_x(eo2, eo); + } + CHILD(0).setToChild(2, true); + CHILDREN_UPDATED; + isolate_x_sub(eo, eo2, x_var, morig); + if(mn1) { + add_nocopy(mn1, ct == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + if(m1) { + add_nocopy(m1, ct == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + if(mtest) { + add_nocopy(mtest, ct == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + if(m0) { + add_nocopy(m0, ct == COMPARISON_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + } + fix_n_multiple(*this, eo2, eo, x_var); + return true; + } + break; + } + case STRUCT_FUNCTION: { + if(CHILD(0).function()->id() == FUNCTION_ID_ROOT && VALID_ROOT(CHILD(0))) { + if(CHILD(0)[0].contains(x_var)) { + MathStructure *mposcheck = NULL; + bool b_test = false; + if(CHILD(0)[1].number().numeratorIsEven() && !CHILD(1).representsNonNegative(true)) { + if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { + if(CHILD(1).representsNegative(true)) { + if(ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_LESS) clear(true); + else {CHILD(0).setToChild(1, true); CHILD(1).clear(true); CHILDREN_UPDATED} + return true; + } + if(ct_comp == COMPARISON_EQUALS_GREATER || ct_comp == COMPARISON_GREATER) { + mposcheck = new MathStructure(CHILD(0)[0]); + mposcheck->add(m_zero, OPERATION_EQUALS_GREATER); + mposcheck->isolate_x_sub(eo, eo2, x_var); + } + } else { + if(CHILD(1).representsNegative(true)) { + if(ct_comp == COMPARISON_EQUALS) { + clear(true); + } else if(ct_comp == COMPARISON_NOT_EQUALS) { + set(1, 1, 0, true); + } + return true; + } + if(CHILD(1).representsNonComplex(true)) { + mposcheck = new MathStructure(CHILD(1)); + mposcheck->add(m_zero, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LESS : OPERATION_EQUALS_GREATER); + mposcheck->isolate_x_sub(eo, eo2, x_var); + } else { + b_test = true; + mposcheck = new MathStructure(*this); + } + } + } + if((ct_comp == COMPARISON_EQUALS_LESS || ct_comp == COMPARISON_LESS) && CHILD(0)[1].number().numeratorIsEven()) { + mposcheck = new MathStructure(CHILD(0)[0]); + mposcheck->add(m_zero, OPERATION_EQUALS_GREATER); + mposcheck->isolate_x_sub(eo, eo2, x_var); + } + CHILD(1).calculateRaise(CHILD(0)[1], eo); + CHILD(0).setToChild(1); + CHILDREN_UPDATED + isolate_x_sub(eo, eo2, x_var, morig); + if(b_test) { + if(test_comparisons(*mposcheck, *this, x_var, eo) < 0) { + mposcheck->unref(); + return false; + } + mposcheck->unref(); + } else if(mposcheck) { + add_nocopy(mposcheck, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + calculatesub(eo2, eo, false); + } + return true; + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_LOG && CHILD(0).size() == 1) { + if(CHILD(0)[0].contains(x_var)) { + if(!CHILD(1).representsNonComplex()) { + if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) return false; + MathStructure mtest(CALCULATOR->getVariableById(VARIABLE_ID_E)); + mtest.raise(CHILD(1)); + mtest.transformById(FUNCTION_ID_LOG); + ComparisonResult cr = mtest.compare(CHILD(1)); + if(!COMPARISON_MIGHT_BE_EQUAL(cr) || cr == COMPARISON_RESULT_UNKNOWN) { + if(COMPARISON_IS_NOT_EQUAL(cr)) { + if(ct_comp == COMPARISON_EQUALS) clear(true); + else set(1, 1, 0, true); + return true; + } + return false; + } + } + MathStructure msave(CHILD(1)); + CHILD(1).set(CALCULATOR->getVariableById(VARIABLE_ID_E)); + CHILD(1).calculateRaise(msave, eo2); + CHILD(0).setToChild(1, true); + CHILDREN_UPDATED; + if(ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) { + MathStructure *mand = new MathStructure(CHILD(0)); + mand->add(m_zero, OPERATION_GREATER); + mand->isolate_x_sub(eo, eo2, x_var); + isolate_x_sub(eo, eo2, x_var, morig); + add_nocopy(mand, OPERATION_LOGICAL_AND); + SWAP_CHILDREN(0, 1); + calculatesub(eo2, eo, false); + } else { + isolate_x_sub(eo, eo2, x_var, morig); + } + return true; + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_LAMBERT_W && (CHILD(0).size() == 1 || (CHILD(0).size() == 2 && CHILD(0)[1].isInteger())) && ((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) || (CHILD(0).size() == 1 || CHILD(0)[1].isZero() || CHILD(0)[1].isMinusOne()))) { + if(CHILD(0)[0].contains(x_var)) { + CHILDREN_UPDATED; + bool b_test = true; + if(ct_comp != COMPARISON_EQUALS && ct_comp != COMPARISON_NOT_EQUALS) { + if(CHILD(0).size() == 2 && CHILD(0)[1].isMinusOne()) { + ComparisonResult cr = CHILD(1).compare(nr_minus_one); + if(cr == COMPARISON_RESULT_LESS) { + if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) {clear(true); return true;} + if(ct_comp == COMPARISON_LESS) ct_comp = COMPARISON_EQUALS_LESS; + CHILD(1) = nr_minus_one; + } else if(cr == COMPARISON_RESULT_EQUAL_OR_LESS) { + if(ct_comp == COMPARISON_GREATER) {clear(true); return true;} + return false; + } else if(cr == COMPARISON_RESULT_EQUAL) { + if(ct_comp == COMPARISON_GREATER) {clear(true); return true;} + if(ct_comp == COMPARISON_EQUALS_GREATER) ct_comp = COMPARISON_EQUALS; + } else if(cr != COMPARISON_RESULT_GREATER && cr != COMPARISON_RESULT_EQUAL_OR_GREATER) { + return false; + } + } else { + ComparisonResult cr = CHILD(1).compare(nr_minus_one); + if(cr == COMPARISON_RESULT_GREATER) { + if(ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) {clear(true); return true;} + if(ct_comp == COMPARISON_GREATER) ct_comp = COMPARISON_EQUALS_GREATER; + CHILD(1) = nr_minus_one; + } else if(cr == COMPARISON_RESULT_EQUAL_OR_GREATER) { + if(ct_comp == COMPARISON_LESS) {clear(true); return true;} + return false; + } else if(cr == COMPARISON_RESULT_EQUAL) { + if(ct_comp == COMPARISON_LESS) {clear(true); return true;} + if(ct_comp == COMPARISON_EQUALS_LESS) ct_comp = COMPARISON_EQUALS; + } else if(cr != COMPARISON_RESULT_LESS && cr != COMPARISON_RESULT_EQUAL_OR_LESS) { + return false; + } + } + } else if(CHILD(0).size() == 1 || CHILD(0)[1].isZero()) { + ComparisonResult cr = CHILD(1).compare(nr_minus_one); + if(COMPARISON_IS_EQUAL_OR_LESS(cr)) { + b_test = false; + } else if(cr == COMPARISON_RESULT_GREATER) { + if(ct_comp == COMPARISON_EQUALS) clear(true); + else set(1, 1, 0, true); + return true; + } + } else if(CHILD(0)[1].isMinusOne()) { + ComparisonResult cr = CHILD(1).compare(nr_minus_one); + if(COMPARISON_IS_EQUAL_OR_GREATER(cr)) { + b_test = false; + } else if(cr == COMPARISON_RESULT_LESS) { + if(ct_comp == COMPARISON_EQUALS) clear(true); + else set(1, 1, 0, true); + return true; + } + } else if(CHILD(1).representsReal()) { + if(ct_comp == COMPARISON_EQUALS) clear(true); + else set(1, 1, 0, true); + return true; + } + MathStructure mtest(*this); + mtest[1].set(CALCULATOR->getVariableById(VARIABLE_ID_E)); + mtest[1].calculateRaise(CHILD(1), eo2); + mtest[1].calculateMultiply(CHILD(1), eo2); + mtest[0].setToChild(1, true); + if((ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) && (CHILD(0).size() == 1 || CHILD(0)[1].isZero())) { + MathStructure *mand = new MathStructure(mtest[0]); + mand->add(MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_E)), CHILD(0).size() == 2 && CHILD(0)[1].isMinusOne() ? OPERATION_EQUALS_LESS : OPERATION_EQUALS_GREATER); + (*mand)[1].inverse(); + (*mand)[1].negate(); + (*mand)[1].calculatesub(eo2, eo, true); + mand->childUpdated(2); + mand->isolate_x_sub(eo, eo2, x_var); + mtest.isolate_x_sub(eo, eo2, x_var, morig); + mtest.add_nocopy(mand, OPERATION_LOGICAL_AND); + SWAP_CHILDREN(0, 1); + mtest.calculatesub(eo2, eo, false); + } else if((ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) && CHILD(0).size() == 2 && CHILD(0)[1].isMinusOne()) { + MathStructure *mand = new MathStructure(mtest[0]); + mand->add(m_zero, OPERATION_EQUALS_LESS); + mand->childUpdated(2); + mand->isolate_x_sub(eo, eo2, x_var); + mtest.isolate_x_sub(eo, eo2, x_var, morig); + mtest.add_nocopy(mand, OPERATION_LOGICAL_AND); + SWAP_CHILDREN(0, 1); + mtest.calculatesub(eo2, eo, false); + } else { + mtest.isolate_x_sub(eo, eo2, x_var, morig); + } + if(!b_test || (!mtest.isLogicalAnd() && !mtest.isLogicalOr() && !mtest.isComparison()) || test_comparisons(*this, mtest, x_var, eo, false, eo2.expand ? 1 : 2) >= 0) { + set(mtest); + return true; + } + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_LOGN && CHILD(0).size() == 2) { + if(CHILD(0)[0].contains(x_var)) { + MathStructure msave(CHILD(1)); + CHILD(1) = CHILD(0)[1]; + CHILD(1).calculateRaise(msave, eo2); + CHILD(0).setToChild(1, true); + CHILDREN_UPDATED; + if(ct_comp == COMPARISON_LESS || ct_comp == COMPARISON_EQUALS_LESS) { + MathStructure *mand = new MathStructure(CHILD(0)); + mand->add(m_zero, OPERATION_GREATER); + mand->isolate_x_sub(eo, eo2, x_var); + isolate_x_sub(eo, eo2, x_var, morig); + add_nocopy(mand, OPERATION_LOGICAL_AND); + SWAP_CHILDREN(0, 1); + calculatesub(eo2, eo, false); + } else { + isolate_x_sub(eo, eo2, x_var, morig); + } + return true; + } + } else if((CHILD(0).function()->id() == FUNCTION_ID_TAN || CHILD(0).function()->id() == FUNCTION_ID_SIN || CHILD(0).function()->id() == FUNCTION_ID_COS) && CHILD(0).size() == 1 && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { + MathFunction *f = CHILD(0).function(); + CHILD(0).setToChild(1, true); + bool b_one = false, b_zero = false; + if(f->id() != FUNCTION_ID_TAN) { + b_zero = CHILD(1).isZero(); + b_one = CHILD(1).isOne(); + } + if(b_one) CHILD(1).clear(true); + if(!b_zero && !b_one) { + if(f->id() == FUNCTION_ID_SIN) CHILD(1).transformById(FUNCTION_ID_ASIN); + else if(f->id() == FUNCTION_ID_COS) CHILD(1).transformById(FUNCTION_ID_ACOS); + else CHILD(1).transformById(FUNCTION_ID_ATAN); + CHILD(1).calculateFunctions(eo); + } + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + EvaluationOptions eo3 = eo2; + eo3.sync_units = true; + CHILD(0) /= CALCULATOR->getDegUnit(); + CHILD(0).calculatesub(eo3, eo, true); + CHILD(1) += Number(180, 1); + break; + } + case ANGLE_UNIT_GRADIANS: { + EvaluationOptions eo3 = eo2; + eo3.sync_units = true; + CHILD(0) /= CALCULATOR->getGraUnit(); + CHILD(0).calculatesub(eo3, eo, true); + CHILD(1) += Number(200, 1); + break; + } + case ANGLE_UNIT_RADIANS: { + CHILD(0).calculateDivide(CALCULATOR->getRadUnit(), eo2); + CHILD(1) += CALCULATOR->getVariableById(VARIABLE_ID_PI); + break; + } + default: { + CHILD(1) += CALCULATOR->getVariableById(VARIABLE_ID_PI); + CHILD(1)[1] *= CALCULATOR->getRadUnit(); + } + } + CHILD(1)[1] *= CALCULATOR->getVariableById(VARIABLE_ID_N); + if(b_zero && f->id() == FUNCTION_ID_COS) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {CHILD(1).add(Number(-90, 1), true); break;} + case ANGLE_UNIT_GRADIANS: {CHILD(1).add(Number(-100, 1), true); break;} + case ANGLE_UNIT_RADIANS: {CHILD(1).add(CALCULATOR->getVariableById(VARIABLE_ID_PI), true); CHILD(1).last() *= nr_minus_half; break;} + default: {CHILD(1).add(CALCULATOR->getVariableById(VARIABLE_ID_PI), true); CHILD(1).last() *= nr_minus_half; CHILD(1).last() *= CALCULATOR->getRadUnit();} + } + } + if(b_one) { + CHILD(1)[1] *= 2; + if(f->id() == FUNCTION_ID_SIN) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {CHILD(1).add(Number(90, 1), true); break;} + case ANGLE_UNIT_GRADIANS: {CHILD(1).add(Number(100, 1), true); break;} + case ANGLE_UNIT_RADIANS: {CHILD(1).add(CALCULATOR->getVariableById(VARIABLE_ID_PI), true); CHILD(1).last() *= nr_half; break;} + default: {CHILD(1).add(CALCULATOR->getVariableById(VARIABLE_ID_PI), true); CHILD(1).last() *= nr_half; CHILD(1).last() *= CALCULATOR->getRadUnit();} + } + } + } + if(!b_one && !b_zero && (f->id() == FUNCTION_ID_SIN || f->id() == FUNCTION_ID_COS)) { + CHILD(1)[1] *= 2; + MathStructure *malt = new MathStructure(*this); + (*malt)[1][0].negate(); + if(f->id() == FUNCTION_ID_SIN) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {(*malt)[1].add(Number(180, 1), true); break;} + case ANGLE_UNIT_GRADIANS: {(*malt)[1].add(Number(200, 1), true); break;} + case ANGLE_UNIT_RADIANS: {(*malt)[1].add(CALCULATOR->getVariableById(VARIABLE_ID_PI), true); break;} + default: {(*malt)[1].add(CALCULATOR->getVariableById(VARIABLE_ID_PI), true); (*malt)[1].last() *= CALCULATOR->getRadUnit();} + } + } + CHILD(1).calculatesub(eo2, eo, true); + (*malt)[1].calculatesub(eo2, eo, true); + CHILDREN_UPDATED; + malt->childrenUpdated(); + isolate_x_sub(eo, eo2, x_var, morig); + malt->isolate_x_sub(eo, eo2, x_var, morig); + if(ct_comp == COMPARISON_NOT_EQUALS) add_nocopy(malt, OPERATION_LOGICAL_AND); + else add_nocopy(malt, OPERATION_LOGICAL_OR); + calculatesub(eo2, eo, false); + } else { + CHILDREN_UPDATED; + CHILD(1).calculatesub(eo2, eo, true); + CHILDREN_UPDATED; + isolate_x_sub(eo, eo2, x_var, morig); + } + fix_n_multiple(*this, eo2, eo, x_var); + return true; + } else if(CHILD(0).function()->id() == FUNCTION_ID_SINH && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { + CHILD(0).setToChild(1, true); + CHILD(1).transformById(FUNCTION_ID_ASINH); + if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); + if(CHILD(0).representsNonComplex()) { + CHILDREN_UPDATED; + isolate_x_sub(eo, eo2, x_var, morig); + } else { + MathStructure *malt = new MathStructure(*this); + CHILD(1) *= nr_one_i; + (*malt)[1] *= nr_minus_i; + CHILD(1) += CALCULATOR->getVariableById(VARIABLE_ID_PI); + CHILD(1) += CALCULATOR->getVariableById(VARIABLE_ID_N); CHILD(1).last() *= CALCULATOR->getVariableById(VARIABLE_ID_PI); CHILD(1).last() *= nr_two; + (*malt)[1] += CALCULATOR->getVariableById(VARIABLE_ID_N); (*malt)[1].last() *= CALCULATOR->getVariableById(VARIABLE_ID_PI); (*malt)[1].last() *= nr_two; + CHILD(1) *= nr_one_i; + (*malt)[1] *= nr_one_i; + CHILD(1).calculatesub(eo2, eo, true); + (*malt)[1].calculatesub(eo2, eo, true); + CHILDREN_UPDATED; + malt->childrenUpdated(); + isolate_x_sub(eo, eo2, x_var, morig); + malt->isolate_x_sub(eo, eo2, x_var, morig); + if(ct_comp == COMPARISON_NOT_EQUALS) add_nocopy(malt, OPERATION_LOGICAL_AND); + else add_nocopy(malt, OPERATION_LOGICAL_OR); + calculatesub(eo2, eo, false); + fix_n_multiple(*this, eo2, eo, x_var); + } + return true; + } else if(CHILD(0).function()->id() == FUNCTION_ID_COSH && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { + CHILD(0).setToChild(1, true); + CHILD(1).transformById(FUNCTION_ID_ACOSH); + if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); + if(CHILD(0).representsNonComplex()) { + MathStructure *malt = new MathStructure(*this); + (*malt)[1].calculateNegate(eo2); + CHILDREN_UPDATED; + malt->childrenUpdated(); + isolate_x_sub(eo, eo2, x_var, morig); + malt->isolate_x_sub(eo, eo2, x_var, morig); + if(ct_comp == COMPARISON_NOT_EQUALS) add_nocopy(malt, OPERATION_LOGICAL_AND); + else add_nocopy(malt, OPERATION_LOGICAL_OR); + calculatesub(eo2, eo, false); + } else { + MathStructure *malt = new MathStructure(*this); + CHILD(1) *= nr_one_i; + (*malt)[1] *= nr_minus_i; + CHILD(1) += CALCULATOR->getVariableById(VARIABLE_ID_N); CHILD(1).last() *= CALCULATOR->getVariableById(VARIABLE_ID_PI); CHILD(1).last() *= nr_two; + (*malt)[1] += CALCULATOR->getVariableById(VARIABLE_ID_N); (*malt)[1].last() *= CALCULATOR->getVariableById(VARIABLE_ID_PI); (*malt)[1].last() *= nr_two; + CHILD(1) *= nr_one_i; + (*malt)[1] *= nr_one_i; + CHILD(1).calculatesub(eo2, eo, true); + (*malt)[1].calculatesub(eo2, eo, true); + CHILDREN_UPDATED; + malt->childrenUpdated(); + isolate_x_sub(eo, eo2, x_var, morig); + malt->isolate_x_sub(eo, eo2, x_var, morig); + if(ct_comp == COMPARISON_NOT_EQUALS) add_nocopy(malt, OPERATION_LOGICAL_AND); + else add_nocopy(malt, OPERATION_LOGICAL_OR); + calculatesub(eo2, eo, false); + fix_n_multiple(*this, eo2, eo, x_var); + } + return true; + } else if(CHILD(0).function()->id() == FUNCTION_ID_TANH && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { + CHILD(0).setToChild(1, true); + CHILD(1).transformById(FUNCTION_ID_ATANH); + if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); + if(CHILD(0).representsNonComplex()) { + CHILDREN_UPDATED; + isolate_x_sub(eo, eo2, x_var, morig); + } else { + CHILD(1) *= nr_minus_i; + CHILD(1) += CALCULATOR->getVariableById(VARIABLE_ID_N); CHILD(1).last() *= CALCULATOR->getVariableById(VARIABLE_ID_PI); + CHILD(1) *= nr_one_i; + CHILD(1).calculatesub(eo2, eo, true); + CHILDREN_UPDATED; + isolate_x_sub(eo, eo2, x_var, morig); + fix_n_multiple(*this, eo2, eo, x_var); + } + return true; + } else if(CHILD(0).function()->id() == FUNCTION_ID_ASIN && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { + MathStructure m1(CHILD(1)); + CHILD(0).setToChild(1, true); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {CHILD(1) *= CALCULATOR->getDegUnit(); break;} + case ANGLE_UNIT_GRADIANS: {CHILD(1) *= CALCULATOR->getGraUnit(); break;} + case ANGLE_UNIT_RADIANS: {CHILD(1) *= CALCULATOR->getRadUnit(); break;} + default: {} + } + CHILD(1).transformById(FUNCTION_ID_SIN); + if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); + CHILDREN_UPDATED; + isolate_x_sub(eo, eo2, x_var, morig); + if(eo.parse_options.angle_unit == ANGLE_UNIT_NONE) { + m1 /= CALCULATOR->getRadUnit(); + m1.convert(CALCULATOR->getRadUnit()); + } + m1.transformById(FUNCTION_ID_RE); + if(m1.calculateFunctions(eo)) m1.calculatesub(eo2, eo, true); + MathStructure *mreq1 = new MathStructure(m1); + MathStructure *mreq2 = new MathStructure(m1); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, Number(90, 1)); + mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, Number(-90, 1)); + break; + } + case ANGLE_UNIT_GRADIANS: { + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, Number(100, 1)); + mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, Number(-100, 1)); + break; + } + default: { + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, CALCULATOR->getVariableById(VARIABLE_ID_PI)); + mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->getVariableById(VARIABLE_ID_PI)); + mreq1->last() *= nr_half; + mreq2->last() *= nr_minus_half; + } + } + mreq1->isolate_x(eo2, eo); + mreq2->isolate_x(eo2, eo); + add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + if(eo.parse_options.angle_unit == ANGLE_UNIT_NONE) convert(CALCULATOR->getRadUnit()); + calculatesub(eo2, eo, false); + return true; + } else if(CHILD(0).function()->id() == FUNCTION_ID_ACOS && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { + MathStructure m1(CHILD(1)), m2(CHILD(1)); + CHILD(0).setToChild(1, true); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {CHILD(1) *= CALCULATOR->getDegUnit(); break;} + case ANGLE_UNIT_GRADIANS: {CHILD(1) *= CALCULATOR->getGraUnit(); break;} + case ANGLE_UNIT_RADIANS: {CHILD(1) *= CALCULATOR->getRadUnit();} + default: {} + } + CHILD(1).transformById(FUNCTION_ID_COS); + if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); + CHILDREN_UPDATED; + isolate_x_sub(eo, eo2, x_var, morig); + if(eo.parse_options.angle_unit == ANGLE_UNIT_NONE) { + m1 /= CALCULATOR->getRadUnit(); + m1.convert(CALCULATOR->getRadUnit()); + m2 /= CALCULATOR->getRadUnit(); + m2.convert(CALCULATOR->getRadUnit()); + } + m2.transformById(FUNCTION_ID_IM); + m1.transformById(FUNCTION_ID_RE); + if(m1.calculateFunctions(eo)) m1.calculatesub(eo2, eo, true); + MathStructure *mreq1 = new MathStructure(m1); + MathStructure *mreq2 = new MathStructure(m1); + MathStructure *mreq3 = new MathStructure(m1); + MathStructure *mreq4 = new MathStructure(m2); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, Number(180, 1)); + break; + } + case ANGLE_UNIT_GRADIANS: { + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, Number(200, 1)); + break; + } + default: { + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, CALCULATOR->getVariableById(VARIABLE_ID_PI)); + } + } + mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, m_zero); + mreq3->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_EQUALS : COMPARISON_NOT_EQUALS, m_zero); + mreq4->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, m_zero); + mreq1->isolate_x(eo2, eo); + mreq2->isolate_x(eo2, eo); + mreq3->isolate_x(eo2, eo); + mreq4->isolate_x(eo2, eo); + add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + mreq3->add_nocopy(mreq4, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_AND : OPERATION_LOGICAL_OR); + mreq3->calculatesub(eo2, eo, false); + add_nocopy(mreq3, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + if(eo.parse_options.angle_unit == ANGLE_UNIT_NONE) convert(CALCULATOR->getRadUnit()); + calculatesub(eo2, eo, false); + return true; + } else if(CHILD(0).function()->id() == FUNCTION_ID_ATAN && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { + MathStructure m1(CHILD(1)); + CHILD(0).setToChild(1, true); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {CHILD(1) *= CALCULATOR->getDegUnit(); break;} + case ANGLE_UNIT_GRADIANS: {CHILD(1) *= CALCULATOR->getGraUnit(); break;} + case ANGLE_UNIT_RADIANS: {CHILD(1) *= CALCULATOR->getRadUnit();} + default: {} + } + CHILD(1).transformById(FUNCTION_ID_TAN); + if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); + CHILDREN_UPDATED; + isolate_x_sub(eo, eo2, x_var, morig); + if(eo.parse_options.angle_unit == ANGLE_UNIT_NONE) { + m1 /= CALCULATOR->getRadUnit(); + m1.convert(CALCULATOR->getRadUnit()); + } + m1.transformById(FUNCTION_ID_RE); + if(m1.calculateFunctions(eo)) m1.calculatesub(eo2, eo, true); + MathStructure *mreq1 = new MathStructure(m1); + MathStructure *mreq2 = new MathStructure(m1); + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: { + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, Number(90, 1)); + mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, Number(-90, 1)); + break; + } + case ANGLE_UNIT_GRADIANS: { + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, Number(100, 1)); + mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, Number(-100, 1)); + break; + } + default: { + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, CALCULATOR->getVariableById(VARIABLE_ID_PI)); + mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->getVariableById(VARIABLE_ID_PI)); + mreq1->last() *= nr_half; + mreq2->last() *= nr_minus_half; + } + } + mreq1->isolate_x(eo2, eo); + mreq2->isolate_x(eo2, eo); + add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + if(eo.parse_options.angle_unit == ANGLE_UNIT_NONE) convert(CALCULATOR->getRadUnit()); + calculatesub(eo2, eo, false); + return true; + } else if(CHILD(0).function()->id() == FUNCTION_ID_ASINH && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { + MathStructure m1(CHILD(1)); + CHILD(0).setToChild(1, true); + CHILD(1).transformById(FUNCTION_ID_SINH); + if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); + CHILDREN_UPDATED; + isolate_x_sub(eo, eo2, x_var, morig); + m1.transformById(FUNCTION_ID_IM); + if(m1.calculateFunctions(eo)) m1.calculatesub(eo2, eo, true); + MathStructure *mreq1 = new MathStructure(m1); + MathStructure *mreq2 = new MathStructure(m1); + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, CALCULATOR->getVariableById(VARIABLE_ID_PI)); + mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->getVariableById(VARIABLE_ID_PI)); + mreq1->last() *= nr_half; + mreq2->last() *= nr_minus_half; + mreq1->isolate_x(eo2, eo); + mreq2->isolate_x(eo2, eo); + add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + calculatesub(eo2, eo, false); + return true; + } else if(CHILD(0).function()->id() == FUNCTION_ID_ACOSH && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { + MathStructure m1(CHILD(1)); + CHILD(0).setToChild(1, true); + CHILD(1).transformById(FUNCTION_ID_COSH); + if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); + CHILDREN_UPDATED; + isolate_x_sub(eo, eo2, x_var, morig); + MathStructure m1im(m1); + m1.transformById(FUNCTION_ID_RE); + m1im.transformById(FUNCTION_ID_IM); + if(m1.calculateFunctions(eo)) m1.calculatesub(eo2, eo, true); + if(m1im.calculateFunctions(eo)) m1im.calculatesub(eo2, eo, true); + MathStructure *mreq1 = new MathStructure(m1); + MathStructure *mreq2 = new MathStructure(m1im); + MathStructure *mreq3 = new MathStructure(m1im); + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, m_zero); + mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, CALCULATOR->getVariableById(VARIABLE_ID_PI)); + mreq3->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, m_zero); + mreq3->last().negate(); + mreq1->isolate_x(eo2, eo); + mreq2->isolate_x(eo2, eo); + mreq3->isolate_x(eo2, eo); + add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + add_nocopy(mreq3, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + calculatesub(eo2, eo, false); + return true; + } else if(CHILD(0).function()->id() == FUNCTION_ID_ATANH && (ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_EQUALS)) { + MathStructure m1(CHILD(1)); + CHILD(0).setToChild(1, true); + CHILD(1).transformById(FUNCTION_ID_TANH); + if(CHILD(1).calculateFunctions(eo)) CHILD(1).calculatesub(eo2, eo, true); + CHILDREN_UPDATED; + isolate_x_sub(eo, eo2, x_var, morig); + m1.transformById(FUNCTION_ID_IM); + if(m1.calculateFunctions(eo)) m1.calculatesub(eo2, eo, true); + MathStructure *mreq1 = new MathStructure(m1); + MathStructure *mreq2 = new MathStructure(m1); + mreq1->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_GREATER : COMPARISON_EQUALS_LESS, CALCULATOR->getVariableById(VARIABLE_ID_PI)); + mreq2->transform(ct_comp == COMPARISON_NOT_EQUALS ? COMPARISON_LESS : COMPARISON_EQUALS_GREATER, CALCULATOR->getVariableById(VARIABLE_ID_PI)); + mreq1->last() *= nr_half; + mreq2->last() *= nr_minus_half; + mreq1->isolate_x(eo2, eo); + mreq2->isolate_x(eo2, eo); + add_nocopy(mreq1, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND); + add_nocopy(mreq2, ct_comp == COMPARISON_NOT_EQUALS ? OPERATION_LOGICAL_OR : OPERATION_LOGICAL_AND, true); + calculatesub(eo2, eo, false); + return true; + } else if(CHILD(0).function()->id() == FUNCTION_ID_ABS && CHILD(0).size() == 1) { + if(CHILD(0)[0].contains(x_var)) { + if(CHILD(1).representsComplex() || CHILD(1).representsNegative()) { + clear(true); + return true; + } else if(CHILD(1).representsReal(true)) { + if(CHILD(0)[0].representsReal(true)) { + CHILD(0).setToChild(1); + CHILD_UPDATED(0) + CHILD(0) ^= nr_two; + CHILD(0) ^= nr_half; + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } else if((ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_NOT_EQUALS) && CHILD(1).representsNonNegative(true)) { + CHILD(0).setToChild(1); + CHILD_UPDATED(0) + CHILD(1) *= CALCULATOR->getVariableById(VARIABLE_ID_E); + CHILD(1).last() ^= CALCULATOR->getVariableById(VARIABLE_ID_N); + CHILD(1).last().last() *= nr_one_i; + CHILD(1).calculatesub(eo2, eo); + isolate_x_sub(eo, eo2, x_var, morig); + fix_n_multiple(*this, eo2, eo, x_var); + return true; + } + } + } + } else if(CHILD(0).function()->id() == FUNCTION_ID_SIGNUM && CHILD(0).size() == 2) { + if(CHILD(0)[0].contains(x_var) && CHILD(0)[0].representsNonComplex(true)) { + if(CHILD(1).isZero() && CHILD(0)[1].isZero()) { + CHILD(0).setToChild(1, true, this, 1); + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } + if(CHILD(1).isNumber() && !CHILD(1).number().isInterval(false)) { + if(CHILD(1).number().isOne()) { + if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_EQUALS_GREATER) ct_comp = (CHILD(0)[1].isOne() ? COMPARISON_EQUALS_GREATER : COMPARISON_GREATER); + else if(ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_LESS) ct_comp = (CHILD(0)[1].isOne() ? COMPARISON_LESS : COMPARISON_EQUALS_LESS); + else if(ct_comp == COMPARISON_GREATER) {clear(true); return 1;} + else {set(1, 1, 0, true); return 1;} + CHILD(0).setToChild(1, true, this, 1); + CHILD(1).clear(true); + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } else if(CHILD(1).number().isMinusOne()) { + if(ct_comp == COMPARISON_EQUALS || ct_comp == COMPARISON_EQUALS_LESS) ct_comp = (CHILD(0)[1].isMinusOne() ?COMPARISON_EQUALS_LESS : COMPARISON_LESS); + else if(ct_comp == COMPARISON_NOT_EQUALS || ct_comp == COMPARISON_GREATER) ct_comp = (CHILD(0)[1].isMinusOne() ? COMPARISON_GREATER : COMPARISON_EQUALS_GREATER); + else if(ct_comp == COMPARISON_LESS) {clear(true); return 1;} + else {set(1, 1, 0, true); return 1;} + CHILD(0).setToChild(1, true, this, 1); + CHILD(1).clear(true); + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } + if(ct_comp == COMPARISON_EQUALS) { + clear(true); + return true; + } else if(ct_comp == COMPARISON_NOT_EQUALS) { + set(1, 1, 0, true); + return true; + } + if(CHILD(0)[1].isZero() || CHILD(0)[1].isOne() || CHILD(0)[1].isMinusOne()) { + if(CHILD(1).number().isPositive()) { + if(CHILD(1).number().isGreaterThan(1)) { + if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) clear(true); + else set(1, 1, 0, true); + return 1; + } + if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) ct_comp = (CHILD(0)[1].isOne() ? COMPARISON_EQUALS_GREATER : COMPARISON_GREATER); + else ct_comp = (CHILD(0)[1].isOne() ? COMPARISON_LESS : COMPARISON_EQUALS_LESS); + CHILD(0).setToChild(1, true, this, 1); + CHILD(1).clear(true); + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } else if(CHILD(1).number().isNegative()) { + if(CHILD(1).number().isLessThan(-1)) { + if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) set(1, 1, 0, true); + else clear(true); + return 1; + } + if(ct_comp == COMPARISON_GREATER || ct_comp == COMPARISON_EQUALS_GREATER) ct_comp = (CHILD(0)[1].isMinusOne() ? COMPARISON_GREATER : COMPARISON_EQUALS_GREATER); + else ct_comp = (CHILD(0)[1].isMinusOne() ? COMPARISON_EQUALS_LESS : COMPARISON_LESS); + CHILD(0).setToChild(1, true, this, 1); + CHILD(1).clear(true); + isolate_x_sub(eo, eo2, x_var, morig); + return true; + } + } + } + } + } + break; + } + default: {} + } + return false; +} + +bool contains_unsolved_equals(const MathStructure &mstruct, const MathStructure &x_var) { + if(mstruct.isComparison()) { + return mstruct.comparisonType() == COMPARISON_EQUALS && mstruct[0] != x_var && mstruct[1] != x_var && mstruct.contains(x_var); + } + for(size_t i = 0; i < mstruct.size(); i++) { + if(contains_unsolved_equals(mstruct[i], x_var)) return true; + } + return false; +} + +bool sync_sine(MathStructure &mstruct, const EvaluationOptions &eo, const MathStructure &x_var, bool use_cos, bool b_hyp = false, const MathStructure &mstruct_parent = m_undefined) { + if(!mstruct_parent.isUndefined() && mstruct.isFunction() && mstruct.function()->id() == (b_hyp ? FUNCTION_ID_SINH : FUNCTION_ID_SIN) && mstruct[0].contains(x_var)) { + MathStructure m_half(mstruct); + m_half[0].calculateDivide(nr_two, eo); + bool b = mstruct_parent.contains(m_half); + if(!b) { + m_half.setFunctionId(b_hyp ? FUNCTION_ID_COSH : FUNCTION_ID_COS); + b = mstruct_parent.contains(m_half); + m_half.setFunctionId(b_hyp ? FUNCTION_ID_SINH : FUNCTION_ID_SIN); + } + if(b) { + mstruct = m_half; + MathStructure *m_cos = new MathStructure(mstruct); + (*m_cos).setFunctionId(b_hyp ? FUNCTION_ID_COSH : FUNCTION_ID_COS); + mstruct.multiply_nocopy(m_cos); + mstruct.multiply(nr_two); + return true; + } + } else if(mstruct.isPower() && mstruct[0].isFunction() && mstruct[1].isNumber() && mstruct[1].number().isEven() && mstruct[0].size() == 1) { + if(!mstruct_parent.isUndefined() && mstruct[0].function()->id() == (b_hyp ? FUNCTION_ID_SINH : FUNCTION_ID_SIN) && mstruct[0][0].contains(x_var)) { + MathStructure m_half(mstruct[0]); + m_half[0].calculateDivide(nr_two, eo); + bool b = mstruct_parent.contains(m_half); + if(!b) { + m_half.setFunctionId(b_hyp ? FUNCTION_ID_COSH : FUNCTION_ID_COS); + b = mstruct_parent.contains(m_half); + m_half.setFunctionId(b_hyp ? FUNCTION_ID_SINH : FUNCTION_ID_SIN); + } + if(b) { + MathStructure *mmul = new MathStructure(2, 1, 0); + mmul->raise(mstruct[1]); + mstruct[0] = m_half; + MathStructure *m_cos = new MathStructure(mstruct); + (*m_cos)[0].setFunctionId(b_hyp ? FUNCTION_ID_COSH : FUNCTION_ID_COS); + mstruct.multiply_nocopy(m_cos); + mstruct.multiply_nocopy(mmul); + sync_sine(mstruct, eo, x_var, use_cos, b_hyp, mstruct_parent); + return true; + } + } + if(mstruct[0].function()->id() == (b_hyp ? FUNCTION_ID_TANH : FUNCTION_ID_TAN) && mstruct[0][0].contains(x_var)) { + mstruct[0].setFunctionId(FUNCTION_ID_SIN); + MathStructure *m_cos = new MathStructure(mstruct); + (*m_cos)[0].setFunctionId(FUNCTION_ID_COS); + (*m_cos)[1].number().negate(); + mstruct.multiply_nocopy(m_cos); + sync_sine(mstruct, eo, x_var, use_cos, b_hyp, mstruct_parent); + return true; + } + if(mstruct[0].function()->id() == (use_cos ? (b_hyp ? FUNCTION_ID_SINH : FUNCTION_ID_SIN) : (b_hyp ? FUNCTION_ID_COSH : FUNCTION_ID_COS)) && mstruct[0][0].contains(x_var)) { + mstruct[0].setFunctionId(use_cos ? (b_hyp ? FUNCTION_ID_COSH : FUNCTION_ID_COS) : (b_hyp ? FUNCTION_ID_SINH : FUNCTION_ID_SIN)); + Number nr_pow = mstruct[1].number(); + nr_pow /= 2; + mstruct[1].set(nr_two, true); + if(b_hyp) { + if(use_cos) mstruct += m_minus_one; + else mstruct += m_one; + } else { + mstruct.negate(); + mstruct += m_one; + } + if(!nr_pow.isOne()) { + mstruct ^= nr_pow; + } + return true; + } + } + bool b = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(CALCULATOR->aborted()) return false; + if(sync_sine(mstruct[i], eo, x_var, use_cos, b_hyp, mstruct_parent.isUndefined() ? mstruct : mstruct_parent)) b = true; + } + return b; +} +void sync_find_cos_sin(const MathStructure &mstruct, const MathStructure &x_var, bool &b_sin, bool &b_cos, bool b_hyp = false) { + if(mstruct.isFunction() && mstruct.size() == 1) { + if(!b_sin && mstruct.function()->id() == (b_hyp ? FUNCTION_ID_SINH : FUNCTION_ID_SIN) && mstruct[0].contains(x_var)) { + b_sin = true; + } else if(!b_cos && mstruct.function()->id() == (b_hyp ? FUNCTION_ID_COSH : FUNCTION_ID_COS) && mstruct[0].contains(x_var)) { + b_cos = true; + } + if(b_sin && b_cos) return; + } + for(size_t i = 0; i < mstruct.size(); i++) { + sync_find_cos_sin(mstruct[i], x_var, b_sin, b_cos, b_hyp); + if(b_sin && b_cos) return; + } +} +bool sync_trigonometric_functions(MathStructure &mstruct, const EvaluationOptions &eo, const MathStructure &x_var, bool use_cos = false) { + bool b_ret = false; + if(sync_sine(mstruct, eo, x_var, use_cos)) b_ret = true; + if(sync_sine(mstruct, eo, x_var, use_cos, true)) b_ret = true; + return b_ret; +} + +bool MathStructure::isolate_x(const EvaluationOptions &eo, const MathStructure &x_varp, bool check_result) { + return isolate_x(eo, eo, x_varp, check_result); +} +bool MathStructure::isolate_x(const EvaluationOptions &eo, const EvaluationOptions &feo, const MathStructure &x_varp, bool check_result) { + if(isProtected()) return false; + if(!isComparison()) { + bool b = false; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isolate_x(eo, feo, x_varp, check_result)) { + CHILD_UPDATED(i); + b = true; + } + } + return b; + } + MathStructure x_var(x_varp); + if(x_var.isUndefined()) { + const MathStructure *x_var2; + if(eo.isolate_var && contains(*eo.isolate_var)) x_var2 = eo.isolate_var; + else x_var2 = &find_x_var(); + if(x_var2->isUndefined()) return false; + x_var = *x_var2; + } + + if(CHILD(0) == x_var && !CHILD(1).contains(x_var)) return true; + if(!CHILD(1).isZero()) { + CHILD(0).calculateSubtract(CHILD(1), eo); + CHILD(1).clear(true); + CHILDREN_UPDATED + } + + if(eo.expand > 0) simplify_functions(*this, eo, feo, x_var); + + EvaluationOptions eo2 = eo; + eo2.calculate_functions = false; + eo2.test_comparisons = false; + eo2.isolate_x = false; + + if(check_result && CHILD(1).isZero() && CHILD(0).isAddition()) { + bool found_1x = false; + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CHILD(0)[i] == x_var) { + found_1x = true; + } else if(CHILD(0)[i].contains(x_var)) { + found_1x = false; + break; + } + } + if(found_1x) check_result = false; + } + + MathStructure msave(*this); + + bool b = isolate_x_sub(feo, eo2, x_var); + + if(CALCULATOR->aborted()) return !check_result && b; + + if(eo.expand > 0 && contains_unsolved_equals(*this, x_var)) { + MathStructure mtest(msave); + EvaluationOptions eo3 = eo; + eo3.transform_trigonometric_functions = false; + eo2.transform_trigonometric_functions = false; + bool do_cos = true; + if(sync_trigonometric_functions(mtest, eo3, x_var, false)) { + mtest.calculatesub(eo3, feo); + if(CALCULATOR->aborted()) return !check_result && b; + if(eo.do_polynomial_division) do_simplification(mtest, eo3, true, eo.structuring == STRUCTURING_NONE || eo.structuring == STRUCTURING_FACTORIZE, false, true, true); + if(CALCULATOR->aborted()) return !check_result && b; + if(mtest.isComparison() && mtest.isolate_x_sub(feo, eo2, x_var) && !contains_unsolved_equals(mtest, x_var)) { + set(mtest); + b = true; + do_cos = false; + } else if(CALCULATOR->aborted()) { + return !check_result && b; + } + } + if(do_cos) { + mtest = msave; + if(sync_trigonometric_functions(mtest, eo3, x_var, true)) { + mtest.calculatesub(eo3, feo); + if(CALCULATOR->aborted()) return !check_result && b; + if(eo.do_polynomial_division) do_simplification(mtest, eo3, true, eo.structuring == STRUCTURING_NONE || eo.structuring == STRUCTURING_FACTORIZE, false, true, true); + if(CALCULATOR->aborted()) return !check_result && b; + if(mtest.isComparison() && mtest.isolate_x_sub(feo, eo2, x_var) && !contains_unsolved_equals(mtest, x_var)) { + b = true; + set(mtest); + } + } + } + } + fix_n_multiple(*this, eo, feo, x_var); + if(check_result && b) { + b = test_comparisons(msave, *this, x_var, eo) >= 0; + } + + return b; + +} + diff -Nru libqalculate-3.6.0/libqalculate/MathStructure-limit.cc libqalculate-3.7.0/libqalculate/MathStructure-limit.cc --- libqalculate-3.6.0/libqalculate/MathStructure-limit.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure-limit.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,1158 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "MathStructure.h" +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "Number.h" +#include "Function.h" +#include "Variable.h" +#include "Unit.h" +#include "Prefix.h" +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +int limit_inf_cmp(const MathStructure &mstruct, const MathStructure &mcmp, const MathStructure &x_var) { + if(mstruct.equals(mcmp)) return 0; + bool b_multi1 = false, b_multi2 = false; + const MathStructure *m1 = NULL, *m2 = NULL; + if(mstruct.isMultiplication()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].contains(x_var)) { + if(!m1) { + m1 = &mstruct[i]; + } else { + int cmp = limit_inf_cmp(mstruct[i], *m1, x_var); + if(cmp > 0) { + m1 = &mstruct[i]; + } else if(cmp != -1) { + return -2; + } + b_multi1 = true; + } + } + } + } else if(mstruct.contains(x_var, true)) { + m1 = &mstruct; + } + if(mcmp.isMultiplication()) { + for(size_t i = 0; i < mcmp.size(); i++) { + if(mcmp[i].contains(x_var)) { + if(!m2) { + m2 = &mcmp[i]; + } else { + int cmp = limit_inf_cmp(mcmp[i], *m2, x_var); + if(cmp > 0) { + m2 = &mcmp[i]; + } else if(cmp != -1) { + return -2; + } + b_multi2 = true; + } + } + } + } else if(mcmp.contains(x_var, true)) { + m2 = &mcmp; + } + if(!m1 && !m2) return 0; + if(!m1) return -1; + if(!m2) return 1; + int itype1 = 0; + int itype2 = 0; + if(m1->isFunction() && m1->function()->id() == FUNCTION_ID_GAMMA) itype1 = 4; + else if(m1->isPower() && m1->exponent()->contains(x_var, true)) itype1 = 3; + else if(m1->equals(x_var) || (m1->isPower() && m1->base()->equals(x_var) && m1->exponent()->representsPositive())) itype1 = 2; + else if(m1->isFunction() && m1->function()->id() == FUNCTION_ID_LOG) itype1 = 1; + else return -2; + if(m2->isFunction() && m2->function()->id() == FUNCTION_ID_GAMMA) itype2 = 4; + else if(m2->isPower() && m2->exponent()->contains(x_var, true)) itype2 = 3; + else if(m2->equals(x_var) || (m2->isPower() && m2->base()->equals(x_var) && m2->exponent()->representsPositive())) itype2 = 2; + else if(m2->isFunction() && m2->function()->id() == FUNCTION_ID_LOG) itype2 = 1; + else return -2; + if(itype1 > itype2) return 1; + if(itype2 > itype1) return -1; + ComparisonResult cr = COMPARISON_RESULT_UNKNOWN; + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(CALCULATOR->usesIntervalArithmetic()) { + if(itype1 == 4) { + cr = m1->getChild(1)->compare(*m2->getChild(1)); + } else if(itype1 == 1) { + int cmp = limit_inf_cmp(*m1->getChild(1), *m2->getChild(1), x_var); + if(cmp > 0) cr = COMPARISON_RESULT_LESS; + else if(cmp == -1) cr = COMPARISON_RESULT_GREATER; + } else if(itype1 == 3) { + if(m1->exponent()->equals(*m2->exponent())) { + if(m1->base()->contains(x_var, true) || m2->base()->contains(x_var, true)) { + int cmp = limit_inf_cmp(*m1->base(), *m2->base(), x_var); + if(cmp > 0) cr = COMPARISON_RESULT_LESS; + else if(cmp == -1) cr = COMPARISON_RESULT_GREATER; + } else { + cr = m1->base()->compare(*m2->base()); + } + } else if(m1->base()->equals(*m2->base())) { + int cmp = limit_inf_cmp(*m1->exponent(), *m2->exponent(), x_var); + if(cmp > 0) cr = COMPARISON_RESULT_LESS; + else if(cmp == -1) cr = COMPARISON_RESULT_GREATER; + else if(cmp == 0) cr = m1->exponent()->compare(*m2->exponent()); + } + } else if(itype1 == 2) { + if(m1->equals(x_var)) { + if(m2->equals(x_var)) cr = COMPARISON_RESULT_EQUAL; + else cr = m_one.compare(*m2->getChild(2)); + } else if(m2->equals(x_var)) { + cr = m1->getChild(2)->compare(m_one); + } else { + cr = m1->getChild(2)->compare(*m2->getChild(2)); + } + } + } + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + if(cr == COMPARISON_RESULT_GREATER) return -1; + else if(cr == COMPARISON_RESULT_LESS) return 1; + else if(cr != COMPARISON_RESULT_EQUAL) return -2; + if(!b_multi1 && !b_multi2) return 0; + if(!b_multi1) return -1; + if(!b_multi2) return 1; + MathStructure mc1(mstruct), mc2(mcmp); + for(size_t i = 0; i < mc1.size(); i++) { + if(&mstruct[i] == m1) {mc1.delChild(i + 1, true); break;} + } + for(size_t i = 0; i < mc2.size(); i++) { + if(&mcmp[i] == m2) {mc2.delChild(i + 1, true); break;} + } + return limit_inf_cmp(mc1, mc2, x_var); +} + +bool is_limit_neg_power(const MathStructure &mstruct, const MathStructure &x_var, bool b_nil) { + return mstruct.isPower() && (((!b_nil || !mstruct[1].contains(x_var, true)) && mstruct[1].representsNegative()) || (b_nil && mstruct[1].isMultiplication() && mstruct[1].size() == 2 && mstruct[1][1] == x_var && mstruct[1][0].representsNegative())); +} + +bool limit_combine_divisions(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &nr_limit) { + if(mstruct.isAddition()) { + bool b = false; + bool b_nil = nr_limit.isInfinite(false) && nr_limit.number().isMinusInfinity(); + // 5/y + x/y + z = (5 + x)/y + z + for(size_t i = 0; i < mstruct.size() && !b; i++) { + if(mstruct[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct[i].size() && !b; i2++) { + if(is_limit_neg_power(mstruct[i][i2], x_var, b_nil)) { + b = true; + } + } + } else if(is_limit_neg_power(mstruct[i], x_var, b_nil)) { + b = true; + } + } + if(!b) return false; + b = false; + MathStructure mstruct_units(mstruct); + MathStructure mstruct_new(mstruct); + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(mstruct_units[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct_units[i].size();) { + if(!is_limit_neg_power(mstruct_units[i][i2], x_var, b_nil)) { + mstruct_units[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); + else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); + for(size_t i2 = 0; i2 < mstruct_new[i].size();) { + if(is_limit_neg_power(mstruct_new[i][i2], x_var, b_nil)) { + mstruct_new[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); + else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); + } else if(is_limit_neg_power(mstruct_new[i], x_var, b_nil)) { + mstruct_new[i].set(1, 1, 0); + } else { + mstruct_units[i].setUndefined(); + } + } + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(!mstruct_units[i].isUndefined()) { + for(size_t i2 = i + 1; i2 < mstruct_units.size();) { + if(mstruct_units[i2] == mstruct_units[i]) { + mstruct_new[i].add(mstruct_new[i2], true); + mstruct_new.delChild(i2 + 1); + mstruct_units.delChild(i2 + 1); + b = true; + } else { + i2++; + } + } + if(mstruct_new[i].isOne()) { + mstruct_new[i].set(mstruct_units[i]); + } else if(mstruct_units[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct_units[i].size(); i2++) { + mstruct_new[i].multiply(mstruct_units[i][i2], true); + } + } else { + mstruct_new[i].multiply(mstruct_units[i], true); + } + } + } + if(b) { + if(mstruct_new.size() == 1) { + mstruct.set(mstruct_new[0], true); + } else { + mstruct = mstruct_new; + } + return true; + } + } + return false; +} +bool limit_combine_divisions2(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &nr_limit, const EvaluationOptions &eo) { + if(mstruct.isAddition()) { + MathStructure mden(1, 1, 0); + bool b = false; + bool b_nil = nr_limit.isInfinite(false) && nr_limit.number().isMinusInfinity(); + size_t i_d = 0; + for(size_t i2 = 0; i2 < mstruct.size(); i2++) { + if(mstruct[i2].isMultiplication()) { + for(size_t i3 = 0; i3 < mstruct[i2].size(); i3++) { + if(is_limit_neg_power(mstruct[i2][i3], x_var, b_nil)) { + mden *= mstruct[i2][i3]; + mden.last()[1].negate(); + i_d++; + } else if(!mstruct[i2][i3].isOne() && !mstruct[i2][i3].isMinusOne()) { + b = true; + } + } + } else if(is_limit_neg_power(mstruct[i2], x_var, b_nil)) { + mden *= mstruct[i2]; + mden.last()[1].negate(); + i_d++; + } else { + b = true; + } + } + if(mden.isOne() || !b || i_d > 10) return false; + for(size_t i = 0; i < mstruct.size(); i++) { + for(size_t i2 = 0; i2 < mstruct.size(); i2++) { + if(i2 != i) { + if(mstruct[i2].isMultiplication()) { + for(size_t i3 = 0; i3 < mstruct[i2].size(); i3++) { + if(is_limit_neg_power(mstruct[i2][i3], x_var, b_nil)) { + mstruct[i].multiply(mstruct[i2][i3], true); + mstruct[i].last()[1].negate(); + } + } + } else if(is_limit_neg_power(mstruct[i2], x_var, b_nil)) { + mstruct[i].multiply(mstruct[i2], true); + mstruct[i].last()[1].negate(); + } + } + } + } + for(size_t i2 = 0; i2 < mstruct.size(); i2++) { + if(mstruct[i2].isMultiplication()) { + for(size_t i3 = 0; i3 < mstruct[i2].size();) { + if(is_limit_neg_power(mstruct[i2][i3], x_var, b_nil)) { + mstruct[i2].delChild(i3 + 1); + } else { + i3++; + } + } + if(mstruct[i2].size() == 0) mstruct[i2].set(1, 1, 0); + else if(mstruct[i2].size() == 1) mstruct[i2].setToChild(1); + } else if(is_limit_neg_power(mstruct[i2], x_var, b_nil)) { + mstruct[i2].set(1, 1, 0); + } + } + mden.calculatesub(eo, eo, true); + mstruct.calculatesub(eo, eo, true); + mstruct /= mden; + return true; + } + return false; +} + +bool contains_zero(const MathStructure &mstruct) { + if(mstruct.isNumber() && !mstruct.number().isNonZero()) return true; + for(size_t i = 0; i < mstruct.size(); i++) { + if(contains_zero(mstruct[i])) return true; + } + return false; +} +bool limit_contains_undefined(const MathStructure &mstruct) { + bool b_zero = false, b_infinity = false; + if(mstruct.isPower() && mstruct[0].isNumber() && ((!mstruct[0].number().isNonZero() && mstruct[1].representsNegative()) || mstruct[1].containsInfinity(true))) return true; + for(size_t i = 0; i < mstruct.size(); i++) { + if(limit_contains_undefined(mstruct[i])) return true; + if(contains_zero(mstruct[i])) { + if(b_infinity) return true; + b_zero = true; + } + if(mstruct[i].containsInfinity(true)) { + if(b_infinity || b_zero) return true; + b_infinity = true; + } + } + return false; +} +bool is_plus_minus_infinity(const MathStructure &mstruct) { + return mstruct.isInfinite(false) || (mstruct.isPower() && mstruct[0].isZero() && mstruct[1].representsNegative()) || (mstruct.isMultiplication() && mstruct.size() == 2 && mstruct[0].representsReal() && mstruct[1].isPower() && mstruct[1][0].isZero() && mstruct[1][1].representsNegative()); +} + +bool calculate_limit_sub(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &nr_limit, const EvaluationOptions &eo, int approach_direction, Number *polydeg = NULL, int lhop_depth = 0, bool keep_inf_x = false, bool reduce_addition = true) { + + if(CALCULATOR->aborted()) return false; + if(mstruct == x_var) { + if(keep_inf_x && nr_limit.isInfinite(false)) return true; + mstruct.set(nr_limit, true); + return true; + } + if(!mstruct.contains(x_var, true)) return true; + + switch(mstruct.type()) { + case STRUCT_MULTIPLICATION: { + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isPower() && mstruct[i][0].isPower() && mstruct[i][0][0].contains(x_var, true) && !mstruct[i][0][0].representsNonPositive()) { + MathStructure mtest(mstruct[i][0][0]); + calculate_limit_sub(mtest, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); + if(mtest.representsPositive()) { + mstruct[i][0][1].calculateMultiply(mstruct[i][1], eo); + mstruct[i].setToChild(1); + } + } + } + MathStructure mzero(1, 1, 0); + MathStructure minfp(1, 1, 0); + MathStructure mleft; + vector irecalc; + MathStructure mbak(mstruct); + bool b_inf = false; + bool b_li = nr_limit.isInfinite(false); + bool b_fail = false; + bool b_test_inf = b_li; + bool b_possible_zero = false; + for(size_t i = 0; i < mstruct.size(); i++) { + bool b = false; + if(!b_fail && mstruct[i].isPower() && mstruct[i][0].contains(x_var, true) && mstruct[i][1].representsNegative()) { + if(mstruct[i][1].isMinusOne()) { + mstruct[i].setToChild(1); + } else { + mstruct[i][1].calculateNegate(eo); + } + calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); + if(mstruct[i].isZero()) { + b = true; + if(b_test_inf && !mbak[i][1].contains(x_var, true)) b_test_inf = false; + if(minfp.isOne()) { + minfp = mbak[i]; + if(!b_li) { + if(minfp[1].isMinusOne()) minfp.setToChild(1); + else minfp[1].calculateNegate(eo); + } + } else { + minfp.multiply(mbak[i], true); + if(!b_li) { + if(minfp.last()[1].isMinusOne()) minfp.last().setToChild(1); + else minfp.last()[1].calculateNegate(eo); + } + } + irecalc.push_back(i); + mstruct[i].inverse(); + } else if(mstruct[i].isInfinite()) { + b = true; + if(mzero.isOne()) { + mzero = mbak[i]; + if(b_li) { + if(mzero[1].isMinusOne()) mzero.setToChild(1); + else mzero[1].calculateNegate(eo); + } + } else { + mzero.multiply(mbak[i], true); + if(b_li) { + if(mzero.last()[1].isMinusOne()) mzero.last().setToChild(1); + else mzero.last()[1].calculateNegate(eo); + } + } + mstruct[i].clear(true); + } else { + mstruct[i].calculateInverse(eo); + } + } else { + calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); + } + if(!b_fail && !b) { + if(mstruct[i].isZero()) { + if(b_li && mbak[i].isPower()) { + if(b_test_inf && !mbak[i][1].contains(x_var, true)) b_test_inf = false; + if(mzero.isOne()) { + mzero = mbak[i]; + if(mzero[1].isMinusOne()) mzero.setToChild(1); + else mzero[1].calculateNegate(eo); + } else { + mzero.multiply(mbak[i], true); + if(mzero.last()[1].isMinusOne()) mzero.last().setToChild(1); + else mzero.last()[1].calculateNegate(eo); + } + } else { + b_test_inf = false; + if(mzero.isOne()) { + mzero = mbak[i]; + if(b_li) { + if(!mzero.isPower()) mzero.inverse(); + else if(mzero[1].isMinusOne()) mzero.setToChild(1); + else mzero[1].calculateNegate(eo); + } + } else { + mzero.multiply(mbak[i], true); + if(b_li) { + if(!mzero.last().isPower()) mzero.last().inverse(); + else if(mzero.last()[1].isMinusOne()) mzero.last().setToChild(1); + else mzero.last()[1].calculateNegate(eo); + } + } + } + } else if(is_plus_minus_infinity(mstruct[i])) { + if(mstruct[i].isInfinite()) { + b_inf = true; + if(minfp.isOne()) { + minfp = mbak[i]; + if(!b_li) { + if(!minfp.isPower()) minfp.inverse(); + else if(minfp[1].isMinusOne()) minfp.setToChild(1); + else minfp[1].calculateNegate(eo); + } + } else { + minfp.multiply(mbak[i], true); + if(!b_li) { + if(!minfp.last().isPower()) minfp.last().inverse(); + else if(minfp.last()[1].isMinusOne()) minfp.last().setToChild(1); + else minfp.last()[1].calculateNegate(eo); + } + } + } else { + b_test_inf = false; + if(minfp.isOne()) { + minfp = mbak[i]; + if(!b_li) { + if(!minfp.isPower()) minfp.inverse(); + else if(minfp[1].isMinusOne()) minfp[1].setToChild(1); + else minfp[1].calculateNegate(eo); + } + } else { + minfp.multiply(mbak[i], true); + if(!b_li) { + if(!minfp.last().isPower()) minfp.last().inverse(); + else if(minfp.last()[1].isMinusOne()) minfp.last().setToChild(1); + else minfp.last()[1].calculateNegate(eo); + } + } + } + } else if(!mstruct[i].representsNonZero(true) || !mstruct[i].representsNumber(true)) { + if(!mstruct[i].contains(x_var) && !mstruct.isZero() && mstruct[i].representsNumber(true)) { + mstruct[i].ref(); + mleft.addChild_nocopy(&mstruct[i]); + b_possible_zero = true; + } else { + b_fail = true; + } + } else { + mstruct[i].ref(); + mleft.addChild_nocopy(&mstruct[i]); + } + } + } + if(b_li) b_inf = !b_inf; + if(!b_fail && b_li && b_test_inf && !mzero.isOne() && !minfp.isOne()) { + MathStructure mnum(minfp); + MathStructure mden(mzero); + mnum.calculatesub(eo, eo, false); + mden.calculatesub(eo, eo, false); + MathStructure mnum_bak(mnum), mden_bak(mden); + calculate_limit_sub(mnum, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true); + calculate_limit_sub(mden, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true); + if(mnum.contains(x_var, true) && mden.contains(x_var, true)) { + int cmp = limit_inf_cmp(mnum, mden, x_var); + if(cmp == 0) { + mstruct.set(mnum); + EvaluationOptions eo2 = eo; + eo2.expand = false; + mstruct.calculateDivide(mden, eo2); + if(!mstruct.contains(x_var)) { + for(size_t i = 0; i < mleft.size(); i++) { + mstruct.calculateMultiply(mleft[i], eo); + } + break; + } + } + MathStructure mnum_b(mnum), mden_b(mden); + calculate_limit_sub(mnum, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); + calculate_limit_sub(mden, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); + if(mnum.isInfinite(false) && mden.isInfinite(false)) { + if(cmp > 0) { + if(keep_inf_x) { + mstruct.set(mnum_b, true); + mstruct.calculateDivide(mden_b, eo); + break; + } + mstruct.set(mnum, true); + if(mden.number().isNegative()) mstruct.calculateNegate(eo); + for(size_t i = 0; i < mleft.size(); i++) { + mstruct.calculateMultiply(mleft[i], eo); + } + break; + } else if(cmp == -1) { + mstruct.clear(true); + break; + } + if(mnum_b.isPower() && mden_b.isPower() && mnum_b[1].contains(x_var, true) && mden_b[1].contains(x_var, true)) { + bool b = true; + if(mden_b[1] != mnum_b[1]) { + b = false; + Number npow1(1, 1, 0), npow2; + MathStructure *x_p = &mnum_b[1]; + if(mnum_b[1].isMultiplication() && mnum_b[1].size() == 2 && mnum_b[1][0].isNumber()) { + npow1 = mnum_b[1][0].number(); + x_p = &mnum_b[1][1]; + } + if(mden_b[1] == *x_p) npow2.set(1, 1, 0); + else if(mden_b[1].isMultiplication() && mden_b[1].size() == 2 && mden_b[1][0].isNumber() && mden_b[1][1] == *x_p) npow2 = mden_b[1][0].number(); + if(!npow2.isZero() && npow1.isRational() && npow2.isRational()) { + if(npow1.isGreaterThan(npow2)) { + npow1 /= npow2; + npow2 = npow1.denominator(); + npow1 = npow1.numerator(); + } + if(mnum.number().isMinusInfinity() && !npow1.isOne()) { + if(npow2.isOne() && mden.number().isPlusInfinity()) { + mden_b[0].factorize(eo, false, false, 0, false, false, NULL, m_undefined, false, true); + if(mden_b[0].isPower() && mden_b[0][1].isInteger()) { + mden_b[0][1].number() /= npow1; + if(mden_b[0][1].number().isInteger()) { + mden_b[0].calculateRaiseExponent(eo); + b = true; + } + } + } + } else if(mden.number().isMinusInfinity() && !npow2.isOne()) { + if(npow1.isOne() && mnum.number().isPlusInfinity()) { + mnum_b[0].factorize(eo, false, false, 0, false, false, NULL, m_undefined, false, true); + if(mnum_b[0].isPower() && mnum_b[0][1].isInteger()) { + mnum_b[0][1].number() /= npow2; + if(mnum_b[0][1].number().isInteger()) { + mnum_b[0].calculateRaiseExponent(eo); + mnum_b[1] = mden_b[1]; + b = true; + } + } + } + } else { + if(!npow1.isOne()) mnum_b[0].calculateRaise(npow1, eo); + if(!npow2.isOne()) mden_b[0].calculateRaise(npow2, eo); + mnum_b.childUpdated(1); + mden_b.childUpdated(1); + if(!npow1.isOne()) { + if(&mnum_b[1] == x_p) { + npow1.recip(); + mnum_b[1] *= npow1; + mnum_b[1].swapChildren(1, 2); + } else { + mnum_b[1][0].number() /= npow1; + } + } + b = true; + } + } + } + if(b) { + mstruct.set(mnum_b[0], true); + mstruct /= mden_b[0]; + mstruct.transformById(FUNCTION_ID_LOG); + mstruct *= mnum_b[1]; + mstruct.raise(CALCULATOR->getVariableById(VARIABLE_ID_E)); + mstruct.swapChildren(1, 2); + calculate_limit_sub(mstruct, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, keep_inf_x); + for(size_t i = 0; i < mleft.size(); i++) { + mstruct.calculateMultiply(mleft[i], eo); + } + break; + } + } + } + } + } + if(!b_possible_zero && !b_fail && lhop_depth < 5 && !mzero.isOne() && !minfp.isOne() && mzero.countTotalChildren(false) + minfp.countTotalChildren(false) < 50) { + //L'Hôpital's rule + MathStructure mden, mnum; + for(size_t i2 = 0; i2 < 2; i2++) { + if((i2 == 0) != b_inf) { + mnum = mzero; + mden = minfp; + if(b_li) { + mden.inverse(); + mnum.inverse(); + } + } else { + mnum = minfp; + mden = mzero; + if(!b_li) { + mden.inverse(); + mnum.inverse(); + } + } + if(mnum.differentiate(x_var, eo) && !contains_diff_for(mnum, x_var) && mden.differentiate(x_var, eo) && !contains_diff_for(mden, x_var)) { + mnum /= mden; + mnum.eval(eo); + calculate_limit_sub(mnum, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth + 1); + if(!limit_contains_undefined(mnum)) { + mstruct.set(mnum, true); + for(size_t i = 0; i < mleft.size(); i++) { + mstruct.calculateMultiply(mleft[i], eo); + } + return true; + } + } + } + } + for(size_t i = 0; i < irecalc.size(); i++) { + mstruct[irecalc[i]] = mbak[irecalc[i]]; + calculate_limit_sub(mstruct[irecalc[i]], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); + } + mstruct.childrenUpdated(); + mstruct.calculatesub(eo, eo, false); + if(keep_inf_x && mstruct.isInfinite(false)) { + mstruct = mbak; + if(reduce_addition) { + for(size_t i = 0; i < mstruct.size(); i++) { + calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true, reduce_addition); + if(mstruct[i].isZero()) mstruct[i] = mbak[i]; + } + mstruct.childrenUpdated(); + mstruct.calculatesub(eo, eo, false); + } + } + break; + } + case STRUCT_ADDITION: { + MathStructure mbak(mstruct); + bool b = limit_combine_divisions(mstruct, x_var, nr_limit); + if(mstruct.isAddition()) b = limit_combine_divisions2(mstruct, x_var, nr_limit, eo); + if(b) { + if(lhop_depth > 0) return calculate_limit_sub(mstruct, x_var, nr_limit, eo, approach_direction, polydeg, lhop_depth); + if(calculate_limit_sub(mstruct, x_var, nr_limit, eo, approach_direction, polydeg, lhop_depth) && !limit_contains_undefined(mstruct)) return true; + mstruct = mbak; + } + if(nr_limit.isInfinite(false)) { + size_t i_cmp = 0; + b = true; + for(size_t i = 0; i < mstruct.size(); i++) { + calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true); + } + if(mstruct.contains(x_var, true) && (!keep_inf_x || reduce_addition)) { + bool bfac = false; + MathStructure mstruct_units(mstruct); + MathStructure mstruct_new(mstruct); + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(mstruct_units[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct_units[i].size();) { + if(!mstruct_units[i][i2].contains(x_var, true)) { + mstruct_units[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_units[i].size() == 0) mstruct_units[i].setUndefined(); + else if(mstruct_units[i].size() == 1) mstruct_units[i].setToChild(1); + for(size_t i2 = 0; i2 < mstruct_new[i].size();) { + if(mstruct_new[i][i2].contains(x_var, true)) { + mstruct_new[i].delChild(i2 + 1); + } else { + i2++; + } + } + if(mstruct_new[i].size() == 0) mstruct_new[i].set(1, 1, 0); + else if(mstruct_new[i].size() == 1) mstruct_new[i].setToChild(1); + } else if(mstruct_units[i].contains(x_var, true)) { + mstruct_new[i].set(1, 1, 0); + } else { + mstruct_units[i].setUndefined(); + } + } + for(size_t i = 0; i < mstruct_units.size(); i++) { + if(!mstruct_units[i].isUndefined()) { + for(size_t i2 = i + 1; i2 < mstruct_units.size(); i2++) { + if(mstruct_units[i2] == mstruct_units[i]) { + mstruct_new[i].add(mstruct_new[i2], true); + bfac = true; + } + } + bool bfac2 = false; + MathStructure mzero(mstruct_new[i]); + mzero.calculatesub(eo, eo, false); + if(bfac && mzero.isZero() && lhop_depth < 5) { + MathStructure mfac(mbak[i]); + bool b_diff = false; + calculate_limit_sub(mfac, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true, false); + if(mfac != mstruct[i]) b_diff = true; + for(size_t i2 = i + 1; i2 < mstruct_units.size(); i2++) { + if(mstruct_units[i2] == mstruct_units[i]) { + mfac.add(mbak[i2], true); + calculate_limit_sub(mfac.last(), x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true, false); + if(!b_diff && mfac.last() != mstruct[i2]) b_diff = true; + bfac2 = true; + } + } + if(bfac2) { + mfac.calculatesub(eo, eo, false); + if(!mfac.isAddition()) { + calculate_limit_sub(mfac, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth + 1, true); + mstruct_new[i].set(mfac, true); + } else if(!b_diff) { + bfac2 = false; + } else if(mfac.size() == 2 && !mfac.containsType(STRUCT_FUNCTION)) { + MathStructure mfac2(mfac); + MathStructure mmul(mfac); + mmul.last().calculateNegate(eo); + mfac.calculateMultiply(mmul, eo); + mfac.divide(mmul); + calculate_limit_sub(mfac, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth + 1, true); + if(limit_contains_undefined(mfac)) { + mfac2.factorize(eo, false, false, 0, false, false, NULL, m_undefined, false, false); + if(!mfac2.isAddition()) { + calculate_limit_sub(mfac2, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth + 1, true); + mstruct_new[i].set(mfac2, true); + } else { + bfac2 = false; + } + } else { + mstruct_new[i].set(mfac, true); + } + } else { + mfac.factorize(eo, false, false, 0, false, false, NULL, m_undefined, false, false); + if(!mfac.isAddition()) { + calculate_limit_sub(mfac, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth + 1, true); + mstruct_new[i].set(mfac, true); + } else if(mstruct_units[i].isFunction() && mstruct_units[i].function()->id() == FUNCTION_ID_LOG) { + mstruct_new[i].clear(true); + } else { + bfac2 = false; + } + } + } + } + if(!bfac2) { + if(mstruct_new[i].isOne()) { + mstruct_new[i].set(mstruct_units[i]); + } else if(mstruct_units[i].isMultiplication()) { + for(size_t i2 = 0; i2 < mstruct_units[i].size(); i2++) { + mstruct_new[i].multiply(mstruct_units[i][i2], true); + } + } else { + mstruct_new[i].multiply(mstruct_units[i], true); + } + } + for(size_t i2 = i + 1; i2 < mstruct_units.size(); i2++) { + if(mstruct_units[i2] == mstruct_units[i]) { + mstruct_units[i2].setUndefined(); + mstruct_new[i2].clear(); + } + } + } + } + if(bfac) { + for(size_t i = 0; mstruct_new.size() > 1 && i < mstruct_new.size();) { + if(mstruct_new[i].isZero()) { + mstruct_new.delChild(i + 1); + } else { + i++; + } + } + mstruct = mstruct_new; + if(mstruct.size() == 1) { + mstruct.setToChild(1, true); + if(!keep_inf_x) calculate_limit_sub(mstruct, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); + break; + } else if(!mstruct.contains(x_var, true)) { + b = false; + } + } + for(size_t i = 0; i < mstruct.size(); i++) { + if(i > 0 && mstruct[i].contains(x_var, true)) { + int cmp = limit_inf_cmp(mstruct[i], mstruct[i_cmp], x_var); + if(cmp > 0) { + mstruct.delChild(i_cmp + 1, false); + i--; + i_cmp = i; + } else if(cmp == -1) { + mstruct.delChild(i + 1, false); + i--; + } else { + b = false; + } + } + } + if(b) { + MathStructure mbak(mstruct); + for(size_t i = 0; i < mstruct.size();) { + if(!mstruct[i].contains(x_var, true)) { + if(mstruct[i].representsNumber()) { + mstruct.delChild(i + 1, false); + } else { + mstruct = mbak; + break; + } + } else { + i++; + } + } + } + } + if(!b || !keep_inf_x) { + for(size_t i = 0; i < mstruct.size(); i++) { + calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); + } + } + mstruct.childrenUpdated(); + if(mstruct.size() == 1) mstruct.setToChild(1, true); + else if(!b || !keep_inf_x) mstruct.calculatesub(eo, eo, false); + break; + } else { + for(size_t i = 0; i < mstruct.size(); i++) { + calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth); + } + } + mstruct.childrenUpdated(); + mstruct.calculatesub(eo, eo, false); + break; + } + case STRUCT_POWER: { + MathStructure mbak(mstruct); + calculate_limit_sub(mstruct[0], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); + calculate_limit_sub(mstruct[1], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); + if(is_plus_minus_infinity(mstruct[1]) && (mstruct[0].isOne() || mstruct[0].isZero()) && mbak[1].contains(x_var, true) && mbak[0].contains(x_var, true)) { + mstruct.set(mbak[0], true); + mstruct.transformById(FUNCTION_ID_LOG); + mstruct *= mbak[1]; + mstruct.raise(CALCULATOR->getVariableById(VARIABLE_ID_E)); + mstruct.swapChildren(1, 2); + calculate_limit_sub(mstruct, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, keep_inf_x); + break; + } + if(mstruct[0].isFunction() && (mstruct[0].function()->id() == FUNCTION_ID_ASIN || mstruct[0].function()->id() == FUNCTION_ID_ACOS) && mstruct[0].size() == 1 && mstruct[0][0].isInfinite(false) && mstruct[1].representsNegative()) { + mstruct.clear(true); + break; + } + if(keep_inf_x && nr_limit.isInfinite(false) && (mstruct[0].isInfinite(false) || mstruct[1].isInfinite(false))) { + MathStructure mbak2(mstruct); + mstruct.calculatesub(eo, eo, false); + if(mstruct.isInfinite(false)) { + mstruct = mbak2; + if(mstruct[0].isInfinite(false)) { + mstruct[0] = mbak[0]; + calculate_limit_sub(mstruct[0], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true, reduce_addition && !mstruct[1].isInfinite(false)); + } else if(mbak[0].contains(x_var, true)) { + mstruct[0] = mbak[0]; + } + if(mstruct[1].isInfinite(false)) { + mstruct[1] = mbak[1]; + calculate_limit_sub(mstruct[1], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true, false); + } else if(mbak[1].contains(x_var, true)) { + mstruct[1] = mbak[1]; + } + } + } else if(mstruct[0].isNumber() && !mstruct[0].number().isNonZero() && mstruct[1].representsNegative() && mbak[0].contains(x_var, true) > 0) { + bool b_test = true; + int i_sgn = 0; + if(mstruct[0].number().isInterval(false) && (mstruct[0].number().hasImaginaryPart() || !mstruct[1].isNumber())) { + b_test = false; + } + if(b_test && ((mbak[0].isFunction() && mbak[0].function()->id() == FUNCTION_ID_ABS) || mstruct[1].representsEven())) { + i_sgn = 1; + b_test = false; + } else if(b_test) { + if(mstruct[0].number().isInterval(false) && !mstruct[0].number().isNonNegative() && !mstruct[0].number().isNonPositive()) { + b_test = false; + } else { + MathStructure mpow(mbak[0]); + if(mstruct[1].isMinusOne()) { + MathStructure mfac(mpow); + mfac.factorize(eo, false, false, 0, false, false, NULL, m_undefined, false, true); + if(mfac.isPower() && mfac[1].representsEven()) { + i_sgn = 1; + b_test = false; + } + } else { + mpow ^= mstruct[1]; + mpow.last().calculateNegate(eo); + } + if(b_test) { + MathStructure mdiff(mpow); + if(mdiff.differentiate(x_var, eo) && !contains_diff_for(mdiff, x_var)) { + mdiff.replace(x_var, nr_limit); + CALCULATOR->beginTemporaryStopMessages(); + mdiff.eval(eo); + if(!CALCULATOR->endTemporaryStopMessages()) { + if(mdiff.representsPositive()) { + b_test = false; + if(approach_direction > 0) i_sgn = 1; + else if(approach_direction < 0) i_sgn = -1; + } else if(mdiff.representsNegative()) { + b_test = false; + if(approach_direction > 0) i_sgn = -1; + else if(approach_direction < 0) i_sgn = 1; + } + } + } + if(b_test) { + MathStructure mtestn(nr_limit); + if(eo.approximation != APPROXIMATION_EXACT) { + EvaluationOptions eo2 = eo; + eo2.approximation = APPROXIMATION_APPROXIMATE; + mtestn.eval(eo2); + } + if(mtestn.isNumber() && mtestn.number().isReal()) { + for(int i = 10; i < 20; i++) { + if(approach_direction == 0 || (i % 2 == (approach_direction < 0))) { + Number nr_test(i % 2 == 0 ? 1 : -1, 1, -(i / 2)); + if(!mtestn.number().isZero()) { + nr_test++; + if(!nr_test.multiply(mtestn.number())) {i_sgn = 0; break;} + } + MathStructure mtest(mpow); + mtest.replace(x_var, nr_test); + CALCULATOR->beginTemporaryStopMessages(); + mtest.eval(eo); + if(CALCULATOR->endTemporaryStopMessages()) {i_sgn = 0; break;} + int new_sgn = 0; + if(mtest.representsPositive()) new_sgn = 1; + else if(mtest.representsNegative()) new_sgn = -1; + if(new_sgn != 0 || mtest.isNumber()) { + if(new_sgn == 0 || (i_sgn != 0 && i_sgn != new_sgn)) {i_sgn = 0; break;} + i_sgn = new_sgn; + } + } + if(CALCULATOR->aborted()) {i_sgn = 0; break;} + } + } + } + } + } + } + if(i_sgn != 0) { + if(mstruct[0].number().isInterval()) { + Number nr_pow = mstruct[1].number(); + Number nr_high(mstruct[0].number()); + if(nr_pow.negate() && nr_high.raise(nr_pow) && !nr_high.hasImaginaryPart()) { + if(nr_high.isNonNegative() && i_sgn > 0) nr_high = nr_high.upperEndPoint(); + else if(nr_high.isNonPositive() && i_sgn < 0) nr_high = nr_high.lowerEndPoint(); + if(nr_high.isNonZero() && nr_high.recip()) { + Number nr; + if(i_sgn > 0) nr.setInterval(nr_high, nr_plus_inf); + else if(i_sgn < 0) nr.setInterval(nr_minus_inf, nr_high); + mstruct.set(nr, true); + if(b_test) CALCULATOR->error(false, _("Limit for %s determined graphically."), format_and_print(mbak).c_str(), NULL); + break; + } + } + } else { + if(b_test) CALCULATOR->error(false, _("Limit for %s determined graphically."), format_and_print(mbak).c_str(), NULL); + if(i_sgn > 0) mstruct.set(nr_plus_inf, true); + else if(i_sgn < 0) mstruct.set(nr_minus_inf, true); + break; + } + } + } + mstruct.childrenUpdated(); + mstruct.calculatesub(eo, eo, false); + break; + } + case STRUCT_FUNCTION: { + if(keep_inf_x && nr_limit.isInfinite(false) && mstruct.size() == 1 && (mstruct.function()->id() == FUNCTION_ID_LOG || mstruct.function()->id() == FUNCTION_ID_GAMMA)) { + MathStructure mbak(mstruct); + calculate_limit_sub(mstruct[0], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); + if(mstruct[0].isInfinite(false) && (mstruct[0].number().isPlusInfinity() || mstruct.function()->id() == FUNCTION_ID_LOG)) { + mstruct[0] = mbak[0]; + calculate_limit_sub(mstruct[0], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, true, mstruct.function()->id() == FUNCTION_ID_LOG && reduce_addition); + break; + } + } else if(approach_direction != 0 && mstruct.function()->id() == FUNCTION_ID_TAN && mstruct.size() == 1) { + MathStructure mbak(mstruct); + mstruct.setFunctionId(FUNCTION_ID_SIN); + mbak.setFunctionId(FUNCTION_ID_COS); + mstruct /= mbak; + return calculate_limit_sub(mstruct, x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, keep_inf_x, reduce_addition); + } else { + for(size_t i = 0; i < mstruct.size(); i++) { + calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false); + } + mstruct.childrenUpdated(); + } + if(approach_direction != 0 && mstruct.function()->id() == FUNCTION_ID_GAMMA && mstruct.size() == 1 && mstruct[0].isInteger() && mstruct[0].number().isNonPositive()) { + if((mstruct[0].number().isEven() && approach_direction < 0) || (mstruct[0].number().isOdd() && approach_direction > 0)) { + mstruct.set(nr_minus_inf, true); + } else { + mstruct.set(nr_plus_inf, true); + } + break; + } + mstruct.calculateFunctions(eo, true); + mstruct.calculatesub(eo, eo, false); + break; + } + default: { + for(size_t i = 0; i < mstruct.size(); i++) { + calculate_limit_sub(mstruct[i], x_var, nr_limit, eo, approach_direction, NULL, lhop_depth, false, reduce_addition); + } + mstruct.childrenUpdated(); + mstruct.calculatesub(eo, eo, false); + } + } + return true; +} + +bool replace_equal_limits(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &nr_limit, const EvaluationOptions &eo, int approach_direction, bool at_top = true) { + if(!nr_limit.isInfinite(false)) return false; + bool b_ret = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(replace_equal_limits(mstruct[i], x_var, nr_limit, eo, approach_direction, false)) { + mstruct.childUpdated(i + 1); + b_ret = true; + } + } + if(at_top) return b_ret; + if(mstruct.isFunction() && (mstruct.function()->id() == FUNCTION_ID_SINH || mstruct.function()->id() == FUNCTION_ID_COSH) && mstruct.size() == 1 && mstruct.contains(x_var, true)) { + MathStructure mterm1(CALCULATOR->getVariableById(VARIABLE_ID_E)); + mterm1.raise(mstruct[0]); + MathStructure mterm2(mterm1); + mterm2[1].negate(); + mterm1 *= nr_half; + mterm2 *= nr_half; + mstruct = mterm1; + if(mstruct.function()->id() == FUNCTION_ID_SINH) mstruct -= mterm2; + else mstruct += mterm2; + return true; + } + return b_ret; +} +bool replace_equal_limits2(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &nr_limit, const EvaluationOptions &eo, int approach_direction, bool at_top = true) { + if(!nr_limit.isInfinite(false)) return false; + bool b_ret = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(replace_equal_limits2(mstruct[i], x_var, nr_limit, eo, approach_direction, false)) { + mstruct.childUpdated(i + 1); + b_ret = true; + } + } + if(mstruct.isMultiplication()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isPower() && mstruct[i][1] == x_var && (nr_limit.number().isMinusInfinity() || mstruct[i][0].representsNonNegative())) { + for(size_t i2 = i + 1; i2 < mstruct.size();) { + if(mstruct[i2].isPower() && mstruct[i2][1] == x_var && (nr_limit.number().isMinusInfinity() || mstruct[i2][0].representsNonNegative())) { + mstruct[i][0].calculateMultiply(mstruct[i2][0], eo); + mstruct.delChild(i2 + 1, false); + } else { + i2++; + } + } + mstruct[i].childUpdated(1); + mstruct.childUpdated(i + 1); + if(mstruct.size() == 1) { + mstruct.setToChild(1, true); + break; + } + } + } + } + return b_ret; +} +bool replace_equal_limits3(MathStructure &mstruct, const MathStructure &x_var, const MathStructure &nr_limit, const EvaluationOptions &eo, int approach_direction, bool at_top = true) { + if(!nr_limit.isInfinite(false)) return false; + bool b_ret = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(replace_equal_limits3(mstruct[i], x_var, nr_limit, eo, approach_direction, false)) { + mstruct.childUpdated(i + 1); + b_ret = true; + } + } + if(at_top) return b_ret; + if(mstruct.isFunction() && (mstruct.function()->id() == FUNCTION_ID_ASINH || mstruct.function()->id() == FUNCTION_ID_ACOSH) && mstruct.size() == 1 && mstruct.contains(x_var, true)) { + MathStructure mtest(mstruct[0]); + calculate_limit_sub(mtest, x_var, nr_limit, eo, approach_direction); + if(mtest.isInfinite(false)) { + if(mtest.number().isPlusInfinity()) { + mstruct.setFunctionId(FUNCTION_ID_LOG); + mstruct[0] *= nr_two; + return true; + } else if(mstruct.function()->id() == FUNCTION_ID_ASINH) { + mstruct.setFunctionId(FUNCTION_ID_LOG); + mstruct[0] *= nr_two; + mstruct.negate(); + return true; + } + } + } + return b_ret; +} + +bool MathStructure::calculateLimit(const MathStructure &x_var, const MathStructure &limit, const EvaluationOptions &eo_pre, int approach_direction) { + EvaluationOptions eo = eo_pre; + eo.assume_denominators_nonzero = true; + eo.warn_about_denominators_assumed_nonzero = false; + eo.do_polynomial_division = false; + UnknownVariable *var = new UnknownVariable("", format_and_print(x_var)); + Assumptions *ass = new Assumptions(); + MathStructure nr_limit(limit); + if(eo.approximation != APPROXIMATION_EXACT && nr_limit.containsInterval(true, true, false, 0, true)) { + eo.approximation = APPROXIMATION_EXACT_VARIABLES; + } + nr_limit.eval(eo); + eo.approximation = eo_pre.approximation; + if(nr_limit.representsReal() || nr_limit.isInfinite()) ass->setType(ASSUMPTION_TYPE_REAL); + if(nr_limit.representsPositive()) ass->setSign(ASSUMPTION_SIGN_POSITIVE); + else if(nr_limit.representsNegative()) ass->setSign(ASSUMPTION_SIGN_NEGATIVE); + else if(nr_limit.isZero()) { + if(approach_direction < 0) ass->setSign(ASSUMPTION_SIGN_NEGATIVE); + else if(approach_direction > 0) ass->setSign(ASSUMPTION_SIGN_POSITIVE); + else ass->setSign(ASSUMPTION_SIGN_NONZERO); + } + var->setAssumptions(ass); + replace(x_var, var); + eval(eo); + CALCULATOR->beginTemporaryStopMessages(); + MathStructure mbak(*this); + if(replace_equal_limits(*this, var, nr_limit, eo, approach_direction)) eval(eo); + replace_equal_limits2(*this, var, nr_limit, eo, approach_direction); + if(replace_equal_limits3(*this, var, nr_limit, eo, approach_direction)) { + eval(eo); + replace_equal_limits2(*this, var, nr_limit, eo, approach_direction); + } + do_simplification(*this, eo, true, false, false, true, true); + eo.do_polynomial_division = true; + calculate_limit_sub(*this, var, nr_limit, eo, approach_direction); + if(CALCULATOR->aborted() || (containsInfinity(true) && !isInfinite(true)) || limit_contains_undefined(*this)) { + set(mbak); + replace(var, x_var); + var->destroy(); + CALCULATOR->endTemporaryStopMessages(); + return false; + } + replace(var, nr_limit); + var->destroy(); + CALCULATOR->endTemporaryStopMessages(true); + return true; +} + diff -Nru libqalculate-3.6.0/libqalculate/MathStructure-matrixvector.cc libqalculate-3.7.0/libqalculate/MathStructure-matrixvector.cc --- libqalculate-3.6.0/libqalculate/MathStructure-matrixvector.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure-matrixvector.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,910 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "MathStructure.h" +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "Number.h" +#include "Function.h" +#include "Variable.h" +#include "Unit.h" +#include "Prefix.h" + +#include +#include + +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +MathStructure &MathStructure::flattenVector(MathStructure &mstruct) const { + if(!isVector()) { + mstruct = *this; + return mstruct; + } + MathStructure mstruct2; + mstruct.clearVector(); + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isVector()) { + CHILD(i).flattenVector(mstruct2); + for(size_t i2 = 0; i2 < mstruct2.size(); i2++) { + mstruct.addChild(mstruct2[i2]); + } + } else { + mstruct.addChild(CHILD(i)); + } + } + return mstruct; +} +bool MathStructure::rankVector(bool ascending) { + vector ranked; + vector ranked_equals_prev; + bool b; + for(size_t index = 0; index < SIZE; index++) { + b = false; + for(size_t i = 0; i < ranked.size(); i++) { + if(CALCULATOR->aborted()) return false; + ComparisonResult cmp = CHILD(index).compare(CHILD(ranked[i])); + if(COMPARISON_NOT_FULLY_KNOWN(cmp)) { + CALCULATOR->error(true, _("Unsolvable comparison at element %s when trying to rank vector."), i2s(index).c_str(), NULL); + return false; + } + if((ascending && cmp == COMPARISON_RESULT_GREATER) || cmp == COMPARISON_RESULT_EQUAL || (!ascending && cmp == COMPARISON_RESULT_LESS)) { + if(cmp == COMPARISON_RESULT_EQUAL) { + ranked.insert(ranked.begin() + i + 1, index); + ranked_equals_prev.insert(ranked_equals_prev.begin() + i + 1, true); + } else { + ranked.insert(ranked.begin() + i, index); + ranked_equals_prev.insert(ranked_equals_prev.begin() + i, false); + } + b = true; + break; + } + } + if(!b) { + ranked.push_back(index); + ranked_equals_prev.push_back(false); + } + } + int n_rep = 0; + for(long int i = (long int) ranked.size() - 1; i >= 0; i--) { + if(CALCULATOR->aborted()) return false; + if(ranked_equals_prev[i]) { + n_rep++; + } else { + if(n_rep) { + MathStructure v(i + 1 + n_rep, 1L, 0L); + v += i + 1; + v *= MathStructure(1, 2, 0); + for(; n_rep >= 0; n_rep--) { + CHILD(ranked[i + n_rep]) = v; + } + } else { + CHILD(ranked[i]).set(i + 1, 1L, 0L); + } + n_rep = 0; + } + } + return true; +} +bool MathStructure::sortVector(bool ascending) { + vector ranked_mstructs; + bool b; + for(size_t index = 0; index < SIZE; index++) { + b = false; + for(size_t i = 0; i < ranked_mstructs.size(); i++) { + if(CALCULATOR->aborted()) return false; + ComparisonResult cmp = CHILD(index).compare(*v_subs[ranked_mstructs[i]]); + if(COMPARISON_MIGHT_BE_LESS_OR_GREATER(cmp)) { + CALCULATOR->error(true, _("Unsolvable comparison at element %s when trying to sort vector."), i2s(index).c_str(), NULL); + return false; + } + if((ascending && COMPARISON_IS_EQUAL_OR_GREATER(cmp)) || (!ascending && COMPARISON_IS_EQUAL_OR_LESS(cmp))) { + ranked_mstructs.insert(ranked_mstructs.begin() + i, v_order[index]); + b = true; + break; + } + } + if(!b) { + ranked_mstructs.push_back(v_order[index]); + } + } + v_order = ranked_mstructs; + return true; +} +MathStructure &MathStructure::getRange(int start, int end, MathStructure &mstruct) const { + if(!isVector()) { + if(start > 1) { + mstruct.clear(); + return mstruct; + } else { + mstruct = *this; + return mstruct; + } + } + if(start < 1) start = 1; + else if(start > (long int) SIZE) { + mstruct.clear(); + return mstruct; + } + if(end < (int) 1 || end > (long int) SIZE) end = SIZE; + else if(end < start) end = start; + mstruct.clearVector(); + for(; start <= end; start++) { + mstruct.addChild(CHILD(start - 1)); + } + return mstruct; +} + +void MathStructure::resizeVector(size_t i, const MathStructure &mfill) { + if(i > SIZE) { + while(i > SIZE) { + APPEND(mfill); + } + } else if(i < SIZE) { + REDUCE(i) + } +} + +size_t MathStructure::rows() const { + if(m_type != STRUCT_VECTOR || SIZE == 0 || (SIZE == 1 && (!CHILD(0).isVector() || CHILD(0).size() == 0))) return 0; + return SIZE; +} +size_t MathStructure::columns() const { + if(m_type != STRUCT_VECTOR || SIZE == 0 || !CHILD(0).isVector()) return 0; + return CHILD(0).size(); +} +const MathStructure *MathStructure::getElement(size_t row, size_t column) const { + if(row == 0 || column == 0 || row > rows() || column > columns()) return NULL; + if(CHILD(row - 1).size() < column) return NULL; + return &CHILD(row - 1)[column - 1]; +} +MathStructure *MathStructure::getElement(size_t row, size_t column) { + if(row == 0 || column == 0 || row > rows() || column > columns()) return NULL; + if(CHILD(row - 1).size() < column) return NULL; + return &CHILD(row - 1)[column - 1]; +} +MathStructure &MathStructure::getArea(size_t r1, size_t c1, size_t r2, size_t c2, MathStructure &mstruct) const { + size_t r = rows(); + size_t c = columns(); + if(r1 < 1) r1 = 1; + else if(r1 > r) r1 = r; + if(c1 < 1) c1 = 1; + else if(c1 > c) c1 = c; + if(r2 < 1 || r2 > r) r2 = r; + else if(r2 < r1) r2 = r1; + if(c2 < 1 || c2 > c) c2 = c; + else if(c2 < c1) c2 = c1; + mstruct.clearMatrix(); mstruct.resizeMatrix(r2 - r1 + 1, c2 - c1 + 1, m_undefined); + for(size_t index_r = r1; index_r <= r2; index_r++) { + for(size_t index_c = c1; index_c <= c2; index_c++) { + mstruct[index_r - r1][index_c - c1] = CHILD(index_r - 1)[index_c - 1]; + } + } + return mstruct; +} +MathStructure &MathStructure::rowToVector(size_t r, MathStructure &mstruct) const { + if(r > rows()) { + mstruct = m_undefined; + return mstruct; + } + if(r < 1) r = 1; + mstruct = CHILD(r - 1); + return mstruct; +} +MathStructure &MathStructure::columnToVector(size_t c, MathStructure &mstruct) const { + if(c > columns()) { + mstruct = m_undefined; + return mstruct; + } + if(c < 1) c = 1; + mstruct.clearVector(); + for(size_t i = 0; i < SIZE; i++) { + mstruct.addChild(CHILD(i)[c - 1]); + } + return mstruct; +} +MathStructure &MathStructure::matrixToVector(MathStructure &mstruct) const { + if(!isVector()) { + mstruct = *this; + return mstruct; + } + mstruct.clearVector(); + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isVector()) { + for(size_t i2 = 0; i2 < CHILD(i).size(); i2++) { + mstruct.addChild(CHILD(i)[i2]); + } + } else { + mstruct.addChild(CHILD(i)); + } + } + return mstruct; +} +void MathStructure::setElement(const MathStructure &mstruct, size_t row, size_t column) { + if(row > rows() || column > columns() || row < 1 || column < 1) return; + CHILD(row - 1)[column - 1] = mstruct; + CHILD(row - 1).childUpdated(column); + CHILD_UPDATED(row - 1); +} +void MathStructure::addRows(size_t r, const MathStructure &mfill) { + if(r == 0) return; + size_t cols = columns(); + MathStructure mstruct; mstruct.clearVector(); + mstruct.resizeVector(cols, mfill); + for(size_t i = 0; i < r; i++) { + APPEND(mstruct); + } +} +void MathStructure::addColumns(size_t c, const MathStructure &mfill) { + if(c == 0) return; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isVector()) { + for(size_t i2 = 0; i2 < c; i2++) { + CHILD(i).addChild(mfill); + } + } + } + CHILDREN_UPDATED; +} +void MathStructure::addRow(const MathStructure &mfill) { + addRows(1, mfill); +} +void MathStructure::addColumn(const MathStructure &mfill) { + addColumns(1, mfill); +} +void MathStructure::resizeMatrix(size_t r, size_t c, const MathStructure &mfill) { + if(r > SIZE) { + addRows(r - SIZE, mfill); + } else if(r != SIZE) { + REDUCE(r); + } + size_t cols = columns(); + if(c > cols) { + addColumns(c - cols, mfill); + } else if(c != cols) { + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).resizeVector(c, mfill); + } + } +} +bool MathStructure::matrixIsSquare() const { + return rows() == columns(); +} + +bool MathStructure::isNumericMatrix() const { + if(!isMatrix()) return false; + for(size_t index_r = 0; index_r < SIZE; index_r++) { + for(size_t index_c = 0; index_c < CHILD(index_r).size(); index_c++) { + if(!CHILD(index_r)[index_c].isNumber() || CHILD(index_r)[index_c].isInfinity()) return false; + } + } + return true; +} + +//from GiNaC +int MathStructure::pivot(size_t ro, size_t co, bool symbolic) { + + size_t k = ro; + if(symbolic) { + while((k < SIZE) && (CHILD(k)[co].isZero())) ++k; + } else { + size_t kmax = k + 1; + Number mmax(CHILD(kmax)[co].number()); + mmax.abs(); + while(kmax < SIZE) { + if(CHILD(kmax)[co].number().isNegative()) { + Number ntmp(CHILD(kmax)[co].number()); + ntmp.negate(); + if(ntmp.isGreaterThan(mmax)) { + mmax = ntmp; + k = kmax; + } + } else if(CHILD(kmax)[co].number().isGreaterThan(mmax)) { + mmax = CHILD(kmax)[co].number(); + k = kmax; + } + ++kmax; + } + if(!mmax.isZero()) k = kmax; + } + if(k == SIZE) return -1; + if(k == ro) return 0; + + SWAP_CHILDREN(ro, k) + + return k; + +} + + +//from GiNaC +void determinant_minor(const MathStructure &mtrx, MathStructure &mdet, const EvaluationOptions &eo) { + size_t n = mtrx.size(); + if(n == 1) { + mdet = mtrx[0][0]; + return; + } + if(n == 2) { + mdet = mtrx[0][0]; + mdet.calculateMultiply(mtrx[1][1], eo); + mdet.add(mtrx[1][0], true); + mdet[mdet.size() - 1].calculateMultiply(mtrx[0][1], eo); + mdet[mdet.size() - 1].calculateNegate(eo); + mdet.calculateAddLast(eo); + return; + } + if(n == 3) { + mdet = mtrx[0][0]; + mdet.calculateMultiply(mtrx[1][1], eo); + mdet.calculateMultiply(mtrx[2][2], eo); + mdet.add(mtrx[0][0], true); + mdet[mdet.size() - 1].calculateMultiply(mtrx[1][2], eo); + mdet[mdet.size() - 1].calculateMultiply(mtrx[2][1], eo); + mdet[mdet.size() - 1].calculateNegate(eo); + mdet.calculateAddLast(eo); + mdet.add(mtrx[0][1], true); + mdet[mdet.size() - 1].calculateMultiply(mtrx[1][0], eo); + mdet[mdet.size() - 1].calculateMultiply(mtrx[2][2], eo); + mdet[mdet.size() - 1].calculateNegate(eo); + mdet.calculateAddLast(eo); + mdet.add(mtrx[0][2], true); + mdet[mdet.size() - 1].calculateMultiply(mtrx[1][0], eo); + mdet[mdet.size() - 1].calculateMultiply(mtrx[2][1], eo); + mdet.calculateAddLast(eo); + mdet.add(mtrx[0][1], true); + mdet[mdet.size() - 1].calculateMultiply(mtrx[1][2], eo); + mdet[mdet.size() - 1].calculateMultiply(mtrx[2][0], eo); + mdet.calculateAddLast(eo); + mdet.add(mtrx[0][2], true); + mdet[mdet.size() - 1].calculateMultiply(mtrx[1][1], eo); + mdet[mdet.size() - 1].calculateMultiply(mtrx[2][0], eo); + mdet[mdet.size() - 1].calculateNegate(eo); + mdet.calculateAddLast(eo); + return; + } + + std::vector Pkey; + Pkey.reserve(n); + std::vector Mkey; + Mkey.reserve(n - 1); + typedef std::map, class MathStructure> Rmap; + typedef std::map, class MathStructure>::value_type Rmap_value; + Rmap A; + Rmap B; + for(size_t r = 0; r < n; ++r) { + Pkey.erase(Pkey.begin(), Pkey.end()); + Pkey.push_back(r); + A.insert(Rmap_value(Pkey, mtrx[r][n - 1])); + } + for(long int c = n - 2; c >= 0; --c) { + Pkey.erase(Pkey.begin(), Pkey.end()); + Mkey.erase(Mkey.begin(), Mkey.end()); + for(size_t i = 0; i < n - c; ++i) Pkey.push_back(i); + size_t fc = 0; + do { + mdet.clear(); + for(size_t r = 0; r < n - c; ++r) { + if (mtrx[Pkey[r]][c].isZero()) continue; + Mkey.erase(Mkey.begin(), Mkey.end()); + for(size_t i = 0; i < n - c; ++i) { + if(i != r) Mkey.push_back(Pkey[i]); + } + mdet.add(mtrx[Pkey[r]][c], true); + mdet[mdet.size() - 1].calculateMultiply(A[Mkey], eo); + if(r % 2) mdet[mdet.size() - 1].calculateNegate(eo); + mdet.calculateAddLast(eo); + } + if(!mdet.isZero()) B.insert(Rmap_value(Pkey, mdet)); + for(fc = n - c; fc > 0; --fc) { + ++Pkey[fc-1]; + if(Pkey[fc - 1] < fc + c) break; + } + if(fc < n - c && fc > 0) { + for(size_t j = fc; j < n - c; ++j) Pkey[j] = Pkey[j - 1] + 1; + } + } while(fc); + A = B; + B.clear(); + } + return; +} + +//from GiNaC +int MathStructure::gaussianElimination(const EvaluationOptions &eo, bool det) { + + if(!isMatrix()) return 0; + bool isnumeric = isNumericMatrix(); + + size_t m = rows(); + size_t n = columns(); + int sign = 1; + + size_t r0 = 0; + for(size_t c0 = 0; c0 < n && r0 < m - 1; ++c0) { + int indx = pivot(r0, c0, true); + if(indx == -1) { + sign = 0; + if(det) return 0; + } + if(indx >= 0) { + if(indx > 0) sign = -sign; + for(size_t r2 = r0 + 1; r2 < m; ++r2) { + if(!CHILD(r2)[c0].isZero()) { + if(isnumeric) { + Number piv(CHILD(r2)[c0].number()); + piv /= CHILD(r0)[c0].number(); + for(size_t c = c0 + 1; c < n; ++c) { + CHILD(r2)[c].number() -= piv * CHILD(r0)[c].number(); + } + } else { + MathStructure piv(CHILD(r2)[c0]); + piv.calculateDivide(CHILD(r0)[c0], eo); + for(size_t c = c0 + 1; c < n; ++c) { + CHILD(r2)[c].add(piv, true); + CHILD(r2)[c][CHILD(r2)[c].size() - 1].calculateMultiply(CHILD(r0)[c], eo); + CHILD(r2)[c][CHILD(r2)[c].size() - 1].calculateNegate(eo); + CHILD(r2)[c].calculateAddLast(eo); + } + } + } + for(size_t c = r0; c <= c0; ++c) CHILD(r2)[c].clear(); + } + if(det) { + for(size_t c = r0 + 1; c < n; ++c) CHILD(r0)[c].clear(); + } + ++r0; + } + } + for(size_t r = r0 + 1; r < m; ++r) { + for(size_t c = 0; c < n; ++c) CHILD(r)[c].clear(); + } + + return sign; +} + +//from GiNaC +template +int permutation_sign(It first, It last) +{ + if (first == last) + return 0; + --last; + if (first == last) + return 0; + It flag = first; + int sign = 1; + + do { + It i = last, other = last; + --other; + bool swapped = false; + while (i != first) { + if (*i < *other) { + std::iter_swap(other, i); + flag = other; + swapped = true; + sign = -sign; + } else if (!(*other < *i)) + return 0; + --i; --other; + } + if (!swapped) + return sign; + ++flag; + if (flag == last) + return sign; + first = flag; + i = first; other = first; + ++other; + swapped = false; + while (i != last) { + if (*other < *i) { + std::iter_swap(i, other); + flag = other; + swapped = true; + sign = -sign; + } else if (!(*i < *other)) + return 0; + ++i; ++other; + } + if (!swapped) + return sign; + last = flag; + --last; + } while (first != last); + + return sign; +} + +//from GiNaC +MathStructure &MathStructure::determinant(MathStructure &mstruct, const EvaluationOptions &eo) const { + + if(!matrixIsSquare()) { + CALCULATOR->error(true, _("The determinant can only be calculated for square matrices."), NULL); + mstruct = m_undefined; + return mstruct; + } + + if(SIZE == 1) { + mstruct = CHILD(0)[0]; + } else if(isNumericMatrix()) { + + mstruct.set(1, 1, 0); + MathStructure mtmp(*this); + int sign = mtmp.gaussianElimination(eo, true); + for(size_t d = 0; d < SIZE; ++d) { + mstruct.number() *= mtmp[d][d].number(); + } + mstruct.number() *= sign; + + } else { + + typedef std::pair sizet_pair; + std::vector c_zeros; + for(size_t c = 0; c < CHILD(0).size(); ++c) { + size_t acc = 0; + for(size_t r = 0; r < SIZE; ++r) { + if(CHILD(r)[c].isZero()) ++acc; + } + c_zeros.push_back(sizet_pair(acc, c)); + } + + std::sort(c_zeros.begin(), c_zeros.end()); + std::vector pre_sort; + for(std::vector::const_iterator i = c_zeros.begin(); i != c_zeros.end(); ++i) { + pre_sort.push_back(i->second); + } + std::vector pre_sort_test(pre_sort); + + int sign = permutation_sign(pre_sort_test.begin(), pre_sort_test.end()); + + MathStructure result; + result.clearMatrix(); + result.resizeMatrix(SIZE, CHILD(0).size(), m_zero); + + size_t c = 0; + for(std::vector::const_iterator i = pre_sort.begin(); i != pre_sort.end(); ++i,++c) { + for(size_t r = 0; r < SIZE; ++r) result[r][c] = CHILD(r)[(*i)]; + } + mstruct.clear(); + + determinant_minor(result, mstruct, eo); + + if(sign != 1) { + mstruct.calculateMultiply(sign, eo); + } + + } + + mstruct.mergePrecision(*this); + return mstruct; + +} + +MathStructure &MathStructure::permanent(MathStructure &mstruct, const EvaluationOptions &eo) const { + if(!matrixIsSquare()) { + CALCULATOR->error(true, _("The permanent can only be calculated for square matrices."), NULL); + mstruct = m_undefined; + return mstruct; + } + if(b_approx) mstruct.setApproximate(); + mstruct.setPrecision(i_precision); + if(SIZE == 1) { + if(CHILD(0).size() >= 1) { + mstruct = CHILD(0)[0]; + } + } else if(SIZE == 2) { + mstruct = CHILD(0)[0]; + if(IS_REAL(mstruct) && IS_REAL(CHILD(1)[1])) { + mstruct.number() *= CHILD(1)[1].number(); + } else { + mstruct.calculateMultiply(CHILD(1)[1], eo); + } + if(IS_REAL(mstruct) && IS_REAL(CHILD(1)[0]) && IS_REAL(CHILD(0)[1])) { + mstruct.number() += CHILD(1)[0].number() * CHILD(0)[1].number(); + } else { + MathStructure mtmp = CHILD(1)[0]; + mtmp.calculateMultiply(CHILD(0)[1], eo); + mstruct.calculateAdd(mtmp, eo); + } + } else { + MathStructure mtrx; + mtrx.clearMatrix(); + mtrx.resizeMatrix(SIZE - 1, CHILD(0).size() - 1, m_undefined); + for(size_t index_c = 0; index_c < CHILD(0).size(); index_c++) { + for(size_t index_r2 = 1; index_r2 < SIZE; index_r2++) { + for(size_t index_c2 = 0; index_c2 < CHILD(index_r2).size(); index_c2++) { + if(index_c2 > index_c) { + mtrx.setElement(CHILD(index_r2)[index_c2], index_r2, index_c2); + } else if(index_c2 < index_c) { + mtrx.setElement(CHILD(index_r2)[index_c2], index_r2, index_c2 + 1); + } + } + } + MathStructure mdet; + mtrx.permanent(mdet, eo); + if(IS_REAL(mdet) && IS_REAL(CHILD(0)[index_c])) { + mdet.number() *= CHILD(0)[index_c].number(); + } else { + mdet.calculateMultiply(CHILD(0)[index_c], eo); + } + if(IS_REAL(mdet) && IS_REAL(mstruct)) { + mstruct.number() += mdet.number(); + } else { + mstruct.calculateAdd(mdet, eo); + } + } + } + return mstruct; +} +void MathStructure::setToIdentityMatrix(size_t n) { + clearMatrix(); + resizeMatrix(n, n, m_zero); + for(size_t i = 0; i < n; i++) { + CHILD(i)[i] = m_one; + } +} +MathStructure &MathStructure::getIdentityMatrix(MathStructure &mstruct) const { + mstruct.setToIdentityMatrix(columns()); + return mstruct; +} + +//modified algorithm from eigenmath +bool MathStructure::invertMatrix(const EvaluationOptions &eo) { + + if(!matrixIsSquare()) return false; + + if(isNumericMatrix()) { + + int d, i, j, n = SIZE; + + MathStructure idstruct; + Number mtmp; + idstruct.setToIdentityMatrix(n); + MathStructure mtrx(*this); + + for(d = 0; d < n; d++) { + if(mtrx[d][d].isZero()) { + for (i = d + 1; i < n; i++) { + if(!mtrx[i][d].isZero()) break; + } + + if(i == n) { + CALCULATOR->error(true, _("Inverse of singular matrix."), NULL); + return false; + } + + mtrx[i].ref(); + mtrx[d].ref(); + MathStructure *mptr = &mtrx[d]; + mtrx.setChild_nocopy(&mtrx[i], d + 1); + mtrx.setChild_nocopy(mptr, i + 1); + + idstruct[i].ref(); + idstruct[d].ref(); + mptr = &idstruct[d]; + idstruct.setChild_nocopy(&idstruct[i], d + 1); + idstruct.setChild_nocopy(mptr, i + 1); + + } + + mtmp = mtrx[d][d].number(); + mtmp.recip(); + + for(j = 0; j < n; j++) { + + if(j > d) { + mtrx[d][j].number() *= mtmp; + } + + idstruct[d][j].number() *= mtmp; + + } + + for(i = 0; i < n; i++) { + + if(i == d) continue; + + mtmp = mtrx[i][d].number(); + mtmp.negate(); + + for(j = 0; j < n; j++) { + + if(j > d) { + mtrx[i][j].number() += mtrx[d][j].number() * mtmp; + } + + idstruct[i][j].number() += idstruct[d][j].number() * mtmp; + + } + } + } + set_nocopy(idstruct); + MERGE_APPROX_AND_PREC(idstruct) + } else { + MathStructure *mstruct = new MathStructure(); + determinant(*mstruct, eo); + mstruct->calculateInverse(eo); + adjointMatrix(eo); + multiply_nocopy(mstruct, true); + calculateMultiplyLast(eo); + } + return true; +} + +bool MathStructure::adjointMatrix(const EvaluationOptions &eo) { + if(!matrixIsSquare()) return false; + if(SIZE == 1) {CHILD(0)[0].set(1, 1, 0); return true;} + MathStructure msave(*this); + for(size_t index_r = 0; index_r < SIZE; index_r++) { + for(size_t index_c = 0; index_c < CHILD(0).size(); index_c++) { + msave.cofactor(index_r + 1, index_c + 1, CHILD(index_r)[index_c], eo); + } + } + transposeMatrix(); + return true; +} +bool MathStructure::transposeMatrix() { + MathStructure msave(*this); + resizeMatrix(CHILD(0).size(), SIZE, m_undefined); + for(size_t index_r = 0; index_r < SIZE; index_r++) { + for(size_t index_c = 0; index_c < CHILD(0).size(); index_c++) { + CHILD(index_r)[index_c] = msave[index_c][index_r]; + } + } + return true; +} +MathStructure &MathStructure::cofactor(size_t r, size_t c, MathStructure &mstruct, const EvaluationOptions &eo) const { + if(r < 1) r = 1; + if(c < 1) c = 1; + if(SIZE == 1 || r > SIZE || c > CHILD(0).size()) { + mstruct = m_undefined; + return mstruct; + } + r--; c--; + mstruct.clearMatrix(); + mstruct.resizeMatrix(SIZE - 1, CHILD(0).size() - 1, m_undefined); + for(size_t index_r = 0; index_r < SIZE; index_r++) { + if(index_r != r) { + for(size_t index_c = 0; index_c < CHILD(0).size(); index_c++) { + if(index_c > c) { + if(index_r > r) { + mstruct[index_r - 1][index_c - 1] = CHILD(index_r)[index_c]; + } else { + mstruct[index_r][index_c - 1] = CHILD(index_r)[index_c]; + } + } else if(index_c < c) { + if(index_r > r) { + mstruct[index_r - 1][index_c] = CHILD(index_r)[index_c]; + } else { + mstruct[index_r][index_c] = CHILD(index_r)[index_c]; + } + } + } + } + } + MathStructure mstruct2; + mstruct = mstruct.determinant(mstruct2, eo); + if((r + c) % 2 == 1) { + mstruct.calculateNegate(eo); + } + return mstruct; +} + +MathStructure MathStructure::generateVector(MathStructure x_mstruct, const MathStructure &min, const MathStructure &max, int steps, MathStructure *x_vector, const EvaluationOptions &eo) const { + if(steps < 1) { + steps = 1; + } + MathStructure x_value(min); + MathStructure y_value; + MathStructure y_vector; + y_vector.clearVector(); + if(steps > 1000000) { + CALCULATOR->error(true, _("Too many data points"), NULL); + return y_vector; + } + MathStructure step(max); + step.calculateSubtract(min, eo); + step.calculateDivide(steps - 1, eo); + if(!step.isNumber() || step.number().isNegative()) { + CALCULATOR->error(true, _("The selected min and max do not result in a positive, finite number of data points"), NULL); + return y_vector; + } + y_vector.resizeVector(steps, m_zero); + if(x_vector) x_vector->resizeVector(steps, m_zero); + for(int i = 0; i < steps; i++) { + if(x_vector) { + (*x_vector)[i] = x_value; + } + y_value = *this; + y_value.replace(x_mstruct, x_value); + y_value.eval(eo); + y_vector[i] = y_value; + if(x_value.isNumber()) x_value.number().add(step.number()); + else x_value.calculateAdd(step, eo); + if(CALCULATOR->aborted()) { + y_vector.resizeVector(i, m_zero); + if(x_vector) x_vector->resizeVector(i, m_zero); + return y_vector; + } + } + return y_vector; +} +MathStructure MathStructure::generateVector(MathStructure x_mstruct, const MathStructure &min, const MathStructure &max, const MathStructure &step, MathStructure *x_vector, const EvaluationOptions &eo) const { + MathStructure x_value(min); + MathStructure y_value; + MathStructure y_vector; + y_vector.clearVector(); + if(min != max) { + MathStructure mtest(max); + mtest.calculateSubtract(min, eo); + if(!step.isZero()) mtest.calculateDivide(step, eo); + if(step.isZero() || !mtest.isNumber() || mtest.number().isNegative()) { + CALCULATOR->error(true, _("The selected min, max and step size do not result in a positive, finite number of data points"), NULL); + return y_vector; + } else if(mtest.number().isGreaterThan(1000000)) { + CALCULATOR->error(true, _("Too many data points"), NULL); + return y_vector; + } + mtest.number().round(); + unsigned int steps = mtest.number().uintValue(); + y_vector.resizeVector(steps, m_zero); + if(x_vector) x_vector->resizeVector(steps, m_zero); + } + ComparisonResult cr = max.compare(x_value); + size_t i = 0; + while(COMPARISON_IS_EQUAL_OR_LESS(cr)) { + if(x_vector) { + if(i >= x_vector->size()) x_vector->addChild(x_value); + else (*x_vector)[i] = x_value; + } + y_value = *this; + y_value.replace(x_mstruct, x_value); + y_value.eval(eo); + if(i >= y_vector.size()) y_vector.addChild(y_value); + else y_vector[i] = y_value; + if(x_value.isNumber()) x_value.number().add(step.number()); + else x_value.calculateAdd(step, eo); + cr = max.compare(x_value); + if(CALCULATOR->aborted()) { + y_vector.resizeVector(i, m_zero); + if(x_vector) x_vector->resizeVector(i, m_zero); + return y_vector; + } + i++; + } + y_vector.resizeVector(i, m_zero); + if(x_vector) x_vector->resizeVector(i, m_zero); + return y_vector; +} +MathStructure MathStructure::generateVector(MathStructure x_mstruct, const MathStructure &x_vector, const EvaluationOptions &eo) const { + MathStructure y_value; + MathStructure y_vector; + y_vector.clearVector(); + for(size_t i = 1; i <= x_vector.countChildren(); i++) { + if(CALCULATOR->aborted()) { + y_vector.clearVector(); + return y_vector; + } + y_value = *this; + y_value.replace(x_mstruct, x_vector.getChild(i)); + y_value.eval(eo); + y_vector.addChild(y_value); + } + return y_vector; +} + diff -Nru libqalculate-3.6.0/libqalculate/MathStructure-polynomial.cc libqalculate-3.7.0/libqalculate/MathStructure-polynomial.cc --- libqalculate-3.6.0/libqalculate/MathStructure-polynomial.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure-polynomial.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,1088 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "MathStructure.h" +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "Number.h" +#include "Function.h" +#include "Variable.h" +#include "Unit.h" +#include "Prefix.h" +#include +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::endl; + +bool sym_desc::operator<(const sym_desc &x) const { + if (max_deg == x.max_deg) return max_lcnops < x.max_lcnops; + else return max_deg.isLessThan(x.max_deg); +} + +int MathStructure::polynomialUnit(const MathStructure &xvar) const { + MathStructure coeff; + lcoefficient(xvar, coeff); + if(coeff.hasNegativeSign()) return -1; + return 1; +} + +void integer_content(const MathStructure &mpoly, Number &icontent) { + if(mpoly.isNumber()) { + icontent = mpoly.number(); + icontent.abs(); + } else if(mpoly.isAddition()) { + icontent.clear(); + Number l(1, 1); + for(size_t i = 0; i < mpoly.size(); i++) { + if(mpoly[i].isNumber()) { + if(!icontent.isOne()) { + Number c = icontent; + icontent = mpoly[i].number().numerator(); + icontent.gcd(c); + } + Number l2 = l; + l = mpoly[i].number().denominator(); + l.lcm(l2); + } else if(mpoly[i].isMultiplication()) { + if(!icontent.isOne()) { + Number c = icontent; + icontent = mpoly[i].overallCoefficient().numerator(); + icontent.gcd(c); + } + Number l2 = l; + l = mpoly[i].overallCoefficient().denominator(); + l.lcm(l2); + } else { + icontent.set(1, 1, 0); + } + } + icontent /= l; + } else if(mpoly.isMultiplication()) { + icontent = mpoly.overallCoefficient(); + icontent.abs(); + } else { + icontent.set(1, 1, 0); + } +} +void MathStructure::polynomialContent(const MathStructure &xvar, MathStructure &mcontent, const EvaluationOptions &eo) const { + if(isZero()) { + mcontent.clear(); + return; + } + if(isNumber()) { + mcontent = *this; + mcontent.number().setNegative(false); + return; + } + + MathStructure c; + integer_content(*this, c.number()); + MathStructure r(*this); + if(!c.isOne()) r.calculateDivide(c, eo); + MathStructure lcoeff; + r.lcoefficient(xvar, lcoeff); + if(lcoeff.isInteger()) { + mcontent = c; + return; + } + Number deg(r.degree(xvar)); + Number ldeg(r.ldegree(xvar)); + if(deg == ldeg) { + mcontent = lcoeff; + if(lcoeff.polynomialUnit(xvar) == -1) { + c.number().negate(); + } + mcontent.calculateMultiply(c, eo); + return; + } + mcontent.clear(); + MathStructure mtmp, coeff; + for(Number i(ldeg); i.isLessThanOrEqualTo(deg); i++) { + coefficient(xvar, i, coeff); + mtmp = mcontent; + if(!MathStructure::gcd(coeff, mtmp, mcontent, eo, NULL, NULL, false)) mcontent.set(1, 1, 0); + if(mcontent.isOne()) break; + } + + if(!c.isOne()) mcontent.calculateMultiply(c, eo); + +} + +void MathStructure::polynomialPrimpart(const MathStructure &xvar, MathStructure &mprim, const EvaluationOptions &eo) const { + if(isZero()) { + mprim.clear(); + return; + } + if(isNumber()) { + mprim.set(1, 1, 0); + return; + } + + MathStructure c; + polynomialContent(xvar, c, eo); + if(c.isZero()) { + mprim.clear(); + return; + } + bool b = (polynomialUnit(xvar) == -1); + if(c.isNumber()) { + if(b) c.number().negate(); + mprim = *this; + mprim.calculateDivide(c, eo); + return; + } + if(b) c.calculateNegate(eo); + MathStructure::polynomialQuotient(*this, c, xvar, mprim, eo, false); +} +void MathStructure::polynomialUnitContentPrimpart(const MathStructure &xvar, int &munit, MathStructure &mcontent, MathStructure &mprim, const EvaluationOptions &eo) const { + + if(isZero()) { + munit = 1; + mcontent.clear(); + mprim.clear(); + return; + } + + if(isNumber()) { + if(o_number.isNegative()) { + munit = -1; + mcontent = *this; + mcontent.number().abs(); + } else { + munit = 1; + mcontent = *this; + } + mprim.set(1, 1, 0); + return; + } + + munit = polynomialUnit(xvar); + + polynomialContent(xvar, mcontent, eo); + + if(mcontent.isZero()) { + mprim.clear(); + return; + } + if(mcontent.isNumber()) { + mprim = *this; + if(munit == -1) { + Number c(mcontent.number()); + c.negate(); + mprim.calculateDivide(c, eo); + } else if(!mcontent.isOne()) { + mprim.calculateDivide(mcontent, eo); + } + } else { + if(munit == -1) { + MathStructure c(mcontent); + c.calculateNegate(eo); + MathStructure::polynomialQuotient(*this, c, xvar, mprim, eo, false); + } else { + MathStructure::polynomialQuotient(*this, mcontent, xvar, mprim, eo, false); + } + } +} + + +void MathStructure::polynomialPrimpart(const MathStructure &xvar, const MathStructure &c, MathStructure &mprim, const EvaluationOptions &eo) const { + if(isZero() || c.isZero()) { + mprim.clear(); + return; + } + if(isNumber()) { + mprim.set(1, 1, 0); + return; + } + bool b = (polynomialUnit(xvar) == -1); + if(c.isNumber()) { + MathStructure cn(c); + if(b) cn.number().negate(); + mprim = *this; + mprim.calculateDivide(cn, eo); + return; + } + if(b) { + MathStructure cn(c); + cn.calculateNegate(eo); + MathStructure::polynomialQuotient(*this, cn, xvar, mprim, eo, false); + } else { + MathStructure::polynomialQuotient(*this, c, xvar, mprim, eo, false); + } +} + +const Number& MathStructure::degree(const MathStructure &xvar) const { + const Number *c = NULL; + const MathStructure *mcur = NULL; + for(size_t i = 0; ; i++) { + if(isAddition()) { + if(i >= SIZE) break; + mcur = &CHILD(i); + } else { + mcur = this; + } + if((*mcur) == xvar) { + if(!c) { + c = &nr_one; + } + } else if(mcur->isPower() && (*mcur)[0] == xvar && (*mcur)[1].isNumber()) { + if(!c || c->isLessThan((*mcur)[1].number())) { + c = &(*mcur)[1].number(); + } + } else if(mcur->isMultiplication()) { + for(size_t i2 = 0; i2 < mcur->size(); i2++) { + if((*mcur)[i2] == xvar) { + if(!c) { + c = &nr_one; + } + } else if((*mcur)[i2].isPower() && (*mcur)[i2][0] == xvar && (*mcur)[i2][1].isNumber()) { + if(!c || c->isLessThan((*mcur)[i2][1].number())) { + c = &(*mcur)[i2][1].number(); + } + } + } + } + if(!isAddition()) break; + } + if(!c) return nr_zero; + return *c; +} +const Number& MathStructure::ldegree(const MathStructure &xvar) const { + const Number *c = NULL; + const MathStructure *mcur = NULL; + for(size_t i = 0; ; i++) { + if(isAddition()) { + if(i >= SIZE) break; + mcur = &CHILD(i); + } else { + mcur = this; + } + if((*mcur) == xvar) { + c = &nr_one; + } else if(mcur->isPower() && (*mcur)[0] == xvar && (*mcur)[1].isNumber()) { + if(!c || c->isGreaterThan((*mcur)[1].number())) { + c = &(*mcur)[1].number(); + } + } else if(mcur->isMultiplication()) { + bool b = false; + for(size_t i2 = 0; i2 < mcur->size(); i2++) { + if((*mcur)[i2] == xvar) { + c = &nr_one; + b = true; + } else if((*mcur)[i2].isPower() && (*mcur)[i2][0] == xvar && (*mcur)[i2][1].isNumber()) { + if(!c || c->isGreaterThan((*mcur)[i2][1].number())) { + c = &(*mcur)[i2][1].number(); + } + b = true; + } + } + if(!b) return nr_zero; + } else { + return nr_zero; + } + if(!isAddition()) break; + } + if(!c) return nr_zero; + return *c; +} +void MathStructure::lcoefficient(const MathStructure &xvar, MathStructure &mcoeff) const { + coefficient(xvar, degree(xvar), mcoeff); +} +void MathStructure::tcoefficient(const MathStructure &xvar, MathStructure &mcoeff) const { + coefficient(xvar, ldegree(xvar), mcoeff); +} +void MathStructure::coefficient(const MathStructure &xvar, const Number &pownr, MathStructure &mcoeff) const { + const MathStructure *mcur = NULL; + mcoeff.clear(); + for(size_t i = 0; ; i++) { + if(isAddition()) { + if(i >= SIZE) break; + mcur = &CHILD(i); + } else { + mcur = this; + } + if((*mcur) == xvar) { + if(pownr.isOne()) { + if(mcoeff.isZero()) mcoeff.set(1, 1, 0); + else mcoeff.add(m_one, true); + } + } else if(mcur->isPower() && (*mcur)[0] == xvar && (*mcur)[1].isNumber()) { + if((*mcur)[1].number() == pownr) { + if(mcoeff.isZero()) mcoeff.set(1, 1, 0); + else mcoeff.add(m_one, true); + } + } else if(mcur->isMultiplication()) { + bool b = false; + for(size_t i2 = 0; i2 < mcur->size(); i2++) { + bool b2 = false; + if((*mcur)[i2] == xvar) { + b = true; + if(pownr.isOne()) b2 = true; + } else if((*mcur)[i2].isPower() && (*mcur)[i2][0] == xvar && (*mcur)[i2][1].isNumber()) { + b = true; + if((*mcur)[i2][1].number() == pownr) b2 = true; + } + if(b2) { + if(mcoeff.isZero()) { + if(mcur->size() == 1) { + mcoeff.set(1, 1, 0); + } else { + for(size_t i3 = 0; i3 < mcur->size(); i3++) { + if(i3 != i2) { + if(mcoeff.isZero()) mcoeff = (*mcur)[i3]; + else mcoeff.multiply((*mcur)[i3], true); + } + } + } + } else if(mcur->size() == 1) { + mcoeff.add(m_one, true); + } else { + mcoeff.add(m_zero, true); + for(size_t i3 = 0; i3 < mcur->size(); i3++) { + if(i3 != i2) { + if(mcoeff[mcoeff.size() - 1].isZero()) mcoeff[mcoeff.size() - 1] = (*mcur)[i3]; + else mcoeff[mcoeff.size() - 1].multiply((*mcur)[i3], true); + } + } + } + break; + } + } + if(!b && pownr.isZero()) { + if(mcoeff.isZero()) mcoeff = *mcur; + else mcoeff.add(*mcur, true); + } + } else if(pownr.isZero()) { + if(mcoeff.isZero()) mcoeff = *mcur; + else mcoeff.add(*mcur, true); + } + if(!isAddition()) break; + } + mcoeff.evalSort(); +} + +bool MathStructure::polynomialQuotient(const MathStructure &mnum, const MathStructure &mden, const MathStructure &xvar, MathStructure &mquotient, const EvaluationOptions &eo, bool check_args) { + mquotient.clear(); + if(CALCULATOR->aborted()) return false; + if(mden.isZero()) { + //division by zero + return false; + } + if(mnum.isZero()) { + mquotient.clear(); + return true; + } + if(mden.isNumber() && mnum.isNumber()) { + mquotient = mnum; + if(IS_REAL(mden) && IS_REAL(mnum)) { + mquotient.number() /= mden.number(); + } else { + mquotient.calculateDivide(mden, eo); + } + return true; + } + if(mnum == mden) { + mquotient.set(1, 1, 0); + return true; + } + if(check_args && (!mnum.isRationalPolynomial() || !mden.isRationalPolynomial())) { + return false; + } + + EvaluationOptions eo2 = eo; + eo2.keep_zero_units = false; + + Number numdeg = mnum.degree(xvar); + Number dendeg = mden.degree(xvar); + MathStructure dencoeff; + mden.coefficient(xvar, dendeg, dencoeff); + MathStructure mrem(mnum); + for(size_t i = 0; numdeg.isGreaterThanOrEqualTo(dendeg); i++) { + if(i > 1000 || CALCULATOR->aborted()) { + return false; + } + MathStructure numcoeff; + mrem.coefficient(xvar, numdeg, numcoeff); + numdeg -= dendeg; + if(numcoeff == dencoeff) { + if(numdeg.isZero()) { + numcoeff.set(1, 1, 0); + } else { + numcoeff = xvar; + if(!numdeg.isOne()) { + numcoeff.raise(numdeg); + } + } + } else { + if(dencoeff.isNumber()) { + if(numcoeff.isNumber()) { + numcoeff.number() /= dencoeff.number(); + } else { + numcoeff.calculateDivide(dencoeff, eo2); + } + } else { + MathStructure mcopy(numcoeff); + if(!MathStructure::polynomialDivide(mcopy, dencoeff, numcoeff, eo2, false)) { + return false; + } + } + if(!numdeg.isZero() && !numcoeff.isZero()) { + if(numcoeff.isOne()) { + numcoeff = xvar; + if(!numdeg.isOne()) { + numcoeff.raise(numdeg); + } + } else { + numcoeff.multiply(xvar, true); + if(!numdeg.isOne()) { + numcoeff[numcoeff.size() - 1].raise(numdeg); + } + numcoeff.calculateMultiplyLast(eo2); + } + } + } + if(mquotient.isZero()) mquotient = numcoeff; + else mquotient.calculateAdd(numcoeff, eo2); + numcoeff.calculateMultiply(mden, eo2); + mrem.calculateSubtract(numcoeff, eo2); + if(mrem.isZero()) break; + numdeg = mrem.degree(xvar); + } + return true; + +} +void add_symbol(const MathStructure &mpoly, sym_desc_vec &v) { + sym_desc_vec::const_iterator it = v.begin(), itend = v.end(); + while (it != itend) { + if(it->sym == mpoly) return; + ++it; + } + sym_desc d; + d.sym = mpoly; + v.push_back(d); +} + +void collect_symbols(const MathStructure &mpoly, sym_desc_vec &v) { + if(IS_A_SYMBOL(mpoly) || mpoly.isUnit()) { + add_symbol(mpoly, v); + } else if(mpoly.isAddition() || mpoly.isMultiplication()) { + for(size_t i = 0; i < mpoly.size(); i++) collect_symbols(mpoly[i], v); + } else if(mpoly.isPower()) { + collect_symbols(mpoly[0], v); + } +} + +void add_symbol(const MathStructure &mpoly, vector &v) { + vector::const_iterator it = v.begin(), itend = v.end(); + while (it != itend) { + if(*it == mpoly) return; + ++it; + } + v.push_back(mpoly); +} + +void collect_symbols(const MathStructure &mpoly, vector &v) { + if(IS_A_SYMBOL(mpoly)) { + add_symbol(mpoly, v); + } else if(mpoly.isAddition() || mpoly.isMultiplication()) { + for(size_t i = 0; i < mpoly.size(); i++) collect_symbols(mpoly[i], v); + } else if(mpoly.isPower()) { + collect_symbols(mpoly[0], v); + } +} + +void get_symbol_stats(const MathStructure &m1, const MathStructure &m2, sym_desc_vec &v) { + collect_symbols(m1, v); + collect_symbols(m2, v); + sym_desc_vec::iterator it = v.begin(), itend = v.end(); + while(it != itend) { + it->deg_a = m1.degree(it->sym); + it->deg_b = m2.degree(it->sym); + if(it->deg_a.isGreaterThan(it->deg_b)) { + it->max_deg = it->deg_a; + } else { + it->max_deg = it->deg_b; + } + it->ldeg_a = m1.ldegree(it->sym); + it->ldeg_b = m2.ldegree(it->sym); + MathStructure mcoeff; + m1.lcoefficient(it->sym, mcoeff); + it->max_lcnops = mcoeff.size(); + m2.lcoefficient(it->sym, mcoeff); + if(mcoeff.size() > it->max_lcnops) it->max_lcnops = mcoeff.size(); + ++it; + } + std::sort(v.begin(), v.end()); + +} + +bool get_first_symbol(const MathStructure &mpoly, MathStructure &xvar) { + if(IS_A_SYMBOL(mpoly) || mpoly.isUnit()) { + xvar = mpoly; + return true; + } else if(mpoly.isAddition() || mpoly.isMultiplication()) { + for(size_t i = 0; i < mpoly.size(); i++) { + if(get_first_symbol(mpoly[i], xvar)) return true; + } + } else if(mpoly.isPower()) { + return get_first_symbol(mpoly[0], xvar); + } + return false; +} + +bool MathStructure::polynomialDivide(const MathStructure &mnum, const MathStructure &mden, MathStructure &mquotient, const EvaluationOptions &eo, bool check_args) { + + mquotient.clear(); + + if(CALCULATOR->aborted()) return false; + + if(mden.isZero()) { + //division by zero + return false; + } + if(mnum.isZero()) { + mquotient.clear(); + return true; + } + if(mden.isNumber()) { + mquotient = mnum; + if(mnum.isNumber()) { + mquotient.number() /= mden.number(); + } else { + mquotient.calculateDivide(mden, eo); + } + return true; + } else if(mnum.isNumber()) { + return false; + } + + if(mnum == mden) { + mquotient.set(1, 1, 0); + return true; + } + + if(check_args && (!mnum.isRationalPolynomial() || !mden.isRationalPolynomial())) { + return false; + } + + + MathStructure xvar; + if(!get_first_symbol(mnum, xvar) && !get_first_symbol(mden, xvar)) return false; + + EvaluationOptions eo2 = eo; + eo2.keep_zero_units = false; + + Number numdeg = mnum.degree(xvar); + Number dendeg = mden.degree(xvar); + MathStructure dencoeff; + mden.coefficient(xvar, dendeg, dencoeff); + + MathStructure mrem(mnum); + + for(size_t i = 0; numdeg.isGreaterThanOrEqualTo(dendeg); i++) { + if(i > 1000 || CALCULATOR->aborted()) { + return false; + } + MathStructure numcoeff; + mrem.coefficient(xvar, numdeg, numcoeff); + numdeg -= dendeg; + if(numcoeff == dencoeff) { + if(numdeg.isZero()) { + numcoeff.set(1, 1, 0); + } else { + numcoeff = xvar; + if(!numdeg.isOne()) { + numcoeff.raise(numdeg); + } + } + } else { + if(dencoeff.isNumber()) { + if(numcoeff.isNumber()) { + numcoeff.number() /= dencoeff.number(); + } else { + numcoeff.calculateDivide(dencoeff, eo2); + } + } else { + MathStructure mcopy(numcoeff); + if((mcopy.equals(mnum, true, true) && dencoeff.equals(mden, true, true)) || !MathStructure::polynomialDivide(mcopy, dencoeff, numcoeff, eo2, false)) { + return false; + } + } + if(!numdeg.isZero() && !numcoeff.isZero()) { + if(numcoeff.isOne()) { + numcoeff = xvar; + if(!numdeg.isOne()) { + numcoeff.raise(numdeg); + } + } else { + numcoeff.multiply(xvar, true); + if(!numdeg.isOne()) { + numcoeff[numcoeff.size() - 1].raise(numdeg); + } + numcoeff.calculateMultiplyLast(eo2); + } + } + } + if(mquotient.isZero()) mquotient = numcoeff; + else mquotient.add(numcoeff, true); + if(numcoeff.isAddition() && mden.isAddition() && numcoeff.size() * mden.size() >= (eo.expand == -1 ? 50 : 500)) return false; + numcoeff.calculateMultiply(mden, eo2); + mrem.calculateSubtract(numcoeff, eo2); + if(mrem.isZero()) { + return true; + } + numdeg = mrem.degree(xvar); + } + return false; +} + +bool divide_in_z(const MathStructure &mnum, const MathStructure &mden, MathStructure &mquotient, const sym_desc_vec &sym_stats, size_t var_i, const EvaluationOptions &eo) { + + mquotient.clear(); + if(mden.isZero()) return false; + if(mnum.isZero()) return true; + if(mden.isOne()) { + mquotient = mnum; + return true; + } + if(mnum.isNumber()) { + if(!mden.isNumber()) { + return false; + } + mquotient = mnum; + return mquotient.number().divide(mden.number()) && mquotient.isInteger(); + } + if(mnum == mden) { + mquotient.set(1, 1, 0); + return true; + } + + if(mden.isPower()) { + MathStructure qbar(mnum); + for(Number ni(mden[1].number()); ni.isPositive(); ni--) { + if(!divide_in_z(qbar, mden[0], mquotient, sym_stats, var_i, eo)) return false; + qbar = mquotient; + } + return true; + } + + if(mden.isMultiplication()) { + MathStructure qbar(mnum); + for(size_t i = 0; i < mden.size(); i++) { + sym_desc_vec sym_stats2; + get_symbol_stats(mnum, mden[i], sym_stats2); + if(!divide_in_z(qbar, mden[i], mquotient, sym_stats2, 0, eo)) return false; + qbar = mquotient; + } + return true; + } + + if(var_i >= sym_stats.size()) return false; + const MathStructure &xvar = sym_stats[var_i].sym; + + Number numdeg = mnum.degree(xvar); + Number dendeg = mden.degree(xvar); + if(dendeg.isGreaterThan(numdeg)) return false; + MathStructure dencoeff; + MathStructure mrem(mnum); + mden.coefficient(xvar, dendeg, dencoeff); + + while(numdeg.isGreaterThanOrEqualTo(dendeg)) { + if(CALCULATOR->aborted()) return false; + MathStructure numcoeff; + mrem.coefficient(xvar, numdeg, numcoeff); + MathStructure term; + if(!divide_in_z(numcoeff, dencoeff, term, sym_stats, var_i + 1, eo)) break; + numdeg -= dendeg; + if(!numdeg.isZero() && !term.isZero()) { + if(term.isOne()) { + term = xvar; + if(!numdeg.isOne()) { + term.raise(numdeg); + } + } else { + term.multiply(xvar, true); + if(!numdeg.isOne()) { + term[term.size() - 1].raise(numdeg); + } + term.calculateMultiplyLast(eo); + } + } + if(mquotient.isZero()) { + mquotient = term; + } else { + mquotient.calculateAdd(term, eo); + } + if(term.isAddition() && mden.isAddition() && term.size() * mden.size() >= (eo.expand == -1 ? 50 : 500)) return false; + term.calculateMultiply(mden, eo); + mrem.calculateSubtract(term, eo); + if(mrem.isZero()) { + return true; + } + numdeg = mrem.degree(xvar); + + } + return false; +} + +bool prem(const MathStructure &mnum, const MathStructure &mden, const MathStructure &xvar, MathStructure &mrem, const EvaluationOptions &eo, bool check_args) { + + mrem.clear(); + if(mden.isZero()) { + //division by zero + return false; + } + if(mnum.isNumber()) { + if(!mden.isNumber()) { + mrem = mden; + } + return true; + } + if(check_args && (!mnum.isRationalPolynomial() || !mden.isRationalPolynomial())) { + return false; + } + + mrem = mnum; + MathStructure eb(mden); + Number rdeg = mrem.degree(xvar); + Number bdeg = eb.degree(xvar); + MathStructure blcoeff; + if(bdeg.isLessThanOrEqualTo(rdeg)) { + eb.coefficient(xvar, bdeg, blcoeff); + if(bdeg == 0) { + eb.clear(); + } else { + MathStructure mpow(xvar); + mpow.raise(bdeg); + mpow.calculateRaiseExponent(eo); + //POWER_CLEAN(mpow) + mpow.calculateMultiply(blcoeff, eo); + eb.calculateSubtract(mpow, eo); + } + } else { + blcoeff.set(1, 1, 0); + } + + Number delta(rdeg); + delta -= bdeg; + delta++; + int i = 0; + while(rdeg.isGreaterThanOrEqualTo(bdeg) && !mrem.isZero()) { + if(CALCULATOR->aborted() || delta < i / 10) {mrem.clear(); return false;} + MathStructure rlcoeff; + mrem.coefficient(xvar, rdeg, rlcoeff); + MathStructure term(xvar); + term.raise(rdeg); + term[1].number() -= bdeg; + term.calculateRaiseExponent(eo); + //POWER_CLEAN(term) + term.calculateMultiply(rlcoeff, eo); + term.calculateMultiply(eb, eo); + if(rdeg == 0) { + mrem = term; + mrem.calculateNegate(eo); + } else { + if(!rdeg.isZero()) { + rlcoeff.multiply(xvar, true); + if(!rdeg.isOne()) { + rlcoeff[rlcoeff.size() - 1].raise(rdeg); + rlcoeff[rlcoeff.size() - 1].calculateRaiseExponent(eo); + } + rlcoeff.calculateMultiplyLast(eo); + } + mrem.calculateSubtract(rlcoeff, eo); + if(mrem.isAddition() && blcoeff.isAddition() && mrem.size() * blcoeff.size() >= (eo.expand == -1 ? 50 : 500)) {mrem.clear(); return false;} + mrem.calculateMultiply(blcoeff, eo); + mrem.calculateSubtract(term, eo); + } + rdeg = mrem.degree(xvar); + i++; + } + delta -= i; + blcoeff.raise(delta); + blcoeff.calculateRaiseExponent(eo); + mrem.calculateMultiply(blcoeff, eo); + return true; +} + +Number MathStructure::maxCoefficient() { + if(isNumber()) { + Number nr(o_number); + nr.abs(); + return nr; + } else if(isAddition()) { + Number cur_max(overallCoefficient()); + cur_max.abs(); + for(size_t i = 0; i < SIZE; i++) { + Number a(CHILD(i).overallCoefficient()); + a.abs(); + if(a.isGreaterThan(cur_max)) cur_max = a; + } + return cur_max; + } else if(isMultiplication()) { + Number nr(overallCoefficient()); + nr.abs(); + return nr; + } else { + return nr_one; + } +} +void polynomial_smod(const MathStructure &mpoly, const Number &xi, MathStructure &msmod, const EvaluationOptions &eo, MathStructure *mparent, size_t index_smod) { + if(mpoly.isNumber()) { + msmod = mpoly; + msmod.number().smod(xi); + } else if(mpoly.isAddition()) { + msmod.clear(); + msmod.setType(STRUCT_ADDITION); + msmod.resizeVector(mpoly.size(), m_zero); + for(size_t i = 0; i < mpoly.size(); i++) { + polynomial_smod(mpoly[i], xi, msmod[i], eo, &msmod, i); + } + msmod.calculatesub(eo, eo, false, mparent, index_smod); + } else if(mpoly.isMultiplication()) { + msmod = mpoly; + if(msmod.size() > 0 && msmod[0].isNumber()) { + if(!msmod[0].number().smod(xi) || msmod[0].isZero()) { + msmod.clear(); + } + } + } else { + msmod = mpoly; + } +} +bool contains_zerointerval_multiplier(MathStructure &mstruct) { + if(mstruct.isAddition()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(contains_zerointerval_multiplier(mstruct[i])) return true; + } + } else if(mstruct.isMultiplication()) { + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isNumber() && !mstruct[i].number().isNonZero()) return true; + } + } else if(mstruct.isNumber() && !mstruct.number().isNonZero()) { + return true; + } + return false; +} + +bool polynomial_long_division(const MathStructure &mnum, const MathStructure &mden, const MathStructure &xvar_pre, MathStructure &mquotient, MathStructure &mrem, const EvaluationOptions &eo, bool check_args, bool for_newtonraphson) { + mquotient.clear(); + mrem.clear(); + + if(CALCULATOR->aborted()) return false; + if(mden.isZero()) { + //division by zero + mrem.set(mnum); + return false; + } + if(mnum.isZero()) { + mquotient.clear(); + return true; + } + if(mden.isNumber() && mnum.isNumber()) { + mquotient = mnum; + if(IS_REAL(mden) && IS_REAL(mnum)) { + mquotient.number() /= mden.number(); + } else { + mquotient.calculateDivide(mden, eo); + } + return true; + } else if(mnum.isNumber()) { + mrem.set(mnum); + return false; + } + if(mnum == mden) { + mquotient.set(1, 1, 0); + return true; + } + + mrem.set(mnum); + + if(check_args && (!mnum.isRationalPolynomial(true, true) || !mden.isRationalPolynomial(true, true))) { + return false; + } + + MathStructure xvar(xvar_pre); + if(xvar.isZero()) { + vector symsd, symsn; + collect_symbols(mnum, symsn); + if(symsn.empty()) return false; + collect_symbols(mden, symsd); + if(symsd.empty()) return false; + for(size_t i = 0; i < symsd.size();) { + bool b_found = false; + for(size_t i2 = 0; i2 < symsn.size(); i2++) { + if(symsn[i2] == symsd[i]) { + b_found = (mnum.degree(symsd[i]) >= mden.degree(symsd[i])); + break; + } + } + if(b_found) i++; + else symsd.erase(symsd.begin() + i); + } + for(size_t i = 0; i < symsd.size(); i++) { + MathStructure mquotient2, mrem2; + if(polynomial_long_division(mrem, mden, symsd[i], mquotient2, mrem2, eo, false, for_newtonraphson) && !mquotient2.isZero()) { + mrem = mrem2; + if(mquotient.isZero()) mquotient = mquotient2; + else mquotient.calculateAdd(mquotient2, eo); + } + if(CALCULATOR->aborted()) { + mrem = mnum; + mquotient.clear(); + return false; + } + } + return true; + } + + EvaluationOptions eo2 = eo; + eo2.keep_zero_units = false; + eo2.do_polynomial_division = false; + + Number numdeg = mnum.degree(xvar); + Number dendeg = mden.degree(xvar); + MathStructure dencoeff; + mden.coefficient(xvar, dendeg, dencoeff); + + for(size_t i = 0; numdeg.isGreaterThanOrEqualTo(dendeg); i++) { + if(i > 10000 || CALCULATOR->aborted()) { + mrem = mnum; + mquotient.clear(); + return false; + } + MathStructure numcoeff; + mrem.coefficient(xvar, numdeg, numcoeff); + numdeg -= dendeg; + if(numcoeff == dencoeff) { + if(numdeg.isZero()) { + numcoeff.set(1, 1, 0); + } else { + numcoeff = xvar; + if(!numdeg.isOne()) { + numcoeff.raise(numdeg); + } + } + } else { + if(dencoeff.isNumber()) { + if(numcoeff.isNumber()) { + numcoeff.number() /= dencoeff.number(); + } else { + numcoeff.calculateDivide(dencoeff, eo2); + } + } else { + if(for_newtonraphson) {mrem = mnum; mquotient.clear(); return false;} + MathStructure mcopy(numcoeff); + if(!MathStructure::polynomialDivide(mcopy, dencoeff, numcoeff, eo2, check_args)) { + if(CALCULATOR->aborted()) {mrem = mnum; mquotient.clear(); return false;} + break; + } + } + if(!numdeg.isZero() && !numcoeff.isZero()) { + if(numcoeff.isOne()) { + numcoeff = xvar; + if(!numdeg.isOne()) { + numcoeff.raise(numdeg); + } + } else { + numcoeff.multiply(xvar, true); + if(!numdeg.isOne()) { + numcoeff[numcoeff.size() - 1].raise(numdeg); + } + numcoeff.calculateMultiplyLast(eo2); + } + } + } + if(mquotient.isZero()) mquotient = numcoeff; + else mquotient.calculateAdd(numcoeff, eo2); + if(numcoeff.isAddition() && mden.isAddition() && numcoeff.size() * mden.size() >= (eo.expand == -1 ? 50 : 500)) {mrem = mnum; mquotient.clear(); return false;} + numcoeff.calculateMultiply(mden, eo2); + mrem.calculateSubtract(numcoeff, eo2); + if(contains_zerointerval_multiplier(mquotient)) {mrem = mnum; mquotient.clear(); return false;} + if(mrem.isZero() || (for_newtonraphson && mrem.isNumber())) break; + if(contains_zerointerval_multiplier(mrem)) {mrem = mnum; mquotient.clear(); return false;} + numdeg = mrem.degree(xvar); + } + return true; + +} +bool MathStructure::isRationalPolynomial(bool allow_non_rational_coefficient, bool allow_interval_coefficient) const { + switch(m_type) { + case STRUCT_NUMBER: { + if(allow_interval_coefficient) return o_number.isReal() && o_number.isNonZero(); + if(allow_non_rational_coefficient) return o_number.isReal() && !o_number.isInterval() && o_number.isNonZero(); + return o_number.isRational() && !o_number.isZero(); + } + case STRUCT_MULTIPLICATION: { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isAddition() || CHILD(i).isMultiplication() || !CHILD(i).isRationalPolynomial(allow_non_rational_coefficient, allow_interval_coefficient)) { + return false; + } + } + return true; + } + case STRUCT_ADDITION: { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isAddition() || !CHILD(i).isRationalPolynomial(allow_non_rational_coefficient, allow_interval_coefficient)) { + return false; + } + } + return true; + } + case STRUCT_POWER: { + return CHILD(1).isInteger() && CHILD(1).number().isNonNegative() && !CHILD(1).number().isOne() && CHILD(1).number() < 1000 && !CHILD(0).isNumber() && !CHILD(0).isMultiplication() && !CHILD(0).isAddition() && !CHILD(0).isPower() && CHILD(0).isRationalPolynomial(allow_non_rational_coefficient, allow_interval_coefficient); + } + case STRUCT_FUNCTION: { + if(o_function->id() == FUNCTION_ID_UNCERTAINTY || o_function->id() == FUNCTION_ID_INTERVAL || containsInterval() || containsInfinity()) return false; + } + case STRUCT_UNIT: {} + case STRUCT_VARIABLE: {} + case STRUCT_SYMBOLIC: { + return representsNonMatrix() && !representsUndefined(true, true); + } + default: {} + } + return false; +} +const Number &MathStructure::overallCoefficient() const { + switch(m_type) { + case STRUCT_NUMBER: { + return o_number; + } + case STRUCT_MULTIPLICATION: { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isNumber()) { + return CHILD(i).number(); + } + } + return nr_one; + } + case STRUCT_ADDITION: { + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isNumber()) { + return CHILD(i).number(); + } + } + return nr_zero; + } + case STRUCT_POWER: { + return nr_zero; + } + default: {} + } + return nr_zero; +} + diff -Nru libqalculate-3.6.0/libqalculate/MathStructure-print.cc libqalculate-3.7.0/libqalculate/MathStructure-print.cc --- libqalculate-3.6.0/libqalculate/MathStructure-print.cc 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure-print.cc 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,3375 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#include "support.h" + +#include "MathStructure.h" +#include "Calculator.h" +#include "BuiltinFunctions.h" +#include "Number.h" +#include "Function.h" +#include "Variable.h" +#include "Unit.h" +#include "Prefix.h" + +#include +#include + +#include "MathStructure-support.h" + +using std::string; +using std::cout; +using std::vector; +using std::ostream; +using std::endl; + +void printRecursive(const MathStructure &mstruct) { + std::cout << "RECURSIVE " << mstruct.print() << std::endl; + for(size_t i = 0; i < mstruct.size(); i++) { + std::cout << i << ": " << mstruct[i].print() << std::endl; + for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) { + std::cout << i << "-" << i2 << ": " << mstruct[i][i2].print() << std::endl; + for(size_t i3 = 0; i3 < mstruct[i][i2].size(); i3++) { + std::cout << i << "-" << i2 << "-" << i3 << ": " << mstruct[i][i2][i3].print() << std::endl; + for(size_t i4 = 0; i4 < mstruct[i][i2][i3].size(); i4++) { + std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << ": " << mstruct[i][i2][i3][i4].print() << std::endl; + for(size_t i5 = 0; i5 < mstruct[i][i2][i3][i4].size(); i5++) { + std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << ": " << mstruct[i][i2][i3][i4][i5].print() << std::endl; + for(size_t i6 = 0; i6 < mstruct[i][i2][i3][i4][i5].size(); i6++) { + std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << "-" << i6 << ": " << mstruct[i][i2][i3][i4][i5][i6].print() << std::endl; + for(size_t i7 = 0; i7 < mstruct[i][i2][i3][i4][i5][i6].size(); i7++) { + std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << "-" << i6 << "-" << i7 << ": " << mstruct[i][i2][i3][i4][i5][i6][i7].print() << std::endl; + for(size_t i8 = 0; i8 < mstruct[i][i2][i3][i4][i5][i6][i7].size(); i8++) { + std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << "-" << i6 << "-" << i7 << "-" << i8 << ": " << mstruct[i][i2][i3][i4][i5][i6][i7][i8].print() << std::endl; + for(size_t i9 = 0; i9 < mstruct[i][i2][i3][i4][i5][i6][i7][i8].size(); i9++) { + std::cout << i << "-" << i2 << "-" << i3 << "-" << i4 << "-" << i5 << "-" << i6 << "-" << i7 << "-" << i8 << "-" << i9 << ": " << mstruct[i][i2][i3][i4][i5][i6][i7][i8][i9].print() << std::endl; + } + } + } + } + } + } + } + } + } +} + +string format_and_print(const MathStructure &mstruct) { + MathStructure m_print(mstruct); + if(CALCULATOR) { + m_print.sort(CALCULATOR->messagePrintOptions()); + m_print.formatsub(CALCULATOR->messagePrintOptions(), NULL, 0, true, &m_print); + return m_print.print(CALCULATOR->messagePrintOptions()); + } else { + PrintOptions po; + po.interval_display = INTERVAL_DISPLAY_PLUSMINUS; + po.spell_out_logical_operators = true; + po.number_fraction_format = FRACTION_FRACTIONAL; + m_print.sort(po); + m_print.formatsub(po, NULL, 0, true, &m_print); + return m_print.print(po); + } +} + +int sortCompare(const MathStructure &mstruct1, const MathStructure &mstruct2, const MathStructure &parent, const PrintOptions &po); +int sortCompare(const MathStructure &mstruct1, const MathStructure &mstruct2, const MathStructure &parent, const PrintOptions &po) { + // returns -1 if mstruct1 should be placed before mstruct2, 1 if mstruct1 should be placed after mstruct2, and 0 if current order should be preserved + if(parent.isMultiplication()) { + if(!mstruct1.representsNonMatrix() && !mstruct2.representsNonMatrix()) { + // the order of matrices should be preserved + return 0; + } + } + if(parent.isAddition() && po.sort_options.minus_last) { + // -a+b=b-a + bool m1 = mstruct1.hasNegativeSign(), m2 = mstruct2.hasNegativeSign(); + if(m1 && !m2) { + return 1; + } else if(m2 && !m1) { + return -1; + } + } + if(parent.isAddition() && (mstruct1.isUnit() || (mstruct1.isMultiplication() && mstruct1.size() == 2 && mstruct1[1].isUnit())) && (mstruct2.isUnit() || (mstruct2.isMultiplication() && mstruct2.size() == 2 && mstruct2[1].isUnit()))) { + Unit *u1, *u2; + if(mstruct1.isUnit()) u1 = mstruct1.unit(); + else u1 = mstruct1[1].unit(); + if(mstruct2.isUnit()) u2 = mstruct2.unit(); + else u2 = mstruct2[1].unit(); + if(u1->isParentOf(u2)) return 1; + if(u2->isParentOf(u1)) return -1; + } + bool isdiv1 = false, isdiv2 = false; + if(!po.negative_exponents) { + // determine if mstruct1 and/or mstruct2 is division (a*b^-1) + if(mstruct1.isMultiplication()) { + for(size_t i = 0; i < mstruct1.size(); i++) { + if(mstruct1[i].isPower() && mstruct1[i][1].hasNegativeSign()) { + isdiv1 = true; + break; + } + } + } else if(mstruct1.isPower() && mstruct1[1].hasNegativeSign()) { + isdiv1 = true; + } + if(mstruct2.isMultiplication()) { + for(size_t i = 0; i < mstruct2.size(); i++) { + if(mstruct2[i].isPower() && mstruct2[i][1].hasNegativeSign()) { + isdiv2 = true; + break; + } + } + } else if(mstruct2.isPower() && mstruct2[1].hasNegativeSign()) { + isdiv2 = true; + } + } + if(parent.isAddition() && isdiv1 == isdiv2) { + // sort using single factors from left to right + if(mstruct1.isMultiplication() && mstruct1.size() > 0) { + size_t start = 0; + while(mstruct1[start].isNumber() && mstruct1.size() > start + 1) { + start++; + } + int i2; + if(mstruct2.isMultiplication()) { + if(mstruct2.size() < 1) return -1; + size_t start2 = 0; + while(mstruct2[start2].isNumber() && mstruct2.size() > start2 + 1) { + start2++; + } + for(size_t i = 0; i + start < mstruct1.size(); i++) { + if(i + start2 >= mstruct2.size()) return 1; + i2 = sortCompare(mstruct1[i + start], mstruct2[i + start2], parent, po); + if(i2 != 0) return i2; + } + if(mstruct1.size() - start == mstruct2.size() - start2) return 0; + if(parent.isMultiplication()) return -1; + else return 1; + } else { + i2 = sortCompare(mstruct1[start], mstruct2, parent, po); + if(i2 != 0) return i2; + } + } else if(mstruct2.isMultiplication() && mstruct2.size() > 0) { + size_t start = 0; + while(mstruct2[start].isNumber() && mstruct2.size() > start + 1) { + start++; + } + int i2; + if(mstruct1.isMultiplication()) { + return 1; + } else { + i2 = sortCompare(mstruct1, mstruct2[start], parent, po); + if(i2 != 0) return i2; + } + } + } + // always place constant of definite integral last + if(mstruct1.isVariable() && mstruct1.variable() == CALCULATOR->getVariableById(VARIABLE_ID_C)) return 1; + if(mstruct2.isVariable() && mstruct2.variable() == CALCULATOR->getVariableById(VARIABLE_ID_C)) return -1; + if(mstruct1.type() != mstruct2.type()) { + if(mstruct1.isVariable() && mstruct2.isSymbolic()) { + if(parent.isMultiplication()) { + // place constant (known) factors first (before symbols) + if(mstruct1.variable()->isKnown()) return -1; + } + // sort variables and symbols in alphabetical order + if(mstruct1.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name < mstruct2.symbol()) return -1; + else return 1; + } + if(mstruct2.isVariable() && mstruct1.isSymbolic()) { + if(parent.isMultiplication()) { + // place constant (known) factors first (before symbols) + if(mstruct2.variable()->isKnown()) return 1; + } + // sort variables and symbols in alphabetical order + if(mstruct1.symbol() < mstruct2.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name) return -1; + else return 1; + } + if(!parent.isMultiplication() || (!mstruct1.isNumber() && !mstruct2.isNumber())) { + // sort exponentiation with non-exponentiation (has exponent 1), excluding number factors + if(mstruct2.isPower()) { + int i = sortCompare(mstruct1, mstruct2[0], parent, po); + if(i == 0) { + return sortCompare(m_one, mstruct2[1], parent, po); + } + return i; + } + if(mstruct1.isPower()) { + int i = sortCompare(mstruct1[0], mstruct2, parent, po); + if(i == 0) { + return sortCompare(mstruct1[1], m_one, parent, po); + } + return i; + } + } + if(parent.isMultiplication()) { + // place unit factors last + if(mstruct2.isUnit()) return -1; + if(mstruct1.isUnit()) return 1; + if(mstruct1.isAddition() && !mstruct2.isAddition() && !mstruct1.containsUnknowns() && (mstruct2.isUnknown_exp() || (mstruct2.isMultiplication() && mstruct2.containsUnknowns()))) return -1; + if(mstruct2.isAddition() && !mstruct1.isAddition() && !mstruct2.containsUnknowns() && (mstruct1.isUnknown_exp() || (mstruct1.isMultiplication() && mstruct1.containsUnknowns()))) return 1; + } + // types listed in sort order (aborted is placed last) + if(mstruct2.isAborted()) return -1; + if(mstruct1.isAborted()) return 1; + if(mstruct2.isInverse()) return -1; + if(mstruct1.isInverse()) return 1; + if(mstruct2.isDivision()) return -1; + if(mstruct1.isDivision()) return 1; + if(mstruct2.isNegate()) return -1; + if(mstruct1.isNegate()) return 1; + if(mstruct2.isLogicalAnd()) return -1; + if(mstruct1.isLogicalAnd()) return 1; + if(mstruct2.isLogicalOr()) return -1; + if(mstruct1.isLogicalOr()) return 1; + if(mstruct2.isLogicalXor()) return -1; + if(mstruct1.isLogicalXor()) return 1; + if(mstruct2.isLogicalNot()) return -1; + if(mstruct1.isLogicalNot()) return 1; + if(mstruct2.isComparison()) return -1; + if(mstruct1.isComparison()) return 1; + if(mstruct2.isBitwiseOr()) return -1; + if(mstruct1.isBitwiseOr()) return 1; + if(mstruct2.isBitwiseXor()) return -1; + if(mstruct1.isBitwiseXor()) return 1; + if(mstruct2.isBitwiseAnd()) return -1; + if(mstruct1.isBitwiseAnd()) return 1; + if(mstruct2.isBitwiseNot()) return -1; + if(mstruct1.isBitwiseNot()) return 1; + if(mstruct2.isUndefined()) return -1; + if(mstruct1.isUndefined()) return 1; + if(mstruct2.isFunction()) return -1; + if(mstruct1.isFunction()) return 1; + if(mstruct2.isAddition()) return -1; + if(mstruct1.isAddition()) return 1; + if(!parent.isMultiplication()) { + // place division last + if(isdiv2 && mstruct2.isMultiplication()) return -1; + if(isdiv1 && mstruct1.isMultiplication()) return 1; + // place number after multiplication, exponentiation, unit, symbol, variable and date/time + if(mstruct2.isNumber()) return -1; + if(mstruct1.isNumber()) return 1; + } + if(mstruct2.isMultiplication()) return -1; + if(mstruct1.isMultiplication()) return 1; + if(mstruct2.isPower()) return -1; + if(mstruct1.isPower()) return 1; + if(mstruct2.isUnit()) return -1; + if(mstruct1.isUnit()) return 1; + if(mstruct2.isSymbolic()) return -1; + if(mstruct1.isSymbolic()) return 1; + if(mstruct2.isVariable()) return -1; + if(mstruct1.isVariable()) return 1; + if(mstruct2.isDateTime()) return -1; + if(mstruct1.isDateTime()) return 1; + if(parent.isMultiplication()) { + // only reached when type of 1 or 2 is a vector (place number factor after vector) + if(mstruct2.isNumber()) return -1; + if(mstruct1.isNumber()) return 1; + } + return -1; + } + switch(mstruct1.type()) { + case STRUCT_NUMBER: { + if(!mstruct1.number().hasImaginaryPart() && !mstruct2.number().hasImaginaryPart()) { + // real numbers + ComparisonResult cmp; + // if the numbers are factors with different signs, place smallest number first (the one with the negative sign) + if(parent.isMultiplication() && mstruct2.number().isNegative() != mstruct1.number().isNegative()) cmp = mstruct2.number().compare(mstruct1.number()); + // otherwise, place largest number first + else cmp = mstruct1.number().compare(mstruct2.number()); + if(cmp == COMPARISON_RESULT_LESS) return -1; + else if(cmp == COMPARISON_RESULT_GREATER) return 1; + return 0; + } else { + if(!mstruct1.number().hasRealPart()) { + if(mstruct2.number().hasRealPart()) { + // place number with real part before number without + return 1; + } else { + // compare imaginary parts + ComparisonResult cmp = mstruct1.number().compareImaginaryParts(mstruct2.number()); + if(cmp == COMPARISON_RESULT_LESS) return -1; + else if(cmp == COMPARISON_RESULT_GREATER) return 1; + return 0; + } + } else if(mstruct2.number().hasRealPart()) { + // compare real parts first + ComparisonResult cmp = mstruct1.number().compareRealParts(mstruct2.number()); + if(cmp == COMPARISON_RESULT_EQUAL) { + // if real parts are equal, compare imaginary parts + cmp = mstruct1.number().compareImaginaryParts(mstruct2.number()); + } + if(cmp == COMPARISON_RESULT_LESS) return -1; + else if(cmp == COMPARISON_RESULT_GREATER) return 1; + return 0; + } else { + return -1; + } + } + return -1; + } + case STRUCT_UNIT: { + if(mstruct1.unit() == mstruct2.unit()) return 0; + // sort units in alphabetical order + if(mstruct1.unit()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, mstruct1.isPlural(), po.use_reference_names).name < mstruct2.unit()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, mstruct2.isPlural(), po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name) return -1; + return 1; + } + case STRUCT_SYMBOLIC: { + // sort symbols in alphabetical order + if(mstruct1.symbol() < mstruct2.symbol()) return -1; + else if(mstruct1.symbol() == mstruct2.symbol()) return 0; + return 1; + } + case STRUCT_VARIABLE: { + if(mstruct1.variable() == mstruct2.variable()) return 0; + if(parent.isMultiplication()) { + // place constant (known) factors first (before unknown variables) + if(mstruct1.variable()->isKnown() && !mstruct2.variable()->isKnown()) return -1; + if(!mstruct1.variable()->isKnown() && mstruct2.variable()->isKnown()) return 1; + } + // sort variables in alphabetical order + if(mstruct1.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names).name < mstruct2.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name) return -1; + return 1; + } + case STRUCT_FUNCTION: { + if(mstruct1.function() == mstruct2.function()) { + for(size_t i = 0; i < mstruct2.size(); i++) { + if(i >= mstruct1.size()) { + // place function with less arguments first (if common arguments are equal) + return -1; + } + // sort same functions using arguments + int i2 = sortCompare(mstruct1[i], mstruct2[i], parent, po); + if(i2 != 0) return i2; + } + return 0; + } + // sort functions in alphabetical order + if(mstruct1.function()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names).name < mstruct2.function()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name) return -1; + return 1; + } + case STRUCT_POWER: { + if(!po.negative_exponents) { + // place exponentiation with negative exponent first (if not displayed as division) + bool b1 = mstruct1[1].hasNegativeSign(); + bool b2 = mstruct2[1].hasNegativeSign(); + if(b1 && !b2) return -1; + if(b2 && !b1) return 1; + } + // compare bases first + int i = sortCompare(mstruct1[0], mstruct2[0], parent, po); + if(i == 0) { + // compare exponents if bases are equal + return sortCompare(mstruct1[1], mstruct2[1], parent, po); + } + return i; + } + case STRUCT_MULTIPLICATION: { + if(isdiv1 != isdiv2) { + // place denominator last + if(isdiv1) return 1; + return -1; + } + } + case STRUCT_COMPARISON: { + if(mstruct1.comparisonType() != mstruct2.comparisonType()) { + // place equality before inequality, place greater before less + if(mstruct2.comparisonType() == COMPARISON_EQUALS || ((mstruct1.comparisonType() == COMPARISON_LESS || mstruct1.comparisonType() == COMPARISON_EQUALS_LESS) && (mstruct2.comparisonType() == COMPARISON_GREATER || mstruct2.comparisonType() == COMPARISON_EQUALS_GREATER))) { + return 1; + } + if(mstruct1.comparisonType() == COMPARISON_EQUALS || ((mstruct1.comparisonType() == COMPARISON_GREATER || mstruct1.comparisonType() == COMPARISON_EQUALS_GREATER) && (mstruct2.comparisonType() == COMPARISON_LESS || mstruct2.comparisonType() == COMPARISON_EQUALS_LESS))) { + return -1; + } + } + } + default: { + int ie; + for(size_t i = 0; i < mstruct1.size(); i++) { + // place MathStructure with less children first (if common children are equal) + if(i >= mstruct2.size()) return 1; + // sort by comparing children + ie = sortCompare(mstruct1[i], mstruct2[i], parent, po); + if(ie != 0) { + return ie; + } + } + } + } + return 0; +} + +void MathStructure::sort(const PrintOptions &po, bool recursive) { + // sort before output + if(recursive) { + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) break; + CHILD(i).sort(po); + } + } + if(m_type == STRUCT_COMPARISON) { + // place zero and numbers last in comparison + if((CHILD(0).isZero() && !CHILD(1).isZero()) || (CHILD(0).isNumber() && !CHILD(1).isNumber())) { + SWAP_CHILDREN(0, 1) + if(ct_comp == COMPARISON_LESS) ct_comp = COMPARISON_GREATER; + else if(ct_comp == COMPARISON_EQUALS_LESS) ct_comp = COMPARISON_EQUALS_GREATER; + else if(ct_comp == COMPARISON_GREATER) ct_comp = COMPARISON_LESS; + else if(ct_comp == COMPARISON_EQUALS_GREATER) ct_comp = COMPARISON_EQUALS_LESS; + } + return; + } + // only sort addition, multiplication, bitwise AND, OR, XOR, and logical AND, OR + if(m_type != STRUCT_ADDITION && m_type != STRUCT_MULTIPLICATION && m_type != STRUCT_BITWISE_AND && m_type != STRUCT_BITWISE_OR && m_type != STRUCT_BITWISE_XOR && m_type != STRUCT_LOGICAL_AND && m_type != STRUCT_LOGICAL_OR) return; + // do not sort addition containing date/time + if(m_type == STRUCT_ADDITION && containsType(STRUCT_DATETIME, false, true, false) > 0) return; + vector sorted; + bool b; + PrintOptions po2 = po; + po2.sort_options.minus_last = po.sort_options.minus_last && SIZE == 2; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return; + b = false; + for(size_t i2 = 0; i2 < sorted.size(); i2++) { + if(sortCompare(CHILD(i), *v_subs[sorted[i2]], *this, po2) < 0) { + sorted.insert(sorted.begin() + i2, v_order[i]); + b = true; + break; + } + } + if(!b) sorted.push_back(v_order[i]); + } + if(CALCULATOR->aborted()) return; + if(m_type == STRUCT_ADDITION && SIZE > 2 && po.sort_options.minus_last && v_subs[sorted[0]]->hasNegativeSign()) { + for(size_t i2 = 1; i2 < sorted.size(); i2++) { + if(CALCULATOR->aborted()) return; + if(!v_subs[sorted[i2]]->hasNegativeSign()) { + sorted.insert(sorted.begin(), sorted[i2]); + sorted.erase(sorted.begin() + (i2 + 1)); + break; + } + } + } + if(CALCULATOR->aborted()) return; + for(size_t i2 = 0; i2 < sorted.size(); i2++) { + v_order[i2] = sorted[i2]; + } +} + +void MathStructure::unformat(const EvaluationOptions &eo) { + if(m_type == STRUCT_FUNCTION && o_function->id() == FUNCTION_ID_STRIP_UNITS) { + EvaluationOptions eo2 = eo; + eo2.keep_prefixes = true; + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).unformat(eo2); + } + } else { + for(size_t i = 0; i < SIZE; i++) { + CHILD(i).unformat(eo); + } + } + switch(m_type) { + case STRUCT_INVERSE: { + APPEND(m_minus_one); + m_type = STRUCT_POWER; + break; + } + case STRUCT_NEGATE: { + PREPEND(m_minus_one); + m_type = STRUCT_MULTIPLICATION; + break; + } + case STRUCT_DIVISION: { + CHILD(1).raise(m_minus_one); + m_type = STRUCT_MULTIPLICATION; + break; + } + case STRUCT_UNIT: { + if(o_prefix && !eo.keep_prefixes) { + if(o_prefix == CALCULATOR->getDecimalNullPrefix() || o_prefix == CALCULATOR->getBinaryNullPrefix()) { + o_prefix = NULL; + } else { + Unit *u = o_unit; + Prefix *p = o_prefix; + set(p->value()); + multiply(u); + } + unformat(eo); + break; + } else if(o_unit->subtype() == SUBTYPE_COMPOSITE_UNIT) { + set(((CompositeUnit*) o_unit)->generateMathStructure(false, eo.keep_prefixes)); + unformat(eo); + break; + } + b_plural = false; + break; + } + default: {} + } +} + +void idm1(const MathStructure &mnum, bool &bfrac, bool &bint) { + switch(mnum.type()) { + case STRUCT_NUMBER: { + if((!bfrac || bint) && mnum.number().isRational()) { + if(!mnum.number().isInteger()) { + bint = false; + bfrac = true; + } + } else { + bint = false; + } + break; + } + case STRUCT_MULTIPLICATION: { + if((!bfrac || bint) && mnum.size() > 0 && mnum[0].isNumber() && mnum[0].number().isRational()) { + if(!mnum[0].number().isInteger()) { + bint = false; + bfrac = true; + } + + } else { + bint = false; + } + break; + } + case STRUCT_ADDITION: { + bool b_a = false; + for(size_t i = 0; i < mnum.size() && (!bfrac || bint); i++) { + if(mnum[i].isAddition()) b_a = true; + else idm1(mnum[i], bfrac, bint); + } + if(b_a) bint = false; + break; + } + default: { + bint = false; + } + } +} +void idm2(const MathStructure &mnum, bool &bfrac, bool &bint, Number &nr) { + switch(mnum.type()) { + case STRUCT_NUMBER: { + if(mnum.number().isRational()) { + if(mnum.number().isInteger()) { + if(bint) { + if(mnum.number().isOne()) { + bint = false; + } else if(nr.isOne()) { + nr = mnum.number(); + } else if(nr != mnum.number()) { + nr.gcd(mnum.number()); + if(nr.isOne()) bint = false; + } + } + } else { + if(nr.isOne()) { + nr = mnum.number().denominator(); + } else { + Number nden(mnum.number().denominator()); + if(nr != nden) { + Number ngcd(nden); + ngcd.gcd(nr); + nden /= ngcd; + nr *= nden; + } + } + } + } + break; + } + case STRUCT_MULTIPLICATION: { + if(mnum.size() > 0 && mnum[0].isNumber() && mnum[0].number().isRational()) { + if(mnum[0].number().isInteger()) { + if(bint) { + if(mnum[0].number().isOne()) { + bint = false; + } else if(nr.isOne()) { + nr = mnum[0].number(); + } else if(nr != mnum[0].number()) { + nr.gcd(mnum[0].number()); + if(nr.isOne()) bint = false; + } + } + } else { + if(nr.isOne()) { + nr = mnum[0].number().denominator(); + } else { + Number nden(mnum[0].number().denominator()); + if(nr != nden) { + Number ngcd(nden); + ngcd.gcd(nr); + nden /= ngcd; + nr *= nden; + } + } + } + } + break; + } + case STRUCT_ADDITION: { + for(size_t i = 0; i < mnum.size() && (bfrac || bint); i++) { + if(!mnum[i].isAddition()) idm2(mnum[i], bfrac, bint, nr); + } + break; + } + default: {} + } +} +int idm3(MathStructure &mnum, Number &nr, bool expand) { + switch(mnum.type()) { + case STRUCT_NUMBER: { + mnum.number() *= nr; + mnum.numberUpdated(); + break; + } + case STRUCT_MULTIPLICATION: { + if(mnum.size() > 0 && mnum[0].isNumber()) { + mnum[0].number() *= nr; + if(mnum[0].number().isOne() && mnum.size() != 1) { + mnum.delChild(1, true); + } + return -1; + } else if(expand) { + for(size_t i = 0; i < mnum.size(); i++) { + if(mnum[i].isAddition()) { + idm3(mnum[i], nr, true); + return -1; + } + } + } + mnum.insertChild(nr, 1); + return 1; + } + case STRUCT_ADDITION: { + if(expand) { + for(size_t i = 0; i < mnum.size(); i++) { + idm3(mnum[i], nr, true); + } + break; + } + } + default: { + mnum.transform(STRUCT_MULTIPLICATION); + mnum.insertChild(nr, 1); + return -1; + } + } + return 0; +} + +void idm1b(const MathStructure &mnum, bool &bint, bool &bint2) { + switch(mnum.type()) { + case STRUCT_NUMBER: { + if(mnum.number().isInteger() && !mnum.number().isOne()) { + bint = true; + if(mnum.number() > 9 || mnum.number() < -9) bint2 = true; + } else { + bint = false; + } + break; + } + case STRUCT_MULTIPLICATION: { + if(mnum.size() > 0 && mnum[0].isNumber()) { + idm1b(mnum[0], bint, bint2); + } else { + bint = false; + } + break; + } + case STRUCT_ADDITION: { + for(size_t i = 0; i < mnum.size(); i++) { + if(mnum[i].isAddition()) bint = false; + else idm1b(mnum[i], bint, bint2); + if(!bint) break; + } + break; + } + default: { + bint = false; + } + } +} +void idm2b(const MathStructure &mnum, Number &nr) { + switch(mnum.type()) { + case STRUCT_NUMBER: { + if(nr.isZero() || mnum.number() < nr) nr = mnum.number(); + break; + } + case STRUCT_MULTIPLICATION: { + idm2b(mnum[0], nr); + break; + } + case STRUCT_ADDITION: { + for(size_t i = 0; i < mnum.size(); i++) { + idm2b(mnum[i], nr); + } + break; + } + default: {} + } +} +void idm3b(MathStructure &mnum, Number &nr) { + switch(mnum.type()) { + case STRUCT_NUMBER: { + mnum.number() /= nr; + break; + } + case STRUCT_MULTIPLICATION: { + idm3b(mnum[0], nr); + break; + } + case STRUCT_ADDITION: { + for(size_t i = 0; i < mnum.size(); i++) { + idm3b(mnum[i], nr); + } + break; + } + default: {} + } +} + +bool displays_number_exact(Number nr, const PrintOptions &po, MathStructure *top_parent) { + if(po.base == BASE_ROMAN_NUMERALS || po.base == BASE_BIJECTIVE_26) return true; + InternalPrintStruct ips_n; + if(top_parent && top_parent->isApproximate()) ips_n.parent_approximate = true; + if(po.show_ending_zeroes && po.restrict_to_parent_precision && ips_n.parent_approximate && (nr > 9 || nr < -9)) return false; + if(top_parent && top_parent->precision() < 0) ips_n.parent_precision = top_parent->precision(); + bool approximately_displayed = false; + PrintOptions po2 = po; + po2.is_approximate = &approximately_displayed; + nr.print(po2, ips_n); + return !approximately_displayed; +} + +bool fix_approximate_multiplier(MathStructure &m, const PrintOptions &po, MathStructure *top_parent = NULL) { + if(!top_parent) top_parent = &m; + if(po.number_fraction_format == FRACTION_DECIMAL) { + PrintOptions po2 = po; + po2.number_fraction_format = FRACTION_FRACTIONAL; + po2.restrict_fraction_length = true; + return fix_approximate_multiplier(m, po2, top_parent); + } + bool b_ret = false; + if(m.isMultiplication() && m.size() >= 2 && m[0].isNumber() && m[0].number().isRational()) { + for(size_t i = 1; i < m.size(); i++) { + if(m[i].isAddition()) { + bool mul_exact = displays_number_exact(m[0].number(), po, top_parent); + bool b = false; + for(size_t i2 = 0; i2 < m[i].size() && !b; i2++) { + if(m[i][i2].isNumber() && (!mul_exact || !displays_number_exact(m[i][i2].number(), po, top_parent))) { + b = true; + } else if(m[i][i2].isMultiplication() && m[i][i2].size() >= 2 && m[i][i2][0].isNumber() && (!mul_exact || !displays_number_exact(m[i][i2][0].number(), po, top_parent))) { + b = true; + } + } + if(b) { + for(size_t i2 = 0; i2 < m[i].size(); i2++) { + if(m[i][i2].isNumber()) { + if(!m[i][i2].number().multiply(m[0].number())) { + m[i][i2].multiply(m[0]); + } + } else if(m[i][i2].isMultiplication()) { + if(m[i][i2].size() < 1 || !m[i][i2][0].isNumber() || !m[i][i2][0].number().multiply(m[0].number())) { + m[i][i2].insertChild(m[0], 1); + } + } else { + m[i][i2].multiply(m[0]); + m[i][i2].swapChildren(1, 2); + } + } + m.delChild(1, true); + b_ret = true; + break; + } + } + } + } + for(size_t i = 0; i < m.size(); i++) { + if(fix_approximate_multiplier(m[i], po, top_parent)) { + m.childUpdated(i + 1); + b_ret = true; + } + } + return b_ret; +} + +int idm3_test(bool &b_fail, const MathStructure &mnum, const Number &nr, bool expand, const PrintOptions &po, MathStructure *top_parent) { + switch(mnum.type()) { + case STRUCT_NUMBER: { + Number nr2(mnum.number()); + nr2 *= nr; + b_fail = !displays_number_exact(nr2, po, top_parent); + break; + } + case STRUCT_MULTIPLICATION: { + if(mnum.size() > 0 && mnum[0].isNumber()) { + Number nr2(mnum[0].number()); + nr2 *= nr; + b_fail = !nr2.isOne() && !displays_number_exact(nr2, po, top_parent); + return -1; + } else if(expand) { + for(size_t i = 0; i < mnum.size(); i++) { + if(mnum[i].isAddition()) { + idm3_test(b_fail, mnum[i], nr, true, po, top_parent); + return -1; + } + } + } + b_fail = !displays_number_exact(nr, po, top_parent); + return 1; + } + case STRUCT_ADDITION: { + if(expand) { + for(size_t i = 0; i < mnum.size(); i++) { + idm3_test(b_fail, mnum[i], nr, true, po, top_parent); + if(b_fail) break; + } + break; + } + } + default: { + b_fail = !displays_number_exact(nr, po, top_parent); + return -1; + } + } + return 0; +} + +bool is_unit_multiexp(const MathStructure &mstruct) { + if(mstruct.isUnit_exp()) return true; + if(mstruct.isMultiplication()) { + for(size_t i3 = 0; i3 < mstruct.size(); i3++) { + if(!mstruct[i3].isUnit_exp()) { + return false; + break; + } + } + return true; + } + if(mstruct.isPower() && mstruct[0].isMultiplication()) { + for(size_t i3 = 0; i3 < mstruct[0].size(); i3++) { + if(!mstruct[0][i3].isUnit_exp()) { + return false; + break; + } + } + return true; + } + return false; +} + +bool MathStructure::improve_division_multipliers(const PrintOptions &po, MathStructure *top_parent) { + if(!top_parent) top_parent = this; + switch(m_type) { + case STRUCT_MULTIPLICATION: { + size_t inum = 0, iden = 0; + bool bfrac = false, bint = true, bdiv = false, bnonunitdiv = false; + size_t index1 = 0, index2 = 0; + bool dofrac = !po.negative_exponents; + for(size_t i2 = 0; i2 < SIZE; i2++) { + if(CHILD(i2).isPower() && CHILD(i2)[1].isMinusOne()) { + if(!po.place_units_separately || !is_unit_multiexp(CHILD(i2)[0])) { + if(iden == 0) index1 = i2; + iden++; + bdiv = true; + if(!CHILD(i2)[0].isUnit()) bnonunitdiv = true; + if(CHILD(i2)[0].containsType(STRUCT_ADDITION)) { + dofrac = true; + } + } + } else if(!bdiv && !po.negative_exponents && CHILD(i2).isPower() && CHILD(i2)[1].hasNegativeSign()) { + if(!po.place_units_separately || !is_unit_multiexp(CHILD(i2)[0])) { + if(!bdiv) index1 = i2; + bdiv = true; + if(!CHILD(i2)[0].isUnit()) bnonunitdiv = true; + } + } else { + if(!po.place_units_separately || !is_unit_multiexp(CHILD(i2))) { + if(inum == 0) index2 = i2; + inum++; + } + } + } + if(!bdiv || !bnonunitdiv) break; + if(iden > 1 && !po.negative_exponents) { + size_t i2 = index1 + 1; + while(i2 < SIZE) { + if(CHILD(i2).isPower() && CHILD(i2)[1].isMinusOne()) { + CHILD(index1)[0].multiply(CHILD(i2)[0], true); + ERASE(i2); + if(index2 > i2) index2--; + } else { + i2++; + } + } + iden = 1; + } + if(bint) bint = inum > 0 && iden == 1; + if(inum > 0) idm1(CHILD(index2), bfrac, bint); + if(iden > 0) idm1(CHILD(index1)[0], bfrac, bint); + bool b = false; + if(!dofrac) bfrac = false; + if(bint || bfrac) { + Number nr(1, 1); + if(inum > 0) idm2(CHILD(index2), bfrac, bint, nr); + if(iden > 0) idm2(CHILD(index1)[0], bfrac, bint, nr); + if((bint || bfrac) && !nr.isOne()) { + if(bint) nr.recip(); + + bool b_fail = false; + if(inum > 1 && !CHILD(index2).isNumber()) { + int i = idm3_test(b_fail, *this, nr, !po.allow_factorization, po, top_parent); + if(i >= 0 && !b_fail && iden > 0) idm3_test(b_fail, CHILD(index1)[0], nr, !po.allow_factorization, po, top_parent); + } else { + if(inum != 0) idm3_test(b_fail, CHILD(index2), nr, !po.allow_factorization, po, top_parent); + if(!b_fail && iden > 0) idm3_test(b_fail, CHILD(index1)[0], nr, !po.allow_factorization, po, top_parent); + } + if(!b_fail) { + if(inum == 0) { + PREPEND(MathStructure(nr)); + index1 += 1; + } else if(inum > 1 && !CHILD(index2).isNumber()) { + int i = idm3(*this, nr, !po.allow_factorization); + if(i == 1) index1++; + else if(i < 0) iden = 0; + } else { + idm3(CHILD(index2), nr, !po.allow_factorization); + } + if(iden > 0) { + idm3(CHILD(index1)[0], nr, !po.allow_factorization); + } else { + MathStructure mstruct(nr); + mstruct.raise(m_minus_one); + insertChild(mstruct, index1); + } + b = true; + } + } + } + if(!b && po.show_ending_zeroes && po.restrict_to_parent_precision && top_parent->isApproximate() && po.base != BASE_ROMAN_NUMERALS && po.base != BASE_BIJECTIVE_26 && inum > 0 && iden > 0) { + bint = false; + bool bint2 = false; + idm1b(CHILD(index2), bint, bint2); + if(bint) idm1b(CHILD(index1)[0], bint, bint2); + if(bint && bint2) { + Number nr; + idm2b(CHILD(index2), nr); + idm2b(CHILD(index1)[0], nr); + idm3b(CHILD(index2), nr); + idm3b(CHILD(index1)[0], nr); + } + } + return b; + } + case STRUCT_DIVISION: { + bool bint = true, bfrac = false; + idm1(CHILD(0), bfrac, bint); + idm1(CHILD(1), bfrac, bint); + if(bint || bfrac) { + Number nr(1, 1); + idm2(CHILD(0), bfrac, bint, nr); + idm2(CHILD(1), bfrac, bint, nr); + if((bint || bfrac) && !nr.isOne()) { + if(bint) nr.recip(); + + bool b_fail = false; + idm3_test(b_fail, CHILD(0), nr, !po.allow_factorization, po, top_parent); + if(b_fail) return false; + idm3_test(b_fail, CHILD(1), nr, !po.allow_factorization, po, top_parent); + if(b_fail) return false; + + idm3(CHILD(0), nr, !po.allow_factorization); + idm3(CHILD(1), nr, !po.allow_factorization); + return true; + } + } + break; + } + case STRUCT_INVERSE: { + bool bint = false, bfrac = false; + idm1(CHILD(0), bfrac, bint); + if(bint || bfrac) { + Number nr(1, 1); + idm2(CHILD(0), bfrac, bint, nr); + if((bint || bfrac) && !nr.isOne()) { + bool b_fail = false; + idm3_test(b_fail, CHILD(0), nr, !po.allow_factorization, po, top_parent); + if(b_fail) return false; + + setToChild(1, true); + idm3(*this, nr, !po.allow_factorization); + transform_nocopy(STRUCT_DIVISION, new MathStructure(nr)); + SWAP_CHILDREN(0, 1); + return true; + } + } + break; + } + case STRUCT_POWER: { + if(CHILD(1).isMinusOne()) { + bool bint = false, bfrac = false; + idm1(CHILD(0), bfrac, bint); + if(bint || bfrac) { + Number nr(1, 1); + idm2(CHILD(0), bfrac, bint, nr); + if((bint || bfrac) && !nr.isOne()) { + bool b_fail = false; + idm3_test(b_fail, CHILD(0), nr, !po.allow_factorization, po, top_parent); + if(b_fail) return false; + + idm3(CHILD(0), nr, !po.allow_factorization); + transform(STRUCT_MULTIPLICATION); + PREPEND(MathStructure(nr)); + return true; + } + } + break; + } + } + default: { + bool b = false; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) break; + if(CHILD(i).improve_division_multipliers(po, top_parent)) b = true; + } + return b; + } + } + return false; +} + +bool use_prefix_with_unit(Unit *u, const PrintOptions &po) { + if(!po.prefix && !po.use_unit_prefixes) {return u->referenceName() == "g" || u->referenceName() == "a";} + if(po.prefix) return true; + if(u->isCurrency()) return po.use_prefixes_for_currencies; + if(po.use_prefixes_for_all_units) return true; + return u->useWithPrefixesByDefault(); +} +bool use_prefix_with_unit(const MathStructure &mstruct, const PrintOptions &po) { + if(mstruct.isUnit()) return use_prefix_with_unit(mstruct.unit(), po); + if(mstruct.isUnit_exp()) return use_prefix_with_unit(mstruct[0].unit(), po); + return false; +} + +bool has_prefix(const MathStructure &mstruct) { + if(mstruct.isUnit()) return mstruct.prefix() != NULL; + for(size_t i = 0; i < mstruct.size(); i++) { + if(has_prefix(mstruct[i])) return true; + } + return false; +} + +void MathStructure::setPrefixes(const PrintOptions &po, MathStructure *parent, size_t pindex) { + switch(m_type) { + case STRUCT_MULTIPLICATION: { + bool b = false; + size_t i = SIZE, im = 0; + bool b_im = false; + for(size_t i2 = 0; i2 < SIZE; i2++) { + if(CHILD(i2).isUnit_exp()) { + if(CHILD(i2).unit_exp_prefix()) { + b = false; + return; + } + if(!b) { + if(use_prefix_with_unit(CHILD(i2), po)) { + b = true; + if(i > i2) {i = i2; b_im = false;} + } else if(i < i2) { + i = i2; + b_im = false; + } + } + } else if(CHILD(i2).isPower() && CHILD(i2)[0].isMultiplication()) { + for(size_t i3 = 0; i3 < CHILD(i2)[0].size(); i3++) { + if(CHILD(i2)[0][i3].isUnit_exp()) { + if(CHILD(i2)[0][i3].unit_exp_prefix()) { + b = false; + return; + } + if(!b) { + if(use_prefix_with_unit(CHILD(i2)[0][i3], po)) { + b = true; + if(i > i2) { + i = i2; + im = i3; + b_im = true; + } + break; + } else if(i < i2 || (i == i2 && im < i3)) { + i = i2; + im = i3; + b_im = true; + } + } + } + } + } + } + if(b) { + Number exp(1, 1); + Number exp2(1, 1); + bool b2 = false; + MathStructure *munit = NULL, *munit2 = NULL; + if(b_im) munit = &CHILD(i)[0][im]; + else munit = &CHILD(i); + if(CHILD(i).isPower()) { + if(CHILD(i)[1].isNumber() && CHILD(i)[1].number().isInteger() && !CHILD(i)[1].number().isZero()) { + if(b_im && munit->isPower()) { + if((*munit)[1].isNumber() && (*munit)[1].number().isInteger() && !(*munit)[1].number().isZero()) { + exp = CHILD(i)[1].number(); + exp *= (*munit)[1].number(); + } else { + b = false; + } + } else { + exp = CHILD(i)[1].number(); + } + } else { + b = false; + } + } + if(po.use_denominator_prefix && !exp.isNegative()) { + for(size_t i2 = i + 1; i2 < SIZE; i2++) { + if(CALCULATOR->aborted()) break; + if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isNegative()) { + if(CHILD(i2)[0].isUnit() && use_prefix_with_unit(CHILD(i2)[0], po)) { + munit2 = &CHILD(i2)[0]; + if(munit2->prefix() || !CHILD(i2)[1].number().isInteger()) { + break; + } + if(!b) { + b = true; + exp = CHILD(i2)[1].number(); + munit = munit2; + } else { + b2 = true; + exp2 = CHILD(i2)[1].number(); + } + break; + } else if(CHILD(i2)[0].isMultiplication()) { + bool b_break = false; + for(size_t im2 = 0; im2 < CHILD(i2)[0].size(); im2++) { + if(CHILD(i2)[0][im2].isUnit_exp() && use_prefix_with_unit(CHILD(i2)[0][im2], po) && (CHILD(i2)[0][im2].isUnit() || (CHILD(i2)[0][im2][1].isNumber() && (CHILD(i2)[0][im2][1].number().isPositive() || (!b && CHILD(i2)[0][im2][1].number().isNegative())) && CHILD(i2)[0][im2][1].number().isInteger()))) { + Number exp_multi(1); + if(CHILD(i2)[0][im2].isUnit()) { + munit2 = &CHILD(i2)[0][im2]; + } else { + munit2 = &CHILD(i2)[0][im2][0]; + exp_multi = CHILD(i2)[0][im2][1].number(); + } + b_break = true; + if(munit2->prefix() || !CHILD(i2)[1].number().isInteger()) { + break; + } + if(!b) { + b = true; + exp = CHILD(i2)[1].number(); + exp *= exp_multi; + i = i2; + } else { + b2 = true; + exp2 = CHILD(i2)[1].number(); + exp2 *= exp_multi; + } + break; + } + } + if(b_break) break; + } + } + } + } else if(exp.isNegative() && b) { + bool had_unit = false; + for(size_t i2 = i + 1; i2 < SIZE; i2++) { + if(CALCULATOR->aborted()) break; + bool b3 = false; + if(CHILD(i2).isPower() && CHILD(i2)[1].isNumber() && CHILD(i2)[1].number().isPositive()) { + if(CHILD(i2)[0].isUnit()) { + if(!use_prefix_with_unit(CHILD(i2)[0], po)) { + had_unit = true; + } else { + munit2 = &CHILD(i2); + if(munit2->prefix() || !CHILD(i2)[1].number().isInteger()) { + break; + } + b3 = true; + exp2 = exp; + exp = CHILD(i2)[1].number(); + } + } else if(CHILD(i2)[0].isMultiplication()) { + bool b_break = false; + for(size_t im2 = 0; im2 < CHILD(i2)[0].size(); im2++) { + if(CHILD(i2)[0][im2].isUnit_exp() && (CHILD(i2)[0][im2].isUnit() || (CHILD(i2)[0][im2][1].isNumber() && CHILD(i2)[0][im2][1].number().isPositive() && CHILD(i2)[0][im2][1].number().isInteger()))) { + if(!use_prefix_with_unit(CHILD(i2)[0][im2], po)) { + had_unit = true; + } else { + Number exp_multi(1); + if(CHILD(i2)[0][im2].isUnit()) { + munit2 = &CHILD(i2)[0][im2]; + } else { + munit2 = &CHILD(i2)[0][im2][0]; + exp_multi = CHILD(i2)[0][im2][1].number(); + } + b_break = true; + if(munit2->prefix() || !CHILD(i2)[1].number().isInteger()) { + break; + } + exp2 = exp; + exp = CHILD(i2)[1].number(); + exp *= exp_multi; + b3 = true; + break; + } + } + } + if(b_break) break; + } + } else if(CHILD(i2).isUnit()) { + if(!use_prefix_with_unit(CHILD(i2), po)) { + had_unit = true; + } else { + if(CHILD(i2).prefix()) break; + exp2 = exp; + exp.set(1, 1, 0); + b3 = true; + munit2 = &CHILD(i2); + } + } + if(b3) { + if(po.use_denominator_prefix) { + b2 = true; + MathStructure *munit3 = munit; + munit = munit2; + munit2 = munit3; + } else { + munit = munit2; + } + had_unit = false; + break; + } + } + if(had_unit && !po.use_denominator_prefix) b = false; + } + Number exp10; + if(b) { + if(po.prefix) { + if(po.prefix != CALCULATOR->getDecimalNullPrefix() && po.prefix != CALCULATOR->getBinaryNullPrefix()) { + if(munit->isUnit()) munit->setPrefix(po.prefix); + else (*munit)[0].setPrefix(po.prefix); + if(CHILD(0).isNumber()) { + CHILD(0).number() /= po.prefix->value(exp); + } else { + PREPEND(po.prefix->value(exp)); + CHILD(0).number().recip(); + } + } + } else if(po.use_unit_prefixes && CHILD(0).isNumber() && exp.isInteger()) { + exp10 = CHILD(0).number(); + exp10.abs(); + exp10.intervalToMidValue(); + if(exp10.isLessThanOrEqualTo(Number(1, 1, 1000)) && exp10.isGreaterThanOrEqualTo(Number(1, 1, -1000))) { + bool use_binary_prefix = (CALCULATOR->usesBinaryPrefixes() > 1 || (CALCULATOR->usesBinaryPrefixes() == 1 && ((munit->isUnit() && munit->unit()->baseUnit()->referenceName() == "bit") || (munit->isPower() && (*munit)[0].unit()->baseUnit()->referenceName() == "bit")))); + exp10.log(use_binary_prefix ? 2 : 10); + exp10.intervalToMidValue(); + exp10.floor(); + if(b2 && exp10.isPositive() && (CALCULATOR->usesBinaryPrefixes() > 1 || (CALCULATOR->usesBinaryPrefixes() == 1 && ((munit2->isUnit() && munit2->unit()->baseUnit()->referenceName() == "bit") || (munit2->isPower() && (*munit2)[0].unit()->baseUnit()->referenceName() == "bit"))))) b2 = false; + if(b2 && use_binary_prefix && CALCULATOR->usesBinaryPrefixes() == 1 && exp10.isNegative()) { + exp10.clear(); + } else if(b2) { + Number tmp_exp(exp10); + tmp_exp.setNegative(false); + Number e1(use_binary_prefix ? 10 : 3, 1, 0); + e1 *= exp; + Number e2(use_binary_prefix ? 10 : 3, 1, 0); + e2 *= exp2; + e2.setNegative(false); + int i4 = 0; + while(true) { + tmp_exp -= e1; + if(!tmp_exp.isPositive()) { + break; + } + if(exp10.isNegative()) i4++; + tmp_exp -= e2; + if(tmp_exp.isNegative()) { + break; + } + if(!exp10.isNegative()) i4++; + } + e2.setNegative(exp10.isNegative()); + e2 *= i4; + exp10 -= e2; + } + Prefix *p = (use_binary_prefix > 0 ? (Prefix*) CALCULATOR->getOptimalBinaryPrefix(exp10, exp) : (Prefix*) CALCULATOR->getOptimalDecimalPrefix(exp10, exp, po.use_all_prefixes)); + if(p) { + Number test_exp(exp10); + if(use_binary_prefix) test_exp -= ((BinaryPrefix*) p)->exponent(exp); + else test_exp -= ((DecimalPrefix*) p)->exponent(exp); + if(test_exp.isInteger()) { + if((exp10.isPositive() && exp10.compare(test_exp) == COMPARISON_RESULT_LESS) || (exp10.isNegative() && exp10.compare(test_exp) == COMPARISON_RESULT_GREATER)) { + CHILD(0).number() /= p->value(exp); + if(munit->isUnit()) munit->setPrefix(p); + else (*munit)[0].setPrefix(p); + } + } + } + } + } else if(!po.use_unit_prefixes) { + Prefix *p = NULL; + if((munit->isUnit() && munit->unit()->referenceName() == "g") || (munit->isPower() && (*munit)[0].unit()->referenceName() == "g")) { + p = CALCULATOR->getExactDecimalPrefix(3); + } else if((munit->isUnit() && munit->unit()->referenceName() == "a") || (munit->isPower() && (*munit)[0].unit()->referenceName() == "a")) { + p = CALCULATOR->getExactDecimalPrefix(2); + } + if(p) { + if(munit->isUnit()) munit->setPrefix(p); + else (*munit)[0].setPrefix(p); + if(CHILD(0).isNumber()) { + CHILD(0).number() /= p->value(exp); + } else { + PREPEND(p->value(exp)); + CHILD(0).number().recip(); + } + } + } + if(b2 && CHILD(0).isNumber() && (po.prefix || po.use_unit_prefixes) && (po.prefix != CALCULATOR->getDecimalNullPrefix() && po.prefix != CALCULATOR->getBinaryNullPrefix())) { + exp10 = CHILD(0).number(); + exp10.abs(); + exp10.intervalToMidValue(); + if(exp10.isLessThanOrEqualTo(Number(1, 1, 1000)) && exp10.isGreaterThanOrEqualTo(Number(1, 1, -1000))) { + bool use_binary_prefix = (CALCULATOR->usesBinaryPrefixes() > 1 || (CALCULATOR->usesBinaryPrefixes() == 1 && ((munit2->isUnit() && munit2->unit()->baseUnit()->referenceName() == "bit") || (munit2->isPower() && (*munit2)[0].unit()->baseUnit()->referenceName() == "bit")))); + exp10.log(use_binary_prefix ? 2 : 10); + exp10.intervalToMidValue(); + exp10.floor(); + Prefix *p = (use_binary_prefix > 0 ? (Prefix*) CALCULATOR->getOptimalBinaryPrefix(exp10, exp2) : (Prefix*) CALCULATOR->getOptimalDecimalPrefix(exp10, exp2, po.use_all_prefixes)); + if(p) { + Number test_exp(exp10); + if(use_binary_prefix) test_exp -= ((BinaryPrefix*) p)->exponent(exp2); + else test_exp -= ((DecimalPrefix*) p)->exponent(exp2); + if(test_exp.isInteger()) { + if((exp10.isPositive() && exp10.compare(test_exp) == COMPARISON_RESULT_LESS) || (exp10.isNegative() && exp10.compare(test_exp) == COMPARISON_RESULT_GREATER)) { + CHILD(0).number() /= p->value(exp2); + if(munit2->isUnit()) munit2->setPrefix(p); + else (*munit2)[0].setPrefix(p); + } + } + } + } + } + } + return; + } + break; + } + case STRUCT_UNIT: { + if(!o_prefix && (po.prefix && po.prefix != CALCULATOR->getDecimalNullPrefix() && po.prefix != CALCULATOR->getBinaryNullPrefix())) { + transform(STRUCT_MULTIPLICATION, m_one); + SWAP_CHILDREN(0, 1); + setPrefixes(po, parent, pindex); + } + return; + } + case STRUCT_POWER: { + if(CHILD(0).isUnit()) { + if(CHILD(1).isNumber() && CHILD(1).number().isReal() && !CHILD(0).prefix() && !o_prefix && (po.prefix && po.prefix != CALCULATOR->getDecimalNullPrefix() && po.prefix != CALCULATOR->getBinaryNullPrefix())) { + transform(STRUCT_MULTIPLICATION, m_one); + SWAP_CHILDREN(0, 1); + setPrefixes(po, parent, pindex); + } + return; + } + break; + } + default: {} + } + if(po.prefix || !has_prefix(*this)) { + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) break; + CHILD(i).setPrefixes(po, this, i + 1); + } + } +} +bool split_unit_powers(MathStructure &mstruct); +bool split_unit_powers(MathStructure &mstruct) { + bool b = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(CALCULATOR->aborted()) break; + if(split_unit_powers(mstruct[i])) { + mstruct.childUpdated(i + 1); + b = true; + } + } + if(mstruct.isPower() && mstruct[0].isMultiplication()) { + bool b2 = mstruct[1].isNumber(); + for(size_t i = 0; i < mstruct[0].size(); i++) { + if(mstruct[0][i].isPower() && (!b2 || !mstruct[0][i][1].isNumber())) return b; + } + MathStructure mpower(mstruct[1]); + mstruct.setToChild(1); + for(size_t i = 0; i < mstruct.size(); i++) { + if(mstruct[i].isPower()) mstruct[i][1].number() *= mpower.number(); + else mstruct[i].raise(mpower); + } + mstruct.childrenUpdated(); + return true; + } + return b; +} +void MathStructure::postFormatUnits(const PrintOptions &po, MathStructure*, size_t) { + switch(m_type) { + case STRUCT_DIVISION: { + if(po.place_units_separately) { + vector nums; + bool b1 = false, b2 = false; + if(CHILD(0).isMultiplication()) { + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CHILD(0)[i].isUnit_exp()) { + nums.push_back(i); + } else { + b1 = true; + } + } + b1 = b1 && !nums.empty(); + } else if(CHILD(0).isUnit_exp()) { + b1 = true; + } + vector dens; + if(CHILD(1).isMultiplication()) { + for(size_t i = 0; i < CHILD(1).size(); i++) { + if(CHILD(1)[i].isUnit_exp()) { + dens.push_back(i); + } else { + b2 = true; + } + } + b2 = b2 && !dens.empty(); + } else if(CHILD(1).isUnit_exp()) { + if(CHILD(0).isUnit_exp()) { + b1 = false; + } else { + b2 = true; + } + } + if(b2 && !b1) b1 = true; + if(b1) { + MathStructure num = m_undefined; + if(CHILD(0).isUnit_exp()) { + num = CHILD(0); + CHILD(0).set(m_one); + } else if(nums.size() > 0) { + num = CHILD(0)[nums[0]]; + for(size_t i = 1; i < nums.size(); i++) { + num.multiply(CHILD(0)[nums[i]], i > 1); + } + for(size_t i = 0; i < nums.size(); i++) { + CHILD(0).delChild(nums[i] + 1 - i); + } + if(CHILD(0).size() == 1) { + CHILD(0).setToChild(1, true); + } + } + MathStructure den = m_undefined; + if(CHILD(1).isUnit_exp()) { + den = CHILD(1); + setToChild(1, true); + } else if(dens.size() > 0) { + den = CHILD(1)[dens[0]]; + for(size_t i = 1; i < dens.size(); i++) { + den.multiply(CHILD(1)[dens[i]], i > 1); + } + for(size_t i = 0; i < dens.size(); i++) { + CHILD(1).delChild(dens[i] + 1 - i); + } + if(CHILD(1).size() == 1) { + CHILD(1).setToChild(1, true); + } + } + if(num.isUndefined()) { + transform(STRUCT_DIVISION, den); + } else { + if(!den.isUndefined()) { + num.transform(STRUCT_DIVISION, den); + } + multiply(num, false); + } + if(CHILD(0).isDivision()) { + if(CHILD(0)[0].isMultiplication()) { + if(CHILD(0)[0].size() == 1) { + CHILD(0)[0].setToChild(1, true); + } else if(CHILD(0)[0].size() == 0) { + CHILD(0)[0] = 1; + } + } + if(CHILD(0)[1].isMultiplication()) { + if(CHILD(0)[1].size() == 1) { + CHILD(0)[1].setToChild(1, true); + } else if(CHILD(0)[1].size() == 0) { + CHILD(0).setToChild(1, true); + } + } else if(CHILD(0)[1].isOne()) { + CHILD(0).setToChild(1, true); + } + if(CHILD(0).isDivision() && CHILD(0)[1].isNumber() && CHILD(0)[0].isMultiplication() && CHILD(0)[0].size() > 1 && CHILD(0)[0][0].isNumber()) { + MathStructure *msave = new MathStructure; + if(CHILD(0)[0].size() == 2) { + msave->set(CHILD(0)[0][1]); + CHILD(0)[0].setToChild(1, true); + } else { + msave->set(CHILD(0)[0]); + CHILD(0)[0].setToChild(1, true); + msave->delChild(1); + } + if(isMultiplication()) { + insertChild_nocopy(msave, 2); + } else { + CHILD(0).multiply_nocopy(msave); + } + } + } + bool do_plural = po.short_multiplication; + CHILD(0).postFormatUnits(po, this, 1); + CHILD_UPDATED(0); + switch(CHILD(0).type()) { + case STRUCT_NUMBER: { + if(CHILD(0).isZero() || CHILD(0).number().isOne() || CHILD(0).number().isMinusOne() || CHILD(0).number().isFraction()) { + do_plural = false; + } + break; + } + case STRUCT_DIVISION: { + if(CHILD(0)[0].isNumber() && CHILD(0)[1].isNumber()) { + if(CHILD(0)[0].number().isLessThanOrEqualTo(CHILD(0)[1].number())) { + do_plural = false; + } + } + break; + } + case STRUCT_INVERSE: { + if(CHILD(0)[0].isNumber() && CHILD(0)[0].number().isGreaterThanOrEqualTo(1)) { + do_plural = false; + } + break; + } + default: {} + } + split_unit_powers(CHILD(1)); + switch(CHILD(1).type()) { + case STRUCT_UNIT: { + CHILD(1).setPlural(do_plural); + break; + } + case STRUCT_POWER: { + CHILD(1)[0].setPlural(do_plural); + break; + } + case STRUCT_MULTIPLICATION: { + if(po.limit_implicit_multiplication) CHILD(1)[0].setPlural(do_plural); + else CHILD(1)[CHILD(1).size() - 1].setPlural(do_plural); + break; + } + case STRUCT_DIVISION: { + switch(CHILD(1)[0].type()) { + case STRUCT_UNIT: { + CHILD(1)[0].setPlural(do_plural); + break; + } + case STRUCT_POWER: { + CHILD(1)[0][0].setPlural(do_plural); + break; + } + case STRUCT_MULTIPLICATION: { + if(po.limit_implicit_multiplication) CHILD(1)[0][0].setPlural(do_plural); + else CHILD(1)[0][CHILD(1)[0].size() - 1].setPlural(do_plural); + break; + } + default: {} + } + break; + } + default: {} + } + } + } else { + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) break; + CHILD(i).postFormatUnits(po, this, i + 1); + CHILD_UPDATED(i); + } + } + break; + } + case STRUCT_UNIT: { + b_plural = false; + break; + } + case STRUCT_MULTIPLICATION: { + if(SIZE > 1 && CHILD(1).isUnit_exp() && CHILD(0).isNumber()) { + bool do_plural = po.short_multiplication && !(CHILD(0).isZero() || CHILD(0).number().isOne() || CHILD(0).number().isMinusOne() || CHILD(0).number().isFraction()); + size_t i = 2; + for(; i < SIZE; i++) { + if(CALCULATOR->aborted()) break; + if(CHILD(i).isUnit()) { + CHILD(i).setPlural(false); + } else if(CHILD(i).isPower() && CHILD(i)[0].isUnit()) { + CHILD(i)[0].setPlural(false); + } else { + break; + } + } + if(do_plural) { + if(po.limit_implicit_multiplication) i = 1; + else i--; + if(CHILD(i).isUnit()) { + CHILD(i).setPlural(true); + } else { + CHILD(i)[0].setPlural(true); + } + } + } else if(SIZE > 0) { + int last_unit = -1; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) break; + if(CHILD(i).isUnit()) { + CHILD(i).setPlural(false); + if(!po.limit_implicit_multiplication || last_unit < 0) { + last_unit = i; + } + } else if(CHILD(i).isPower() && CHILD(i)[0].isUnit()) { + CHILD(i)[0].setPlural(false); + if(!po.limit_implicit_multiplication || last_unit < 0) { + last_unit = i; + } + } else if(last_unit >= 0) { + break; + } + } + if(po.short_multiplication && last_unit > 0) { + if(CHILD(last_unit).isUnit()) { + CHILD(last_unit).setPlural(true); + } else { + CHILD(last_unit)[0].setPlural(true); + } + } + } + break; + } + case STRUCT_POWER: { + if(CHILD(0).isUnit()) { + CHILD(0).setPlural(false); + break; + } + } + default: { + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) break; + CHILD(i).postFormatUnits(po, this, i + 1); + CHILD_UPDATED(i); + } + } + } +} +void MathStructure::prefixCurrencies(const PrintOptions &po) { + if(isMultiplication()) { + int index = -1; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) break; + if(CHILD(i).isUnit_exp()) { + if(CHILD(i).isUnit() && CHILD(i).unit()->isCurrency()) { + const ExpressionName *ename = &CHILD(i).unit()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, CHILD(i).isPlural(), po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); + bool do_prefix = false; + if(ename->reference) do_prefix = (hasNegativeSign() ? CALCULATOR->place_currency_code_before_negative : CALCULATOR->place_currency_code_before); + else if(ename->abbreviation) do_prefix = (hasNegativeSign() ? CALCULATOR->place_currency_sign_before_negative : CALCULATOR->place_currency_sign_before); + if(!do_prefix || index >= 0) { + index = -1; + break; + } + index = i; + } else { + index = -1; + break; + } + } + } + if(index >= 0) { + v_order.insert(v_order.begin(), v_order[index]); + v_order.erase(v_order.begin() + (index + 1)); + } + } else { + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) break; + CHILD(i).prefixCurrencies(po); + } + } +} +void remove_multi_one(MathStructure &mstruct) { + if(mstruct.isMultiplication() && mstruct.size() > 1) { + if(mstruct[0].isOne() && !mstruct[1].isUnit_exp() && (mstruct.size() != 2 || !mstruct[1].isFunction() || mstruct[1].function()->referenceName() != "cis" || mstruct[1].size() != 1)) { + if(mstruct.size() == 2) mstruct.setToChild(2, true); + else mstruct.delChild(1); + } + } + for(size_t i = 0; i < mstruct.size(); i++) { + if(CALCULATOR->aborted()) break; + remove_multi_one(mstruct[i]); + } +} +bool unnegate_multiplier(MathStructure &mstruct, const PrintOptions &po) { + if(mstruct.isMultiplication() && mstruct.size() >= 2 && mstruct[0].isNumber() && mstruct[0].number().isNegative()) { + for(size_t i = 1; i < mstruct.size(); i++) { + if(CALCULATOR->aborted()) break; + if(mstruct[i].isAddition() || (mstruct[i].isPower() && mstruct[i][0].isAddition() && mstruct[i][1].isMinusOne())) { + MathStructure *mden; + if(mstruct[i].isAddition()) mden = &mstruct[i]; + else mden = &mstruct[i][0]; + bool b_pos = false, b_neg = false; + for(size_t i2 = 0; i2 < mden->size(); i2++) { + if((*mden)[i2].hasNegativeSign()) { + b_neg = true; + } else { + b_pos = true; + } + if(b_neg && b_pos) break; + } + if(b_neg && b_pos) { + for(size_t i2 = 0; i2 < mden->size(); i2++) { + if((*mden)[i2].isNumber()) { + (*mden)[i2].number().negate(); + } else if((*mden)[i2].isMultiplication() && (*mden)[i2].size() > 0) { + if((*mden)[i2][0].isNumber()) { + if((*mden)[i2][0].number().isMinusOne() && (*mden)[i2].size() > 1) { + if((*mden)[i2].size() == 2) (*mden)[i2].setToChild(2, true); + else (*mden)[i2].delChild(1); + } else (*mden)[i2][0].number().negate(); + } else { + (*mden)[i2].insertChild(m_minus_one, 1); + } + } else { + (*mden)[i2].negate(); + } + } + mden->sort(po, false); + if(mstruct[0].number().isMinusOne()) { + if(mstruct.size() == 2) mstruct.setToChild(2, true); + else mstruct.delChild(1); + } else { + mstruct[0].number().negate(); + } + return true; + } + } + } + } + bool b = false; + for(size_t i = 0; i < mstruct.size(); i++) { + if(CALCULATOR->aborted()) break; + if(unnegate_multiplier(mstruct[i], po)) { + b = true; + } + } + if(b) { + mstruct.sort(po, false); + return true; + } + return false; +} +Unit *default_angle_unit(const EvaluationOptions &eo) { + switch(eo.parse_options.angle_unit) { + case ANGLE_UNIT_DEGREES: {return CALCULATOR->getDegUnit();} + case ANGLE_UNIT_GRADIANS: {return CALCULATOR->getGraUnit();} + case ANGLE_UNIT_RADIANS: {return CALCULATOR->getRadUnit();} + default: {} + } + return NULL; +} + +bool remove_angle_unit(MathStructure &m, Unit *u) { + // remove angle unit from trigonometric function arguments + bool b_ret = false; + for(size_t i = 0; i < m.size(); i++) { + if(remove_angle_unit(m[i], u)) b_ret = true; + if(m.isFunction() && m.function()->getArgumentDefinition(i + 1) && m.function()->getArgumentDefinition(i + 1)->type() == ARGUMENT_TYPE_ANGLE) { + if(m[i].isMultiplication()) { + // f(a)*u: f(a) + for(size_t i3 = 0; i3 < m[i].size(); i3++) { + // ignore units with prefix + if(m[i][i3].isUnit() && !m[i][i3].prefix() && m[i][i3].unit() == u) { + m[i].delChild(i3 + 1, true); + b_ret = true; + break; + } + } + } else if(m[i].isAddition()) { + bool b = true; + // f(a)*u+f(b)*u: f(a)+f(b) + // check if unit is present in all terms first + for(size_t i2 = 0; i2 < m[i].size(); i2++) { + bool b2 = false; + if(m[i][i2].isMultiplication()) { + for(size_t i3 = 0; i3 < m[i][i2].size(); i3++) { + if(m[i][i2][i3].isUnit() && !m[i][i2][i3].prefix() && m[i][i2][i3].unit() == u) { + b2 = true; + break; + } + } + } + if(!b2) { + b = false; + break; + } + } + if(b) { + b_ret = true; + for(size_t i2 = 0; i2 < m[i].size(); i2++) { + for(size_t i3 = 0; i3 < m[i][i2].size(); i3++) { + if(m[i][i2][i3].isUnit() && !m[i][i2][i3].prefix() && m[i][i2][i3].unit() == u) { + m[i][i2].delChild(i3 + 1, true); + break; + } + } + } + } + } + } + } + return b_ret; +} +bool MathStructure::removeDefaultAngleUnit(const EvaluationOptions &eo) { + // remove default angle unit from trigonometric function arguments + Unit *u = default_angle_unit(eo); + if(!u) return false; + return remove_angle_unit(*this, u); +} +void MathStructure::format(const PrintOptions &po) { + if(!po.preserve_format) { + if(po.place_units_separately) { + // a*u+b*u=(a+b)*u + factorizeUnits(); + } + sort(po); + // 5000 u = 5 ku + setPrefixes(po); + // -1/(a-b)=1/(b-a) + unnegate_multiplier(*this, po); + // a(bx+y)=abx+ay if a and/or b are rational number displayed approximately + fix_approximate_multiplier(*this, po); + if(po.improve_division_multipliers) { + // 0.5x/y=x/(2y) + if(improve_division_multipliers(po)) sort(po); + } + // 1*a=a + remove_multi_one(*this); + } + formatsub(po, NULL, 0, true, this); + if(!po.preserve_format) { + postFormatUnits(po); + if(po.sort_options.prefix_currencies) { + prefixCurrencies(po); + } + } +} + +void MathStructure::formatsub(const PrintOptions &po, MathStructure *parent, size_t pindex, bool recursive, MathStructure *top_parent) { + + if(recursive) { + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) break; + if(i == 1 && m_type == STRUCT_POWER && po.number_fraction_format < FRACTION_FRACTIONAL && CHILD(1).isNumber() && CHILD(1).number().isRational() && !CHILD(1).number().isInteger() && CHILD(1).number().numeratorIsLessThan(10) && CHILD(1).number().numeratorIsGreaterThan(-10) && CHILD(1).number().denominatorIsLessThan(10)) { + // always display rational number exponents with small numerator and denominator as fraction (e.g. 5^(2/3) instead of 5^0.666...) + PrintOptions po2 = po; + po2.number_fraction_format = FRACTION_FRACTIONAL; + CHILD(i).formatsub(po2, this, i + 1, false, top_parent); + } else { + CHILD(i).formatsub(po, this, i + 1, true, top_parent); + } + CHILD_UPDATED(i); + } + } + switch(m_type) { + case STRUCT_ADDITION: { + break; + } + case STRUCT_NEGATE: { + break; + } + case STRUCT_DIVISION: { + if(po.preserve_format) break; + if(CHILD(0).isAddition() && CHILD(0).size() > 0 && CHILD(0)[0].isNegate()) { + // (-a-b)/(c-d)=-(a+b)/(c-d); (-a+b)/(-c-d)=(a-b)/(c+d) + int imin = 1; + for(size_t i = 1; i < CHILD(0).size(); i++) { + if(CHILD(0)[i].isNegate()) { + imin++; + } else { + imin--; + } + } + bool b = CHILD(1).isAddition() && CHILD(1).size() > 0 && CHILD(1)[0].isNegate(); + if(b) { + imin++; + for(size_t i = 1; i < CHILD(1).size(); i++) { + if(CHILD(1)[i].isNegate()) { + imin++; + } else { + imin--; + } + } + } + if(imin > 0 || (imin == 0 && parent && parent->isNegate())) { + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CHILD(0)[i].isNegate()) { + CHILD(0)[i].setToChild(1, true); + } else { + CHILD(0)[i].transform(STRUCT_NEGATE); + } + } + if(b) { + for(size_t i = 0; i < CHILD(1).size(); i++) { + if(CHILD(1)[i].isNegate()) { + CHILD(1)[i].setToChild(1, true); + } else { + CHILD(1)[i].transform(STRUCT_NEGATE); + } + } + } else { + transform(STRUCT_NEGATE); + } + break; + } + } else if(CHILD(1).isAddition() && CHILD(1).size() > 0 && CHILD(1)[0].isNegate()) { + // (a+b)/(-c-d)=-(a+b)/(c+d) + int imin = 1; + for(size_t i = 1; i < CHILD(1).size(); i++) { + if(CHILD(1)[i].isNegate()) { + imin++; + } else { + imin--; + } + } + if(imin > 0 || (imin == 0 && parent && parent->isNegate())) { + for(size_t i = 0; i < CHILD(1).size(); i++) { + if(CHILD(1)[i].isNegate()) { + CHILD(1)[i].setToChild(1, true); + } else { + CHILD(1)[i].transform(STRUCT_NEGATE); + } + } + transform(STRUCT_NEGATE); + } + } + break; + } + case STRUCT_INVERSE: { + if(po.preserve_format) break; + if((!parent || !parent->isMultiplication()) && CHILD(0).isAddition() && CHILD(0).size() > 0 && CHILD(0)[0].isNegate()) { + // (-a-b+c)^-1=-(a+b-c)^-1 + int imin = 1; + for(size_t i = 1; i < CHILD(0).size(); i++) { + if(CHILD(0)[i].isNegate()) { + imin++; + } else { + imin--; + } + } + if(imin > 0 || (imin == 0 && parent && parent->isNegate())) { + for(size_t i = 0; i < CHILD(0).size(); i++) { + if(CHILD(0)[i].isNegate()) { + CHILD(0)[i].setToChild(1, true); + } else { + CHILD(0)[i].transform(STRUCT_NEGATE); + } + } + transform(STRUCT_NEGATE); + } + } + break; + } + case STRUCT_MULTIPLICATION: { + if(po.preserve_format) break; + if(CHILD(0).isNegate()) { + if(CHILD(0)[0].isOne()) { + // (-1)x=-(x) + ERASE(0); + if(SIZE == 1) { + setToChild(1, true); + } + } else { + // -(a)x=-(ax) + CHILD(0).setToChild(1, true); + } + transform(STRUCT_NEGATE); + CHILD(0).formatsub(po, this, 1, false, top_parent); + break; + } + + bool b = false; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) break; + if(CHILD(i).isInverse()) { + if(!po.negative_exponents || !CHILD(i)[0].isNumber()) { + b = true; + break; + } + } else if(CHILD(i).isDivision()) { + if(!CHILD(i)[0].isNumber() || !CHILD(i)[1].isNumber() || (!po.negative_exponents && CHILD(i)[0].number().isOne())) { + b = true; + break; + } + } + } + + if(b) { + MathStructure *den = new MathStructure(); + MathStructure *num = new MathStructure(); + num->setUndefined(); + short ds = 0, ns = 0; + MathStructure *mnum = NULL, *mden = NULL; + for(size_t i = 0; i < SIZE; i++) { + if(CHILD(i).isInverse()) { + mden = &CHILD(i)[0]; + } else if(CHILD(i).isDivision()) { + mnum = &CHILD(i)[0]; + mden = &CHILD(i)[1]; + } else { + mnum = &CHILD(i); + } + if(mnum && !mnum->isOne()) { + if(ns > 0) { + if(mnum->isMultiplication() && num->isNumber()) { + for(size_t i2 = 0; i2 < mnum->size(); i2++) { + num->multiply((*mnum)[i2], true); + } + } else { + num->multiply(*mnum, ns > 1); + } + } else { + num->set(*mnum); + } + ns++; + mnum = NULL; + } + if(mden) { + if(ds > 0) { + if(mden->isMultiplication() && den->isNumber()) { + for(size_t i2 = 0; i2 < mden->size(); i2++) { + den->multiply((*mden)[i2], true); + } + } else { + den->multiply(*mden, ds > 1); + } + } else { + den->set(*mden); + } + ds++; + mden = NULL; + } + } + clear(true); + m_type = STRUCT_DIVISION; + if(num->isUndefined()) num->set(m_one); + APPEND_POINTER(num); + APPEND_POINTER(den); + num->formatsub(po, this, 1, false, top_parent); + den->formatsub(po, this, 2, false, top_parent); + formatsub(po, parent, pindex, false, top_parent); + break; + } + + size_t index = 0; + if(CHILD(0).isOne()) { + index = 1; + } + switch(CHILD(index).type()) { + case STRUCT_POWER: { + if(!CHILD(index)[0].isUnit_exp()) { + break; + } + } + case STRUCT_UNIT: { + if(index == 0) { + if(!parent || (!parent->isPower() && !parent->isMultiplication() && !parent->isInverse() && (!parent->isDivision() || pindex != 2))) { + PREPEND(m_one); + break; + } + } + break; + } + case STRUCT_FUNCTION: { + if(index == 1 && SIZE == 2 && CHILD(index).function()->referenceName() == "cis" && CHILD(index).size() == 1) break; + } + default: { + if(index == 1) { + ERASE(0); + if(SIZE == 1) { + setToChild(1, true); + } + break; + } + } + } + break; + } + case STRUCT_UNIT: { + if(po.preserve_format) break; + if(!parent || (!parent->isPower() && !parent->isMultiplication() && !parent->isInverse() && !(parent->isDivision() && pindex == 2))) { + // u = 1 u + multiply(m_one); + SWAP_CHILDREN(0, 1); + } + break; + } + case STRUCT_POWER: { + if(po.preserve_format) break; + if(!po.negative_exponents && CHILD(1).isNegate() && (!CHILD(0).isVector() || !CHILD(1).isMinusOne())) { + if(CHILD(1)[0].isOne()) { + // f(a)^-1=1/f(a) + m_type = STRUCT_INVERSE; + ERASE(1); + } else { + // f(a)^-b=1/f(a)^b + CHILD(1).setToChild(1, true); + transform(STRUCT_INVERSE); + } + formatsub(po, parent, pindex, true, top_parent); + break; + } else if(po.halfexp_to_sqrt && ((CHILD(1).isDivision() && CHILD(1)[0].isNumber() && CHILD(1)[0].number().isInteger() && CHILD(1)[1].isNumber() && CHILD(1)[1].number().isTwo() && ((!po.negative_exponents && (CHILD(0).countChildren() == 0 || CHILD(0).isFunction())) || CHILD(1)[0].isOne())) || (CHILD(1).isNumber() && CHILD(1).number().denominatorIsTwo() && ((!po.negative_exponents && (CHILD(0).countChildren() == 0 || CHILD(0).isFunction())) || CHILD(1).number().numeratorIsOne())) || (CHILD(1).isInverse() && CHILD(1)[0].isNumber() && CHILD(1)[0].number() == 2))) { + if(CHILD(1).isInverse() || (CHILD(1).isDivision() && CHILD(1)[0].number().isOne()) || (CHILD(1).isNumber() && CHILD(1).number().numeratorIsOne())) { + // f(a)^(1/2)=sqrt(f(a)) + m_type = STRUCT_FUNCTION; + ERASE(1) + setFunctionId(FUNCTION_ID_SQRT); + } else { + // f(a)^(b+1/2)=f(b)^(sqrt(f(a)) + if(CHILD(1).isNumber()) { + // f(a)^b + CHILD(1).number() -= nr_half; + } else { + // f(a)^(b/2) + Number nr = CHILD(1)[0].number(); + nr /= CHILD(1)[1].number(); + nr.floor(); + CHILD(1).set(nr); + } + if(CHILD(1).number().isOne()) { + setToChild(1, true); + if(parent && parent->isMultiplication()) { + parent->insertChild_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SQRT), this, NULL), pindex + 1); + } else { + multiply_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SQRT), this, NULL)); + } + } else { + if(parent && parent->isMultiplication()) { + parent->insertChild_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SQRT), &CHILD(0), NULL), pindex + 1); + } else { + multiply_nocopy(new MathStructure(CALCULATOR->getFunctionById(FUNCTION_ID_SQRT), &CHILD(0), NULL)); + } + } + } + formatsub(po, parent, pindex, false, top_parent); + break; + } else if(po.exp_to_root && CHILD(0).representsNonNegative(true) && ((CHILD(1).isDivision() && CHILD(1)[0].isNumber() && CHILD(1)[0].number().isInteger() && CHILD(1)[1].isNumber() && CHILD(1)[1].number().isGreaterThan(1) && CHILD(1)[1].number().isLessThan(10) && ((!po.negative_exponents && (CHILD(0).countChildren() == 0 || CHILD(0).isFunction())) || CHILD(1)[0].isOne())) || (CHILD(1).isNumber() && CHILD(1).number().isRational() && !CHILD(1).number().isInteger() && CHILD(1).number().denominatorIsLessThan(10) && ((!po.negative_exponents && (CHILD(0).countChildren() == 0 || CHILD(0).isFunction())) || CHILD(1).number().numeratorIsOne())) || (CHILD(1).isInverse() && CHILD(1)[0].isNumber() && CHILD(1)[0].number().isInteger() && CHILD(1)[0].number().isPositive() && CHILD(1)[0].number().isLessThan(10)))) { + // f(a)^(b/c)=root(f(a),c)^b + Number nr_int, nr_num, nr_den; + if(CHILD(1).isNumber()) { + nr_num = CHILD(1).number().numerator(); + nr_den = CHILD(1).number().denominator(); + } else if(CHILD(1).isDivision()) { + nr_num.set(CHILD(1)[0].number()); + nr_den.set(CHILD(1)[1].number()); + } else if(CHILD(1).isInverse()) { + nr_num.set(1, 1, 0); + nr_den.set(CHILD(1)[0].number()); + } + if(!nr_num.isOne() && (nr_num - 1).isIntegerDivisible(nr_den)) { + nr_int = nr_num; + nr_int--; + nr_int.divide(nr_den); + nr_num = 1; + } + MathStructure mbase(CHILD(0)); + CHILD(1) = nr_den; + m_type = STRUCT_FUNCTION; + setFunctionId(FUNCTION_ID_ROOT); + formatsub(po, parent, pindex, false, top_parent); + if(!nr_num.isOne()) { + raise(nr_num); + formatsub(po, parent, pindex, false, top_parent); + } + if(!nr_int.isZero()) { + if(!nr_int.isOne()) mbase.raise(nr_int); + multiply(mbase); + sort(po); + formatsub(po, parent, pindex, false, top_parent); + } + break; + } + if(CHILD(0).isUnit_exp() && (!parent || (!parent->isPower() && !parent->isMultiplication() && !parent->isInverse() && !(parent->isDivision() && pindex == 2)))) { + multiply(m_one); + SWAP_CHILDREN(0, 1); + } + break; + } + case STRUCT_FUNCTION: { + if(po.preserve_format) break; + if(o_function->id() == FUNCTION_ID_ROOT && SIZE == 2 && CHILD(1) == 3) { + // root(f(a),3)=cbrt(f(a)) + ERASE(1) + setFunctionId(FUNCTION_ID_CBRT); + } else if(o_function->id() == FUNCTION_ID_INTERVAL && SIZE == 2 && CHILD(0).isAddition() && CHILD(0).size() == 2 && CHILD(1).isAddition() && CHILD(1).size() == 2) { + // interval(f(a)+c,f(a)-c)=uncertainty(f(a),c) + MathStructure *mmid = NULL, *munc = NULL; + if(CHILD(0)[0].equals(CHILD(1)[0], true, true)) { + mmid = &CHILD(0)[0]; + if(CHILD(0)[1].isNegate() && CHILD(0)[1][0].equals(CHILD(1)[1], true, true)) munc = &CHILD(1)[1]; + if(CHILD(1)[1].isNegate() && CHILD(1)[1][0].equals(CHILD(0)[1], true, true)) munc = &CHILD(0)[1]; + } else if(CHILD(0)[1].equals(CHILD(1)[1], true, true)) { + mmid = &CHILD(0)[1]; + if(CHILD(0)[0].isNegate() && CHILD(0)[0][0].equals(CHILD(1)[0], true, true)) munc = &CHILD(1)[0]; + if(CHILD(1)[0].isNegate() && CHILD(1)[0][0].equals(CHILD(0)[0], true, true)) munc = &CHILD(0)[0]; + } else if(CHILD(0)[0].equals(CHILD(1)[1], true, true)) { + mmid = &CHILD(0)[0]; + if(CHILD(0)[1].isNegate() && CHILD(0)[1][0].equals(CHILD(1)[0], true, true)) munc = &CHILD(1)[0]; + if(CHILD(1)[0].isNegate() && CHILD(1)[0][0].equals(CHILD(0)[1], true, true)) munc = &CHILD(0)[1]; + } else if(CHILD(0)[1].equals(CHILD(1)[0], true, true)) { + mmid = &CHILD(0)[0]; + if(CHILD(0)[0].isNegate() && CHILD(0)[0][0].equals(CHILD(1)[1], true, true)) munc = &CHILD(1)[1]; + if(CHILD(1)[1].isNegate() && CHILD(1)[1][0].equals(CHILD(0)[0], true, true)) munc = &CHILD(0)[0]; + } + if(mmid && munc) { + setFunctionId(FUNCTION_ID_UNCERTAINTY); + mmid->ref(); + munc->ref(); + CLEAR + APPEND_POINTER(mmid) + APPEND_POINTER(munc) + APPEND(m_zero) + } + } + break; + } + case STRUCT_VARIABLE: { + if(o_variable == CALCULATOR->getVariableById(VARIABLE_ID_PLUS_INFINITY) || o_variable == CALCULATOR->getVariableById(VARIABLE_ID_MINUS_INFINITY)) { + // replace infinity variable with infinity number + set(((KnownVariable*) o_variable)->get()); + } + break; + } + case STRUCT_NUMBER: { + bool force_fraction = false; + if(parent && parent->isMultiplication() && o_number.isRational()) { + // always show fraction format for rational number a in a(f(b)+f(c)) + for(size_t i = 0; i < parent->size(); i++) { + if((*parent)[i].isAddition()) { + force_fraction = true; + break; + } + } + } + if((o_number.isNegative() || ((parent || po.interval_display != INTERVAL_DISPLAY_SIGNIFICANT_DIGITS) && o_number.isInterval() && o_number.isNonPositive())) && (po.base != BASE_CUSTOM || !CALCULATOR->customOutputBase().isNegative())) { + if((((po.base != 2 || !po.twos_complement) && (po.base != 16 || !po.hexadecimal_twos_complement)) || !o_number.isInteger()) && (!o_number.isMinusInfinity() || (parent && parent->isAddition()))) { + // a=-(-a), if a is a negative number (or a is interval from negative value to 0), and not using two's complement and not using negative number base + o_number.negate(); + transform(STRUCT_NEGATE); + formatsub(po, parent, pindex, true, top_parent); + } + } else if(po.number_fraction_format == FRACTION_COMBINED && po.base != BASE_SEXAGESIMAL && po.base != BASE_TIME && o_number.isRational() && !o_number.isInteger() && (!po.show_ending_zeroes || !po.restrict_to_parent_precision || po.base == BASE_ROMAN_NUMERALS || po.base == BASE_BIJECTIVE_26 || ((!top_parent || !top_parent->isApproximate()) && !isApproximate()) || (o_number.denominatorIsLessThan(10) && o_number < 10 && o_number > -10))) { + // mixed fraction format (e.g. 5/3=1+2/3); only used is number is non-integer rational, and current mode does not dictate showing ending zeroes of approximate number, and number base is not sexagesimal + if(o_number.isFraction()) { + // split number in numerator and denominator, if numerator < denominator + Number num(o_number.numerator()); + Number den(o_number.denominator()); + clear(true); + if(num.isOne()) { + m_type = STRUCT_INVERSE; + } else { + m_type = STRUCT_DIVISION; + APPEND_NEW(num); + } + APPEND_NEW(den); + } else { + // split number in integer part, numerator and denominator, if numerator > denominator + Number frac(o_number); + frac.frac(); + MathStructure *num = new MathStructure(frac.numerator()); + num->transform(STRUCT_DIVISION, frac.denominator()); + o_number.trunc(); + add_nocopy(num); + } + } else if((force_fraction || po.number_fraction_format == FRACTION_FRACTIONAL || po.base == BASE_ROMAN_NUMERALS || po.number_fraction_format == FRACTION_DECIMAL_EXACT) && po.base != BASE_SEXAGESIMAL && po.base != BASE_TIME && o_number.isRational() && !o_number.isInteger() && (force_fraction || !o_number.isApproximate())) { + // split rational number in numerator and denominator, if display of fractions is requested for rational numbers and number base is not sexagesimal and number is not approximate + + InternalPrintStruct ips_n; + + // parent approximate status affects the display of numbers if force_fraction is not true + if(!force_fraction && (isApproximate() || (top_parent && top_parent->isApproximate()))) ips_n.parent_approximate = true; + + // if current mode and parent precision dictates showing of ending zeroes, number is not shown as fraction + if(po.show_ending_zeroes && po.restrict_to_parent_precision && ips_n.parent_approximate && po.base != BASE_ROMAN_NUMERALS && po.base != BASE_BIJECTIVE_26 && (o_number.numeratorIsGreaterThan(9) || o_number.numeratorIsLessThan(-9) || o_number.denominatorIsGreaterThan(9))) { + break; + } + ips_n.parent_precision = precision(); + if(top_parent && top_parent->precision() < 0 && top_parent->precision() < ips_n.parent_precision) ips_n.parent_precision = top_parent->precision(); + + bool approximately_displayed = false; + PrintOptions po2 = po; + po2.is_approximate = &approximately_displayed; + if(force_fraction && (po2.number_fraction_format == FRACTION_DECIMAL || po2.number_fraction_format == FRACTION_DECIMAL_EXACT)) po2.number_fraction_format = FRACTION_FRACTIONAL; + if(!force_fraction && po.base != BASE_ROMAN_NUMERALS && po.base != BASE_BIJECTIVE_26 && po.number_fraction_format == FRACTION_DECIMAL_EXACT) { + // if FRACTION_DECIMAL_EXACT is active, numbers is not displayed as fraction if they can be shown exact using decimals + po2.number_fraction_format = FRACTION_DECIMAL; + o_number.print(po2, ips_n); + if(!approximately_displayed) break; + approximately_displayed = false; + } + + // test if numerator and denominator is displayed exact using current mode + Number num(o_number.numerator()); + Number den(o_number.denominator()); + if(isApproximate()) { + num.setApproximate(); + den.setApproximate(); + } + num.print(po2, ips_n); + if(!approximately_displayed || po.base == BASE_ROMAN_NUMERALS || po.base == BASE_BIJECTIVE_26) { + den.print(po2, ips_n); + if(!approximately_displayed || po.base == BASE_ROMAN_NUMERALS || po.base == BASE_BIJECTIVE_26) { + // both numerator and denominator is displayed exact: split up number + clear(true); + if(num.isOne()) { + m_type = STRUCT_INVERSE; + } else { + m_type = STRUCT_DIVISION; + APPEND_NEW(num); + } + APPEND_NEW(den); + } + } + } else if(o_number.hasImaginaryPart()) { + if(o_number.hasRealPart()) { + // split up complex number in real and imaginary part (Z=re(Z)+im(Z)*i) + Number re(o_number.realPart()); + Number im(o_number.imaginaryPart()); + MathStructure *mstruct = new MathStructure(im); + if(im.isOne()) { + mstruct->set(CALCULATOR->getVariableById(VARIABLE_ID_I)); + } else { + mstruct->multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_I))); + if(CALCULATOR->getVariableById(VARIABLE_ID_I)->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name == "j") mstruct->swapChildren(1, 2); + } + o_number = re; + add_nocopy(mstruct); + formatsub(po, parent, pindex, true, top_parent); + } else { + // transform imaginary number to imaginary part * i (Z=im(Z)*i) + Number im(o_number.imaginaryPart()); + if(im.isOne()) { + set(CALCULATOR->getVariableById(VARIABLE_ID_I), true); + } else if(im.isMinusOne()) { + set(CALCULATOR->getVariableById(VARIABLE_ID_I), true); + transform(STRUCT_NEGATE); + } else { + o_number = im; + multiply_nocopy(new MathStructure(CALCULATOR->getVariableById(VARIABLE_ID_I))); + if(CALCULATOR->getVariableById(VARIABLE_ID_I)->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name == "j") SWAP_CHILDREN(0, 1); + } + formatsub(po, parent, pindex, true, top_parent); + } + } + break; + } + default: {} + } +} + +int namelen(const MathStructure &mstruct, const PrintOptions &po, const InternalPrintStruct&, bool *abbreviated = NULL) { + // returns the length of the name used (for mstruct) with the current mode (and if the name is an abbreviation) + const string *str; + switch(mstruct.type()) { + case STRUCT_FUNCTION: { + const ExpressionName *ename = &mstruct.function()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); + str = &ename->name; + if(abbreviated) *abbreviated = ename->abbreviation; + break; + } + case STRUCT_VARIABLE: { + const ExpressionName *ename = &mstruct.variable()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); + str = &ename->name; + if(abbreviated) *abbreviated = ename->abbreviation; + break; + } + case STRUCT_ABORTED: {} + case STRUCT_SYMBOLIC: { + str = &mstruct.symbol(); + if(abbreviated) *abbreviated = false; + break; + } + case STRUCT_UNIT: { + const ExpressionName *ename = &mstruct.unit()->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, mstruct.isPlural(), po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); + str = &ename->name; + if(abbreviated) *abbreviated = ename->abbreviation; + break; + } + default: {if(abbreviated) *abbreviated = false; return 0;} + } + if(text_length_is_one(*str)) return 1; + return str->length(); +} + +bool MathStructure::needsParenthesis(const PrintOptions &po, const InternalPrintStruct &ips, const MathStructure &parent, size_t index, bool flat_division, bool) const { + // determines, using the type of the parent, the type of the child, the index of the child, and if division is displayed on one line or not (only relevant in the GUI), if this child should be displayed surrounded by parentheses + switch(parent.type()) { + case STRUCT_MULTIPLICATION: { + switch(m_type) { + case STRUCT_MULTIPLICATION: {return true;} + case STRUCT_DIVISION: {return flat_division && (index < parent.size() || po.excessive_parenthesis);} + case STRUCT_INVERSE: {return flat_division;} + case STRUCT_ADDITION: {return true;} + case STRUCT_POWER: {return po.excessive_parenthesis;} + case STRUCT_NEGATE: {return po.excessive_parenthesis;} + case STRUCT_BITWISE_AND: {return true;} + case STRUCT_BITWISE_OR: {return true;} + case STRUCT_BITWISE_XOR: {return true;} + case STRUCT_BITWISE_NOT: {return po.excessive_parenthesis;} + case STRUCT_LOGICAL_AND: {return true;} + case STRUCT_LOGICAL_OR: {return true;} + case STRUCT_LOGICAL_XOR: {return true;} + case STRUCT_LOGICAL_NOT: {return po.excessive_parenthesis;} + case STRUCT_COMPARISON: {return true;} + case STRUCT_FUNCTION: {return o_function->id() == FUNCTION_ID_UNCERTAINTY;} + case STRUCT_VECTOR: {return false;} + case STRUCT_NUMBER: {return o_number.isInfinite() || (o_number.hasImaginaryPart() && o_number.hasRealPart());} + case STRUCT_VARIABLE: {return false;} + case STRUCT_ABORTED: {return false;} + case STRUCT_SYMBOLIC: {return false;} + case STRUCT_UNIT: {return false;} + case STRUCT_UNDEFINED: {return po.excessive_parenthesis;} + case STRUCT_DATETIME: {return false;} + default: {return true;} + } + } + case STRUCT_INVERSE: {} + case STRUCT_DIVISION: { + switch(m_type) { + case STRUCT_MULTIPLICATION: {return flat_division || po.excessive_parenthesis;} + case STRUCT_DIVISION: {return flat_division || po.excessive_parenthesis;} + case STRUCT_INVERSE: {return flat_division || po.excessive_parenthesis;} + case STRUCT_ADDITION: {return flat_division || po.excessive_parenthesis;} + case STRUCT_POWER: {return flat_division && po.excessive_parenthesis;} + case STRUCT_NEGATE: {return flat_division && po.excessive_parenthesis;} + case STRUCT_BITWISE_AND: {return flat_division || po.excessive_parenthesis;} + case STRUCT_BITWISE_OR: {return flat_division || po.excessive_parenthesis;} + case STRUCT_BITWISE_XOR: {return flat_division || po.excessive_parenthesis;} + case STRUCT_BITWISE_NOT: {return flat_division && po.excessive_parenthesis;} + case STRUCT_LOGICAL_AND: {return flat_division || po.excessive_parenthesis;} + case STRUCT_LOGICAL_OR: {return flat_division || po.excessive_parenthesis;} + case STRUCT_LOGICAL_XOR: {return flat_division || po.excessive_parenthesis;} + case STRUCT_LOGICAL_NOT: {return flat_division && po.excessive_parenthesis;} + case STRUCT_COMPARISON: {return flat_division || po.excessive_parenthesis;} + case STRUCT_FUNCTION: {return o_function->id() == FUNCTION_ID_UNCERTAINTY;} + case STRUCT_VECTOR: {return false;} + case STRUCT_NUMBER: {return (flat_division || po.excessive_parenthesis) && (o_number.isInfinite() || o_number.hasImaginaryPart());} + case STRUCT_VARIABLE: {return false;} + case STRUCT_ABORTED: {return false;} + case STRUCT_SYMBOLIC: {return false;} + case STRUCT_UNIT: {return false;} + case STRUCT_UNDEFINED: {return false;} + case STRUCT_DATETIME: {return false;} + default: {return true;} + } + } + case STRUCT_ADDITION: { + switch(m_type) { + case STRUCT_MULTIPLICATION: {return po.excessive_parenthesis;} + case STRUCT_DIVISION: {return flat_division && po.excessive_parenthesis;} + case STRUCT_INVERSE: {return flat_division && po.excessive_parenthesis;} + case STRUCT_ADDITION: {return true;} + case STRUCT_POWER: {return po.excessive_parenthesis;} + case STRUCT_NEGATE: {return index > 1 || po.excessive_parenthesis;} + case STRUCT_BITWISE_AND: {return true;} + case STRUCT_BITWISE_OR: {return true;} + case STRUCT_BITWISE_XOR: {return true;} + case STRUCT_BITWISE_NOT: {return false;} + case STRUCT_LOGICAL_AND: {return true;} + case STRUCT_LOGICAL_OR: {return true;} + case STRUCT_LOGICAL_XOR: {return true;} + case STRUCT_LOGICAL_NOT: {return false;} + case STRUCT_COMPARISON: {return true;} + case STRUCT_FUNCTION: {return false;} + case STRUCT_VECTOR: {return false;} + case STRUCT_NUMBER: {return o_number.isInfinite();} + case STRUCT_VARIABLE: {return false;} + case STRUCT_ABORTED: {return false;} + case STRUCT_SYMBOLIC: {return false;} + case STRUCT_UNIT: {return false;} + case STRUCT_UNDEFINED: {return false;} + case STRUCT_DATETIME: {return false;} + default: {return true;} + } + } + case STRUCT_POWER: { + switch(m_type) { + case STRUCT_MULTIPLICATION: {return true;} + case STRUCT_DIVISION: {return index == 1 || flat_division || po.excessive_parenthesis;} + case STRUCT_INVERSE: {return index == 1 || flat_division || po.excessive_parenthesis;} + case STRUCT_ADDITION: {return true;} + case STRUCT_POWER: {return true;} + case STRUCT_NEGATE: {return index == 1 || CHILD(0).needsParenthesis(po, ips, parent, index, flat_division);} + case STRUCT_BITWISE_AND: {return true;} + case STRUCT_BITWISE_OR: {return true;} + case STRUCT_BITWISE_XOR: {return true;} + case STRUCT_BITWISE_NOT: {return index == 1 || po.excessive_parenthesis;} + case STRUCT_LOGICAL_AND: {return true;} + case STRUCT_LOGICAL_OR: {return true;} + case STRUCT_LOGICAL_XOR: {return true;} + case STRUCT_LOGICAL_NOT: {return index == 1 || po.excessive_parenthesis;} + case STRUCT_COMPARISON: {return true;} + case STRUCT_FUNCTION: {return o_function->id() == FUNCTION_ID_UNCERTAINTY;} + case STRUCT_VECTOR: {return false;} + case STRUCT_NUMBER: {return o_number.isInfinite() || o_number.hasImaginaryPart();} + case STRUCT_VARIABLE: {return false;} + case STRUCT_ABORTED: {return false;} + case STRUCT_SYMBOLIC: {return false;} + case STRUCT_UNIT: {return false;} + case STRUCT_UNDEFINED: {return false;} + default: {return true;} + } + } + case STRUCT_NEGATE: { + switch(m_type) { + case STRUCT_MULTIPLICATION: {return po.excessive_parenthesis;} + case STRUCT_DIVISION: {return po.excessive_parenthesis;} + case STRUCT_INVERSE: {return flat_division && po.excessive_parenthesis;} + case STRUCT_ADDITION: {return true;} + case STRUCT_POWER: {return true;} + case STRUCT_NEGATE: {return true;} + case STRUCT_BITWISE_AND: {return true;} + case STRUCT_BITWISE_OR: {return true;} + case STRUCT_BITWISE_XOR: {return true;} + case STRUCT_BITWISE_NOT: {return po.excessive_parenthesis;} + case STRUCT_LOGICAL_AND: {return true;} + case STRUCT_LOGICAL_OR: {return true;} + case STRUCT_LOGICAL_XOR: {return true;} + case STRUCT_LOGICAL_NOT: {return po.excessive_parenthesis;} + case STRUCT_COMPARISON: {return true;} + case STRUCT_FUNCTION: {return false;} + case STRUCT_VECTOR: {return false;} + case STRUCT_NUMBER: {return o_number.isInfinite() || (o_number.hasImaginaryPart() && o_number.hasRealPart());} + case STRUCT_VARIABLE: {return false;} + case STRUCT_ABORTED: {return false;} + case STRUCT_SYMBOLIC: {return false;} + case STRUCT_UNIT: {return false;} + case STRUCT_UNDEFINED: {return false;} + default: {return true;} + } + } + case STRUCT_LOGICAL_OR: {} + case STRUCT_LOGICAL_AND: {} + case STRUCT_LOGICAL_XOR: { + switch(m_type) { + case STRUCT_MULTIPLICATION: {return true;} + case STRUCT_DIVISION: {return flat_division;} + case STRUCT_INVERSE: {return flat_division;} + case STRUCT_ADDITION: {return true;} + case STRUCT_POWER: {return po.excessive_parenthesis;} + case STRUCT_NEGATE: {return po.excessive_parenthesis;} + case STRUCT_BITWISE_AND: {return true;} + case STRUCT_BITWISE_OR: {return true;} + case STRUCT_BITWISE_XOR: {return true;} + case STRUCT_BITWISE_NOT: {return false;} + case STRUCT_LOGICAL_AND: {return true;} + case STRUCT_LOGICAL_OR: {return true;} + case STRUCT_LOGICAL_XOR: {return true;} + case STRUCT_LOGICAL_NOT: {return false;} + case STRUCT_COMPARISON: {return false;} + case STRUCT_FUNCTION: {return false;} + case STRUCT_VECTOR: {return false;} + case STRUCT_NUMBER: {return po.excessive_parenthesis && o_number.isInfinite();} + case STRUCT_VARIABLE: {return false;} + case STRUCT_ABORTED: {return false;} + case STRUCT_SYMBOLIC: {return false;} + case STRUCT_UNIT: {return false;} + case STRUCT_UNDEFINED: {return false;} + case STRUCT_DATETIME: {return false;} + default: {return true;} + } + } + case STRUCT_BITWISE_AND: {} + case STRUCT_BITWISE_OR: {} + case STRUCT_BITWISE_XOR: { + switch(m_type) { + case STRUCT_MULTIPLICATION: {return true;} + case STRUCT_DIVISION: {return flat_division;} + case STRUCT_INVERSE: {return flat_division;} + case STRUCT_ADDITION: {return true;} + case STRUCT_POWER: {return po.excessive_parenthesis;} + case STRUCT_NEGATE: {return po.excessive_parenthesis;} + case STRUCT_BITWISE_AND: {return true;} + case STRUCT_BITWISE_OR: {return true;} + case STRUCT_BITWISE_XOR: {return true;} + case STRUCT_BITWISE_NOT: {return false;} + case STRUCT_LOGICAL_AND: {return true;} + case STRUCT_LOGICAL_OR: {return true;} + case STRUCT_LOGICAL_XOR: {return true;} + case STRUCT_LOGICAL_NOT: {return false;} + case STRUCT_COMPARISON: {return true;} + case STRUCT_FUNCTION: {return false;} + case STRUCT_VECTOR: {return false;} + case STRUCT_NUMBER: {return po.excessive_parenthesis && o_number.isInfinite();} + case STRUCT_VARIABLE: {return false;} + case STRUCT_ABORTED: {return false;} + case STRUCT_SYMBOLIC: {return false;} + case STRUCT_UNIT: {return false;} + case STRUCT_UNDEFINED: {return false;} + default: {return true;} + } + } + case STRUCT_COMPARISON: { + switch(m_type) { + case STRUCT_MULTIPLICATION: {return po.excessive_parenthesis;} + case STRUCT_DIVISION: {return flat_division && po.excessive_parenthesis;} + case STRUCT_INVERSE: {return flat_division && po.excessive_parenthesis;} + case STRUCT_ADDITION: {return po.excessive_parenthesis;} + case STRUCT_POWER: {return po.excessive_parenthesis;} + case STRUCT_NEGATE: {return po.excessive_parenthesis;} + case STRUCT_BITWISE_AND: {return true;} + case STRUCT_BITWISE_OR: {return true;} + case STRUCT_BITWISE_XOR: {return true;} + case STRUCT_BITWISE_NOT: {return false;} + case STRUCT_LOGICAL_AND: {return true;} + case STRUCT_LOGICAL_OR: {return true;} + case STRUCT_LOGICAL_XOR: {return true;} + case STRUCT_LOGICAL_NOT: {return false;} + case STRUCT_COMPARISON: {return true;} + case STRUCT_FUNCTION: {return false;} + case STRUCT_VECTOR: {return false;} + case STRUCT_NUMBER: {return po.excessive_parenthesis && o_number.isInfinite();} + case STRUCT_VARIABLE: {return false;} + case STRUCT_ABORTED: {return false;} + case STRUCT_SYMBOLIC: {return false;} + case STRUCT_UNIT: {return false;} + case STRUCT_UNDEFINED: {return false;} + case STRUCT_DATETIME: {return false;} + default: {return true;} + } + } + case STRUCT_LOGICAL_NOT: {} + case STRUCT_BITWISE_NOT: { + switch(m_type) { + case STRUCT_MULTIPLICATION: {return true;} + case STRUCT_DIVISION: {return true;} + case STRUCT_INVERSE: {return true;} + case STRUCT_ADDITION: {return true;} + case STRUCT_POWER: {return po.excessive_parenthesis;} + case STRUCT_NEGATE: {return po.excessive_parenthesis;} + case STRUCT_BITWISE_AND: {return true;} + case STRUCT_BITWISE_OR: {return true;} + case STRUCT_BITWISE_XOR: {return true;} + case STRUCT_BITWISE_NOT: {return true;} + case STRUCT_LOGICAL_AND: {return true;} + case STRUCT_LOGICAL_OR: {return true;} + case STRUCT_LOGICAL_XOR: {return true;} + case STRUCT_LOGICAL_NOT: {return true;} + case STRUCT_COMPARISON: {return true;} + case STRUCT_FUNCTION: {return po.excessive_parenthesis;} + case STRUCT_VECTOR: {return po.excessive_parenthesis;} + case STRUCT_NUMBER: {return po.excessive_parenthesis;} + case STRUCT_VARIABLE: {return po.excessive_parenthesis;} + case STRUCT_ABORTED: {return po.excessive_parenthesis;} + case STRUCT_SYMBOLIC: {return po.excessive_parenthesis;} + case STRUCT_UNIT: {return po.excessive_parenthesis;} + case STRUCT_UNDEFINED: {return po.excessive_parenthesis;} + default: {return true;} + } + } + case STRUCT_FUNCTION: { + return false; + } + case STRUCT_VECTOR: { + return false; + } + default: { + return true; + } + } +} + +int MathStructure::neededMultiplicationSign(const PrintOptions &po, const InternalPrintStruct &ips, const MathStructure &parent, size_t index, bool par, bool par_prev, bool flat_division, bool flat_power) const { + // returns the suggested multiplication sign in front of this MathStrcture + + // do not display anything on front of the first factor (this function is normally not called in this case) + if(index <= 1) return MULTIPLICATION_SIGN_NONE; + // short multiplication is disabled or number base might use digits other than 0-9, alawys show multiplication symbol + if(!po.short_multiplication || po.base > 10 || po.base < 2) return MULTIPLICATION_SIGN_OPERATOR; + // no multiplication sign between factors in parentheses + if(par_prev && par) return MULTIPLICATION_SIGN_NONE; + if(par_prev) { + // (a)*u=(a) u + if(isUnit_exp()) return MULTIPLICATION_SIGN_SPACE; + if(isUnknown_exp()) { + // (a)*"xy"=(a) "xy", (a)*"xy"^b=(a) "xy"^b, (a)*x=(a)x, (a)*x^b=ax^b + if(isSymbolic() || (isPower() && CHILD(0).isSymbolic())) return MULTIPLICATION_SIGN_SPACE; + return (namelen(isPower() ? CHILD(0) : *this, po, ips, NULL) > 1 ? MULTIPLICATION_SIGN_SPACE : MULTIPLICATION_SIGN_NONE); + } + if(isMultiplication() && SIZE > 0) { + // (a)*uv=(a) uv + if(CHILD(0).isUnit_exp()) return MULTIPLICATION_SIGN_SPACE; + if(CHILD(0).isUnknown_exp()) { + // (a)*"xy"z=(a) "xy"z, (a)*xy=(a)xy + if(CHILD(0).isSymbolic() || (CHILD(0).isPower() && CHILD(0)[0].isSymbolic())) return MULTIPLICATION_SIGN_SPACE; + return (namelen(CHILD(0).isPower() ? CHILD(0)[0] : CHILD(0), po, ips, NULL) > 1 ? MULTIPLICATION_SIGN_SPACE : MULTIPLICATION_SIGN_NONE); + } + } else if(isDivision()) { + // (a)*(u1/u2)=(a) u1/u2 + for(size_t i = 0; i < SIZE; i++) { + if(!CHILD(i).isUnit_exp()) { + return MULTIPLICATION_SIGN_OPERATOR; + } + } + return MULTIPLICATION_SIGN_SPACE; + } + // (a)*bc + return MULTIPLICATION_SIGN_OPERATOR; + } + // type of factor in front in this factor + int t = parent[index - 2].type(); + // a^b*c (if b is not shown using superscript or similar) + if(flat_power && t == STRUCT_POWER) return MULTIPLICATION_SIGN_OPERATOR; + // a^b*(c)=a^b c + if(par && t == STRUCT_POWER) return MULTIPLICATION_SIGN_SPACE; + // a*(b)=a(b) + if(par) return MULTIPLICATION_SIGN_NONE; + // check if involved names have only one character + bool abbr_prev = false, abbr_this = false; + int namelen_this = namelen(*this, po, ips, &abbr_this); + int namelen_prev = namelen(parent[index - 2], po, ips, &abbr_prev); + switch(t) { + case STRUCT_MULTIPLICATION: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_INVERSE: {} + case STRUCT_DIVISION: {if(flat_division) return MULTIPLICATION_SIGN_OPERATOR; return MULTIPLICATION_SIGN_SPACE;} + case STRUCT_ADDITION: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_POWER: {if(flat_power) return MULTIPLICATION_SIGN_OPERATOR; break;} + case STRUCT_NEGATE: {break;} + case STRUCT_BITWISE_AND: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_BITWISE_OR: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_BITWISE_XOR: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_BITWISE_NOT: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_LOGICAL_AND: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_LOGICAL_OR: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_LOGICAL_XOR: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_LOGICAL_NOT: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_COMPARISON: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_FUNCTION: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_VECTOR: {break;} + case STRUCT_NUMBER: {break;} + case STRUCT_VARIABLE: {break;} + case STRUCT_ABORTED: {break;} + case STRUCT_SYMBOLIC: {break;} + case STRUCT_UNIT: { + if(m_type == STRUCT_UNIT) { + if(!po.limit_implicit_multiplication && !abbr_prev && !abbr_this) { + return MULTIPLICATION_SIGN_SPACE; + } + if(po.place_units_separately) { + return MULTIPLICATION_SIGN_OPERATOR_SHORT; + } else { + return MULTIPLICATION_SIGN_OPERATOR; + } + } else if(m_type == STRUCT_NUMBER) { + if(namelen_prev > 1) { + return MULTIPLICATION_SIGN_SPACE; + } else { + return MULTIPLICATION_SIGN_NONE; + } + } + //return MULTIPLICATION_SIGN_SPACE; + } + case STRUCT_UNDEFINED: {break;} + default: {return MULTIPLICATION_SIGN_OPERATOR;} + } + switch(m_type) { + case STRUCT_MULTIPLICATION: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_INVERSE: {} + case STRUCT_DIVISION: {return MULTIPLICATION_SIGN_SPACE;} + case STRUCT_ADDITION: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_POWER: {return CHILD(0).neededMultiplicationSign(po, ips, parent, index, par, par_prev, flat_division, flat_power);} + case STRUCT_NEGATE: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_BITWISE_AND: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_BITWISE_OR: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_BITWISE_XOR: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_BITWISE_NOT: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_LOGICAL_AND: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_LOGICAL_OR: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_LOGICAL_XOR: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_LOGICAL_NOT: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_COMPARISON: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_FUNCTION: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_VECTOR: {return MULTIPLICATION_SIGN_OPERATOR;} + case STRUCT_NUMBER: { + if(t == STRUCT_VARIABLE && parent[index - 2].variable() == CALCULATOR->getVariableById(VARIABLE_ID_I)) return MULTIPLICATION_SIGN_NONE; + return MULTIPLICATION_SIGN_OPERATOR; + } + case STRUCT_VARIABLE: { + if(!o_variable->isRegistered() && o_variable->getName(1).name.length() > 0 && o_variable->getName(1).name[0] >= '0' && o_variable->getName(1).name[0] <= '9') return MULTIPLICATION_SIGN_OPERATOR; + } + case STRUCT_ABORTED: {} + case STRUCT_SYMBOLIC: { + if(po.limit_implicit_multiplication && t != STRUCT_NUMBER) return MULTIPLICATION_SIGN_OPERATOR; + if(t != STRUCT_NUMBER && ((namelen_prev > 1 || namelen_this > 1) || equals(parent[index - 2]))) return MULTIPLICATION_SIGN_OPERATOR; + if(namelen_this > 1 || (m_type == STRUCT_SYMBOLIC && !po.allow_non_usable)) return MULTIPLICATION_SIGN_SPACE; + return MULTIPLICATION_SIGN_NONE; + } + case STRUCT_UNIT: { + if((t == STRUCT_POWER && parent[index - 2][0].isUnit_exp()) || (o_unit == CALCULATOR->getDegUnit() && print(po) == SIGN_DEGREE)) { + return MULTIPLICATION_SIGN_NONE; + } + return MULTIPLICATION_SIGN_SPACE; + } + case STRUCT_UNDEFINED: {return MULTIPLICATION_SIGN_OPERATOR;} + default: {return MULTIPLICATION_SIGN_OPERATOR;} + } +} + +ostream& operator << (ostream &os, const MathStructure &mstruct) { + os << format_and_print(mstruct); + return os; +} +string MathStructure::print(const PrintOptions &po, const InternalPrintStruct &ips) const { + if(ips.depth == 0 && po.is_approximate) *po.is_approximate = false; + string print_str; + InternalPrintStruct ips_n = ips; + if(isApproximate()) ips_n.parent_approximate = true; + if(precision() >= 0 && (ips_n.parent_precision < 0 || precision() < ips_n.parent_precision)) ips_n.parent_precision = precision(); + switch(m_type) { + case STRUCT_NUMBER: { + print_str = o_number.print(po, ips_n); + break; + } + case STRUCT_ABORTED: {} + case STRUCT_SYMBOLIC: { + if(po.allow_non_usable) { + print_str = s_sym; + } else { + if((text_length_is_one(s_sym) && s_sym.find("\'") == string::npos) || s_sym.find("\"") != string::npos) { + print_str = "\'"; + print_str += s_sym; + print_str += "\'"; + } else { + print_str = "\""; + print_str += s_sym; + print_str += "\""; + } + } + break; + } + case STRUCT_DATETIME: { + print_str = "\""; + print_str += o_datetime->print(po); + print_str += "\""; + break; + } + case STRUCT_ADDITION: { + ips_n.depth++; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); + if(i > 0) { + if(CHILD(i).type() == STRUCT_NEGATE) { + if(po.spacious) print_str += " "; + if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MINUS, po.can_display_unicode_string_arg))) print_str += SIGN_MINUS; + else print_str += "-"; + if(po.spacious) print_str += " "; + ips_n.wrap = CHILD(i)[0].needsParenthesis(po, ips_n, *this, i + 1, true, true); + print_str += CHILD(i)[0].print(po, ips_n); + } else { + if(po.spacious) print_str += " "; + print_str += "+"; + if(po.spacious) print_str += " "; + ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); + print_str += CHILD(i).print(po, ips_n); + } + } else { + ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); + print_str += CHILD(i).print(po, ips_n); + } + } + break; + } + case STRUCT_NEGATE: { + if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MINUS, po.can_display_unicode_string_arg))) print_str += SIGN_MINUS; + else print_str = "-"; + ips_n.depth++; + ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); + print_str += CHILD(0).print(po, ips_n); + break; + } + case STRUCT_MULTIPLICATION: { + ips_n.depth++; + if(!po.preserve_format && SIZE == 2 && (CHILD(0).isNumber() || (CHILD(0).isNegate() && CHILD(0)[0].isNumber())) && CHILD(1).isFunction() && CHILD(1).size() == 1 && CHILD(1).function()->id() == FUNCTION_ID_CIS && CHILD(1).function()->referenceName() == "cis") { + ips_n.wrap = false; + print_str += CHILD(0).print(po, ips_n); + print_str += " "; + print_str += "cis"; + print_str += " "; + ips_n.wrap = (CHILD(1)[0].size() > 0 && (!CHILD(1)[0].isMultiplication() || CHILD(1)[0].size() != 2 || CHILD(1)[0][1].neededMultiplicationSign(po, ips_n, CHILD(1)[0], 2, false, false, false, false) != MULTIPLICATION_SIGN_NONE) && (!CHILD(1)[0].isNegate() || (CHILD(1)[0][0].size() > 0 && (!CHILD(1)[0][0].isMultiplication() || CHILD(1)[0][0][1].neededMultiplicationSign(po, ips_n, CHILD(1)[0][0], 2, false, false, false, false) != MULTIPLICATION_SIGN_NONE)))); + print_str += CHILD(1)[0].print(po, ips_n); + break; + } + bool par_prev = false; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); + ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); + if(!po.short_multiplication && i > 0) { + if(po.spacious) print_str += " "; + if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_DOT && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIDOT, po.can_display_unicode_string_arg))) print_str += SIGN_MULTIDOT; + else if(po.use_unicode_signs && (po.multiplication_sign == MULTIPLICATION_SIGN_DOT || po.multiplication_sign == MULTIPLICATION_SIGN_ALTDOT) && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MIDDLEDOT, po.can_display_unicode_string_arg))) print_str += SIGN_MIDDLEDOT; + else if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_X && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIPLICATION, po.can_display_unicode_string_arg))) print_str += SIGN_MULTIPLICATION; + else print_str += "*"; + if(po.spacious) print_str += " "; + } else if(i > 0) { + switch(CHILD(i).neededMultiplicationSign(po, ips_n, *this, i + 1, ips_n.wrap || (CHILD(i).isPower() && CHILD(i)[0].needsParenthesis(po, ips_n, CHILD(i), 1, true, true)), par_prev, true, true)) { + case MULTIPLICATION_SIGN_SPACE: {print_str += " "; break;} + case MULTIPLICATION_SIGN_OPERATOR: { + if(po.spacious) { + if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_DOT && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIDOT, po.can_display_unicode_string_arg))) print_str += " " SIGN_MULTIDOT " "; + else if(po.use_unicode_signs && (po.multiplication_sign == MULTIPLICATION_SIGN_DOT || po.multiplication_sign == MULTIPLICATION_SIGN_ALTDOT) && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MIDDLEDOT, po.can_display_unicode_string_arg))) print_str += " " SIGN_MIDDLEDOT " "; + else if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_X && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIPLICATION, po.can_display_unicode_string_arg))) print_str += " " SIGN_MULTIPLICATION " "; + else print_str += " * "; + break; + } + } + case MULTIPLICATION_SIGN_OPERATOR_SHORT: { + if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_DOT && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIDOT, po.can_display_unicode_string_arg))) print_str += SIGN_MULTIDOT; + else if(po.use_unicode_signs && (po.multiplication_sign == MULTIPLICATION_SIGN_DOT || po.multiplication_sign == MULTIPLICATION_SIGN_ALTDOT) && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MIDDLEDOT, po.can_display_unicode_string_arg))) print_str += SIGN_MIDDLEDOT; + else if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_X && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIPLICATION, po.can_display_unicode_string_arg))) print_str += SIGN_MULTIPLICATION; + else print_str += "*"; + break; + } + } + } + print_str += CHILD(i).print(po, ips_n); + par_prev = ips_n.wrap; + } + break; + } + case STRUCT_INVERSE: { + ips_n.depth++; + ips_n.division_depth++; + ips_n.wrap = false; + print_str = m_one.print(po, ips_n); + if(po.spacious) print_str += " "; + if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION, po.can_display_unicode_string_arg))) { + print_str += SIGN_DIVISION; + } else if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION_SLASH && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION_SLASH, po.can_display_unicode_string_arg))) { + print_str += SIGN_DIVISION_SLASH; + } else { + print_str += "/"; + } + if(po.spacious) print_str += " "; + if(CHILD(0).isNumber() && (po.number_fraction_format == FRACTION_DECIMAL || po.number_fraction_format == FRACTION_DECIMAL_EXACT)) { + PrintOptions po2 = po; + po2.number_fraction_format = FRACTION_FRACTIONAL; + ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); + print_str += CHILD(0).print(po, ips_n); + } else { + ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); + print_str += CHILD(0).print(po, ips_n); + } + break; + } + case STRUCT_DIVISION: { + ips_n.depth++; + ips_n.division_depth++; + if(CHILD(0).isNumber() && CHILD(1).isNumber() && (po.number_fraction_format == FRACTION_DECIMAL || po.number_fraction_format == FRACTION_DECIMAL_EXACT)) { + PrintOptions po2 = po; + po2.number_fraction_format = FRACTION_FRACTIONAL; + ips_n.wrap = CHILD(0).needsParenthesis(po2, ips_n, *this, 1, true, true); + print_str = CHILD(0).print(po2, ips_n); + if(po.spacious) print_str += " "; + if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION, po.can_display_unicode_string_arg))) { + print_str += SIGN_DIVISION; + } else if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION_SLASH && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION_SLASH, po.can_display_unicode_string_arg))) { + print_str += SIGN_DIVISION_SLASH; + } else { + print_str += "/"; + } + if(po.spacious) print_str += " "; + ips_n.wrap = CHILD(1).needsParenthesis(po2, ips_n, *this, 2, true, true); + print_str += CHILD(1).print(po2, ips_n); + } else { + ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); + print_str = CHILD(0).print(po, ips_n); + if(po.spacious) print_str += " "; + if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION, po.can_display_unicode_string_arg))) { + print_str += SIGN_DIVISION; + } else if(po.use_unicode_signs && po.division_sign == DIVISION_SIGN_DIVISION_SLASH && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_DIVISION_SLASH, po.can_display_unicode_string_arg))) { + print_str += SIGN_DIVISION_SLASH; + } else { + print_str += "/"; + } + if(po.spacious) print_str += " "; + ips_n.wrap = CHILD(1).needsParenthesis(po, ips_n, *this, 2, true, true); + print_str += CHILD(1).print(po, ips_n); + } + break; + } + case STRUCT_POWER: { + ips_n.depth++; + ips_n.power_depth++; + ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); + print_str = CHILD(0).print(po, ips_n); + print_str += "^"; + ips_n.wrap = CHILD(1).needsParenthesis(po, ips_n, *this, 2, true, true); + PrintOptions po2 = po; + po2.show_ending_zeroes = false; + print_str += CHILD(1).print(po2, ips_n); + break; + } + case STRUCT_COMPARISON: { + ips_n.depth++; + ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); + print_str = CHILD(0).print(po, ips_n); + if(po.spacious) print_str += " "; + switch(ct_comp) { + case COMPARISON_EQUALS: { + if(po.use_unicode_signs && po.interval_display != INTERVAL_DISPLAY_INTERVAL && isApproximate() && containsInterval() && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_ALMOST_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_ALMOST_EQUAL; + else print_str += "="; + break; + } + case COMPARISON_NOT_EQUALS: { + if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_NOT_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_NOT_EQUAL; + else print_str += "!="; + break; + } + case COMPARISON_GREATER: {print_str += ">"; break;} + case COMPARISON_LESS: {print_str += "<"; break;} + case COMPARISON_EQUALS_GREATER: { + if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_GREATER_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_GREATER_OR_EQUAL; + else print_str += ">="; + break; + } + case COMPARISON_EQUALS_LESS: { + if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_LESS_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_LESS_OR_EQUAL; + else print_str += "<="; + break; + } + } + if(po.spacious) print_str += " "; + ips_n.wrap = CHILD(1).needsParenthesis(po, ips_n, *this, 2, true, true); + print_str += CHILD(1).print(po, ips_n); + break; + } + case STRUCT_BITWISE_AND: { + ips_n.depth++; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); + if(i > 0) { + if(po.spacious) print_str += " "; + print_str += "&"; + if(po.spacious) print_str += " "; + } + ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); + print_str += CHILD(i).print(po, ips_n); + } + break; + } + case STRUCT_BITWISE_OR: { + ips_n.depth++; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); + if(i > 0) { + if(po.spacious) print_str += " "; + print_str += "|"; + if(po.spacious) print_str += " "; + } + ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); + print_str += CHILD(i).print(po, ips_n); + } + break; + } + case STRUCT_BITWISE_XOR: { + ips_n.depth++; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); + if(i > 0) { + print_str += " "; + print_str += "xor"; + print_str += " "; + } + ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); + print_str += CHILD(i).print(po, ips_n); + } + break; + } + case STRUCT_BITWISE_NOT: { + print_str = "~"; + ips_n.depth++; + ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); + print_str += CHILD(0).print(po, ips_n); + break; + } + case STRUCT_LOGICAL_AND: { + ips_n.depth++; + if(!po.preserve_format && SIZE == 2 && CHILD(0).isComparison() && CHILD(1).isComparison() && CHILD(0).comparisonType() != COMPARISON_EQUALS && CHILD(0).comparisonType() != COMPARISON_NOT_EQUALS && CHILD(1).comparisonType() != COMPARISON_EQUALS && CHILD(1).comparisonType() != COMPARISON_NOT_EQUALS && CHILD(0)[0] == CHILD(1)[0]) { + ips_n.wrap = CHILD(0)[1].needsParenthesis(po, ips_n, CHILD(0), 2, true, true); + print_str += CHILD(0)[1].print(po, ips_n); + if(po.spacious) print_str += " "; + switch(CHILD(0).comparisonType()) { + case COMPARISON_LESS: {print_str += ">"; break;} + case COMPARISON_GREATER: {print_str += "<"; break;} + case COMPARISON_EQUALS_LESS: { + if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_GREATER_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_GREATER_OR_EQUAL; + else print_str += ">="; + break; + } + case COMPARISON_EQUALS_GREATER: { + if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_LESS_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_LESS_OR_EQUAL; + else print_str += "<="; + break; + } + default: {} + } + if(po.spacious) print_str += " "; + + ips_n.wrap = CHILD(0)[0].needsParenthesis(po, ips_n, CHILD(0), 1, true, true); + print_str += CHILD(0)[0].print(po, ips_n); + + if(po.spacious) print_str += " "; + switch(CHILD(1).comparisonType()) { + case COMPARISON_GREATER: {print_str += ">"; break;} + case COMPARISON_LESS: {print_str += "<"; break;} + case COMPARISON_EQUALS_GREATER: { + if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_GREATER_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_GREATER_OR_EQUAL; + else print_str += ">="; + break; + } + case COMPARISON_EQUALS_LESS: { + if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_LESS_OR_EQUAL, po.can_display_unicode_string_arg))) print_str += SIGN_LESS_OR_EQUAL; + else print_str += "<="; + break; + } + default: {} + } + if(po.spacious) print_str += " "; + + ips_n.wrap = CHILD(1)[1].needsParenthesis(po, ips_n, CHILD(1), 2, true, true); + print_str += CHILD(1)[1].print(po, ips_n); + + break; + } + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); + if(i > 0) { + if(po.spell_out_logical_operators) { + print_str += " "; + print_str += _("and"); + print_str += " "; + } else { + if(po.spacious) print_str += " "; + print_str += "&&"; + if(po.spacious) print_str += " "; + } + } + ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); + print_str += CHILD(i).print(po, ips_n); + } + break; + } + case STRUCT_LOGICAL_OR: { + ips_n.depth++; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); + if(i > 0) { + if(po.spell_out_logical_operators) { + print_str += " "; + print_str += _("or"); + print_str += " "; + } else { + if(po.spacious) print_str += " "; + print_str += "||"; + if(po.spacious) print_str += " "; + } + } + ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); + print_str += CHILD(i).print(po, ips_n); + } + break; + } + case STRUCT_LOGICAL_XOR: { + ips_n.depth++; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); + if(i > 0) { + print_str += " "; + print_str += "xor"; + print_str += " "; + } + ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); + print_str += CHILD(i).print(po, ips_n); + } + break; + } + case STRUCT_LOGICAL_NOT: { + print_str = "!"; + ips_n.depth++; + ips_n.wrap = CHILD(0).needsParenthesis(po, ips_n, *this, 1, true, true); + print_str += CHILD(0).print(po, ips_n); + break; + } + case STRUCT_VECTOR: { + ips_n.depth++; + print_str = "["; + for(size_t i = 0; i < SIZE; i++) { + if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); + if(i > 0) { + print_str += po.comma(); + if(po.spacious) print_str += " "; + } + ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); + print_str += CHILD(i).print(po, ips_n); + } + print_str += "]"; + break; + } + case STRUCT_UNIT: { + const ExpressionName *ename = &o_unit->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, b_plural, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); + if(o_prefix) print_str += o_prefix->name(po.abbreviate_names && ename->abbreviation, po.use_unicode_signs, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); + print_str += ename->name; + if(ename->suffix && !po.preserve_format && !po.use_reference_names) { + size_t i = print_str.rfind('_'); + if(i != string::npos && i + 5 <= print_str.length() && print_str.substr(print_str.length() - 4, 4) == "unit") { + if(i + 5 == print_str.length()) { + print_str = print_str.substr(0, i); + if(po.hide_underscore_spaces) gsub("_", " ", print_str); + } else { + print_str = print_str.substr(0, print_str.length() - 4); + } + } + } + if(po.hide_underscore_spaces && !ename->suffix) { + gsub("_", " ", print_str); + } + break; + } + case STRUCT_VARIABLE: { + const ExpressionName *ename = &o_variable->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); + print_str += ename->name; + if(ename->suffix && !po.preserve_format && !po.use_reference_names) { + size_t i = print_str.rfind('_'); + if(i != string::npos && i + 9 <= print_str.length() && print_str.substr(print_str.length() - 8, 8) == "constant") { + if(i + 9 == print_str.length()) { + print_str = print_str.substr(0, i); + if(po.hide_underscore_spaces) gsub("_", " ", print_str); + } else { + print_str = print_str.substr(0, print_str.length() - 8); + } + } + } + if(po.hide_underscore_spaces && !ename->suffix) { + gsub("_", " ", print_str); + } + break; + } + case STRUCT_FUNCTION: { + ips_n.depth++; + if(o_function->id() == FUNCTION_ID_UNCERTAINTY && SIZE == 3 && CHILD(2).isZero()) { + MathStructure *mmid = NULL, *munc = NULL; + if(o_function->id() == FUNCTION_ID_UNCERTAINTY) { + mmid = &CHILD(0); + munc = &CHILD(1); + } else if(CHILD(0)[0].equals(CHILD(1)[0], true, true)) { + mmid = &CHILD(0)[0]; + if(CHILD(0)[1].isNegate() && CHILD(0)[1][0].equals(CHILD(1)[1], true, true)) munc = &CHILD(1)[1]; + if(CHILD(1)[1].isNegate() && CHILD(1)[1][0].equals(CHILD(0)[1], true, true)) munc = &CHILD(0)[1]; + } else if(CHILD(0)[1].equals(CHILD(1)[1], true, true)) { + mmid = &CHILD(0)[1]; + if(CHILD(0)[0].isNegate() && CHILD(0)[0][0].equals(CHILD(1)[0], true, true)) munc = &CHILD(1)[0]; + if(CHILD(1)[0].isNegate() && CHILD(1)[0][0].equals(CHILD(0)[0], true, true)) munc = &CHILD(0)[0]; + } else if(CHILD(0)[0].equals(CHILD(1)[1], true, true)) { + mmid = &CHILD(0)[0]; + if(CHILD(0)[1].isNegate() && CHILD(0)[1][0].equals(CHILD(1)[0], true, true)) munc = &CHILD(1)[0]; + if(CHILD(1)[0].isNegate() && CHILD(1)[0][0].equals(CHILD(0)[1], true, true)) munc = &CHILD(0)[1]; + } else if(CHILD(0)[1].equals(CHILD(1)[0], true, true)) { + mmid = &CHILD(0)[0]; + if(CHILD(0)[0].isNegate() && CHILD(0)[0][0].equals(CHILD(1)[1], true, true)) munc = &CHILD(1)[1]; + if(CHILD(1)[1].isNegate() && CHILD(1)[1][0].equals(CHILD(0)[0], true, true)) munc = &CHILD(0)[0]; + } + if(mmid && munc) { + PrintOptions po2 = po; + po2.show_ending_zeroes = false; + po2.number_fraction_format = FRACTION_DECIMAL; + ips_n.wrap = !CHILD(0).isNumber(); + print_str += CHILD(0).print(po2, ips_n); + print_str += SIGN_PLUSMINUS; + ips_n.wrap = !CHILD(1).isNumber(); + print_str += CHILD(1).print(po2, ips_n); + break; + } + } + const ExpressionName *ename = &o_function->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg); + print_str += ename->name; + if(po.hide_underscore_spaces && !ename->suffix) { + gsub("_", " ", print_str); + } + print_str += "("; + size_t argcount = SIZE; + if(o_function->id() == FUNCTION_ID_SIGNUM && argcount > 1) { + argcount = 1; + } else if(o_function->maxargs() > 0 && o_function->minargs() < o_function->maxargs() && SIZE > (size_t) o_function->minargs()) { + while(true) { + string defstr = o_function->getDefaultValue(argcount); + Argument *arg = o_function->getArgumentDefinition(argcount); + remove_blank_ends(defstr); + if(defstr.empty()) break; + if(CHILD(argcount - 1).isUndefined() && defstr == "undefined") { + argcount--; + } else if(argcount > 1 && arg && arg->type() == ARGUMENT_TYPE_SYMBOLIC && defstr == "undefined" && CHILD(argcount - 1) == CHILD(0).find_x_var()) { + argcount--; + } else if(CHILD(argcount - 1).isVariable() && (!arg || arg->type() != ARGUMENT_TYPE_TEXT) && defstr == CHILD(argcount - 1).variable()->referenceName()) { + argcount--; + } else if(CHILD(argcount - 1).isInteger() && (!arg || arg->type() != ARGUMENT_TYPE_TEXT) && defstr.find_first_not_of(NUMBERS) == string::npos && CHILD(argcount - 1).number() == s2i(defstr)) { + argcount--; + } else if(CHILD(argcount - 1).isSymbolic() && arg && arg->type() == ARGUMENT_TYPE_TEXT && CHILD(argcount - 1).symbol() == defstr) { + argcount--; + } else { + break; + } + if(argcount == 0 || argcount == (size_t) o_function->minargs()) break; + } + } + for(size_t i = 0; i < argcount; i++) { + if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); + if(i > 0) { + print_str += po.comma(); + if(po.spacious) print_str += " "; + } + ips_n.wrap = CHILD(i).needsParenthesis(po, ips_n, *this, i + 1, true, true); + if(o_function->id() == FUNCTION_ID_INTERVAL) { + PrintOptions po2 = po; + po2.show_ending_zeroes = false; + print_str += CHILD(i).print(po2, ips_n); + } else { + print_str += CHILD(i).print(po, ips_n); + } + } + print_str += ")"; + break; + } + case STRUCT_UNDEFINED: { + print_str = _("undefined"); + break; + } + } + if(CALCULATOR->aborted()) print_str = CALCULATOR->abortedMessage(); + if(ips.wrap) { + print_str.insert(0, "("); + print_str += ")"; + } + return print_str; +} + diff -Nru libqalculate-3.6.0/libqalculate/MathStructure-support.h libqalculate-3.7.0/libqalculate/MathStructure-support.h --- libqalculate-3.6.0/libqalculate/MathStructure-support.h 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/MathStructure-support.h 2020-01-21 22:54:40.000000000 +0000 @@ -0,0 +1,134 @@ +/* + Qalculate (library) + + Copyright (C) 2003-2007, 2008, 2016-2019 Hanna Knutsson (hanna.knutsson@protonmail.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#ifndef MATHSTRUCTURE_SUPPORT_H +#define MATHSTRUCTURE_SUPPORT_H + +#include "support.h" + +#include "MathStructure.h" + +#define SWAP_CHILDREN(i1, i2) {MathStructure *swap_mstruct = v_subs[v_order[i1]]; v_subs[v_order[i1]] = v_subs[v_order[i2]]; v_subs[v_order[i2]] = swap_mstruct;} +#define CHILD_TO_FRONT(i) v_order.insert(v_order.begin(), v_order[i]); v_order.erase(v_order.begin() + (i + 1)); +#define SET_CHILD_MAP(i) setToChild(i + 1, true); +#define SET_MAP(o) set(o, true); +#define SET_MAP_NOCOPY(o) set_nocopy(o, true); +#define MERGE_APPROX_AND_PREC(o) if(!b_approx && o.isApproximate()) b_approx = true; if(o.precision() > 0 && (i_precision < 1 || o.precision() < i_precision)) i_precision = o.precision(); +#define CHILD_UPDATED(i) if(!b_approx && CHILD(i).isApproximate()) b_approx = true; if(CHILD(i).precision() > 0 && (i_precision < 1 || CHILD(i).precision() < i_precision)) i_precision = CHILD(i).precision(); +#define CHILDREN_UPDATED for(size_t child_i = 0; child_i < SIZE; child_i++) {if(!b_approx && CHILD(child_i).isApproximate()) b_approx = true; if(CHILD(child_i).precision() > 0 && (i_precision < 1 || CHILD(child_i).precision() < i_precision)) i_precision = CHILD(child_i).precision();} + +#define APPEND(o) v_order.push_back(v_subs.size()); v_subs.push_back(new MathStructure(o)); if(!b_approx && o.isApproximate()) b_approx = true; if(o.precision() > 0 && (i_precision < 1 || o.precision() < i_precision)) i_precision = o.precision(); +#define APPEND_NEW(o) {v_order.push_back(v_subs.size()); MathStructure *m_append_new = new MathStructure(o); v_subs.push_back(m_append_new); if(!b_approx && m_append_new->isApproximate()) b_approx = true; if(m_append_new->precision() > 0 && (i_precision < 1 || m_append_new->precision() < i_precision)) i_precision = m_append_new->precision();} +#define APPEND_COPY(o) v_order.push_back(v_subs.size()); v_subs.push_back(new MathStructure(*(o))); if(!b_approx && (o)->isApproximate()) b_approx = true; if((o)->precision() > 0 && (i_precision < 1 || (o)->precision() < i_precision)) i_precision = (o)->precision(); +#define APPEND_POINTER(o) v_order.push_back(v_subs.size()); v_subs.push_back(o); if(!b_approx && (o)->isApproximate()) b_approx = true; if((o)->precision() > 0 && (i_precision < 1 || (o)->precision() < i_precision)) i_precision = (o)->precision(); +#define APPEND_REF(o) v_order.push_back(v_subs.size()); v_subs.push_back(o); (o)->ref(); if(!b_approx && (o)->isApproximate()) b_approx = true; if((o)->precision() > 0 && (i_precision < 1 || (o)->precision() < i_precision)) i_precision = (o)->precision(); +#define PREPEND(o) v_order.insert(v_order.begin(), v_subs.size()); v_subs.push_back(new MathStructure(o)); if(!b_approx && o.isApproximate()) b_approx = true; if(o.precision() > 0 && (i_precision < 1 || o.precision() < i_precision)) i_precision = o.precision(); +#define PREPEND_REF(o) v_order.insert(v_order.begin(), v_subs.size()); v_subs.push_back(o); (o)->ref(); if(!b_approx && (o)->isApproximate()) b_approx = true; if((o)->precision() > 0 && (i_precision < 1 || (o)->precision() < i_precision)) i_precision = (o)->precision(); +#define INSERT_REF(o, i) v_order.insert(v_order.begin() + i, v_subs.size()); v_subs.push_back(o); (o)->ref(); if(!b_approx && (o)->isApproximate()) b_approx = true; if((o)->precision() > 0 && (i_precision < 1 || (o)->precision() < i_precision)) i_precision = (o)->precision(); +#define CLEAR v_order.clear(); for(size_t i = 0; i < v_subs.size(); i++) {v_subs[i]->unref();} v_subs.clear(); +//#define REDUCE(v_size) for(size_t v_index = v_size; v_index < v_order.size(); v_index++) {v_subs[v_order[v_index]]->unref(); v_subs.erase(v_subs.begin() + v_order[v_index]);} v_order.resize(v_size); +#define REDUCE(v_size) {std::vector v_tmp; v_tmp.resize(SIZE, 0); for(size_t v_index = v_size; v_index < v_order.size(); v_index++) {v_subs[v_order[v_index]]->unref(); v_subs[v_order[v_index]] = NULL; v_tmp[v_order[v_index]] = 1;} v_order.resize(v_size); for(std::vector::iterator v_it = v_subs.begin(); v_it != v_subs.end();) {if(*v_it == NULL) v_it = v_subs.erase(v_it); else ++v_it;} size_t i_change = 0; for(size_t v_index = 0; v_index < v_tmp.size(); v_index++) {if(v_tmp[v_index] == 1) i_change++; v_tmp[v_index] = i_change;} for(size_t v_index = 0; v_index < v_order.size(); v_index++) v_order[v_index] -= v_tmp[v_index];} +#define CHILD(v_index) (*v_subs[v_order[v_index]]) +#define SIZE v_order.size() +#define LAST (*v_subs[v_order[v_order.size() - 1]]) +#define ERASE(v_index) v_subs[v_order[v_index]]->unref(); v_subs.erase(v_subs.begin() + v_order[v_index]); for(size_t v_index2 = 0; v_index2 < v_order.size(); v_index2++) {if(v_order[v_index2] > v_order[v_index]) v_order[v_index2]--;} v_order.erase(v_order.begin() + (v_index)); + +#define IS_REAL(o) (o.isNumber() && o.number().isReal()) +#define IS_RATIONAL(o) (o.isNumber() && o.number().isRational()) + +#define IS_A_SYMBOL(o) ((o.isSymbolic() || o.isVariable() || o.isFunction()) && o.representsScalar()) + +#define POWER_CLEAN(o) if(o[1].isOne()) {o.setToChild(1);} else if(o[1].isZero()) {o.set(1, 1, 0);} + +#define VALID_ROOT(o) (o.size() == 2 && o[1].isNumber() && o[1].number().isInteger() && o[1].number().isPositive()) +#define THIS_VALID_ROOT (SIZE == 2 && CHILD(1).isNumber() && CHILD(1).number().isInteger() && CHILD(1).number().isPositive()) + +#define FUNCTION_PROTECTED(evalops, id) (evalops.protected_function != NULL && evalops.protected_function == CALCULATOR->getFunctionById(id)) + +void printRecursive(const MathStructure &mstruct); + +std::string format_and_print(const MathStructure &mstruct); + +struct sym_desc { + MathStructure sym; + Number deg_a; + Number deg_b; + Number ldeg_a; + Number ldeg_b; + Number max_deg; + size_t max_lcnops; + bool operator<(const sym_desc &x) const; +}; +typedef std::vector sym_desc_vec; + +bool polynomial_long_division(const MathStructure &mnum, const MathStructure &mden, const MathStructure &xvar_pre, MathStructure &mquotient, MathStructure &mrem, const EvaluationOptions &eo, bool check_args = false, bool for_newtonraphson = false); +void integer_content(const MathStructure &mpoly, Number &icontent); +bool interpolate(const MathStructure &gamma, const Number &xi, const MathStructure &xvar, MathStructure &minterp, const EvaluationOptions &eo); +bool get_first_symbol(const MathStructure &mpoly, MathStructure &xvar); +bool divide_in_z(const MathStructure &mnum, const MathStructure &mden, MathStructure &mquotient, const sym_desc_vec &sym_stats, size_t var_i, const EvaluationOptions &eo); +bool prem(const MathStructure &mnum, const MathStructure &mden, const MathStructure &xvar, MathStructure &mrem, const EvaluationOptions &eo, bool check_args = true); +bool sr_gcd(const MathStructure &m1, const MathStructure &m2, MathStructure &mgcd, const sym_desc_vec &sym_stats, size_t var_i, const EvaluationOptions &eo); +void polynomial_smod(const MathStructure &mpoly, const Number &xi, MathStructure &msmod, const EvaluationOptions &eo, MathStructure *mparent = NULL, size_t index_smod = 0); +bool heur_gcd(const MathStructure &m1, const MathStructure &m2, MathStructure &mgcd, const EvaluationOptions &eo, MathStructure *ca, MathStructure *cb, const sym_desc_vec &sym_stats, size_t var_i); +void add_symbol(const MathStructure &mpoly, sym_desc_vec &v); +void collect_symbols(const MathStructure &mpoly, sym_desc_vec &v); +void add_symbol(const MathStructure &mpoly, std::vector &v); +void collect_symbols(const MathStructure &mpoly, std::vector &v); +void get_symbol_stats(const MathStructure &m1, const MathStructure &m2, sym_desc_vec &v); +bool sqrfree(MathStructure &mpoly, const EvaluationOptions &eo); +bool sqrfree(MathStructure &mpoly, const std::vector &symbols, const EvaluationOptions &eo); +bool simplify_functions(MathStructure &mstruct, const EvaluationOptions &eo, const EvaluationOptions &feo, const MathStructure &x_var = m_undefined); +bool factorize_find_multiplier(const MathStructure &mstruct, MathStructure &mnew, MathStructure &factor_mstruct, bool only_units = false); +bool is_unit_multiexp(const MathStructure &mstruct); +bool has_approximate_relation_to_base(Unit *u, bool do_intervals = true); +bool contains_approximate_relation_to_base(const MathStructure &m, bool do_intervals = true); +bool contains_diff_for(const MathStructure &m, const MathStructure &x_var); +bool separate_unit_vars(MathStructure &m, const EvaluationOptions &eo, bool only_approximate, bool dry_run = false); +void lcm_of_coefficients_denominators(const MathStructure &e, Number &nlcm); +void multiply_lcm(const MathStructure &e, const Number &lcm, MathStructure &mmul, const EvaluationOptions &eo); +bool do_simplification(MathStructure &mstruct, const EvaluationOptions &eo, bool combine_divisions = true, bool only_gcd = false, bool combine_only = false, bool recursive = true, bool limit_size = false, int i_run = 1); +bool warn_about_assumed_not_value(const MathStructure &mstruct, const MathStructure &mvalue, const EvaluationOptions &eo); +bool warn_about_denominators_assumed_nonzero(const MathStructure &mstruct, const EvaluationOptions &eo); +bool warn_about_denominators_assumed_nonzero_or_positive(const MathStructure &mstruct, const MathStructure &mstruct2, const EvaluationOptions &eo); +bool warn_about_denominators_assumed_nonzero_llgg(const MathStructure &mstruct, const MathStructure &mstruct2, const MathStructure &mstruct3, const EvaluationOptions &eo); +bool is_differentiable(const MathStructure &m); +int test_comparisons(const MathStructure &msave, MathStructure &mthis, const MathStructure &x_var, const EvaluationOptions &eo, bool sub = false, int alt = 0); +bool replace_function(MathStructure &m, MathFunction *f1, MathFunction *f2, const EvaluationOptions &eo); +bool replace_intervals_f(MathStructure &mstruct); +bool replace_f_interval(MathStructure &mstruct, const EvaluationOptions &eo); +bool fix_intervals(MathStructure &mstruct, const EvaluationOptions &eo, bool *failed = NULL, long int min_precision = 2, bool function_middle = false); +bool set_uncertainty(MathStructure &mstruct, MathStructure &munc, const EvaluationOptions &eo = default_evaluation_options, bool do_eval = false); +bool create_interval(MathStructure &mstruct, const MathStructure &m1, const MathStructure &m2); +bool combine_powers(MathStructure &m, const MathStructure &x_var, const EvaluationOptions &eo); +bool contains_angle_unit(const MathStructure &m, const ParseOptions &po); +bool has_predominately_negative_sign(const MathStructure &mstruct); +void negate_struct(MathStructure &mstruct); +bool test_eval(MathStructure &mtest, const EvaluationOptions &eo); +bool has_interval_unknowns(MathStructure &m); +bool flattenMultiplication(MathStructure &mstruct); +void idm1(const MathStructure &mnum, bool &bfrac, bool &bint); +void idm2(const MathStructure &mnum, bool &bfrac, bool &bint, Number &nr); +int idm3(MathStructure &mnum, Number &nr, bool expand); +bool combination_factorize(MathStructure &mstruct); +bool replace_interval_unknowns(MathStructure &m, bool do_assumptions = false); +bool remove_rad_unit(MathStructure &m, const EvaluationOptions &eo, bool top = true); +int contains_ass_intval(const MathStructure &m); +int compare_check_incompability(MathStructure *mtest); +bool calculate_nondifferentiable_functions(MathStructure &m, const EvaluationOptions &eo, bool recursive = true, bool do_unformat = true, int i_type = 0); +bool function_differentiable(MathFunction *o_function); +bool montecarlo(const MathStructure &minteg, Number &nvalue, const MathStructure &x_var, const EvaluationOptions &eo, Number a, Number b, Number n); +bool romberg(const MathStructure &minteg, Number &nvalue, const MathStructure &x_var, const EvaluationOptions &eo, Number a, Number b, long int max_steps = -1, long int min_steps = 6, bool safety_measures = true); +bool sync_approximate_units(MathStructure &m, const EvaluationOptions &feo, std::vector *vars = NULL, std::vector *uncs = NULL, bool do_intervals = true); +void fix_to_struct(MathStructure &m); +int has_information_unit(const MathStructure &m, bool top = true); + +#endif + diff -Nru libqalculate-3.6.0/libqalculate/Number.cc libqalculate-3.7.0/libqalculate/Number.cc --- libqalculate-3.6.0/libqalculate/Number.cc 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Number.cc 2020-01-21 22:54:40.000000000 +0000 @@ -12,7 +12,9 @@ #include "support.h" #include "Number.h" +#include "bernoulli_numbers.h" #include "Calculator.h" +#include "BuiltinFunctions.h" #include "Function.h" #include "Variable.h" @@ -28,6 +30,7 @@ using std::endl; #define BIT_PRECISION ((long int) ((PRECISION) * 3.3219281) + 100) +#define NUMBER_BIT_PRECISION (n_type == NUMBER_TYPE_FLOAT ? mpfr_get_prec(fl_value) : BIT_PRECISION) #define PRECISION_TO_BITS(p) (((p) * 3.3219281) + 100) #define BITS_TO_PRECISION(p) (::ceil(((p) - 100) / 3.3219281)) @@ -62,6 +65,7 @@ size_t i; if(i_deci != string::npos) { i = i_deci; + // no separator is currently used among decimals /*i += 5 + po.decimalpoint().length(); while(i < str.length()) { str.insert(i, po.thousandsseparator()); @@ -81,9 +85,11 @@ i -= group_size; if(po.digit_grouping != DIGIT_GROUPING_LOCALE) { #ifdef _WIN32 + // do not use thin space on Windows str.insert(i, " "); #else if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (" ", po.can_display_unicode_string_arg))) { + // thin space is preferred str.insert(i, " "); } else { str.insert(i, " "); @@ -104,6 +110,7 @@ string format_number_string(string cl_str, int base, BaseDisplay base_display, bool show_neg, bool format_base_two = true, const PrintOptions &po = default_print_options) { if(format_base_two && (base == 2 || (base == 16 && po.binary_bits >= 8)) && base_display != BASE_DISPLAY_NONE) { + // use an appropriate number of bits (digits) for binary and hexadecimal numbers unsigned int bits = po.binary_bits; size_t l = cl_str.find(po.decimalpoint()); if(l == string::npos) l = cl_str.length(); @@ -120,6 +127,7 @@ cl_str = str + cl_str; l = bits; } + // place binary digits in groups of four if(base == 2 && base_display == BASE_DISPLAY_NORMAL) { for(int i = (int) l - 4; i > 0; i -= 4) { cl_str.insert(i, 1, ' '); @@ -147,6 +155,7 @@ } } if(base == BASE_DUODECIMAL) { + // use X and E instead of A and B for duodecimal numbers for(size_t i = 0; i < cl_str.length(); i++) { if(cl_str[i] == 'A' || cl_str[i] == 'a' || cl_str[i] == 'X') { if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) ("↊", po.can_display_unicode_string_arg))) {cl_str.replace(i, 1, "↊"); i += strlen("↊") - 1;} @@ -339,12 +348,15 @@ void Number::set(string number, const ParseOptions &po) { if(po.base == BASE_BIJECTIVE_26) { + // Bijective base 26 (digits A-Z, case insensitive, A=1) remove_blanks(number); clear(); string str = number; + // remove characters other than a-z, A-Z for(size_t i = 0; i < str.length();) { if(!(str[i] >= 'a' && str[i] <= 'z') && !(str[i] >= 'A' && str[i] <= 'Z')) { size_t n = 1; + // include whole Unicode character in error message while(i + n < str.length() && str[i + n] < 0 && (unsigned char) str[i + n] < 0xC0) { n++; } @@ -354,6 +366,7 @@ i++; } } + // ABC...=1*26^(n-1)+2*26^(n-2)+3*26^(n-3)... + c_n*26^0 (n = number of digits) for(size_t i = 0; i < str.length(); i++) { Number nri(26); nri ^= (str.length() - i - 1); @@ -364,9 +377,11 @@ return; } if(po.base < BASE_CUSTOM || (po.base == BASE_CUSTOM && (!CALCULATOR->customInputBase().isInteger() || CALCULATOR->customInputBase() < 2 || CALCULATOR->customInputBase() > 62))) { + // handle non-integer bases, negative bases and bases > 62 Number base; switch(po.base) { case BASE_GOLDEN_RATIO: { + // golden ratio = (sqrt(5)+1)/2 base.set(5); base.sqrt(); base.add(1); @@ -374,17 +389,22 @@ break; } case BASE_SUPER_GOLDEN_RATIO: { + // supergolden ratio = (1+cbrt((29+3*sqrt(93))/2)+cbrt((29-3*sqrt(93))/2))/3 + // a=3*sqrt(93) base.set(93); base.sqrt(); base.multiply(3); + // b=cbrt((29-a)/2) Number b2(base); b2.negate(); b2.add(29); b2.divide(2); b2.cbrt(); + // c=cbrt((29+a)/2) base.add(29); base.divide(2); base.cbrt(); + // (1+a+b)/3 base.add(b2); base.add(1); base.divide(3); @@ -393,20 +413,26 @@ case BASE_PI: {base.pi(); break;} case BASE_E: {base.e(); break;} case BASE_SQRT2: {base.set(2); base.sqrt(); break;} + // Unicode base uses all 1114111 Unicode characters as digits case BASE_UNICODE: {base.set(1114112L); break;} default: {base = CALCULATOR->customInputBase();} } + // abs_base=number of digits used by the number base Number abs_base(base); abs_base.abs(); abs_base.ceil(); if(abs_base < 2) abs_base = 2; + // position of decimal separator size_t i_dot = number.length(); vector digits; bool b_minus = false; if(abs_base <= 62) { + // whitespace is ignored remove_blanks(number); + // bases over 36 are case insensitive bool b_case = abs_base > 36; i_dot = number.length(); + // iterate the string and place the value of each recognized digit in a vector (base <= abs(62) uses digits 0-9, a-z, A-Z) for(size_t i = 0; i < number.length(); i++) { long int c = -1; if(number[i] >= '0' && number[i] <= '9') { @@ -417,11 +443,15 @@ } else if(number[i] >= 'A' && number[i] <= 'Z') { c = number[i] - 'A' + 10; } else if(number[i] == '.') { + // save the position of the first dot as decimal separator position if(i_dot == number.length()) i_dot = digits.size(); } else if(number[i] == '-' && digits.empty()) { + // number starts with minus b_minus = !b_minus; } else { + // unrecognized character string str_char = number.substr(i, 1); + // include whole Unicode character in error message while(i + 1 < number.length() && number[i + 1] < 0 && (unsigned char) number[i + 1] < 0xC0) { i++; str_char += number[i]; @@ -430,26 +460,32 @@ } if(c >= 0) { if(abs_base <= c && !abs_base.isFraction()) { + // digit value is higher than allowed by the base: show a warning, but use anyway CALCULATOR->error(false, _("Digit \'%s\' is too high for number base."), number.substr(i, 1).c_str(), NULL); } digits.push_back(c); } } } else { + // iterate the string and place the value of each recognized digit in a vector + // bases with absolute value over 62 uses Unicode characters as digits with the Unicode code as digit value for(size_t i = 0; i < number.length(); i++) { size_t i_prev = i; long int c = (unsigned char) number[i]; bool b_esc = false; if(number[i] == '\\' && i < number.length() - 1) { + // backslash is used for specifying the digit value at the current position directly (escaped value) i++; Number nrd; if(is_in(NUMBERS, number[i])) { + // value begins with a decimal digit (0-9): read as decimal number to the next non-decimal digit size_t i2 = number.find_first_not_of(NUMBERS, i); if(i2 == string::npos) i2 = number.length(); nrd.set(number.substr(i, i2 - i)); i = i2 - 1; b_esc = true; } else if(number[i] == 'x' && i < number.length() - 1 && is_in(NUMBERS "ABCDEFabcdef", number[i + 1])) { + // value begins with a x, follow by a hexadecimal digit (0-9, a-z, A-Z): read as hexadecimal number to the next non-hexadecimal digit i++; size_t i2 = number.find_first_not_of(NUMBERS "ABCDEFabcdef", i); if(i2 == string::npos) i2 = number.length(); @@ -460,26 +496,32 @@ b_esc = true; } if(digits.empty() && number[i] == (char) -30 && i + 3 < number.length() && number[i + 1] == (char) -120 && number[i + 2] == (char) -110) { + // \ follow by Unicode subtraction symbol: read as minus i += 2; b_minus = !b_minus; b_esc = true; } else if(digits.empty() && number[i] == '-') { + // \-: read as minus b_minus = !b_minus; b_esc = true; } else if(i_dot == number.size() && (number[i] == CALCULATOR->getDecimalPoint()[0] || (!po.dot_as_separator && number[i] == '.'))) { + // \.: read as decimal separator i_dot = digits.size(); b_esc = true; } else if(b_esc) { + // digit value found, check if value is allowed by base and show a warning if not (use anyway) if(abs_base.isLessThanOrEqualTo(nrd)) { CALCULATOR->error(false, _("Digit \'%s\' is too high for number base."), number.substr(i_prev, i - i_prev + 1).c_str(), NULL); } digits.push_back(nrd); } else if(number[i] != '\\') { + // \\: read as \ digit i--; } } if(!b_esc) { + // not an escaped value: read the whole Unicode character and calculate the Unicode code if((c & 0x80) != 0) { if(c<0xe0) { i++; @@ -498,6 +540,7 @@ } } if(abs_base.isLessThanOrEqualTo(c)) { + // digit value is higher than allowed by base: show a warning, but use anyway CALCULATOR->error(false, _("Digit \'%s\' is too high for number base."), number.substr(i_prev, i - i_prev + 1).c_str(), NULL); } digits.push_back(c); @@ -507,6 +550,7 @@ clear(); if(i_dot > digits.size()) i_dot = digits.size(); Number nr_mul; + // value=d_0*base^(n-1)+d_1*base^(n-2)+d_2*base^(n-3)... + d_(n - 1) (n = number of digits, d_i=digit from left to right) for(size_t i = 0; i < digits.size(); i++) { long int exp = i_dot - 1 - i; if(exp != 0) { @@ -516,18 +560,23 @@ } add(digits[i]); } + // if number string begins with an odd number of minus symbols, negate the value if(b_minus) negate(); return; } + // look for +/- for specified uncertainty of number size_t pm_index = number.find(SIGN_PLUSMINUS); if(pm_index == string::npos) pm_index = number.find("+/-"); if(pm_index != string::npos) { ParseOptions po2 = po; + // +/- overrides read precision option po2.read_precision = DONT_READ_PRECISION; + // read number without uncertainty set(number.substr(0, pm_index), po2); number = number.substr(pm_index + (number[pm_index] == '+' ? strlen("+/-") : strlen(SIGN_PLUSMINUS))); if(!number.empty()) { + // read number after +/- and set uncertainty Number pm_nr(number, po2); setUncertainty(pm_nr); } @@ -535,6 +584,7 @@ } if(po.base == BASE_ROMAN_NUMERALS) { + // read roman numerals remove_blanks(number); string number_bak = number; bool rev_c = (number.find("Ɔ") != string::npos); @@ -735,6 +785,7 @@ return; } + // read numbers with positive integer bases >=2 and <= 36 int base = po.base; if(base == BASE_CUSTOM) base = CALCULATOR->customInputBase().intValue(); else if(base < 2 || base > 36) base = 10; @@ -746,6 +797,8 @@ mpz_init_set_ui(den, 1); remove_blank_ends(number); + + // remove base prefixes if(po.base == 16 && number.length() >= 2 && number[0] == '0' && (number[1] == 'x' || number[1] == 'X')) { number = number.substr(2, number.length() - 2); } else if(po.base == 8 && number.length() >= 2 && number[0] == '0' && (number[1] == 'o' || number[1] == 'O')) { @@ -755,24 +808,31 @@ } else if(po.base == 2 && number.length() >= 2 && number[0] == '0' && (number[1] == 'b' || number[1] == 'B')) { number = number.substr(2, number.length() - 2); } + + // determine if value is negative for numbers using binary or hexadecimal complement representation (number that begins with 1 or 8 is negative) bool b_twos = (po.twos_complement && po.base == 2 && number.length() > 1 && number[0] == '1') || (po.hexadecimal_twos_complement && po.base == 16 && number.length() > 0 && (number[0] == '8' || number[0] == '9' || (number[0] >= 'a' && number[0] <= 'f') || (number[0] >= 'A' && number[0] <= 'F'))); long int readprec = 0; bool numbers_started = false, minus = false, in_decimals = false, b_cplx = false, had_nonzero = false; for(size_t index = 0; index < number.size(); index++) { if(number[index] >= '0' && ((base >= 10 && number[index] <= '9') || (base < 10 && number[index] < '0' + base))) { + // multiply previous value with base mpz_mul_si(num, num, base); if(number[index] != (b_twos ? '0' + (base - 1) : '0')) { + // for negative numbers using complement representation, digit value = base - digit - 1 (e.g. 0=1, 1=0 in binary base) mpz_add_ui(num, num, b_twos ? (unsigned long int) (base - 1) - (number[index] - '0') : (unsigned long int) number[index] - '0'); + // ignore zeroes at the beginning of the number when determining the number of significant digits if(!had_nonzero) readprec = 0; had_nonzero = true; } if(in_decimals) { + // if after decimal separator: multiply denominator by base mpz_mul_si(den, den, base); } readprec++; numbers_started = true; } else if(po.base == BASE_DUODECIMAL && (number[index] == 'X' || number[index] == 'E' || number[index] == 'x' || number[index] == 'e')) { + // duo decimal numbers uses X and E instead of A and B mpz_mul_si(num, num, base); mpz_add_ui(num, num, (number[index] == 'E' || number[index] == 'e') ? 11L : 10L); if(in_decimals) { @@ -785,6 +845,8 @@ } else if(base > 10 && number[index] >= 'a' && number[index] < 'a' + base - (base > 36 ? 36 : 10)) { mpz_mul_si(num, num, base); if(!b_twos || (number[index] != 'a' + (base - (base > 36 ? 37 : 11)))) { + // for negative numbers using complement representation, digit value = base - digit - 1 (e.g. F=0, 0=15 (F) in hexadecimal base) + // for bases over 36 digits are case sensitive mpz_add_ui(num, num, b_twos ? (unsigned long int) (base - 1) - (number[index] - 'a' + (base > 36 ? 36 : 10)) : (unsigned long int) number[index] - 'a' + (base > 36 ? 36 : 10)); if(!had_nonzero) readprec = 0; had_nonzero = true; @@ -812,6 +874,7 @@ bool exp_minus = false; unsigned long int exp = 0; unsigned long int max_exp = ULONG_MAX / 10; + // scientific e-notation: read base-10 exponent after E while(index < number.size()) { if(number[index] >= '0' && number[index] <= '9') { if(exp > max_exp) { @@ -827,6 +890,7 @@ index++; } if(exp_minus) { + // if negative exponent multiply denominator mpz_t e_den; mpz_init(e_den); mpz_ui_pow_ui(e_den, 10, exp); @@ -834,6 +898,7 @@ if(i_unc > 0) mpz_mul(mpq_denref(unc), mpq_denref(unc), e_den); mpz_clear(e_den); } else { + // if positive exponent multiply numerator mpz_t e_num; mpz_init(e_num); mpz_ui_pow_ui(e_num, 10, exp); @@ -846,7 +911,9 @@ if(in_decimals) CALCULATOR->error(false, "Misplaced decimal separator ignored", NULL); else in_decimals = true; } else if(number[index] == ':') { + // sexagesimal number if(in_decimals) { + // only allow decimals after last ":" CALCULATOR->error(true, _("\':\' in decimal number ignored (decimal point detected)."), NULL); } else { size_t index_colon = index; @@ -875,9 +942,11 @@ } } else if(!numbers_started && number[index] == '-') { minus = !minus; - } else if(number[index] == 'i' || (CALCULATOR && number[index] == 'j' && CALCULATOR->v_i->hasName("j"))) { + } else if(number[index] == 'i' || (CALCULATOR && number[index] == 'j' && CALCULATOR->getVariableById(VARIABLE_ID_I)->hasName("j"))) { + // i or j (if imaginary i variable has j name) found: number is imaginary b_cplx = true; } else if(base == 10 && number[index] == '(' && index <= number.length() - 2) { + // two digits in parentheses at the end of number speicifies the uncertainty of the previous two digits size_t par_i = number.find(')', index + 1); if(par_i == string::npos) { i_unc = s2i(number.substr(index + 1)); @@ -893,6 +962,7 @@ } } else if(number[index] != ' ') { string str_char = number.substr(index, 1); + // unrecognized digit: read whole Unicode character and show error while(index + 1 < number.length() && number[index + 1] < 0 && (unsigned char) number[index + 1] < 0xC0) { index++; str_char += number[index]; @@ -906,6 +976,11 @@ } clear(); if(i_unc <= 0 && (po.read_precision == ALWAYS_READ_PRECISION || (in_decimals && po.read_precision == READ_PRECISION_WHEN_DECIMALS))) { + + // read precision: uncertainty = value of last digit / 2 (e.g. 22.0=22.0+/-0.05) + // upper end point = ((num * 2) + 1)/(den * 2) + // lower end point = ((num * 2) - 1)/(den * 2) + mpz_mul_si(num, num, 2); mpz_mul_si(den, den, 2); @@ -928,10 +1003,12 @@ mpfr_init2(fl_value, BIT_PRECISION); mpfr_clear_flags(); + // numbers with uncertainty/interval are always floating point mpfr_set_q(fu_value, minus ? rv2 : rv1, MPFR_RNDD); mpfr_set_q(fl_value, minus ? rv1 : rv2, MPFR_RNDU); - for(int i = 0; i < 3; i++) {mpfr_nextbelow(fu_value); mpfr_nextabove(fl_value);} + // avoid rounding issues when displaying the significant digits of the number + for(int i = 0; i < 3; i++) {mpfr_nextbelow(fu_value); mpfr_nextabove(fl_value);} if(mpfr_cmp(fl_value, fu_value) > 0) mpfr_swap(fl_value, fu_value); @@ -942,6 +1019,7 @@ testErrors(2); if(b_cplx) { + // i was found: this is an imaginary number if(!i_value) {i_value = new Number(); i_value->markAsImaginaryPart();} i_value->set(*this, false, true); clearReal(); @@ -951,31 +1029,23 @@ } else { if(minus) mpz_neg(num, num); if(b_cplx) { + // i was found: this is an imaginary number if(!i_value) {i_value = new Number(); i_value->markAsImaginaryPart();} i_value->setInternal(num, den, false, true); mpq_canonicalize(i_value->internalRational()); } else { + // set numerator and denominator of rational value mpz_set(mpq_numref(r_value), num); mpz_set(mpq_denref(r_value), den); mpq_canonicalize(r_value); } if(i_unc > 0) { + // set uncertainty specified in parentheses at end of number string Number nr_unc; mpq_canonicalize(unc); nr_unc.setInternal(unc); setUncertainty(nr_unc); mpq_clear(unc); - } else if(po.read_precision == ALWAYS_READ_PRECISION || (in_decimals && po.read_precision == READ_PRECISION_WHEN_DECIMALS)) { - if(base != 10) { - Number precmax(10); - precmax.raise(readprec); - precmax--; - precmax.log(base); - precmax.floor(); - readprec = precmax.intValue(); - } - if(b_cplx) i_value->setPrecision(readprec); - setPrecision(readprec); } } mpz_clears(num, den, NULL); @@ -1100,6 +1170,10 @@ else if(i_value) setPrecisionAndApproximateFrom(*i_value); } void Number::setInternal(const mpfr_t &mpfr_value, bool merge_precision, bool keep_imag) { + if(mpfr_inf_p(mpfr_value)) { + if(mpfr_sgn(mpfr_value) > 0) {setPlusInfinity(merge_precision, keep_imag); return;} + if(mpfr_sgn(mpfr_value) < 0) {setMinusInfinity(merge_precision, keep_imag); return;} + } b_approx = true; if(n_type != NUMBER_TYPE_FLOAT) {mpfr_init2(fu_value, BIT_PRECISION); mpfr_init2(fl_value, BIT_PRECISION);} if(CREATE_INTERVAL) { @@ -1292,7 +1366,8 @@ } else if(i_value && !i_value->intervalToPrecision()) return false; return true; } -void Number::intervalToMidValue() { +void Number::intervalToMidValue(bool increase_precision_if_close) { + if(i_value) i_value->intervalToMidValue(); if(n_type == NUMBER_TYPE_FLOAT && !mpfr_equal_p(fl_value, fu_value)) { if(mpfr_inf_p(fl_value) || mpfr_inf_p(fu_value)) { if(mpfr_inf_p(fl_value) && mpfr_inf_p(fu_value) && mpfr_sgn(fl_value) != mpfr_sgn(fu_value)) clearReal(); @@ -1300,15 +1375,25 @@ else mpfr_set(fl_value, fu_value, MPFR_RNDN); } else { mpfr_clear_flags(); - mpfr_sub(fu_value, fu_value, fl_value, MPFR_RNDN); - mpfr_div_ui(fu_value, fu_value, 2, MPFR_RNDN); - mpfr_add(fl_value, fl_value, fu_value, MPFR_RNDN); - mpfr_set(fu_value, fl_value, MPFR_RNDN); + mpfr_nextbelow(fu_value); + if(!mpfr_equal_p(fl_value, fu_value)) { + mpfr_nextabove(fu_value); + mpfr_sub(fu_value, fu_value, fl_value, MPFR_RNDN); + mpfr_div_ui(fu_value, fu_value, 2, MPFR_RNDN); + mpfr_add(fl_value, fl_value, fu_value, MPFR_RNDN); + mpfr_set(fu_value, fl_value, MPFR_RNDN); + } else if(increase_precision_if_close) { + mpfr_set_prec(fl_value, mpfr_get_prec(fu_value) + 1); + mpfr_set(fl_value, fu_value, MPFR_RNDN); + mpfr_nextbelow(fl_value); + mpfr_set_prec(fu_value, mpfr_get_prec(fl_value)); + mpfr_set(fu_value, fl_value, MPFR_RNDN); + } if(!testFloatResult()) clearReal(); } } - if(i_value) i_value->intervalToMidValue(); } +void Number::intervalToMidValue() {return intervalToMidValue(false);} void Number::splitInterval(unsigned int nr_of_parts, vector &v) const { if(n_type == NUMBER_TYPE_FLOAT && isReal()) { if(nr_of_parts == 2) { @@ -1995,6 +2080,8 @@ } bool testComplex(Number *this_nr, Number *i_nr) { + // remove imaginary or real part if zero using the magnitude and (internal) precision of the opposite part (e.g. 1e100+1e-100i=1e100) + // this might be problematic in some situations, but generally makes life easier... if(!i_nr) return false; if(!this_nr->isInfinite(true) && !i_nr->isInfinite(true) && !i_nr->isZero() && !this_nr->isZero()) { if(i_nr->isFloatingPoint() && (!i_nr->isInterval() || !i_nr->isNonZero())) { @@ -2069,6 +2156,7 @@ return false; } bool Number::testFloatResult(bool allow_infinite_result, int error_level, bool test_integer) { + // test calculated floating point value and show mpfr errors (show as errors if error_level > 1, show as warnings if error_level = 1, do not generate message if error_level is zero) if(mpfr_underflow_p()) {if(error_level) CALCULATOR->error(error_level > 1, _("Floating point underflow"), NULL); return false;} if(mpfr_overflow_p()) {if(error_level) CALCULATOR->error(error_level > 1, _("Floating point overflow"), NULL); return false;} if(mpfr_divby0_p()) {if(error_level) CALCULATOR->error(error_level > 1, _("Floating point division by zero exception"), NULL); return false;} @@ -2076,11 +2164,13 @@ if(mpfr_nan_p(fu_value) || mpfr_nan_p(fl_value)) return false; if(mpfr_nanflag_p()) {if(error_level) CALCULATOR->error(error_level > 1, _("Floating point not a number exception"), NULL); return false;} if(mpfr_inexflag_p()) { + // calculated value is approximate b_approx = true; if(!CREATE_INTERVAL && !isInterval() && (i_precision < 0 || i_precision > FROM_BIT_PRECISION(BIT_PRECISION))) i_precision = FROM_BIT_PRECISION(BIT_PRECISION); } mpfr_clear_flags(); if(mpfr_inf_p(fl_value) && mpfr_inf_p(fu_value) && mpfr_sgn(fl_value) == mpfr_sgn(fu_value)) { + // lower and upper value is infinite with same sign: set number type accordingly if(!allow_infinite_result) return false; int sign = mpfr_sgn(fl_value); if(sign >= 0) n_type = NUMBER_TYPE_PLUS_INFINITY; @@ -2089,8 +2179,10 @@ } else if(mpfr_inf_p(fl_value) || mpfr_inf_p(fu_value)) { if(!allow_infinite_result) return false; } else if(mpfr_cmp(fl_value, fu_value) > 0) { + // lower value > upper value (should not happen) mpfr_swap(fl_value, fu_value); } + // test if floating point value can be converted to an integer if(test_integer) testInteger(); if(!b_imag) testComplex(this, i_value); return true; @@ -2099,15 +2191,18 @@ if(isFloatingPoint()) { if(mpfr_equal_p(fu_value, fl_value)) { if(mpfr_integer_p(fl_value) && mpfr_integer_p(fu_value)) { + // upper and lower value is equal integers: set to rational number mpfr_get_z(mpq_numref(r_value), fl_value, MPFR_RNDN); mpfr_clears(fl_value, fu_value, NULL); n_type = NUMBER_TYPE_RATIONAL; } } else if(mpfr_zero_p(fu_value) && mpfr_zero_p(fl_value)) { + // value is zero mpfr_clears(fl_value, fu_value, NULL); n_type = NUMBER_TYPE_RATIONAL; } } + // test imaginary part if(i_value) i_value->testInteger(); } void Number::setPrecisionAndApproximateFrom(const Number &o) { @@ -2317,14 +2412,28 @@ } bool prec_choosen = prec >= 0; if(prec == EQUALS_PRECISION_LOWEST) { - prec = PRECISION; - if(i_precision >= 0 && i_precision < prec) prec = i_precision; - if(o.precision() >= 0 && o.precision() < prec) prec = o.precision(); + prec = i_precision; + if(o.precision() >= 0 && (prec < 0 || o.precision() < prec)) prec = o.precision(); } else if(prec == EQUALS_PRECISION_HIGHEST) { prec = i_precision; - if(o.precision() >= 0 && o.precision() > prec) prec = o.precision(); - if(prec < 0) prec = PRECISION; - } else if(prec == EQUALS_PRECISION_DEFAULT) { + if(o.precision() >= 0 && (o.precision() < 0 || o.precision() > prec)) prec = o.precision(); + } + if(prec < 0) { + if(isInterval()) { + if(o.isFloatingPoint()) { + if(mpfr_cmp(fl_value, o.internalUpperFloat()) > 0) return 0; + if(mpfr_cmp(fu_value, o.internalLowerFloat()) < 0) return 0; + } else { + if(mpfr_cmp_q(fl_value, o.internalRational()) > 0 || mpfr_cmp_q(fu_value, o.internalRational()) < 0) return 0; + } + } else if(o.isInterval()) { + if(isFloatingPoint()) { + if(mpfr_cmp(o.internalLowerFloat(), fu_value) > 0) return 0; + if(mpfr_cmp(o.internalUpperFloat(), fl_value) < 0) return 0; + } else { + if(mpfr_cmp_q(o.internalLowerFloat(), r_value) > 0 || mpfr_cmp_q(o.internalUpperFloat(), r_value) < 0) return 0; + } + } prec = PRECISION; } if(prec_choosen || isApproximate() || o.isApproximate()) { @@ -3033,7 +3142,7 @@ setPrecisionAndApproximateFrom(*i_value); } if(hasRealPart()) { - if(isNegative()) setMinusInfinity(true, true); + if(realPartIsNegative()) setMinusInfinity(true, true); else setPlusInfinity(true, true); setPrecisionAndApproximateFrom(o); } @@ -3046,7 +3155,7 @@ setPrecisionAndApproximateFrom(*i_value); } if(hasRealPart()) { - if(isNegative()) setPlusInfinity(true, true); + if(realPartIsNegative()) setPlusInfinity(true, true); else setMinusInfinity(true, true); } setPrecisionAndApproximateFrom(o); @@ -4933,26 +5042,88 @@ b_approx = true; } bool Number::zeta() { - if(!isInteger() || !isPositive() || isOne()) { + if(!isGreaterThan(1) && !isLessThan(1)) { + // zeta(1) is undefined return false; } - bool overflow = false; - long int i = lintValue(&overflow); - if(overflow) { - CALCULATOR->error(true, _("Cannot handle an argument (s) that large for Riemann Zeta."), NULL); - return false; - } - + if(isPlusInfinity()) {set(1, 1, 0, true); return true;} + if(isMinusInfinity()) return false; Number nr_bak(*this); if(!setToFloatingPoint()) return false; mpfr_clear_flags(); if(!CREATE_INTERVAL && !isInterval()) { - mpfr_zeta_ui(fl_value, (unsigned long int) i, MPFR_RNDN); + mpfr_zeta(fl_value, fl_value, MPFR_RNDN); mpfr_set(fu_value, fl_value, MPFR_RNDN); + } else if(mpfr_cmp_si(fl_value, -2) >= 0) { + // zeta(x) is decreases when x increases in intervals (-2, 1) and (1, infinity) + mpfr_zeta(fu_value, fu_value, MPFR_RNDD); + mpfr_zeta(fl_value, fl_value, MPFR_RNDU); + mpfr_swap(fl_value, fu_value); } else { - mpfr_zeta_ui(fu_value, (unsigned long int) i, MPFR_RNDU); - mpfr_zeta_ui(fl_value, (unsigned long int) i, MPFR_RNDD); + mpfr_t fu_test, fl_test; + mpfr_init2(fu_test, mpfr_get_prec(fu_value)); + mpfr_init2(fl_test, mpfr_get_prec(fl_value)); + mpfr_sub(fl_test, fu_value, fl_value, MPFR_RNDU); + // unable to detect zeta(x) interval errors reliably for intervals larger than 1 (for x < -2) + bool b_iverror = mpfr_cmp_ui(fl_test, 1) > 0; + + mpfr_set(fu_test, fu_value, MPFR_RNDN); + mpfr_set(fl_test, fl_value, MPFR_RNDN); + mpfr_zeta(fu_value, fu_value, MPFR_RNDU); + mpfr_zeta(fl_value, fl_value, MPFR_RNDD); + int c1 = mpfr_cmp(fl_value, fu_value); + if(c1 > 0) { + mpfr_zeta(fu_value, fl_test, MPFR_RNDU); + mpfr_zeta(fl_value, fu_test, MPFR_RNDD); + } + if(!b_iverror && !mpfr_equal_p(fu_test, fl_test)) { + //detect direction changes within the original interval + mpfr_nextabove(fl_test); + if(mpfr_equal_p(fu_test, fl_test)) { + mpfr_set_prec(fl_test, mpfr_get_prec(fu_test) + 1); + mpfr_set(fl_test, fu_test, MPFR_RNDN); + mpfr_nextbelow(fl_test); + mpfr_set_prec(fu_test, mpfr_get_prec(fl_test)); + mpfr_zeta(fu_test, fl_test, MPFR_RNDU); + if(mpfr_cmp(fu_test, fl_value) < 0) { + mpfr_zeta(fl_value, fl_test, MPFR_RNDD); + b_iverror = true; + } else if(mpfr_cmp(fu_test, fu_value) > 0) { + mpfr_set(fu_value, fu_test, MPFR_RNDU); + b_iverror = true; + } + } else { + mpfr_t f_test; + mpfr_init2(f_test, mpfr_get_prec(fl_test)); + mpfr_nextbelow(fl_test); + while(true) { + // from lower to upper value + mpfr_nextabove(fl_test); + if(mpfr_equal_p(fu_test, fl_test)) break; + mpfr_zeta(f_test, fl_test, c1 > 0 ? MPFR_RNDU : MPFR_RNDD); + int c2 = mpfr_cmp(f_test, c1 > 0 ? fu_value : fl_value); + if(c2 != 0) { + if(c1 > 0 ? c2 > 0 : c2 < 0) b_iverror = true; + break; + } + } + while(!b_iverror && !mpfr_equal_p(fu_test, fl_test)) { + // from upper to lower value + mpfr_nextbelow(fu_test); + if(mpfr_equal_p(fu_test, fl_test)) break; + mpfr_zeta(f_test, fu_test, c1 > 0 ? MPFR_RNDD : MPFR_RNDU); + int c2 = mpfr_cmp(f_test, c1 > 0 ? fl_value : fu_value); + if(c2 != 0) { + if(c1 > 0 ? c2 < 0 : c2 > 0) b_iverror = true; + break; + } + } + mpfr_clear(f_test); + } + } + mpfr_clears(fu_test, fl_test, NULL); + if(b_iverror) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_ZETA)->name().c_str(), NULL); } mpq_set_ui(r_value, 0, 1); @@ -4965,6 +5136,113 @@ return true; } +bool Number::zeta(const Number &o) { + if(o.isOne()) return zeta(); + if(o.includesInfinity() || !isGreaterThan(1) || !o.isPositive()) return false; + if(isPlusInfinity()) {set(1, 1, 0, true); return true;} + if(isMinusInfinity()) return false; + if(isInterval()) { + Number nr_l, nr_u; + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + if(!nr_l.zeta(o) || !nr_u.zeta(o)) return false; + setInterval(nr_l, nr_u); + return true; + } + if(o.isInterval()) { + Number nr_l(*this), nr_u(*this), nr_lo, nr_uo; + nr_lo.setInternal(o.internalLowerFloat()); + nr_uo.setInternal(o.internalUpperFloat()); + if(!nr_l.zeta(nr_lo) || !nr_u.zeta(nr_uo)) return false; + setInterval(nr_l, nr_u); + return true; + } + Number nr_bak(*this); + // zeta(x, q)=sum(1/(q+n)^x,0,infinity,n) + mpfr_clear_flags(); + mpfr_t n, x, wprec, q, qns, yprev, v; + mpfr_inits2(BIT_PRECISION * 2, n, x, q, qns, yprev, wprec, v, NULL); + if(n_type == NUMBER_TYPE_FLOAT) { + mpfr_set(x, fl_value, MPFR_RNDN); + } else { + mpfr_set_q(x, r_value, MPFR_RNDN); + if(!setToFloatingPoint()) return false; + } + if(o.isFloatingPoint()) { + mpfr_set(q, o.internalLowerFloat(), MPFR_RNDN); + } else { + mpfr_set_q(q, o.internalRational(), MPFR_RNDN); + } + mpfr_set_zero(v, 0); + mpfr_set_zero(n, 0); + mpfr_set_si(wprec, -BIT_PRECISION + (mpfr_cmp_ui(x, 10) > 0 ? 10 : 70), MPFR_RNDN); + mpfr_exp2(wprec, wprec, MPFR_RNDN); + PRINT_MPFR(wprec, 10) + mpfr_neg(x, x, MPFR_RNDN); + while(true) { + if(CALCULATOR->aborted()) {mpfr_clears(n, x, q, qns, yprev, wprec, v, NULL); set(nr_bak); return false;} + mpfr_set(yprev, v, MPFR_RNDN); + mpfr_add(qns, q, n, MPFR_RNDN); + mpfr_pow(qns, qns, x, MPFR_RNDN); + mpfr_add(v, v, qns, MPFR_RNDN); + mpfr_sub(yprev, yprev, v, MPFR_RNDU); + mpfr_div(yprev, yprev, v, MPFR_RNDU); + mpfr_abs(yprev, yprev, MPFR_RNDU); + if(mpfr_cmp(yprev, wprec) < 0) { + mpfr_set(fl_value, v, MPFR_RNDD); + mpfr_set(fu_value, v, MPFR_RNDU); + if(CREATE_INTERVAL) { + if(mpfr_zero_p(yprev)) mpfr_set(yprev, wprec, MPFR_RNDN); + mpfr_mul(yprev, yprev, v, MPFR_RNDA); + mpfr_abs(yprev, yprev, MPFR_RNDU); + mpfr_mul_ui(yprev, yprev, 1000, MPFR_RNDA); + mpfr_mul_ui(yprev, yprev, 1000, MPFR_RNDA); + mpfr_sub(fu_value, fu_value, yprev, MPFR_RNDU); + mpfr_add(fl_value, fl_value, yprev, MPFR_RNDD); + } + break; + } + mpfr_add_ui(n, n, 1, MPFR_RNDN); + } + PRINT_MPFR(n, 10); + mpfr_clears(n, x, q, qns, yprev, wprec, v, NULL); + if(!testFloatResult()) { + set(nr_bak); + return false; + } + b_approx = true; + return true; +} +bool Number::bernoulli() { + if(!isInteger() || isNegative()) return false; + if(isGreaterThan(498)) { + if(isOdd()) {clear(true); return true;} + Number nr_zeta(*this); + if(!nr_zeta.negate() || !nr_zeta.add(1) || !nr_zeta.zeta() || !nr_zeta.multiply(*this) || !nr_zeta.negate()) return false; + set(nr_zeta); + return true; + } + long int m = mpz_get_si(mpq_numref(r_value)); + if(m < 0 || m > 498) return false; + switch(m) { + case 0: {set(1, 1, 0, true); return true;} + case 1: {set(-1, 2, 0, true); return true;} + case 2: {set(1, 6, 0, true); return true;} + case 4: {set(-1, 30, 0, true); return true;} + case 6: {set(1, 42, 0, true); return true;} + case 8: {set(-1, 30, 0, true); return true;} + case 10: {set(5, 66, 0, true); return true;} + case 12: {set(-691, 2730, 0, true); return true;} + case 14: {set(7, 6, 0, true); return true;} + case 16: {set(-3617, 510, 0, true); return true;} + case 18: {set(43867L, 798, 0, true); return true;} + case 22: {set(854513L, 138, 0, true); return true;} + } + if(m % 2 == 1) {clear(true); return true;} + set(Number(bernoulli_numbers[m - 2]), true); + divide(Number(bernoulli_numbers[m - 1])); + return true; +} bool Number::gamma() { if(isPlusInfinity()) return true; if(!isReal()) return false; @@ -4980,6 +5258,7 @@ if(mpfr_cmp_d(fl_value, 1.5) < 0) { mpfr_t f_gamma_minx; mpfr_init2(f_gamma_minx, BIT_PRECISION); + // gamma(x) changes direction when at x=1.46... mpfr_set_str(f_gamma_minx, "1.46163214496836234126265954232572132846819620400644635129598840859878644035380181024307499273372559", 10, MPFR_RNDN); if(mpfr_cmp(fl_value, f_gamma_minx) < 0) { if(mpfr_cmp(fu_value, f_gamma_minx) < 0) { @@ -5006,16 +5285,71 @@ return false; } else { mpfr_t fu_test, fl_test; - mpfr_init2(fu_test, BIT_PRECISION); - mpfr_init2(fl_test, BIT_PRECISION); + mpfr_init2(fu_test, mpfr_get_prec(fu_value)); + mpfr_init2(fl_test, mpfr_get_prec(fl_value)); mpfr_floor(fu_test, fu_value); mpfr_floor(fl_test, fl_value); + + // The value is an opposite sides of a negative integer (gamma(x) is undefined for negative integers) if(!mpfr_equal_p(fu_test, fl_test) || mpfr_equal_p(fl_test, fl_value)) {set(nr_bak); return false;} - mpfr_gamma(fu_value, fu_value, MPFR_RNDN); - mpfr_gamma(fl_value, fl_value, MPFR_RNDN); - if(mpfr_cmp(fl_value, fu_value) > 0) mpfr_swap(fl_value, fu_value); - if(nr_bak.isInterval() && nr_bak.precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->f_gamma->name().c_str(), NULL); + + mpfr_set(fu_test, fu_value, MPFR_RNDN); + mpfr_set(fl_test, fl_value, MPFR_RNDN); + mpfr_gamma(fu_value, fu_value, MPFR_RNDU); + mpfr_gamma(fl_value, fl_value, MPFR_RNDD); + int c1 = mpfr_cmp(fl_value, fu_value); + if(c1 > 0) { + mpfr_gamma(fu_value, fl_test, MPFR_RNDU); + mpfr_gamma(fl_value, fu_test, MPFR_RNDD); + } + bool b_iverror = false; + if(!mpfr_equal_p(fu_test, fl_test)) { + //detect direction changes within the original interval + mpfr_nextabove(fl_test); + if(mpfr_equal_p(fu_test, fl_test)) { + mpfr_set_prec(fl_test, mpfr_get_prec(fu_test) + 1); + mpfr_set(fl_test, fu_test, MPFR_RNDN); + mpfr_nextbelow(fl_test); + mpfr_set_prec(fu_test, mpfr_get_prec(fl_test)); + mpfr_gamma(fu_test, fl_test, MPFR_RNDU); + if(mpfr_cmp(fu_test, fl_value) < 0) { + mpfr_gamma(fl_value, fl_test, MPFR_RNDD); + b_iverror = true; + } else if(mpfr_cmp(fu_test, fu_value) > 0) { + mpfr_set(fu_value, fu_test, MPFR_RNDU); + b_iverror = true; + } + } else { + mpfr_t f_test; + mpfr_init2(f_test, mpfr_get_prec(fl_test)); + mpfr_nextbelow(fl_test); + while(true) { + // from lower to upper value + mpfr_nextabove(fl_test); + if(mpfr_equal_p(fu_test, fl_test)) break; + mpfr_gamma(f_test, fl_test, c1 > 0 ? MPFR_RNDU : MPFR_RNDD); + int c2 = mpfr_cmp(f_test, c1 > 0 ? fu_value : fl_value); + if(c2 != 0) { + if(c1 > 0 ? c2 > 0 : c2 < 0) b_iverror = true; + break; + } + } + while(!b_iverror && !mpfr_equal_p(fu_test, fl_test)) { + // from upper to lower value + mpfr_nextbelow(fu_test); + if(mpfr_equal_p(fu_test, fl_test)) break; + mpfr_gamma(f_test, fu_test, c1 > 0 ? MPFR_RNDD : MPFR_RNDU); + int c2 = mpfr_cmp(f_test, c1 > 0 ? fl_value : fu_value); + if(c2 != 0) { + if(c1 > 0 ? c2 < 0 : c2 > 0) b_iverror = true; + break; + } + } + mpfr_clear(f_test); + } + } mpfr_clears(fu_test, fl_test, NULL); + if(b_iverror) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_GAMMA)->name().c_str(), NULL); } } if(!testFloatResult()) { @@ -5059,9 +5393,131 @@ return true; } bool Number::erf() { - if(hasImaginaryPart()) return false; + if(hasImaginaryPart()) { + if(hasRealPart()) { + if(includesInfinity()) return false; + if(isInterval(false)) { + Number nr_l, nr_u; + if(i_value->isInterval()) { + Number nr_il, nr_iu; + nr_il.setInternal(i_value->internalLowerFloat()); + nr_iu.setInternal(i_value->internalUpperFloat()); + if(isInterval(true)) { + Number nr_l2, nr_u2; + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + nr_l.setImaginaryPart(nr_il); + nr_u.setImaginaryPart(nr_iu); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + nr_l2.setInternal(fl_value); + nr_u2.setInternal(fu_value); + nr_l2.setImaginaryPart(nr_iu); + nr_u2.setImaginaryPart(nr_il); + nr_l2.intervalToMidValue(); + nr_u2.intervalToMidValue(); + if(!nr_l.erf() || !nr_u.erf() || !nr_l2.erf() || !nr_u2.erf()) return false; + nr_u.setInterval(nr_u, nr_u2); + nr_l.setInterval(nr_l, nr_l2); + } else { + nr_l.set(*this); nr_u.set(*this); + nr_l.setImaginaryPart(nr_il); + nr_u.setImaginaryPart(nr_iu); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(!nr_l.erf() || !nr_u.erf()) return false; + } + } else { + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + nr_l.setImaginaryPart(*i_value); + nr_u.setImaginaryPart(*i_value); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(!nr_l.erf() || !nr_u.erf()) return false; + } + if(precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_ERF)->name().c_str(), NULL); + setPrecisionAndApproximateFrom(nr_l); + setPrecisionAndApproximateFrom(nr_u); + return setInterval(nr_l, nr_u, true); + } + // erf(x)=2/sqrt(pi)*sum((-1)^k*x^(1+2k)/((1+2k)*k!),0,infinity,k) + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(!CALCULATOR->usesIntervalArithmetic()) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + mpfr_clear_flags(); + int prec_bak = PRECISION; + CALCULATOR->setPrecision(PRECISION * 2 + 20); + Number v(*this); + if(!v.setToFloatingPoint()) {CALCULATOR->setPrecision(prec_bak); CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + Number xpow, num, den, yprev, yprevi, ytest, ytesti; + Number x(v); + Number k(1, 1); + Number kfac(1, 1); + Number wprec(1, 1, -(prec_bak + 20)); + Number wprec2(1, 1, -prec_bak); + yprev = v; + yprev.clearImaginary(); + if(v.internalImaginary()) yprevi.set(*v.internalImaginary()); + for(int i = 0; ; i++) { + den = k; den *= 2; + xpow = k; xpow *= 2; xpow++; + num = x; + if(i > PRECISION * 100 || CALCULATOR->aborted() || !kfac.multiply(k) || !den.multiply(kfac) || !den.add(kfac) || !num.raise(xpow) || !num.divide(den) || (k.isOdd() && !num.negate()) || !v.add(num) || v.includesInfinity()) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + if(v.isInterval() && v.precision(true) < prec_bak + 10) { + if(v.precision(true) < prec_bak) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + wprec.set(1, 1, -prec_bak); + wprec2.set(1, 1, -prec_bak + 2); + } + ytest = yprev; + ytesti = yprevi; + yprev = v; + yprev.clearImaginary(); + if(v.internalImaginary()) yprevi.set(*v.internalImaginary()); + else yprevi.clear(); + if(!ytest.subtract(yprev) || (yprev.isNonZero() && !ytest.divide(yprev)) || !ytest.abs() || !ytesti.subtract(yprevi) || (yprevi.isNonZero() && !ytesti.divide(yprevi)) || !ytesti.abs()) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + if((ytest < wprec || (!ytest.isNonZero() && ytest < wprec2)) && (ytesti < wprec || (!ytesti.isNonZero() && ytesti < wprec2))) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + if(ytest.isZero()) {ytest++; ytest.setToFloatingPoint(); mpfr_nextabove(ytest.internalUpperFloat()); ytest--;} + if(ytesti.isZero()) {ytesti++; ytesti.setToFloatingPoint(); mpfr_nextabove(ytesti.internalUpperFloat()); ytesti--;} + ytest.setImaginaryPart(ytesti); + ytest *= 10; + CALCULATOR->setPrecision(prec_bak); + v.setRelativeUncertainty(ytest, !CREATE_INTERVAL); + break; + } + k++; + } + if(!v.testFloatResult(true)) { + return false; + } + Number nr_pi; nr_pi.pi(); + if(!v.multiply(2) || !nr_pi.sqrt() || !v.divide(nr_pi)) { + return false; + } + set(v); + b_approx = true; + return true; + } + // erf(x*i)=erfi(x)i + if(!i_value->erfi()) return false; + setPrecisionAndApproximateFrom(*i_value); + return true; + } if(isPlusInfinity()) {set(1, 1, 0, true); return true;} if(isMinusInfinity()) {set(-1, 1, 0, true); return true;} + if(isZero()) return true; Number nr_bak(*this); if(!setToFloatingPoint()) return false; mpfr_clear_flags(); @@ -5078,8 +5534,102 @@ } return true; } +bool Number::erfi() { + if(hasImaginaryPart()) { + if(hasRealPart()) { + Number nr_bak(*this); + // erfi(x)=-i*erf(i*x) + if(!multiply(nr_one_i) || !erf() || !multiply(nr_minus_i)) { + set(nr_bak); + return false; + } + return true; + } + // erfi(x*i)=erf(x)i + if(!i_value->erf()) return false; + setPrecisionAndApproximateFrom(*i_value); + return true; + } + if(isZero() || isInfinite()) return true; + if(isInterval()) { + Number nr_l, nr_u; + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + if(!nr_l.erfi() || !nr_u.erfi()) return false; + setInterval(nr_l, nr_u); + return true; + } + if(isGreaterThan(1000) || isLessThan(-1000)) return false; + Number nr_bak(*this); + // erfi(x)=2/sqrt(pi)*sum(x^(1+2k)/(k!+2k*k!),0,infinity,k) + mpfr_clear_flags(); + mpfr_t k, kfac, xpow, x, num, den, yprev, wprec, v; + mpfr_inits2(BIT_PRECISION * 2, k, kfac, xpow, x, num, den, yprev, wprec, v, NULL); + if(n_type == NUMBER_TYPE_FLOAT) { + mpfr_set(x, fl_value, MPFR_RNDN); + } else { + mpfr_set_q(x, r_value, MPFR_RNDN); + if(!setToFloatingPoint()) return false; + } + mpfr_set(v, x, MPFR_RNDN); + mpfr_set_si(k, 1, MPFR_RNDN); + mpfr_set_si(kfac, 1, MPFR_RNDN); + mpfr_set_si(wprec, -BIT_PRECISION - 2, MPFR_RNDN); + mpfr_exp2(wprec, wprec, MPFR_RNDN); + while(true) { + if(CALCULATOR->aborted()) {mpfr_clears(k, kfac, xpow, x, num, den, yprev, wprec, v, NULL); set(nr_bak); return false;} + mpfr_set(yprev, v, MPFR_RNDN); + mpfr_mul(kfac, kfac, k, MPFR_RNDN); + mpfr_mul(den, kfac, k, MPFR_RNDN); + mpfr_mul_ui(den, den, 2, MPFR_RNDN); + mpfr_add(den, den, kfac, MPFR_RNDN); + mpfr_mul_ui(xpow, k, 2, MPFR_RNDN); + mpfr_add_ui(xpow, xpow, 1, MPFR_RNDN); + mpfr_pow(num, x, xpow, MPFR_RNDN); + mpfr_div(num, num, den, MPFR_RNDN); + mpfr_add(v, v, num, MPFR_RNDN); + mpfr_sub(yprev, yprev, v, MPFR_RNDU); + mpfr_div(yprev, yprev, v, MPFR_RNDU); + mpfr_abs(yprev, yprev, MPFR_RNDU); + if(mpfr_cmp(yprev, wprec) < 0) { + mpfr_set(fl_value, v, MPFR_RNDD); + mpfr_set(fu_value, v, MPFR_RNDU); + if(CREATE_INTERVAL) { + if(mpfr_zero_p(yprev)) { + mpfr_nextbelow(fl_value); + mpfr_nextabove(fu_value); + } else { + mpfr_mul(yprev, yprev, v, MPFR_RNDA); + mpfr_abs(yprev, yprev, MPFR_RNDU); + mpfr_sub(fu_value, fu_value, yprev, MPFR_RNDU); + mpfr_add(fl_value, fl_value, yprev, MPFR_RNDD); + } + } + break; + } + mpfr_add_ui(k, k, 1, MPFR_RNDN); + } + mpfr_clears(k, kfac, xpow, x, num, den, yprev, wprec, v, NULL); + if(!testFloatResult()) { + set(nr_bak); + return false; + } + Number nr_pi; nr_pi.pi(); + if(!multiply(2) || !nr_pi.sqrt() || !divide(nr_pi)) { + set(nr_bak); + return false; + } + b_approx = true; + return true; +} bool Number::erfc() { - if(hasImaginaryPart()) return false; + if(hasImaginaryPart()) { + // erfc(x)=1-erf(x) + if(!erf()) return false; + negate(); + add(1); + return true; + } if(isPlusInfinity()) {clear(true); return true;} if(isMinusInfinity()) {set(2, 1, 0, true); return true;} Number nr_bak(*this); @@ -5113,10 +5663,64 @@ mpfr_ai(fu_value, fu_value, MPFR_RNDD); mpfr_swap(fl_value, fu_value); } else { - mpfr_ai(fl_value, fl_value, MPFR_RNDN); - mpfr_ai(fu_value, fu_value, MPFR_RNDN); - if(mpfr_cmp(fl_value, fu_value) > 0) mpfr_swap(fl_value, fu_value); - if(nr_bak.isInterval() && nr_bak.precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->f_airy->name().c_str(), NULL); + mpfr_t fu_test, fl_test; + mpfr_init2(fu_test, mpfr_get_prec(fu_value)); + mpfr_init2(fl_test, mpfr_get_prec(fl_value)); + mpfr_sub(fl_test, fu_value, fl_value, MPFR_RNDU); + bool b_iverror = (mpfr_cmp_si(fl_value, -30) < 0 && mpfr_cmp_d(fl_test, 0.1) > 0) || mpfr_cmp_d(fl_test, 0.5) > 0; + mpfr_set(fu_test, fu_value, MPFR_RNDN); + mpfr_set(fl_test, fl_value, MPFR_RNDN); + mpfr_ai(fu_value, fu_value, MPFR_RNDU); + mpfr_ai(fl_value, fl_value, MPFR_RNDD); + int c1 = mpfr_cmp(fl_value, fu_value); + if(c1 > 0) { + mpfr_ai(fu_value, fl_test, MPFR_RNDU); + mpfr_ai(fl_value, fu_test, MPFR_RNDD); + } + if(!b_iverror && !mpfr_equal_p(fu_test, fl_test)) { + mpfr_nextabove(fl_test); + if(mpfr_equal_p(fu_test, fl_test)) { + mpfr_set_prec(fl_test, mpfr_get_prec(fu_test) + 1); + mpfr_set(fl_test, fu_test, MPFR_RNDN); + mpfr_nextbelow(fl_test); + mpfr_set_prec(fu_test, mpfr_get_prec(fl_test)); + mpfr_ai(fu_test, fl_test, MPFR_RNDU); + if(mpfr_cmp(fu_test, fl_value) < 0) { + mpfr_ai(fl_value, fl_test, MPFR_RNDD); + b_iverror = true; + } else if(mpfr_cmp(fu_test, fu_value) > 0) { + mpfr_set(fu_value, fu_test, MPFR_RNDU); + b_iverror = true; + } + } else { + mpfr_t f_test; + mpfr_init2(f_test, mpfr_get_prec(fl_test)); + mpfr_nextbelow(fl_test); + while(true) { + mpfr_nextabove(fl_test); + if(mpfr_equal_p(fu_test, fl_test)) break; + mpfr_ai(f_test, fl_test, c1 > 0 ? MPFR_RNDU : MPFR_RNDD); + int c2 = mpfr_cmp(f_test, c1 > 0 ? fu_value : fl_value); + if(c2 != 0) { + if(c1 > 0 ? c2 > 0 : c2 < 0) b_iverror = true; + break; + } + } + while(!b_iverror && !mpfr_equal_p(fu_test, fl_test)) { + mpfr_nextbelow(fu_test); + if(mpfr_equal_p(fu_test, fl_test)) break; + mpfr_ai(f_test, fu_test, c1 > 0 ? MPFR_RNDD : MPFR_RNDU); + int c2 = mpfr_cmp(f_test, c1 > 0 ? fl_value : fu_value); + if(c2 != 0) { + if(c1 > 0 ? c2 < 0 : c2 > 0) b_iverror = true; + break; + } + } + mpfr_clear(f_test); + } + } + mpfr_clears(fu_test, fl_test, NULL); + if(b_iverror) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_AIRY)->name().c_str(), NULL); } if(!testFloatResult()) { set(nr_bak); @@ -5144,10 +5748,65 @@ mpfr_jn(fl_value, n, fl_value, MPFR_RNDN); mpfr_set(fu_value, fl_value, MPFR_RNDN); } else { - mpfr_jn(fl_value, n, fl_value, MPFR_RNDN); - mpfr_jn(fu_value, n, fu_value, MPFR_RNDN); - if(mpfr_cmp(fl_value, fu_value) > 0) mpfr_swap(fl_value, fu_value); - if(nr_bak.isInterval() && nr_bak.precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->f_besselj->name().c_str(), NULL); + mpfr_t fu_test, fl_test; + mpfr_init2(fu_test, mpfr_get_prec(fu_value)); + mpfr_init2(fl_test, mpfr_get_prec(fl_value)); + mpfr_sub(fl_test, fu_value, fl_value, MPFR_RNDU); + // besselj(n, x) changing direction after every increase by approximately 3 of x + bool b_iverror = mpfr_cmp_d(fl_test, 3) > 0; + mpfr_set(fu_test, fu_value, MPFR_RNDN); + mpfr_set(fl_test, fl_value, MPFR_RNDN); + mpfr_jn(fu_value, n, fu_value, MPFR_RNDU); + mpfr_jn(fl_value, n, fl_value, MPFR_RNDD); + int c1 = mpfr_cmp(fl_value, fu_value); + if(c1 > 0) { + mpfr_jn(fu_value, n, fl_test, MPFR_RNDU); + mpfr_jn(fl_value, n, fu_test, MPFR_RNDD); + } + if(!b_iverror && !mpfr_equal_p(fu_test, fl_test)) { + mpfr_nextabove(fl_test); + if(mpfr_equal_p(fu_test, fl_test)) { + mpfr_set_prec(fl_test, mpfr_get_prec(fu_test) + 1); + mpfr_set(fl_test, fu_test, MPFR_RNDN); + mpfr_nextbelow(fl_test); + mpfr_set_prec(fu_test, mpfr_get_prec(fl_test)); + mpfr_jn(fu_test, n, fl_test, MPFR_RNDU); + if(mpfr_cmp(fu_test, fl_value) < 0) { + mpfr_jn(fl_value, n, fl_test, MPFR_RNDD); + b_iverror = true; + } else if(mpfr_cmp(fu_test, fu_value) > 0) { + mpfr_set(fu_value, fu_test, MPFR_RNDU); + b_iverror = true; + } + } else { + mpfr_t f_test; + mpfr_init2(f_test, mpfr_get_prec(fl_test)); + mpfr_nextbelow(fl_test); + while(true) { + mpfr_nextabove(fl_test); + if(mpfr_equal_p(fu_test, fl_test)) break; + mpfr_jn(f_test, n, fl_test, c1 > 0 ? MPFR_RNDU : MPFR_RNDD); + int c2 = mpfr_cmp(f_test, c1 > 0 ? fu_value : fl_value); + if(c2 != 0) { + if(c1 > 0 ? c2 > 0 : c2 < 0) b_iverror = true; + break; + } + } + while(!b_iverror && !mpfr_equal_p(fu_test, fl_test)) { + mpfr_nextbelow(fu_test); + if(mpfr_equal_p(fu_test, fl_test)) break; + mpfr_jn(f_test, n, fu_test, c1 > 0 ? MPFR_RNDD : MPFR_RNDU); + int c2 = mpfr_cmp(f_test, c1 > 0 ? fl_value : fu_value); + if(c2 != 0) { + if(c1 > 0 ? c2 < 0 : c2 > 0) b_iverror = true; + break; + } + } + mpfr_clear(f_test); + } + } + mpfr_clears(fu_test, fl_test, NULL); + if(b_iverror) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_BESSELJ)->name().c_str(), NULL); } if(!testFloatResult()) { set(nr_bak); @@ -5175,10 +5834,65 @@ mpfr_yn(fl_value, n, fl_value, MPFR_RNDN); mpfr_set(fu_value, fl_value, MPFR_RNDN); } else { - mpfr_yn(fl_value, n, fl_value, MPFR_RNDN); - mpfr_yn(fu_value, n, fu_value, MPFR_RNDN); - if(mpfr_cmp(fl_value, fu_value) > 0) mpfr_swap(fl_value, fu_value); - if(nr_bak.isInterval() && nr_bak.precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->f_bessely->name().c_str(), NULL); + mpfr_t fu_test, fl_test; + mpfr_init2(fu_test, mpfr_get_prec(fu_value)); + mpfr_init2(fl_test, mpfr_get_prec(fl_value)); + mpfr_sub(fl_test, fu_value, fl_value, MPFR_RNDU); + // bessely(n, x) changing direction after every increase by approximately 3 of x + bool b_iverror = mpfr_cmp_d(fl_test, 3) > 0; + mpfr_set(fu_test, fu_value, MPFR_RNDN); + mpfr_set(fl_test, fl_value, MPFR_RNDN); + mpfr_yn(fu_value, n, fu_value, MPFR_RNDU); + mpfr_yn(fl_value, n, fl_value, MPFR_RNDD); + int c1 = mpfr_cmp(fl_value, fu_value); + if(c1 > 0) { + mpfr_yn(fu_value, n, fl_test, MPFR_RNDU); + mpfr_yn(fl_value, n, fu_test, MPFR_RNDD); + } + if(!b_iverror && !mpfr_equal_p(fu_test, fl_test)) { + mpfr_nextabove(fl_test); + if(mpfr_equal_p(fu_test, fl_test)) { + mpfr_set_prec(fl_test, mpfr_get_prec(fu_test) + 1); + mpfr_set(fl_test, fu_test, MPFR_RNDN); + mpfr_nextbelow(fl_test); + mpfr_set_prec(fu_test, mpfr_get_prec(fl_test)); + mpfr_yn(fu_test, n, fl_test, MPFR_RNDU); + if(mpfr_cmp(fu_test, fl_value) < 0) { + mpfr_yn(fl_value, n, fl_test, MPFR_RNDD); + b_iverror = true; + } else if(mpfr_cmp(fu_test, fu_value) > 0) { + mpfr_set(fu_value, fu_test, MPFR_RNDU); + b_iverror = true; + } + } else { + mpfr_t f_test; + mpfr_init2(f_test, mpfr_get_prec(fl_test)); + mpfr_nextbelow(fl_test); + while(true) { + mpfr_nextabove(fl_test); + if(mpfr_equal_p(fu_test, fl_test)) break; + mpfr_yn(f_test, n, fl_test, c1 > 0 ? MPFR_RNDU : MPFR_RNDD); + int c2 = mpfr_cmp(f_test, c1 > 0 ? fu_value : fl_value); + if(c2 != 0) { + if(c1 > 0 ? c2 > 0 : c2 < 0) b_iverror = true; + break; + } + } + while(!b_iverror && !mpfr_equal_p(fu_test, fl_test)) { + mpfr_nextbelow(fu_test); + if(mpfr_equal_p(fu_test, fl_test)) break; + mpfr_yn(f_test, n, fu_test, c1 > 0 ? MPFR_RNDD : MPFR_RNDU); + int c2 = mpfr_cmp(f_test, c1 > 0 ? fl_value : fu_value); + if(c2 != 0) { + if(c1 > 0 ? c2 < 0 : c2 > 0) b_iverror = true; + break; + } + } + mpfr_clear(f_test); + } + } + mpfr_clears(fu_test, fl_test, NULL); + if(b_iverror) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_BESSELY)->name().c_str(), NULL); } if(!testFloatResult()) { set(nr_bak); @@ -6400,10 +7114,201 @@ } return true; } +// Modified version of https://github.com/IstvanMezo/LambertW-function +bool Number::lambertW(const Number &k) { + + if(!k.isInteger()) return false; + if(isZero()) { + if(k.isZero()) return true; + setMinusInfinity(true); + return true; + } + if(isInfinite()) {setPlusInfinity(true); return true;} + if(includesInfinity()) return false; + if(isInterval(false)) { + if(hasImaginaryPart() && i_value->isInterval()) { + Number nr_il, nr_iu; + nr_il.setInternal(i_value->internalLowerFloat()); + nr_iu.setInternal(i_value->internalUpperFloat()); + Number nr_l, nr_u; + if(isInterval(true)) { + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + nr_l.setImaginaryPart(nr_il); + nr_u.setImaginaryPart(nr_iu); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(!nr_l.lambertW(k) || !nr_u.lambertW(k)) return false; + if(precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_LAMBERT_W)->name().c_str(), NULL); + setPrecisionAndApproximateFrom(nr_l); + setPrecisionAndApproximateFrom(nr_u); + return setInterval(nr_l, nr_u, true); + } else { + nr_l = realPart(); + nr_u = realPart(); + nr_l.setImaginaryPart(nr_il); + nr_u.setImaginaryPart(nr_iu); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(!nr_l.lambertW(k) || !nr_u.lambertW(k)) return false; + setPrecisionAndApproximateFrom(nr_l); + setPrecisionAndApproximateFrom(nr_u); + if(!i_value->isNonZero()) { + if(k.isZero()) nr_l.setInterval(nr_zero, nr_l); + else nr_l.setInterval(nr_minus_inf, nr_l); + } + if(hasRealPart() && precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_LAMBERT_W)->name().c_str(), NULL); + return setInterval(nr_l, nr_u, true); + } + } else { + Number nr_l, nr_u; + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(hasImaginaryPart()) {nr_l.setImaginaryPart(*i_value); nr_u.setImaginaryPart(*i_value);} + if(!nr_l.lambertW(k) || !nr_u.lambertW(k)) return false; + setPrecisionAndApproximateFrom(nr_l); + setPrecisionAndApproximateFrom(nr_u); + if(k.isZero()) { + Number mexpm1(-1, 1); mexpm1.exp(); mexpm1.negate(); + if(COMPARISON_MIGHT_BE_EQUAL(compare(mexpm1))) nr_l.setInterval(nr_minus_one, nr_l); + } else { + if(!isNonZero()) nr_l.setInterval(nr_minus_inf, nr_l); + } + if(hasImaginaryPart() && precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_LAMBERT_W)->name().c_str(), NULL); + return setInterval(nr_l, nr_u, true); + } + } + if(k.isZero() && !hasImaginaryPart()) { + Number mexpm1(-1, 1); mexpm1.exp(); mexpm1.negate(); + if(isGreaterThanOrEqualTo(mexpm1)) return lambertW(); + } + bool b_real = false; + if(k.isMinusOne() && isNonPositive() && isFraction()) { + Number mexpm1(-1, 1); mexpm1.exp(); mexpm1.negate(); + if(isGreaterThanOrEqualTo(mexpm1)) b_real = true; + } + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(!CALCULATOR->usesIntervalArithmetic()) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + mpfr_clear_flags(); + int prec_bak = PRECISION; + CALCULATOR->setPrecision(PRECISION * 2 + 20); + Number v(*this); + if(!v.setToFloatingPoint()) {CALCULATOR->setPrecision(prec_bak); CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + Number z(v); + Number wprec(1, 1, -(prec_bak + 20)); + Number wprec2(1, 1, -prec_bak); + bool ip1 = true; + if(k.isZero() || k.isMinusOne()) { + if(ip1 && !k.isOne()) { + Number nr(-1, 2); nr.add(z); nr.abs(); + if(nr <= nr_half || (k.isZero() && nr <= Number(5, 8))) { + if(k.isZero()) { + Number ndiv(z); if(!ndiv.multiply(2) || !ndiv.add(1) || !ndiv.multiply(Number("0.827184")) || !ndiv.add(2) || !v.multiply(Number("7.061302897")) || !v.add(Number("0.1237166")) || !v.multiply(Number("0.35173371")) || !v.divide(ndiv)) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); CALCULATOR->setPrecision(prec_bak); return false;} + } else { + Number i1("2.2591588985"); i1.setImaginaryPart(Number("4.22096")); + Number i2("-14.073271"); i2.setImaginaryPart(Number("-33.767687754")); + Number i3("-12.7127"); i3.setImaginaryPart(Number("19.071643")); + Number i4("-17.23103"); i4.setImaginaryPart(Number("10.629721")); + Number n1p2z(z); if(!n1p2z.multiply(2) || !n1p2z.add(1) || !i4.multiply(n1p2z) || !i4.add(2) || !i3.multiply(n1p2z)) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); CALCULATOR->setPrecision(prec_bak); return false;} + v.set(i2); if(!v.multiply(z) || !v.add(i3) || !v.multiply(i1) || !v.divide(i4) || !v.negate()) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); CALCULATOR->setPrecision(prec_bak); return false;} + } + ip1 = false; + } + } + if(ip1 && (!k.isMinusOne() || z.imaginaryPartIsPositive())) { + Number nr(-1, 1); nr.exp(); nr.add(z); nr.abs(); + if(nr <= 1) { + Number p; p.e(); if(!p.multiply(z) || !p.add(1) || !p.multiply(2) || !p.sqrt()) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); CALCULATOR->setPrecision(prec_bak); return false;} + Number p2(p); if(!p2.square() || !p2.multiply(Number(-1, 3))) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); CALCULATOR->setPrecision(prec_bak); return false;} + Number p3(p); if(!p3.raise(nr_three) || !p3.multiply(Number(k.isZero() ? 11 : -11, 72))) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); CALCULATOR->setPrecision(prec_bak); return false;} + v.set(p); if((!k.isZero() && !v.negate()) || !v.add(-1) || !v.add(p2) || !v.add(p3)) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); CALCULATOR->setPrecision(prec_bak); return false;} + ip1 = false; + } + } + } + if(ip1) { + Number twopiKI; + if(!k.isZero()) { + twopiKI.pi(); if(!twopiKI.multiply(k) || !twopiKI.multiply(2) || !twopiKI.multiply(nr_one_i)) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); CALCULATOR->setPrecision(prec_bak); return false;} + } + Number logz(z); if(!logz.ln() || !logz.add(twopiKI)) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); CALCULATOR->setPrecision(prec_bak); return false;} + v.set(logz); if(!v.ln() || !v.negate() || !v.add(logz)) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); CALCULATOR->setPrecision(prec_bak); return false;} + } + Number w, wprev, wprevi, wtest, wtesti, wexp, wexpw, wexpw_d, wexpw_dd, wdiff; + wprev = v; + wprev.clearImaginary(); + if(v.internalImaginary()) wprevi.set(*v.internalImaginary()); + for(int i = 0; ; i++) { + wexp.set(v); wexp.exp(); // exp(w) + wexpw = wexp; wexpw.multiply(v); // w*exp(w) + wexpw_d = wexpw; wexpw_d.add(wexp); // wexp(w)+w*exp(w) + wexpw_dd = wexp; wexpw_dd.multiply(2); wexpw_dd.add(wexpw); // 2*wexp(w)+w*exp(w) + // w -= 2*(wexpw-z)*wexpw_d/(2*wexpw_d^2-(wexpw-z)*wexpw_dd) + if(i > PRECISION * 100 || !wexpw.subtract(z) || !wexpw_dd.multiply(wexpw) || !wexpw.multiply(wexpw_d) || !wexpw.multiply(-2) || !wexpw_d.square() || !wexpw_d.multiply(2) || !wexpw_d.subtract(wexpw_dd) || !wexpw.divide(wexpw_d) || !v.add(wexpw) || v.includesInfinity()) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + CALCULATOR->setPrecision(prec_bak); + return false; + } + if(b_real) v.clearImaginary(); + if(v.isInterval()) { + int p = v.precision(true); + if(p < prec_bak + 10) { + if(v.hasImaginaryPart() && !v.imaginaryPartIsNonZero()) { + wtest = v; + wtest.clearImaginary(); + if(wtest.isInterval() && wtest.isNonZero()) p = wtest.precision(true); + else p = INT_MAX; + } else if(v.hasRealPart() && !v.realPartIsNonZero()) { + if(v.hasImaginaryPart() && v.imaginaryPartIsNonZero()) p = v.internalImaginary()->precision(true); + else p = INT_MAX; + } + } + if(p < prec_bak) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + if(p < prec_bak + 10) { + wprec.set(1, 1, -prec_bak); + wprec2.set(1, 1, -prec_bak + 2); + } + } + wtest = wprev; + wtesti = wprevi; + wprev = v; + wprev.clearImaginary(); + if(v.internalImaginary()) wprevi.set(*v.internalImaginary()); + else wprevi.clear(); + if(CALCULATOR->aborted() || !wtest.subtract(wprev) || (wprev.isNonZero() && !wtest.divide(wprev)) || !wtest.abs() || !wtesti.subtract(wprevi) || (wprevi.isNonZero() && !wtesti.divide(wprevi)) || !wtesti.abs()) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + CALCULATOR->setPrecision(prec_bak); + return false; + } + if((wtest < wprec || (!wtest.isNonZero() && wtest < wprec2)) && (wtesti < wprec || (!wtesti.isNonZero() && wtesti < wprec2))) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + if(wtest.isZero()) {wtest++; wtest.setToFloatingPoint(); mpfr_nextabove(wtest.internalUpperFloat()); wtest--;} + if(wtesti.isZero() && v.hasImaginaryPart() && !b_real) {wtesti++; wtesti.setToFloatingPoint(); mpfr_nextabove(wtesti.internalUpperFloat()); wtesti--;} + wtest.setImaginaryPart(wtesti); + v.setRelativeUncertainty(wtest, !CREATE_INTERVAL); + CALCULATOR->setPrecision(prec_bak); + break; + } + } + if(!v.testFloatResult(true)) { + return false; + } + set(v); + if(b_real) clearImaginary(); + b_approx = true; + return true; +} bool Number::lambertW() { if(!isReal()) return false; if(isZero()) return true; + if(isInfinite()) {setPlusInfinity(true); return true;} if(isInterval()) { Number nr_l, nr_u; @@ -6494,13 +7399,17 @@ n_type = NUMBER_TYPE_FLOAT; mpq_set_ui(r_value, 0, 1); } - mpfr_set(fl_value, w, MPFR_RNDN); - mpfr_set(fu_value, fl_value, MPFR_RNDN); - mpfr_clears(x, m1_div_exp1, w, wPrec, wTimesExpW, wPlusOneTimesExpW, testXW, tmp1, tmp2, NULL); - if(i_precision < 0 || i_precision > PRECISION) i_precision = FROM_BIT_PRECISION(BIT_PRECISION - 30); if(CREATE_INTERVAL) { - precisionToInterval(); + mpfr_mul(wPrec, wPrec, w, MPFR_RNDA); + mpfr_abs(wPrec, wPrec, MPFR_RNDU); + mpfr_sub(fl_value, w, wPrec, MPFR_RNDD); + mpfr_add(fu_value, w, wPrec, MPFR_RNDD); + } else { + mpfr_set(fl_value, w, MPFR_RNDN); + mpfr_set(fu_value, fl_value, MPFR_RNDN); + if(i_precision < 0 || i_precision > FROM_BIT_PRECISION(BIT_PRECISION - 30)) i_precision = FROM_BIT_PRECISION(BIT_PRECISION - 30); } + mpfr_clears(x, m1_div_exp1, w, wPrec, wTimesExpW, wPlusOneTimesExpW, testXW, tmp1, tmp2, NULL); } if(!testFloatResult(true)) { set(nr_bak); @@ -6532,7 +7441,237 @@ bool Number::polylog(const Number &o) { if(isZero()) return true; - if(!o.isTwo() || !isLessThanOrEqualTo(1)) return false; + if(isMinusInfinity()) return false; + if(isPlusInfinity()) { + if(!o.isInteger() || !o.isPositive()) return false; + setMinusInfinity(true); + return true; + } + if(o.includesInfinity()) return false; + if(o.isOne()) { + Number nln(*this); + if(!nln.negate() || !nln.add(1) || !nln.ln() || !nln.negate()) return false; + set(nln); + setPrecisionAndApproximateFrom(o); + return true; + } + if(isOne() && o < 1) return false; + if(o.isZero()) { + Number n0(*this); + if(!n0.negate() || !n0.add(1) || !n0.recip() || !n0.add(-1)) return false; + set(n0); + setPrecisionAndApproximateFrom(o); + return true; + } + if(o.isMinusOne()) { + Number nr(*this); + if(!nr.negate() || !nr.add(1) || !nr.square() || !nr.recip() || !nr.multiply(*this)) return false; + set(nr); + setPrecisionAndApproximateFrom(o); + return true; + } + if(!o.isTwo() || !isLessThanOrEqualTo(1)) { + if(isInterval(false)) { + Number nr_l, nr_u; + if(i_value && i_value->isInterval()) { + Number nr_il, nr_iu; + nr_il.setInternal(i_value->internalLowerFloat()); + nr_iu.setInternal(i_value->internalUpperFloat()); + if(isInterval(true)) { + Number nr_l2, nr_u2; + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + nr_l.setImaginaryPart(nr_il); + nr_u.setImaginaryPart(nr_iu); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + nr_l2.setInternal(fl_value); + nr_u2.setInternal(fu_value); + nr_l2.setImaginaryPart(nr_iu); + nr_u2.setImaginaryPart(nr_il); + nr_l2.intervalToMidValue(); + nr_u2.intervalToMidValue(); + if(!nr_l.polylog(o) || !nr_u.polylog(o) || !nr_l2.polylog(o) || !nr_u2.polylog(o)) return false; + nr_u.setInterval(nr_u, nr_u2); + nr_l.setInterval(nr_l, nr_l2); + } else { + nr_l.set(*this); nr_u.set(*this); + nr_l.setImaginaryPart(nr_il); + nr_u.setImaginaryPart(nr_iu); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(!nr_l.polylog(o) || !nr_u.polylog(o)) return false; + } + } else { + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + if(i_value) nr_l.setImaginaryPart(*i_value); + if(i_value) nr_u.setImaginaryPart(*i_value); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(!nr_l.polylog(o) || !nr_u.polylog(o)) return false; + } + if(o.isNegative() || hasImaginaryPart() || o.hasImaginaryPart() || (isInterval(false) && o.isInterval(false))) { + if(precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_POLYLOG)->name().c_str(), NULL); + } + setPrecisionAndApproximateFrom(nr_l); + setPrecisionAndApproximateFrom(nr_u); + return setInterval(nr_l, nr_u, true); + } + if(o.isInterval(false)) { + Number nr_l(*this), nr_lo, nr_u(*this), nr_uo; + if(o.hasImaginaryPart() && o.internalImaginary()->isInterval()) { + Number nr_il, nr_iu; + nr_il.setInternal(o.internalImaginary()->internalLowerFloat()); + nr_iu.setInternal(o.internalImaginary()->internalUpperFloat()); + if(o.isInterval(true)) { + Number nr_l2(*this), nr_u2(*this), nr_lo2, nr_uo2; + nr_lo.setInternal(o.internalLowerFloat()); + nr_uo.setInternal(o.internalUpperFloat()); + nr_lo.setImaginaryPart(nr_il); + nr_uo.setImaginaryPart(nr_iu); + nr_lo.intervalToMidValue(); + nr_uo.intervalToMidValue(); + nr_lo2.setInternal(o.internalLowerFloat()); + nr_uo2.setInternal(o.internalUpperFloat()); + nr_lo2.setImaginaryPart(nr_iu); + nr_uo2.setImaginaryPart(nr_il); + nr_lo2.intervalToMidValue(); + nr_uo2.intervalToMidValue(); + if(!nr_l.polylog(nr_lo) || !nr_u.polylog(nr_uo) || !nr_l2.polylog(nr_lo2) || !nr_u2.polylog(nr_uo2)) return false; + nr_u.setInterval(nr_u, nr_u2); + nr_l.setInterval(nr_l, nr_l2); + } else { + nr_lo.set(o); nr_uo.set(o); + nr_lo.setImaginaryPart(nr_il); + nr_uo.setImaginaryPart(nr_iu); + nr_lo.intervalToMidValue(); + nr_uo.intervalToMidValue(); + if(!nr_l.polylog(nr_lo) || !nr_u.polylog(nr_uo)) return false; + } + } else { + nr_lo.setInternal(o.internalLowerFloat()); + nr_uo.setInternal(o.internalUpperFloat()); + if(o.hasImaginaryPart()) nr_lo.setImaginaryPart(*o.internalImaginary()); + if(o.hasImaginaryPart()) nr_uo.setImaginaryPart(*o.internalImaginary()); + nr_lo.intervalToMidValue(); + nr_uo.intervalToMidValue(); + if(!nr_l.polylog(nr_lo) || !nr_u.polylog(nr_uo)) return false; + } + if(o.isNegative() || hasImaginaryPart() || o.hasImaginaryPart() || (isInterval(false) && o.isInterval(false))) { + if(o.precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_POLYLOG)->name().c_str(), NULL); + } + setPrecisionAndApproximateFrom(nr_l); + setPrecisionAndApproximateFrom(nr_u); + return setInterval(nr_l, nr_u, true); + + } + if(includesInfinity()) return false; + Number absx(*this); + absx.abs(); + int i = 0; + if(absx < 1) i = 1; + else if(absx > 1 && o.isInteger() && o.isNegative()) i = 2; + Number nradd; + if(i == 0) { + if(o.isInteger() && o.isPositive()) { + if(o == 2 && absx > 1) { + i = 2; + Number nrpi; nrpi.pi(); + nradd = *this; + if(!nrpi.square() || !nrpi.divide(-6) || !nradd.negate() || !nradd.ln() || !nradd.square() || !nradd.divide(-2) || !nradd.add(nrpi)) return false; + } else if(o == 3 && absx > 1) { + i = 2; + Number nrpi; nrpi.pi(); + Number nrlog(*this); + if(!nrpi.square() || !nrpi.divide(-6) || !nrlog.negate() || !nrlog.ln() || !nrpi.multiply(nrlog)) return false; + nradd = nrlog; + if(!nradd.raise(3) || !nradd.divide(-6) || !nradd.add(nrpi)) return false; + } + } else { + Number nrgamma(o); + nradd = *this; + if(!nrgamma.negate() || !nrgamma.add(1) || !nrgamma.gamma() || !nradd.ln() || !nradd.negate() || !nradd.raise(o - 1) || !nradd.multiply(nrgamma)) return false; + } + } + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(!CALCULATOR->usesIntervalArithmetic()) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + mpfr_clear_flags(); + int prec_bak = PRECISION; + CALCULATOR->setPrecision(PRECISION * 2 + 20); + Number v(*this); + if(!v.setToFloatingPoint()) {CALCULATOR->setPrecision(prec_bak); CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + Number xpow, kpow, yprev, yprevi, ytest, ytesti; + Number x(v); + if(i == 2 && !v.recip()) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); CALCULATOR->setPrecision(prec_bak); return false;} + Number oneg(o); + oneg.negate(); + Number k(i == 0 ? 1 : 2, 1); + Number kfac(1, 1); + Number wprec(1, 1, -(prec_bak + 20)); + Number wprec2(1, 1, -prec_bak); + if(i == 0) { + v = o; + if(!v.zeta()) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); CALCULATOR->setPrecision(prec_bak); return false;} + } + yprev = v; + yprev.clearImaginary(); + if(v.internalImaginary()) yprevi.set(*v.internalImaginary()); + for(int c = 0; ; c++) { + xpow = x; + kpow = k; + if(i == 0) { + if(c > PRECISION * 1000 || CALCULATOR->aborted() || !kfac.multiply(k) || !kpow.negate() || !kpow.add(o) || !kpow.zeta() || !xpow.ln() || !xpow.raise(k) || !xpow.multiply(kpow) || !xpow.divide(kfac) || !v.add(xpow) || v.includesInfinity()) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + CALCULATOR->setPrecision(prec_bak); + return false; + } + } else { + kpow = k; + if(c > PRECISION * 1000 || CALCULATOR->aborted() || !kpow.raise(oneg) || !xpow.raise(k) || (i == 2 && !xpow.recip()) || !xpow.multiply(kpow) || !v.add(xpow) || v.includesInfinity()) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + CALCULATOR->setPrecision(prec_bak); + return false; + } + } + if(v.isInterval() && v.precision(true) < prec_bak + 10) { + if(v.precision(true) < prec_bak) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + wprec.set(1, 1, -prec_bak); + wprec2.set(1, 1, -prec_bak + 2); + } + ytest = yprev; + ytesti = yprevi; + yprev = v; + yprev.clearImaginary(); + if(v.internalImaginary()) yprevi.set(*v.internalImaginary()); + else yprevi.clear(); + if(!ytest.subtract(yprev) || (yprev.isNonZero() && !ytest.divide(yprev)) || !ytest.abs() || !ytesti.subtract(yprevi) || (yprevi.isNonZero() && !ytesti.divide(yprevi)) || !ytesti.abs()) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + CALCULATOR->setPrecision(prec_bak); + return false; + } + if((ytest < wprec || (!ytest.isNonZero() && ytest < wprec2)) && (ytesti < wprec || (!ytesti.isNonZero() && ytesti < wprec2))) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + if(ytest.isZero()) {ytest++; ytest.setToFloatingPoint(); mpfr_nextabove(ytest.internalUpperFloat()); ytest--;} + if(ytesti.isZero() && v.hasImaginaryPart()) {ytesti++; ytesti.setToFloatingPoint(); mpfr_nextabove(ytesti.internalUpperFloat()); ytesti--;} + ytest.setImaginaryPart(ytesti); + v.setRelativeUncertainty(ytest, !CREATE_INTERVAL); + CALCULATOR->setPrecision(prec_bak); + break; + } + k++; + } + if(!v.testFloatResult(true)) return false; + if(i == 2 && o.isEven()) v.negate(); + if(!nradd.isZero() && !v.add(nradd)) return false; + set(v); + b_approx = true; + return true; + } Number nr_bak(*this); if(!setToFloatingPoint()) return false; mpfr_clear_flags(); @@ -6553,7 +7692,7 @@ #if MPFR_VERSION_MAJOR < 4 return false; #else - if(!isReal() || (!o.isNonZero() && !isNonZero())) return false; + if(!o.isReal() || !isReal() || (!o.isNonZero() && !isNonZero())) return false; Number nr_bak(*this); if(!setToFloatingPoint()) return false; Number o_float(o); @@ -6565,7 +7704,7 @@ } else { mpfr_gamma_inc(fl_value, fl_value, o_float.internalUpperFloat(), MPFR_RNDD); mpfr_gamma_inc(fu_value, fu_value, o_float.internalLowerFloat(), MPFR_RNDU); - if(!o.isGreaterThanOrEqualTo(1) && !nr_bak.isGreaterThan(2) && nr_bak.isInterval() && nr_bak.precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->f_igamma->name().c_str(), NULL); + if(!o.isGreaterThanOrEqualTo(1) && !nr_bak.isGreaterThan(2) && nr_bak.isInterval() && nr_bak.precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_I_GAMMA)->name().c_str(), NULL); } if(!testFloatResult()) { set(nr_bak); @@ -6574,9 +7713,401 @@ return true; #endif } -bool Number::expint() { +bool Number::fresnels() { + if(hasImaginaryPart()) return false; + if(isZero()) return true; + if(isPlusInfinity()) {set(1, 2, 0, true); return true;} + if(isMinusInfinity()) {set(-1, 2, 0, true); return true;} + // precision failure occurs when x>6 or x<-6 + if(!isLessThanOrEqualTo(6) || !isGreaterThanOrEqualTo(-6)) return false; + if(isInterval()) { + Number nr_l, nr_u; + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + if(!nr_l.fresnels() || !nr_u.fresnels()) return false; + mpfr_t nsqrt; + mpfr_init2(nsqrt, BIT_PRECISION); + unsigned long int i = 2; + mpfr_sqrt_ui(nsqrt, i, MPFR_RNDN); + while(mpfr_cmp(fu_value, nsqrt) > 0) { + if(mpfr_cmp(fl_value, nsqrt) < 0) { + Number nrt; + nrt.setInternal(nsqrt); + if(!nrt.fresnels()) {mpfr_clear(nsqrt); return false;} + nr_u.setInterval(nr_u, nrt); + break; + } + i += 4; + mpfr_sqrt_ui(nsqrt, i, MPFR_RNDN); + } + if(mpfr_sgn(fl_value) > 0) { + if(i > 2) i -= 2; + else i += 2; + mpfr_sqrt_ui(nsqrt, i, MPFR_RNDN); + while(mpfr_cmp(fu_value, nsqrt) > 0) { + if(mpfr_cmp(fl_value, nsqrt) < 0) { + Number nrt; + nrt.setInternal(nsqrt); + if(!nrt.fresnels()) {mpfr_clear(nsqrt); return false;} + nr_l.setInterval(nrt, nr_l); + break; + } + i += 4; + mpfr_sqrt_ui(nsqrt, i, MPFR_RNDN); + } + } else { + i = 2; + mpfr_sqrt_ui(nsqrt, i, MPFR_RNDN); + mpfr_neg(nsqrt, nsqrt, MPFR_RNDN); + while(mpfr_cmp(fl_value, nsqrt) < 0) { + if(mpfr_cmp(fu_value, nsqrt) > 0) { + Number nrt; + nrt.setInternal(nsqrt); + if(!nrt.fresnels()) {mpfr_clear(nsqrt); return false;} + nr_l.setInterval(nrt, nr_l); + break; + } + i += 4; + mpfr_sqrt_ui(nsqrt, i, MPFR_RNDN); + mpfr_neg(nsqrt, nsqrt, MPFR_RNDN); + } + if(mpfr_sgn(fu_value) < 0) { + if(i > 2) i -= 2; + else i += 2; + mpfr_sqrt_ui(nsqrt, i, MPFR_RNDN); + mpfr_neg(nsqrt, nsqrt, MPFR_RNDN); + while(mpfr_cmp(fl_value, nsqrt) < 0) { + if(mpfr_cmp(fu_value, nsqrt) > 0) { + Number nrt; + nrt.setInternal(nsqrt); + if(!nrt.fresnels()) {mpfr_clear(nsqrt); return false;} + nr_u.setInterval(nr_u, nrt); + break; + } + i += 4; + mpfr_sqrt_ui(nsqrt, i, MPFR_RNDN); + mpfr_neg(nsqrt, nsqrt, MPFR_RNDN); + } + } + } + mpfr_clear(nsqrt); + setInterval(nr_l, nr_u); + return true; + } + Number nr_bak(*this); + // fresnels(x)=x^3*sum(2^(-1-2k)*pi^(1+2k)*(-x^4)^k/((3+4k)(1+2k)!),0,infinity,k) + mpfr_clear_flags(); + unsigned long int k = 0; + mpfr_t pipow, xpow, x, num, den, yprev, wprec, v; + mpfr_inits2(BIT_PRECISION * 2, v, pipow, xpow, x, num, den, yprev, wprec, NULL); + if(n_type == NUMBER_TYPE_FLOAT) { + mpfr_set(x, fl_value, MPFR_RNDN); + } else { + mpfr_set_q(x, r_value, MPFR_RNDN); + if(!setToFloatingPoint()) return false; + } + mpfr_set_si(wprec, -BIT_PRECISION - 2, MPFR_RNDN); + mpfr_exp2(wprec, wprec, MPFR_RNDN); + mpfr_set_ui(v, 0, MPFR_RNDN); + while(true) { + if(CALCULATOR->aborted()) {mpfr_clears(pipow, xpow, x, num, den, yprev, wprec, v, NULL); set(nr_bak); return false;} + mpfr_set(yprev, v, MPFR_RNDN); + mpfr_fac_ui(den, 1 + (2 * k), MPFR_RNDN); + mpfr_mul_ui(den, den, 3 + (4 * k), MPFR_RNDN); + mpfr_const_pi(pipow, MPFR_RNDN); + mpfr_pow_ui(pipow, pipow, 1 + (2 * k), MPFR_RNDN); + mpfr_pow_ui(xpow, x, 4 * k, MPFR_RNDN); + mpfr_set_ui(num, 2, MPFR_RNDN); + mpfr_ui_div(num, 1, num, MPFR_RNDN); + mpfr_pow_si(num, num, (1 + (2 * k)), MPFR_RNDN); + mpfr_mul(num, num, pipow, MPFR_RNDN); + mpfr_mul(num, num, xpow, MPFR_RNDN); + mpfr_div(num, num, den, MPFR_RNDN); + if(k % 2 == 1) mpfr_neg(num, num, MPFR_RNDN); + mpfr_add(v, v, num, MPFR_RNDN); + mpfr_sub(yprev, yprev, v, MPFR_RNDU); + mpfr_div(yprev, yprev, v, MPFR_RNDU); + mpfr_abs(yprev, yprev, MPFR_RNDU); + if(mpfr_cmp(yprev, wprec) < 0) { + mpfr_pow_ui(x, x, 3, MPFR_RNDN); + mpfr_mul(v, v, x, MPFR_RNDN); + mpfr_set(fl_value, v, MPFR_RNDD); + mpfr_set(fu_value, v, MPFR_RNDU); + if(CREATE_INTERVAL) { + mpfr_mul(yprev, yprev, v, MPFR_RNDA); + mpfr_abs(yprev, yprev, MPFR_RNDU); + mpfr_sub(fl_value, fl_value, yprev, MPFR_RNDD); + mpfr_add(fu_value, fu_value, yprev, MPFR_RNDU); + } + break; + } + k++; + } + mpfr_clears(pipow, xpow, x, num, den, yprev, wprec, v, NULL); + if(!testFloatResult()) { + set(nr_bak); + return false; + } + b_approx = true; + return true; +} +bool Number::fresnelc() { if(hasImaginaryPart()) return false; - if(isInfinite()) {clear(); return true;} + if(isZero()) return true; + if(isPlusInfinity()) {set(1, 2, 0, true); return true;} + if(isMinusInfinity()) {set(-1, 2, 0, true); return true;} + // precision failure occurs when x>6 or x<-6 + if(!isLessThanOrEqualTo(6) || !isGreaterThanOrEqualTo(-6)) return false; + if(isInterval()) { + Number nr_l, nr_u; + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + if(!nr_l.fresnelc() || !nr_u.fresnelc()) return false; + mpfr_t nsqrt; + mpfr_init2(nsqrt, BIT_PRECISION); + unsigned long int i = 1; + mpfr_set_ui(nsqrt, 1, MPFR_RNDN); + while(mpfr_cmp(fu_value, nsqrt) > 0) { + if(mpfr_cmp(fl_value, nsqrt) < 0) { + Number nrt; + nrt.setInternal(nsqrt); + if(!nrt.fresnelc()) {mpfr_clear(nsqrt); return false;} + nr_u.setInterval(nr_u, nrt); + break; + } + i += 4; + mpfr_sqrt_ui(nsqrt, i, MPFR_RNDN); + } + if(mpfr_sgn(fl_value) > 0) { + if(i > 2) i -= 2; + else i += 2; + mpfr_sqrt_ui(nsqrt, i, MPFR_RNDN); + while(mpfr_cmp(fu_value, nsqrt) > 0) { + if(mpfr_cmp(fl_value, nsqrt) < 0) { + Number nrt; + nrt.setInternal(nsqrt); + if(!nrt.fresnelc()) {mpfr_clear(nsqrt); return false;} + nr_l.setInterval(nrt, nr_l); + break; + } + i += 4; + mpfr_sqrt_ui(nsqrt, i, MPFR_RNDN); + } + } else { + i = 1; + mpfr_set_si(nsqrt, -1, MPFR_RNDN); + while(mpfr_cmp(fl_value, nsqrt) < 0) { + if(mpfr_cmp(fu_value, nsqrt) > 0) { + Number nrt; + nrt.setInternal(nsqrt); + if(!nrt.fresnelc()) {mpfr_clear(nsqrt); return false;} + nr_l.setInterval(nrt, nr_l); + break; + } + i += 4; + mpfr_sqrt_ui(nsqrt, i, MPFR_RNDN); + mpfr_neg(nsqrt, nsqrt, MPFR_RNDN); + } + if(mpfr_sgn(fu_value) < 0) { + if(i > 2) i -= 2; + else i += 2; + mpfr_sqrt_ui(nsqrt, i, MPFR_RNDN); + mpfr_neg(nsqrt, nsqrt, MPFR_RNDN); + while(mpfr_cmp(fl_value, nsqrt) < 0) { + if(mpfr_cmp(fu_value, nsqrt) > 0) { + Number nrt; + nrt.setInternal(nsqrt); + if(!nrt.fresnelc()) {mpfr_clear(nsqrt); return false;} + nr_u.setInterval(nr_u, nrt); + break; + } + i += 4; + mpfr_sqrt_ui(nsqrt, i, MPFR_RNDN); + mpfr_neg(nsqrt, nsqrt, MPFR_RNDN); + } + } + } + mpfr_clear(nsqrt); + setInterval(nr_l, nr_u); + return true; + } + Number nr_bak(*this); + // fresnelc(x)=x*sum(4^(-k)*pi^(2k)*(-x^4)^k/((2k)!+4k*(2k)!),0,infinity,k) + mpfr_clear_flags(); + unsigned long int k = 0; + mpfr_t pipow, xpow, x, num, den, yprev, wprec, v; + mpfr_inits2(BIT_PRECISION * 2, pipow, xpow, x, num, den, yprev, wprec, v, NULL); + if(n_type == NUMBER_TYPE_FLOAT) { + mpfr_set(x, fl_value, MPFR_RNDN); + } else { + mpfr_set_q(x, r_value, MPFR_RNDN); + if(!setToFloatingPoint()) return false; + } + mpfr_set_si(wprec, -BIT_PRECISION - 2, MPFR_RNDN); + mpfr_exp2(wprec, wprec, MPFR_RNDN); + mpfr_set_ui(v, 0, MPFR_RNDN); + while(true) { + if(CALCULATOR->aborted()) {mpfr_clears(pipow, xpow, x, num, den, yprev, wprec, v, NULL); set(nr_bak); return false;} + mpfr_set(yprev, v, MPFR_RNDN); + mpfr_fac_ui(den, 2 * k, MPFR_RNDN); + mpfr_mul_ui(den, den, 1 + (4 * k), MPFR_RNDN); + mpfr_const_pi(pipow, MPFR_RNDN); + mpfr_pow_ui(pipow, pipow, 2 * k, MPFR_RNDN); + mpfr_pow_ui(xpow, x, 4 * k, MPFR_RNDN); + mpfr_set_ui(num, 4, MPFR_RNDN); + mpfr_ui_div(num, 1, num, MPFR_RNDN); + mpfr_pow_si(num, num, k, MPFR_RNDN); + mpfr_mul(num, num, pipow, MPFR_RNDN); + mpfr_mul(num, num, xpow, MPFR_RNDN); + mpfr_div(num, num, den, MPFR_RNDN); + if(k % 2 == 1) mpfr_neg(num, num, MPFR_RNDN); + mpfr_add(v, v, num, MPFR_RNDN); + mpfr_sub(yprev, yprev, v, MPFR_RNDU); + mpfr_div(yprev, yprev, v, MPFR_RNDU); + mpfr_abs(yprev, yprev, MPFR_RNDU); + if(mpfr_cmp(yprev, wprec) < 0) { + mpfr_mul(v, v, x, MPFR_RNDN); + mpfr_set(fl_value, v, MPFR_RNDD); + mpfr_set(fu_value, v, MPFR_RNDU); + if(CREATE_INTERVAL) { + mpfr_mul(yprev, yprev, v, MPFR_RNDA); + mpfr_abs(yprev, yprev, MPFR_RNDU); + mpfr_sub(fl_value, fl_value, yprev, MPFR_RNDD); + mpfr_add(fu_value, fu_value, yprev, MPFR_RNDU); + } + break; + } + k++; + } + mpfr_clears(pipow, xpow, x, num, den, yprev, wprec, v, NULL); + if(!testFloatResult()) { + set(nr_bak); + return false; + } + b_approx = true; + return true; +} +bool Number::expint() { + if(isZero()) {setMinusInfinity(true); return true;} + if(hasImaginaryPart()) { + if(i_value->includesInfinity() && includesInfinity(true)) return false; + if(i_value->isPlusInfinity()) {i_value->pi(); setPrecisionAndApproximateFrom(*i_value); return true;} + if(i_value->isMinusInfinity()) {if(includesInfinity(true)) return false; i_value->pi(); i_value->negate(); setPrecisionAndApproximateFrom(*i_value); return true;} + if(isMinusInfinity(true)) {clear(); return true;} + if(isPlusInfinity(true)) {clearImaginary(); return true;} + if(includesInfinity()) return false; + if(isInterval(false)) { + Number nr_l, nr_u; + if(i_value->isInterval()) { + Number nr_il, nr_iu; + nr_il.setInternal(i_value->internalLowerFloat()); + nr_iu.setInternal(i_value->internalUpperFloat()); + if(isInterval(true)) { + Number nr_l2, nr_u2; + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + nr_l.setImaginaryPart(nr_il); + nr_u.setImaginaryPart(nr_iu); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + nr_l2.setInternal(fl_value); + nr_u2.setInternal(fu_value); + nr_l2.setImaginaryPart(nr_iu); + nr_u2.setImaginaryPart(nr_il); + nr_l2.intervalToMidValue(); + nr_u2.intervalToMidValue(); + if(!nr_l.expint() || !nr_u.expint() || !nr_l2.expint() || !nr_u2.expint()) return false; + nr_u.setInterval(nr_u, nr_u2); + nr_l.setInterval(nr_l, nr_l2); + } else { + nr_l.set(*this); nr_u.set(*this); + nr_l.setImaginaryPart(nr_il); + nr_u.setImaginaryPart(nr_iu); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(!nr_l.expint() || !nr_u.expint()) return false; + } + } else { + Number nr_l2, nr_u2; + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + nr_l.setImaginaryPart(*i_value); + nr_u.setImaginaryPart(*i_value); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(!nr_l.expint() || !nr_u.expint()) return false; + } + if(precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_EXPINT)->name().c_str(), NULL); + setPrecisionAndApproximateFrom(nr_l); + setPrecisionAndApproximateFrom(nr_u); + return setInterval(nr_l, nr_u, true); + } + Number nr_euler; nr_euler.euler(); + Number nr_lnr(*this), nr_ln(*this); + if(!nr_lnr.recip() || !nr_lnr.ln() || !nr_ln.ln() || !nr_ln.divide(2) || !nr_lnr.divide(-2)) return false; + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(!CALCULATOR->usesIntervalArithmetic()) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + mpfr_clear_flags(); + int prec_bak = PRECISION; + CALCULATOR->setPrecision(PRECISION * 2 + 20); + Number v(*this); + if(!v.setToFloatingPoint()) {CALCULATOR->setPrecision(prec_bak); CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + Number xpow, yprev, yprevi, ytest, ytesti; + Number x(v); + Number k(2, 1); + Number kfac(1, 1); + Number wprec(1, 1, -(prec_bak + 20)); + Number wprec2(1, 1, -prec_bak); + yprev = v; + yprev.clearImaginary(); + if(v.internalImaginary()) yprevi.set(*v.internalImaginary()); + for(int i = 0; ; i++) { + xpow = x; + if(i > PRECISION * 100 || CALCULATOR->aborted() || !kfac.multiply(k) || !xpow.raise(k) || !xpow.divide(kfac) || !xpow.divide(k) || !v.add(xpow) || v.includesInfinity()) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + CALCULATOR->setPrecision(prec_bak); + return false; + } + if(v.isInterval() && v.precision(true) < prec_bak + 10) { + if(v.precision(true) < prec_bak) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + wprec.set(1, 1, -prec_bak); + wprec2.set(1, 1, -prec_bak + 2); + } + ytest = yprev; + ytesti = yprevi; + yprev = v; + yprev.clearImaginary(); + if(v.internalImaginary()) yprevi.set(*v.internalImaginary()); + else yprevi.clear(); + if(!ytest.subtract(yprev) || (yprev.isNonZero() && !ytest.divide(yprev)) || !ytest.abs() || !ytesti.subtract(yprevi) || (yprevi.isNonZero() && !ytesti.divide(yprevi)) || !ytesti.abs()) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + CALCULATOR->setPrecision(prec_bak); + return false; + } + if((ytest < wprec || (!ytest.isNonZero() && ytest < wprec2)) && (ytesti < wprec || (!ytesti.isNonZero() && ytesti < wprec2))) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + if(ytest.isZero()) {ytest++; ytest.setToFloatingPoint(); mpfr_nextabove(ytest.internalUpperFloat()); ytest--;} + if(ytesti.isZero()) {ytesti++; ytesti.setToFloatingPoint(); mpfr_nextabove(ytesti.internalUpperFloat()); ytesti--;} + ytest.setImaginaryPart(ytesti); + v.setRelativeUncertainty(ytest, !CREATE_INTERVAL); + CALCULATOR->setPrecision(prec_bak); + break; + } + k++; + } + if(!v.testFloatResult(true)) return false; + if(!v.add(nr_euler) || !v.add(nr_ln) || !v.add(nr_lnr)) return false; + set(v); + b_approx = true; + return true; + } + if(isMinusInfinity()) {clear(); return true;} + if(isPlusInfinity()) {return true;} + if(!isNonZero()) return false; Number nr_bak(*this); if(!setToFloatingPoint()) return false; mpfr_clear_flags(); @@ -6620,7 +8151,120 @@ if(isMinusInfinity()) {pi(); multiply(-2); return true;} if(isZero()) return true; if(hasImaginaryPart()) { - if(hasRealPart()) return false; + if(hasRealPart()) { + if(includesInfinity()) return false; + if(isInterval(false)) { + Number nr_l, nr_u; + if(i_value->isInterval()) { + Number nr_il, nr_iu; + nr_il.setInternal(i_value->internalLowerFloat()); + nr_iu.setInternal(i_value->internalUpperFloat()); + if(isInterval(true)) { + Number nr_l2, nr_u2; + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + nr_l.setImaginaryPart(nr_il); + nr_u.setImaginaryPart(nr_iu); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + nr_l2.setInternal(fl_value); + nr_u2.setInternal(fu_value); + nr_l2.setImaginaryPart(nr_iu); + nr_u2.setImaginaryPart(nr_il); + nr_l2.intervalToMidValue(); + nr_u2.intervalToMidValue(); + if(!nr_l.sinint() || !nr_u.sinint() || !nr_l2.sinint() || !nr_u2.sinint()) return false; + nr_u.setInterval(nr_u, nr_u2); + nr_l.setInterval(nr_l, nr_l2); + } else { + nr_l.set(*this); nr_u.set(*this); + nr_l.setImaginaryPart(nr_il); + nr_u.setImaginaryPart(nr_iu); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(!nr_l.sinint() || !nr_u.sinint()) return false; + } + } else { + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + nr_l.setImaginaryPart(*i_value); + nr_u.setImaginaryPart(*i_value); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(!nr_l.sinint() || !nr_u.sinint()) return false; + } + if(precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_SININT)->name().c_str(), NULL); + setPrecisionAndApproximateFrom(nr_l); + setPrecisionAndApproximateFrom(nr_u); + return setInterval(nr_l, nr_u, true); + } + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(!CALCULATOR->usesIntervalArithmetic()) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + mpfr_clear_flags(); + int prec_bak = PRECISION; + CALCULATOR->setPrecision(PRECISION * 2 + 20); + Number x(*this); + if(!x.setToFloatingPoint()) {CALCULATOR->setPrecision(prec_bak); CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + Number xpow, num, den, yprev, yprevi, ytest, ytesti; + Number v(1, 1); + Number k(1, 1); + Number k2(1, 1); + Number kfac(1, 1); + Number wprec(1, 1, -(prec_bak + 20)); + Number wprec2(1, 1, -prec_bak); + yprev = v; + yprev.clearImaginary(); + if(v.internalImaginary()) yprevi.set(*v.internalImaginary()); + for(int i = 0; ; i++) { + den = k; den *= 2; den++; + xpow = k; xpow *= 2; + num = x; + if(i > PRECISION * 100 || CALCULATOR->aborted() || !kfac.multiply(k2) || !k2.add(1) || !kfac.multiply(k2) || !den.square() ||!den.multiply(kfac) || !num.raise(xpow) || !num.divide(den) || (k.isOdd() && !num.negate()) || !v.add(num) || v.includesInfinity()) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + if(v.isInterval() && v.precision(true) < prec_bak + 10) { + if(v.precision(true) < prec_bak) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + wprec.set(1, 1, -prec_bak); + wprec2.set(1, 1, -prec_bak + 2); + } + ytest = yprev; + ytesti = yprevi; + yprev = v; + yprev.clearImaginary(); + if(v.internalImaginary()) yprevi.set(*v.internalImaginary()); + else yprevi.clear(); + if(!ytest.subtract(yprev) || (yprev.isNonZero() && !ytest.divide(yprev)) || !ytest.abs() || !ytesti.subtract(yprevi) || (yprevi.isNonZero() && !ytesti.divide(yprevi)) || !ytesti.abs()) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + if((ytest < wprec || (!ytest.isNonZero() && ytest < wprec2)) && (ytesti < wprec || (!ytesti.isNonZero() && ytesti < wprec2))) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + if(ytest.isZero()) {ytest++; ytest.setToFloatingPoint(); mpfr_nextabove(ytest.internalUpperFloat()); ytest--;} + if(ytesti.isZero()) {ytesti++; ytesti.setToFloatingPoint(); mpfr_nextabove(ytesti.internalUpperFloat()); ytesti--;} + ytest.setImaginaryPart(ytesti); + ytest *= 10; + CALCULATOR->setPrecision(prec_bak); + v.setRelativeUncertainty(ytest, !CREATE_INTERVAL); + if(!v.multiply(x)) return false; + break; + } + k++; + k2++; + } + if(!v.testFloatResult(true)) { + return false; + } + set(v); + b_approx = true; + return true; + } if(!i_value->sinhint()) return false; setPrecisionAndApproximateFrom(*i_value); return true; @@ -6866,7 +8510,11 @@ if(isMinusInfinity()) {return true;} if(isZero()) return true; if(hasImaginaryPart()) { - if(hasRealPart()) return false; + if(hasRealPart()) { + Number nr_bak(*this); + if(!multiply(nr_one_i) || !sinint() || !multiply(nr_minus_i)) {set(nr_bak); return false;} + return true; + } if(!i_value->sinhint()) return false; setPrecisionAndApproximateFrom(*i_value); return true; @@ -6934,7 +8582,122 @@ bool Number::cosint() { if(isPlusInfinity()) {clear(true); return true;} if(isZero()) {setMinusInfinity(true); return true;} - if(hasImaginaryPart() && !hasRealPart()) { + if(hasImaginaryPart()) { + if(hasRealPart()) { + if(includesInfinity()) return false; + if(isInterval(false)) { + Number nr_l, nr_u; + if(i_value->isInterval()) { + Number nr_il, nr_iu; + nr_il.setInternal(i_value->internalLowerFloat()); + nr_iu.setInternal(i_value->internalUpperFloat()); + if(isInterval(true)) { + Number nr_l2, nr_u2; + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + nr_l.setImaginaryPart(nr_il); + nr_u.setImaginaryPart(nr_iu); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + nr_l2.setInternal(fl_value); + nr_u2.setInternal(fu_value); + nr_l2.setImaginaryPart(nr_iu); + nr_u2.setImaginaryPart(nr_il); + nr_l2.intervalToMidValue(); + nr_u2.intervalToMidValue(); + if(!nr_l.cosint() || !nr_u.cosint() || !nr_l2.cosint() || !nr_u2.cosint()) return false; + nr_u.setInterval(nr_u, nr_u2); + nr_l.setInterval(nr_l, nr_l2); + } else { + nr_l.set(*this); nr_u.set(*this); + nr_l.setImaginaryPart(nr_il); + nr_u.setImaginaryPart(nr_iu); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(!nr_l.cosint() || !nr_u.cosint()) return false; + } + } else { + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + nr_l.setImaginaryPart(*i_value); + nr_u.setImaginaryPart(*i_value); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(!nr_l.cosint() || !nr_u.cosint()) return false; + } + if(precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_COSINT)->name().c_str(), NULL); + setPrecisionAndApproximateFrom(nr_l); + setPrecisionAndApproximateFrom(nr_u); + return setInterval(nr_l, nr_u, true); + } + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(!CALCULATOR->usesIntervalArithmetic()) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + mpfr_clear_flags(); + int prec_bak = PRECISION; + CALCULATOR->setPrecision(PRECISION * 2 + 20); + Number x(*this); + if(!x.setToFloatingPoint()) {CALCULATOR->setPrecision(prec_bak); CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + Number xpow, num, den, yprev, yprevi, ytest, ytesti; + Number v; + Number k(1, 1); + Number k2(1, 1); + Number kfac(1, 1); + Number wprec(1, 1, -(prec_bak + 20)); + Number wprec2(1, 1, -prec_bak); + yprev = v; + yprev.clearImaginary(); + if(v.internalImaginary()) yprevi.set(*v.internalImaginary()); + for(int i = 0; ; i++) { + den = k; + xpow = k; xpow *= 2; + num = x; + if(i > PRECISION * 100 || CALCULATOR->aborted() || !kfac.multiply(k2) || !k2.add(1) || !kfac.multiply(k2) ||!den.multiply(kfac) || !num.raise(xpow) || !num.divide(den) || (k.isOdd() && !num.negate()) || !v.add(num) || v.includesInfinity()) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + if(v.isInterval() && v.precision(true) < prec_bak + 10) { + if(v.precision(true) < prec_bak) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + wprec.set(1, 1, -prec_bak); + wprec2.set(1, 1, -prec_bak + 2); + } + ytest = yprev; + ytesti = yprevi; + yprev = v; + yprev.clearImaginary(); + if(v.internalImaginary()) yprevi.set(*v.internalImaginary()); + else yprevi.clear(); + if(!ytest.subtract(yprev) || (yprev.isNonZero() && !ytest.divide(yprev)) || !ytest.abs() || !ytesti.subtract(yprevi) || (yprevi.isNonZero() && !ytesti.divide(yprevi)) || !ytesti.abs()) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + if((ytest < wprec || (!ytest.isNonZero() && ytest < wprec2)) && (ytesti < wprec || (!ytesti.isNonZero() && ytesti < wprec2))) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + if(ytest.isZero()) {ytest++; ytest.setToFloatingPoint(); mpfr_nextabove(ytest.internalUpperFloat()); ytest--;} + if(ytesti.isZero()) {ytesti++; ytesti.setToFloatingPoint(); mpfr_nextabove(ytesti.internalUpperFloat()); ytesti--;} + ytest.setImaginaryPart(ytesti); + ytest *= 10; + CALCULATOR->setPrecision(prec_bak); + v.setRelativeUncertainty(ytest, !CREATE_INTERVAL); + Number nr_euler; nr_euler.euler(); + if(!x.ln() || !v.divide(2) || !v.add(x) || !v.add(nr_euler)) return false; + break; + } + k++; + k2++; + } + if(!v.testFloatResult(true)) { + return false; + } + set(v); + b_approx = true; + return true; + } if(i_value->isNegative()) { set(*i_value, true); negate(); @@ -7214,7 +8977,122 @@ bool Number::coshint() { if(isPlusInfinity()) {return true;} if(isZero()) {setMinusInfinity(true); return true;} - if(hasImaginaryPart() && !hasRealPart()) { + if(hasImaginaryPart()) { + if(hasRealPart()) { + if(includesInfinity()) return false; + if(isInterval(false)) { + Number nr_l, nr_u; + if(i_value->isInterval()) { + Number nr_il, nr_iu; + nr_il.setInternal(i_value->internalLowerFloat()); + nr_iu.setInternal(i_value->internalUpperFloat()); + if(isInterval(true)) { + Number nr_l2, nr_u2; + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + nr_l.setImaginaryPart(nr_il); + nr_u.setImaginaryPart(nr_iu); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + nr_l2.setInternal(fl_value); + nr_u2.setInternal(fu_value); + nr_l2.setImaginaryPart(nr_iu); + nr_u2.setImaginaryPart(nr_il); + nr_l2.intervalToMidValue(); + nr_u2.intervalToMidValue(); + if(!nr_l.coshint() || !nr_u.coshint() || !nr_l2.coshint() || !nr_u2.coshint()) return false; + nr_u.setInterval(nr_u, nr_u2); + nr_l.setInterval(nr_l, nr_l2); + } else { + nr_l.set(*this); nr_u.set(*this); + nr_l.setImaginaryPart(nr_il); + nr_u.setImaginaryPart(nr_iu); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(!nr_l.coshint() || !nr_u.coshint()) return false; + } + } else { + nr_l.setInternal(fl_value); + nr_u.setInternal(fu_value); + nr_l.setImaginaryPart(*i_value); + nr_u.setImaginaryPart(*i_value); + nr_l.intervalToMidValue(); + nr_u.intervalToMidValue(); + if(!nr_l.coshint() || !nr_u.coshint()) return false; + } + if(precision(1) <= PRECISION + 20) CALCULATOR->error(false, _("%s() lacks proper support interval arithmetic."), CALCULATOR->getFunctionById(FUNCTION_ID_COSHINT)->name().c_str(), NULL); + setPrecisionAndApproximateFrom(nr_l); + setPrecisionAndApproximateFrom(nr_u); + return setInterval(nr_l, nr_u, true); + } + CALCULATOR->beginTemporaryEnableIntervalArithmetic(); + if(!CALCULATOR->usesIntervalArithmetic()) {CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + mpfr_clear_flags(); + int prec_bak = PRECISION; + CALCULATOR->setPrecision(PRECISION * 2 + 20); + Number x(*this); + if(!x.setToFloatingPoint()) {CALCULATOR->setPrecision(prec_bak); CALCULATOR->endTemporaryEnableIntervalArithmetic(); return false;} + Number xpow, num, den, yprev, yprevi, ytest, ytesti; + Number v; + Number k(1, 1); + Number k2(1, 1); + Number kfac(1, 1); + Number wprec(1, 1, -(prec_bak + 20)); + Number wprec2(1, 1, -prec_bak); + yprev = v; + yprev.clearImaginary(); + if(v.internalImaginary()) yprevi.set(*v.internalImaginary()); + for(int i = 0; ; i++) { + den = k; + xpow = k; xpow *= 2; + num = x; + if(i > PRECISION * 100 || CALCULATOR->aborted() || !kfac.multiply(k2) || !k2.add(1) || !kfac.multiply(k2) ||!den.multiply(kfac) || !num.raise(xpow) || !num.divide(den) || !v.add(num) || v.includesInfinity()) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + if(v.isInterval() && v.precision(true) < prec_bak + 10) { + if(v.precision(true) < prec_bak) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + wprec.set(1, 1, -prec_bak); + wprec2.set(1, 1, -prec_bak + 2); + } + ytest = yprev; + ytesti = yprevi; + yprev = v; + yprev.clearImaginary(); + if(v.internalImaginary()) yprevi.set(*v.internalImaginary()); + else yprevi.clear(); + if(!ytest.subtract(yprev) || (yprev.isNonZero() && !ytest.divide(yprev)) || !ytest.abs() || !ytesti.subtract(yprevi) || (yprevi.isNonZero() && !ytesti.divide(yprevi)) || !ytesti.abs()) { + CALCULATOR->setPrecision(prec_bak); + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + return false; + } + if((ytest < wprec || (!ytest.isNonZero() && ytest < wprec2)) && (ytesti < wprec || (!ytesti.isNonZero() && ytesti < wprec2))) { + CALCULATOR->endTemporaryEnableIntervalArithmetic(); + if(ytest.isZero()) {ytest++; ytest.setToFloatingPoint(); mpfr_nextabove(ytest.internalUpperFloat()); ytest--;} + if(ytesti.isZero()) {ytesti++; ytesti.setToFloatingPoint(); mpfr_nextabove(ytesti.internalUpperFloat()); ytesti--;} + ytest.setImaginaryPart(ytesti); + ytest *= 10; + CALCULATOR->setPrecision(prec_bak); + v.setRelativeUncertainty(ytest, !CREATE_INTERVAL); + Number nr_euler; nr_euler.euler(); + if(!x.ln() || !v.divide(2) || !v.add(x) || !v.add(nr_euler)) return false; + break; + } + k++; + k2++; + } + if(!v.testFloatResult(true)) { + return false; + } + set(v); + b_approx = true; + return true; + } if(i_value->isNegative()) { set(*i_value, true); negate(); @@ -7735,6 +9613,7 @@ string Number::print(const PrintOptions &po, const InternalPrintStruct &ips) const { if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); + // reset InternalPrintStruct (used for separate handling sign, scientific notation, numerator/denominator, imaginary/real parts, etc) if(ips.minus) *ips.minus = false; if(ips.exp_minus) *ips.exp_minus = false; if(ips.num) *ips.num = ""; @@ -7745,17 +9624,22 @@ if(ips.iexp) *ips.iexp = 0; if(po.is_approximate && isApproximate()) *po.is_approximate = true; if(po.base == BASE_BIJECTIVE_26 && isReal()) { + // bijective base 26 (uses digits A-Z, A=1) Number nr(*this); + // number can only be displayed as integers using bijective bases if(!nr.isInteger()) { if(po.is_approximate) *po.is_approximate = true; nr.round(po.round_halfway_to_even); } + // return empty string if number is zero if(nr.isZero()) return ""; + // handle negative sign separately bool neg = nr.isNegative(); if(neg) nr.negate(); Number nri, nra; string str; do { + // value at position nra = nr - (ceil(nr / 26) - 1) * 26 nri = nr; nri /= 26; nri.ceil(); @@ -7763,9 +9647,11 @@ nra = nri; nra *= 26; nra = nr - nra; + // nr left = (ceil(nr / 26) - 1); nr = nri; - str.insert(0, 1, ('A' + nra.intValue() - 1)); + str.insert(0, 1, (char) ('A' + nra.intValue() - 1)); } while(!nr.isZero()); + // add sign if(ips.minus) { *ips.minus = neg; } else if(neg) { @@ -7775,9 +9661,11 @@ return str; } if(((po.base < BASE_CUSTOM && po.base != BASE_BIJECTIVE_26) || (po.base == BASE_CUSTOM && (!CALCULATOR->customOutputBase().isInteger() || CALCULATOR->customOutputBase() > 62 || CALCULATOR->customOutputBase() < 2))) && isReal()) { + // non-integer bases, negative bases, and bases > 62 Number base; switch(po.base) { case BASE_GOLDEN_RATIO: { + // golden ratio = (sqrt(5)+1)/2 base.set(5); base.sqrt(); base.add(1); @@ -7785,17 +9673,22 @@ break; } case BASE_SUPER_GOLDEN_RATIO: { + // supergolden ratio = (1+cbrt((29+3*sqrt(93))/2)+cbrt((29-3*sqrt(93))/2))/3 + // a=3*sqrt(93) base.set(93); base.sqrt(); base.multiply(3); + // b=cbrt((29-a)/2) Number b2(base); b2.negate(); b2.add(29); b2.divide(2); b2.cbrt(); + // c=cbrt((29+a)/2) base.add(29); base.divide(2); base.cbrt(); + // (1+a+b)/3 base.add(b2); base.add(1); base.divide(3); @@ -7804,20 +9697,18 @@ case BASE_PI: {base.pi(); break;} case BASE_E: {base.e(); break;} case BASE_SQRT2: {base.set(2); base.sqrt(); break;} + // Unicode base uses all 1114111 Unicode characters as digits case BASE_UNICODE: {base.set(1114112L); break;} default: {base = CALCULATOR->customOutputBase();} } - if(base.isInteger() && base >= 2 && base <= 36) { - PrintOptions po2 = po; - po2.base = base.intValue(); - return print(po2, ips); - } + // negative non-integer bases, complex bases, and bases where absolute value is <= 1 if(!base.isReal() || (base.isNegative() && !base.isInteger()) || !(base > 1 || base < -1)) { CALCULATOR->error(true, _("Unsupported base"), NULL); PrintOptions po2 = po; po2.base = BASE_DECIMAL; return print(po2, ips); } + // use mid value for low precision intervals and any interval with negative bases if((base.isNegative() && isInterval()) || (isInterval() && precision(true) < 1)) { Number nr(*this); if(!nr.intervalToPrecision()) { @@ -7826,6 +9717,7 @@ } return nr.print(po, ips); } + // use mid value for bases with low precision interval if(base.isInterval() && base.precision(true) < 1) { if(!base.intervalToPrecision()) { base.intervalToMidValue(); @@ -7834,15 +9726,23 @@ } Number abs_base(base); abs_base.abs(); + // use unicode ditis for base 1114112 bool b_uni = (abs_base == 1114112L); + // use escaped digit value for absolute base > 62 bool b_num = abs_base > 62; + // digits are case sensitive for absolute base > 36 bool b_case = !b_num && abs_base > 36; + // if base is approximate, output is approximate if(po.is_approximate && base.isApproximate()) *po.is_approximate = true; long int precision = PRECISION; + // adjust output precision if precision of number or base is lower than global precision if(b_approx && i_precision >= 0 && i_precision < precision) precision = i_precision; if(base.isApproximate() && base.precision() >= 0 && base.precision() < precision) precision = base.precision(); + // adjust output precision to precision of parent MathStructure if(po.restrict_to_parent_precision && ips.parent_precision >= 0 && ips.parent_precision < precision) precision = ips.parent_precision; + + // calculate number of digits allowed for the number base with the current precision: floor(log(10^precision-1, abs(base))) long int precision_base = precision; Number precmax(10); precmax.raise(precision_base); @@ -7853,10 +9753,13 @@ string str; + // number is zero if(isZero()) { + // escaped digit if(b_num) str += '\\'; str += '0'; if(po.show_ending_zeroes && isApproximate()) { + // show the number of decimals allowed by the current precision str += po.decimalpoint(); while(precision_base > 1) { precision_base--; @@ -8161,9 +10064,16 @@ return str; } if((po.base == BASE_SEXAGESIMAL || po.base == BASE_TIME) && isReal()) { + // sexagesimal base or time format + Number nr(*this); + + // handle sign separately bool neg = nr.isNegative(); nr.setNegative(false); + + // from left to right + // first section: integer part nr.trunc(); PrintOptions po2 = po; po2.base = 10; @@ -8177,13 +10087,16 @@ } } nr = *this; + // second section: trunc(fractional part * 60) nr.frac(); nr *= 60; Number nr2(nr); nr.trunc(); if(po.base == BASE_TIME) { + // hour, minus, seconds is separated by colons str += ":"; if(nr.isLessThan(10)) { + // always use two digits for second and third sections of time output str += "0"; } } @@ -8196,10 +10109,14 @@ } } nr2.frac(); + // do not show zero seconds in time format if(!nr2.isZero() || po.base == BASE_SEXAGESIMAL) { + // third section: trunc((fractional part of (fractional part * 60)) * 60) nr2.multiply(60); nr = nr2; nr.trunc(); + + // if left over fractional part != 0, output is approximate, round upwards if >= 0.5 nr2.frac(); if(!nr2.isZero()) { if(po.is_approximate) *po.is_approximate = true; @@ -8222,6 +10139,7 @@ } } } + // add sign if(ips.minus) { *ips.minus = neg; } else if(neg) { @@ -8232,18 +10150,24 @@ return str; } + string str; int base; + long int min_decimals = 0; if(po.use_min_decimals && po.min_decimals > 0) min_decimals = po.min_decimals; + // min decimals is greater than max decimals if((int) min_decimals > po.max_decimals && po.use_max_decimals && po.max_decimals >= 0) { min_decimals = po.max_decimals; } + if(po.base == BASE_CUSTOM) base = CALCULATOR->customOutputBase().intValue(); else if(po.base <= 1 && po.base != BASE_ROMAN_NUMERALS && po.base != BASE_TIME) base = 10; else if(po.base > 36 && po.base != BASE_SEXAGESIMAL) base = 36; else base = po.base; + if(po.base == BASE_ROMAN_NUMERALS) { + // do not display roman numerals for non-rational numbers and numbers with absolute value > 9999; use decimal base instead if(!isRational()) { CALCULATOR->error(false, _("Can only display rational numbers as roman numerals."), NULL); base = 10; @@ -8254,14 +10178,11 @@ } if(hasImaginaryPart()) { - if(i_value->isZero()) { - Number nr; - nr.set(*this, false, true); - return nr.print(po, ips); - } - string str_i = (CALCULATOR ? CALCULATOR->v_i->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name : "i"); + // imaginary unit + string str_i = (CALCULATOR ? CALCULATOR->getVariableById(VARIABLE_ID_I)->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name : "i"); bool bre = hasRealPart(); if(bre) { + // output real and imaginary part separately (they are normally already separeted in the parent MathStructure) Number r_nr(*this); r_nr.clearImaginary(); str = r_nr.print(po, ips); @@ -8272,31 +10193,40 @@ string str2 = i_value->print(po, ips_n); if(ips.im) *ips.im = str2; if(!po.short_multiplication && (str2 != "1" || po.base == BASE_UNICODE)) { - if(po.spacious) { - str2 += " * "; - } else { - str2 += "*"; - } + // show multiplication symbol between 1 and i + if(po.spacious) str2 += " "; + if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_DOT && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIDOT, po.can_display_unicode_string_arg))) str2 += SIGN_MULTIDOT; + else if(po.use_unicode_signs && (po.multiplication_sign == MULTIPLICATION_SIGN_DOT || po.multiplication_sign == MULTIPLICATION_SIGN_ALTDOT) && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MIDDLEDOT, po.can_display_unicode_string_arg))) str2 += SIGN_MIDDLEDOT; + else if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_X && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIPLICATION, po.can_display_unicode_string_arg))) str2 += SIGN_MULTIPLICATION; + else str2 += "*"; + if(po.spacious) str2 += " "; } + // do not show 1 (i instead of 1i); 'i' is placed after the number, while 'j' is placed before if(str2 == "1" && po.base != BASE_UNICODE) str2 = str_i; else if(str_i == "j") str2.insert(0, str_i); else str2 += str_i; + if(po.spacious) str += " "; if(*ips_n.minus) { - str += " - "; + if(po.use_unicode_signs && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MINUS, po.can_display_unicode_string_arg))) str += SIGN_MINUS; + else str += "-"; } else { - str += " + "; + str += "+"; } + if(po.spacious) str += " "; str += str2; } else { str = i_value->print(po, ips); if(ips.im) *ips.im = str; if(!po.short_multiplication && (str != "1" || po.base == BASE_UNICODE)) { - if(po.spacious) { - str += " * "; - } else { - str += "*"; - } + // show multiplication symbol between 1 and i + if(po.spacious) str += " "; + if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_DOT && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIDOT, po.can_display_unicode_string_arg))) str += SIGN_MULTIDOT; + else if(po.use_unicode_signs && (po.multiplication_sign == MULTIPLICATION_SIGN_DOT || po.multiplication_sign == MULTIPLICATION_SIGN_ALTDOT) && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MIDDLEDOT, po.can_display_unicode_string_arg))) str += SIGN_MIDDLEDOT; + else if(po.use_unicode_signs && po.multiplication_sign == MULTIPLICATION_SIGN_X && (!po.can_display_unicode_string_function || (*po.can_display_unicode_string_function) (SIGN_MULTIPLICATION, po.can_display_unicode_string_arg))) str += SIGN_MULTIPLICATION; + else str += "*"; + if(po.spacious) str += " "; } + // do not show 1 (i instead of 1i); 'i' is placed after the number, while 'j' is placed before if(str == "1" && po.base != BASE_UNICODE) str = str_i; else if(str_i == "j") str.insert(0, str_i); else str += str_i; @@ -8306,10 +10236,18 @@ } long int precision = PRECISION; + + // adjust output precision if precision of the number is lower than global precision if(b_approx && i_precision >= 0 && (po.preserve_precision || po.preserve_format || i_precision < PRECISION)) precision = i_precision; - else if(b_approx && i_precision < 0 && po.preserve_precision && FROM_BIT_PRECISION(BIT_PRECISION) > precision) precision = FROM_BIT_PRECISION(BIT_PRECISION); - else if(b_approx && i_precision < 0 && po.preserve_format && FROM_BIT_PRECISION(BIT_PRECISION) - 1 > precision) precision = FROM_BIT_PRECISION(BIT_PRECISION) - 1; + // if preserve_precision is true, use full precision + else if(b_approx && i_precision < 0 && po.preserve_precision && FROM_BIT_PRECISION(NUMBER_BIT_PRECISION) > precision) precision = FROM_BIT_PRECISION(NUMBER_BIT_PRECISION); + // if preserve_format is true, use full precision - 1 (avoids confusing output) + else if(b_approx && i_precision < 0 && po.preserve_format && FROM_BIT_PRECISION(NUMBER_BIT_PRECISION) - 1 > precision) precision = FROM_BIT_PRECISION(NUMBER_BIT_PRECISION) - 1; + + // adjust output precision to precision of parent MathStructure if(po.restrict_to_parent_precision && ips.parent_precision >= 0 && ips.parent_precision < precision) precision = ips.parent_precision; + + // calculate number of digits allowed for the number base with the current precision: floor(log(10^precision-1, abs(base))) long int precision_base = precision; if(base != 10 && ((base >= 2 && base <= 36) || po.base == BASE_CUSTOM)) { Number precmax(10); @@ -8319,9 +10257,11 @@ precmax.floor(); precision_base = precmax.lintValue(); } + + // calculate number of digits allowed for the number base with the full precision of the number long int i_precision_base = precision_base; - if((i_precision < 0 && FROM_BIT_PRECISION(BIT_PRECISION) > precision) || i_precision > precision) { - if(i_precision < 0) i_precision_base = FROM_BIT_PRECISION(BIT_PRECISION); + if((i_precision < 0 && FROM_BIT_PRECISION(NUMBER_BIT_PRECISION) > precision) || i_precision > precision) { + if(i_precision < 0) i_precision_base = FROM_BIT_PRECISION(NUMBER_BIT_PRECISION); else i_precision_base = i_precision; if(po.restrict_to_parent_precision && ips.parent_precision >= 0 && ips.parent_precision < i_precision_base) i_precision_base = ips.parent_precision; if(base != 10 && ((base >= 2 && base <= 36) || po.base == BASE_CUSTOM)) { @@ -8333,10 +10273,18 @@ i_precision_base = precmax.lintValue(); } } + + // number or parent is approximate bool approx = isApproximate() || (ips.parent_approximate && po.restrict_to_parent_precision); if(isInteger()) { + // Output integer + + // output extremely large integers as floating point + // condition: number of digits > 1000 and number is approximate, or base = 10 and scientific notation and not unrestricted fraction format + // or number of digits > 10000 and base != 10 + // or number of digits > 1000000 long int length = mpz_sizeinbase(mpq_numref(r_value), base); if(precision_base + min_decimals + 1000 + ::abs(po.min_exp) < length && ((approx || (base == 10 && po.min_exp != 0 && (po.restrict_fraction_length || po.number_fraction_format == FRACTION_DECIMAL || po.number_fraction_format == FRACTION_DECIMAL_EXACT))) || length > (po.base == 10 ? 1000000L : 100000L))) { Number nr(*this); @@ -8347,12 +10295,14 @@ CALCULATOR->endTemporaryStopMessages(true); return nr.print(po2, ips); } else { + // floating point conversion failed (might happen with extremely large numbers): use scientific notation and divide original number length--; mpz_t ivalue; mpz_init(ivalue); mpz_ui_pow_ui(ivalue, base, length); Number nrexp; nrexp.setInternal(ivalue); + // divide by base^(output length - 1) if(nr.divide(nrexp)) { CALCULATOR->endTemporaryStopMessages(); str = nr.print(po2, ips); @@ -8393,6 +10343,7 @@ } return str; } + // division failed: unable to display number CALCULATOR->endTemporaryStopMessages(true); return "(floating point error)"; } @@ -8400,9 +10351,11 @@ if(po.base == 2 || (po.base == 16 && po.hexadecimal_twos_complement)) { if((po.base == 16 || po.twos_complement) && isNegative()) { + // show negative number using two's complement Number nr; unsigned int bits = po.binary_bits; if(bits == 0) { + // determine appropriate number of bits nr = *this; nr.floor(); nr++; @@ -8419,6 +10372,7 @@ } nr = bits; nr.exp2(); + // two's complement number = negative number + 2^(number of bits) nr += *this; PrintOptions po2 = po; po2.twos_complement = false; @@ -8438,6 +10392,7 @@ po2.binary_bits = bits; return nr.print(po2, ips); } else if(po.binary_bits == 0) { + // determine appropriate number of bits for binary (and hexadecimal, when using hexadecimal two's complement) numbers Number nr(*this); nr.ceil(); unsigned int bits = nr.integerLength() + 1; @@ -8464,26 +10419,32 @@ integer_rerun: + // full integer string (without sign; roman numerals never use lower case) string mpz_str = printMPZ(ivalue, base, false, base != BASE_ROMAN_NUMERALS && po.lower_case_numbers); if(CALCULATOR->aborted()) return CALCULATOR->abortedMessage(); + // determine exponent for scientific notation length = mpz_str.length(); long int expo = 0; if(base == 10 && !po.preserve_format) { if(length == 1 && mpz_str[0] == '0') { + // number is zero expo = 0; } else if(length > 0 && (po.restrict_fraction_length || po.number_fraction_format == FRACTION_DECIMAL || po.number_fraction_format == FRACTION_DECIMAL_EXACT)) { if(po.number_fraction_format == FRACTION_FRACTIONAL) { + // restricted fraction format: exponent = length - 1 if exponent >= precision; increase precision if possible to avoid lengthening of the output long int precexp = i_precision_base; if(precision < 8 && precexp > precision + 2) precexp = precision + 2; else if(precexp > precision + 3) precexp = precision + 3; if(exact && ((expo >= 0 && length - 1 < precexp) || (expo < 0 && expo > -PRECISION))) expo = 0; else expo = length - 1; } else { + // by default exponent = output string length - 1 expo = length - 1; } } else if(length > 0) { + // unrestricted fractional format: only use scientific notation in order to remove trailing zeroes for(long int i = length - 1; i >= 0; i--) { if(mpz_str[i] != '0') { break; @@ -8492,6 +10453,7 @@ } } if(po.min_exp == EXP_PRECISION || (po.min_exp == EXP_NONE && (expo > 100000L || expo < -100000L))) { + // use scientific notation if exponent >= precision; increase precision if possible to avoid lengthening of the output long int precexp = i_precision_base; if(precision < 8 && precexp > precision + 2) precexp = precision + 2; else if(precexp > precision + 3) precexp = precision + 3; @@ -8499,14 +10461,17 @@ if(precision_base < length) precision_base = length; expo = 0; } - } else if(po.min_exp < -1) { + } else if(po.min_exp < 0) { + // exponent should be multiple of -po.min_exp expo -= expo % (-po.min_exp); if(expo < 0) expo = 0; - } else if(po.min_exp != 0) { + } else if(po.min_exp > 0) { + // use scientific notation if exponent >= po.min_exp if((long int) expo > -po.min_exp && (long int) expo < po.min_exp) { expo = 0; } } else { + // po.min_exp = 0: do not use scientific notation expo = 0; } } @@ -8517,6 +10482,7 @@ if(!rerun && mpz_sgn(ivalue) != 0) { long int precision2 = precision_base; + // increase output precision to include minimum number of decimals if(min_decimals > 0 && min_decimals + nondecimals > precision_base) { precision2 = min_decimals + nondecimals; if(approx && precision2 > i_precision_base) precision2 = i_precision_base; @@ -8730,7 +10696,7 @@ po2.interval_display = INTERVAL_DISPLAY_UPPER; string str2 = print(po2, ips2); if(str1 == str2) return print(po2, ips); - str = CALCULATOR->f_interval->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name; + str = CALCULATOR->getFunctionById(FUNCTION_ID_INTERVAL)->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, po.use_reference_names, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).name; str += LEFT_PARENTHESIS; str += str1; str += po.comma(); diff -Nru libqalculate-3.6.0/libqalculate/Number.h libqalculate-3.7.0/libqalculate/Number.h --- libqalculate-3.6.0/libqalculate/Number.h 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Number.h 2020-01-21 22:54:40.000000000 +0000 @@ -125,6 +125,7 @@ bool setToFloatingPoint(); void precisionToInterval(); bool intervalToPrecision(long int min_precision = 2); + void intervalToMidValue(bool increase_precision_if_close); void intervalToMidValue(); void splitInterval(unsigned int nr_of_parts, std::vector &v) const; bool getCentralInteger(Number &nr_int, bool *b_multiple = NULL, std::vector *v = NULL) const; @@ -461,10 +462,14 @@ */ bool zeta(); + /// Hurwitz zeta function + bool zeta(const Number &o); + bool gamma(); bool digamma(); bool airy(); bool erf(); + bool erfi(); bool erfc(); bool besselj(const Number &o); bool bessely(const Number &o); @@ -487,11 +492,14 @@ bool log(const Number &o); bool exp(); bool lambertW(); + bool lambertW(const Number &k); bool gcd(const Number &o); bool lcm(const Number &o); bool polylog(const Number &o); bool igamma(const Number &o); + bool fresnels(); + bool fresnelc(); bool expint(); bool logint(); bool sinint(); @@ -505,6 +513,8 @@ bool binomial(const Number &m, const Number &k); bool factorize(std::vector &factors); + bool bernoulli(); + void rand(); void randn(); void intRand(const Number &ceil); @@ -522,4 +532,6 @@ std::ostream& operator << (std::ostream &os, const Number&); +bool testComplexZero(const Number *this_nr, const Number *i_nr); + #endif diff -Nru libqalculate-3.6.0/libqalculate/Unit.cc libqalculate-3.7.0/libqalculate/Unit.cc --- libqalculate-3.6.0/libqalculate/Unit.cc 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Unit.cc 2020-01-21 22:54:40.000000000 +0000 @@ -16,6 +16,7 @@ #include "Calculator.h" #include "MathStructure.h" #include "Prefix.h" +#include "BuiltinFunctions.h" using std::string; using std::vector; @@ -116,7 +117,7 @@ b_use_with_prefixes = use_with_prefixes; } bool Unit::isCurrency() const { - return baseUnit() == CALCULATOR->u_euro; + return baseUnit() == CALCULATOR->getUnitById(UNIT_ID_EURO); } const string &Unit::countries() const {return scountries;} void Unit::setCountries(string country_names) { @@ -252,16 +253,19 @@ } else if(u->baseUnit() == baseUnit()) { u->convertToBaseUnit(mvalue, mexp); convertFromBaseUnit(mvalue, mexp); - if(isCurrency() && u->isCurrency() && ((isBuiltin() && this != CALCULATOR->u_euro) || (u->isBuiltin() && u != CALCULATOR->u_euro))) { + if(isCurrency() && u->isCurrency() && ((isBuiltin() && this != CALCULATOR->getUnitById(UNIT_ID_EURO)) || (u->isBuiltin() && u != CALCULATOR->getUnitById(UNIT_ID_EURO)))) { int i = 1; - if(u == CALCULATOR->u_btc || this == CALCULATOR->u_btc) i = 2; - if(u->subtype() == SUBTYPE_ALIAS_UNIT) { - if(i < 2 && ((AliasUnit*) u)->firstBaseUnit() == CALCULATOR->u_btc) i = 2; - else if(((AliasUnit*) u)->firstBaseUnit() != CALCULATOR->u_euro) i = 3; - } - if(i < 3 && subtype() == SUBTYPE_ALIAS_UNIT) { - if(i < 2 && ((AliasUnit*) this)->firstBaseUnit() == CALCULATOR->u_btc) i = 2; - else if(((AliasUnit*) this)->firstBaseUnit() != CALCULATOR->u_euro) i = 3; + if(i < 4 && (u == CALCULATOR->getUnitById(UNIT_ID_BYN) || this == CALCULATOR->getUnitById(UNIT_ID_BYN))) i = (i == 3 ? 5 : 4); + if(i < 2 && (u == CALCULATOR->getUnitById(UNIT_ID_BTC) || this == CALCULATOR->getUnitById(UNIT_ID_BTC))) i = 2; + if(i < 5 && u->subtype() == SUBTYPE_ALIAS_UNIT) { + if(i < 2 && ((AliasUnit*) u)->firstBaseUnit() == CALCULATOR->getUnitById(UNIT_ID_BTC)) i = 2; + else if(i < 5 && ((AliasUnit*) u)->firstBaseUnit() != CALCULATOR->getUnitById(UNIT_ID_EURO)) i = (i == 4 ? 5 : 3); + else if(i < 4 && ((AliasUnit*) u)->firstBaseUnit() == CALCULATOR->getUnitById(UNIT_ID_BYN)) i = (i == 3 ? 5 : 4); + } + if(i < 5 && subtype() == SUBTYPE_ALIAS_UNIT) { + if(i < 2 && ((AliasUnit*) this)->firstBaseUnit() == CALCULATOR->getUnitById(UNIT_ID_BTC)) i = 2; + else if(i < 5 && ((AliasUnit*) this)->firstBaseUnit() != CALCULATOR->getUnitById(UNIT_ID_EURO)) i = (i == 4 ? 5 : 3); + else if(i < 4 && ((AliasUnit*) this)->firstBaseUnit() == CALCULATOR->getUnitById(UNIT_ID_BYN)) i = (i == 3 ? 5 : 4); } CALCULATOR->setExchangeRatesUsed(i); } @@ -457,7 +461,7 @@ } else { CALCULATOR->parse(mstruct, svalue, po); if(mstruct->containsType(STRUCT_UNIT, false, true, true)) { - mstruct->transform(CALCULATOR->f_stripunits); + mstruct->transformById(FUNCTION_ID_STRIP_UNITS); } } if(!suncertainty.empty()) { @@ -597,7 +601,7 @@ } else { CALCULATOR->parse(mstruct, svalue, po); if(mstruct->containsType(STRUCT_UNIT, false, true, true) > 0) { - mstruct->transform(CALCULATOR->f_stripunits); + mstruct->transformById(FUNCTION_ID_STRIP_UNITS); } } if(!suncertainty.empty()) { @@ -1011,7 +1015,7 @@ if(!has_p || units[i]->prefix()) { mstruct2.set(units[i]->firstBaseUnit(), units[i]->prefix()); } else { - mstruct2.set(units[i]->firstBaseUnit(), CALCULATOR->decimal_null_prefix); + mstruct2.set(units[i]->firstBaseUnit(), CALCULATOR->getDecimalNullPrefix()); } if(make_division && units[i]->firstBaseExponent() < 0) { if(units[i]->firstBaseExponent() != -1) { diff -Nru libqalculate-3.6.0/libqalculate/util.cc libqalculate-3.7.0/libqalculate/util.cc --- libqalculate-3.6.0/libqalculate/util.cc 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/util.cc 2020-01-21 22:54:40.000000000 +0000 @@ -706,7 +706,7 @@ char *dest, *buffer; buffer = dest = (char*) malloc((outlength + 4) * sizeof(char)); if(!buffer) return NULL; - size_t err = iconv(conv, (char **) &str, &inlength, &buffer, &outlength); + size_t err = iconv(conv, (ICONV_CONST char **) &str, &inlength, &buffer, &outlength); if(err != (size_t) -1) err = iconv(conv, NULL, &inlength, &buffer, &outlength); iconv_close(conv); memset(buffer, 0, 4); @@ -721,7 +721,7 @@ char *dest, *buffer; buffer = dest = (char*) malloc((outlength + 4) * sizeof(char)); if(!buffer) return NULL; - size_t err = iconv(conv, (char**) &str, &inlength, &buffer, &outlength); + size_t err = iconv(conv, (ICONV_CONST char**) &str, &inlength, &buffer, &outlength); if(err != (size_t) -1) err = iconv(conv, NULL, &inlength, &buffer, &outlength); iconv_close(conv); memset(buffer, 0, 4 * sizeof(char)); diff -Nru libqalculate-3.6.0/libqalculate/Variable.cc libqalculate-3.7.0/libqalculate/Variable.cc --- libqalculate-3.6.0/libqalculate/Variable.cc 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Variable.cc 2020-01-21 22:54:40.000000000 +0000 @@ -16,6 +16,7 @@ #include "Calculator.h" #include "MathStructure.h" #include "Number.h" +#include "BuiltinFunctions.h" using std::string; using std::vector; @@ -389,7 +390,7 @@ extern bool set_uncertainty(MathStructure &mstruct, MathStructure &munc, const EvaluationOptions &eo = default_evaluation_options, bool do_eval = false); extern bool create_interval(MathStructure &mstruct, const MathStructure &m1, const MathStructure &m2); bool replace_f_interval(MathStructure &mstruct) { - if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_interval && mstruct.size() == 2) { + if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_INTERVAL && mstruct.size() == 2) { if(mstruct[0].isNumber() && mstruct[1].isNumber()) { Number nr; if(nr.setInterval(mstruct[0].number(), mstruct[1].number())) { @@ -401,7 +402,7 @@ MathStructure m2(mstruct[1]); if(create_interval(mstruct, m1, m2)) return true; } - } else if(mstruct.isFunction() && mstruct.function() == CALCULATOR->f_uncertainty && mstruct.size() == 3 && mstruct[2].isNumber()) { + } else if(mstruct.isFunction() && mstruct.function()->id() == FUNCTION_ID_UNCERTAINTY && mstruct.size() == 3 && mstruct[2].isNumber()) { bool b_rel = mstruct[2].number().getBoolean(); if(mstruct[0].isNumber() && mstruct[1].isNumber()) { Number nr(mstruct[0].number()); @@ -465,7 +466,7 @@ } if(!sunit.empty() && (!CALCULATOR->variableUnitsEnabled() || sunit != "auto")) { m->removeType(STRUCT_UNIT); - if(m->containsType(STRUCT_UNIT, false, true, true) != 0) m->transform(CALCULATOR->f_stripunits); + if(m->containsType(STRUCT_UNIT, false, true, true) != 0) m->transformById(FUNCTION_ID_STRIP_UNITS); } if(!suncertainty.empty()) { Number nr_u(suncertainty); @@ -641,3 +642,40 @@ m.set(dt); } +#ifdef __linux__ +# include +#endif + +#if defined __linux__ || defined _WIN32 + +#include + +void UptimeVariable:: calculate(MathStructure &m) const { + Number nr; +# ifdef __linux__ + std::ifstream proc_uptime("/proc/uptime", std::ios::in); + if(proc_uptime.is_open()) { + string s_uptime; + getline(proc_uptime, s_uptime, ' '); + nr.set(s_uptime); + } else { + struct sysinfo sf; + if(!sysinfo(&sf)) nr = (long int) sf.uptime; + } +# elif _WIN32 + ULONGLONG i_uptime = GetTickCount64(); + nr.set((long int) (i_uptime % 1000), 1000); + nr += (long int) (i_uptime / 1000); +# endif + m = nr; + Unit *u = CALCULATOR->getUnit("s"); + if(u) m *= u; +} +UptimeVariable::UptimeVariable() : DynamicVariable("", "uptime") { + setApproximate(false); + always_recalculate = true; +} +UptimeVariable::UptimeVariable(const UptimeVariable *variable) {set(variable);} +ExpressionItem *UptimeVariable::copy() const {return new UptimeVariable(this);} +#endif + diff -Nru libqalculate-3.6.0/libqalculate/Variable.h libqalculate-3.7.0/libqalculate/Variable.h --- libqalculate-3.6.0/libqalculate/Variable.h 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/libqalculate/Variable.h 2020-01-21 22:54:40.000000000 +0000 @@ -17,13 +17,14 @@ /** @file */ -#define DECLARE_BUILTIN_VARIABLE(x) class x : public DynamicVariable { \ +#define DECLARE_BUILTIN_VARIABLE(x, i) class x : public DynamicVariable { \ private: \ void calculate(MathStructure &m) const; \ public: \ x(); \ x(const x *variable) {set(variable);} \ ExpressionItem *copy() const {return new x(this);} \ + int id() const {return i;} \ }; /// Type assumption. @@ -163,6 +164,8 @@ virtual bool representsNonMatrix() {return false;} virtual bool representsScalar() {return false;} + virtual int id() const {return 0;} + }; /// A variable with unknown value. @@ -340,6 +343,8 @@ virtual bool representsNonMatrix(); virtual bool representsScalar(); + virtual int id() const {return 0;} + }; /// Abstract base class for variables with a value which is recalculated when the precision has changed. @@ -393,14 +398,27 @@ }; +enum { + VARIABLE_ID_E = 100, + VARIABLE_ID_PI = 101, + VARIABLE_ID_EULER = 102, + VARIABLE_ID_CATALAN = 103, + VARIABLE_ID_PRECISION = 140, + VARIABLE_ID_TODAY = 161, + VARIABLE_ID_TOMORROW = 162, + VARIABLE_ID_YESTERDAY = 163, + VARIABLE_ID_NOW = 164 +}; + /// Dynamic variable for Pi -DECLARE_BUILTIN_VARIABLE(PiVariable) +DECLARE_BUILTIN_VARIABLE(PiVariable, VARIABLE_ID_PI) /// Dynamic variable for e, the base of natural logarithms -DECLARE_BUILTIN_VARIABLE(EVariable) +DECLARE_BUILTIN_VARIABLE(EVariable, VARIABLE_ID_E) /// Dynamic variable for Euler's constant -DECLARE_BUILTIN_VARIABLE(EulerVariable) +DECLARE_BUILTIN_VARIABLE(EulerVariable, VARIABLE_ID_EULER) /// Dynamic variable for Catalan's constant -DECLARE_BUILTIN_VARIABLE(CatalanVariable) +DECLARE_BUILTIN_VARIABLE(CatalanVariable, VARIABLE_ID_CATALAN) + /// Dynamic variable for current precision class PrecisionVariable : public DynamicVariable { private: @@ -411,6 +429,7 @@ ExpressionItem *copy() const {return new PrecisionVariable(this);} bool representsInteger(bool = false) {return true;} bool representsNonInteger(bool = false) {return false;} + int id() const {return VARIABLE_ID_PRECISION;} }; class TodayVariable : public DynamicVariable { @@ -426,6 +445,7 @@ virtual bool representsNumber(bool b = false) {return b;} virtual bool representsReal(bool b = false) {return b;} virtual bool representsNonZero(bool b = false) {return b;} + int id() const {return VARIABLE_ID_TODAY;} }; class TomorrowVariable : public DynamicVariable { private: @@ -440,6 +460,7 @@ virtual bool representsNumber(bool b = false) {return b;} virtual bool representsReal(bool b = false) {return b;} virtual bool representsNonZero(bool b = false) {return b;} + int id() const {return VARIABLE_ID_TOMORROW;} }; class YesterdayVariable : public DynamicVariable { private: @@ -454,6 +475,7 @@ virtual bool representsNumber(bool b = false) {return b;} virtual bool representsReal(bool b = false) {return b;} virtual bool representsNonZero(bool b = false) {return b;} + int id() const {return VARIABLE_ID_YESTERDAY;} }; class NowVariable : public DynamicVariable { private: @@ -468,6 +490,15 @@ virtual bool representsNumber(bool b = false) {return b;} virtual bool representsReal(bool b = false) {return b;} virtual bool representsNonZero(bool b = false) {return b;} + int id() const {return VARIABLE_ID_NOW;} +}; +class UptimeVariable : public DynamicVariable { + private: + void calculate(MathStructure &m) const; + public: + UptimeVariable(); + UptimeVariable(const UptimeVariable *variable); + ExpressionItem *copy() const; }; #endif diff -Nru libqalculate-3.6.0/m4/libtool.m4 libqalculate-3.7.0/m4/libtool.m4 --- libqalculate-3.6.0/m4/libtool.m4 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/m4/libtool.m4 2020-01-21 22:54:40.000000000 +0000 @@ -728,7 +728,6 @@ cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. diff -Nru libqalculate-3.6.0/.pc/000-fix_autogen.patch/configure.ac libqalculate-3.7.0/.pc/000-fix_autogen.patch/configure.ac --- libqalculate-3.6.0/.pc/000-fix_autogen.patch/configure.ac 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/.pc/000-fix_autogen.patch/configure.ac 2020-01-21 22:54:43.000000000 +0000 @@ -0,0 +1,289 @@ +dnl +dnl configure.in for libqalculate +dnl + +dnl ---------------------- +dnl | initialize autotools |--------------------------------------------------- +dnl ---------------------- + +AC_INIT([libqalculate], [3.7.0]) +AC_CONFIG_SRCDIR(libqalculate/Calculator.cc) +AM_INIT_AUTOMAKE +AM_CONFIG_HEADER(config.h) +AM_MAINTAINER_MODE + +AC_CONFIG_MACRO_DIRS([m4]) + +AC_ARG_ENABLE(textport, + [ --disable-textport Disable compiling the text port], + enable_textport=$enableval, + enable_textport="yes") + +AC_ARG_ENABLE(defs2doc, + [ --enable-defs2doc Enable compiling the definitions documentation generator], + enable_defs2doc=$enableval, + enable_defs2doc="no") + +AC_ARG_ENABLE(tests, + [ --enable-tests Enable compiling test programs], + enable_tests=$enableval, + enable_tests="no") + + +dnl ------------------------------- +dnl | check for neccessary programs |------------------------------------------ +dnl ------------------------------- + +AC_ISC_POSIX +AC_PROG_CC +AC_PROG_CXX +AM_PROG_CC_STDC +AC_PROG_LN_S +AC_HEADER_STDC +AC_PROG_INTLTOOL +AM_PROG_LIBTOOL + +dnl ------------------------------------ +dnl | check for compiler characteristics |------------------------------------- +dnl ------------------------------------ + +dnl Replace -Os with -O2 to stop segfault on startup +if test "x$GCC" = "xyes"; then + case $CFLAGS in + *-Os*) + CFLAGS="$CFLAGS -O2" + ;; + esac + case $CXXFLAGS in + *-Os*) + CXXFLAGS="$CXXFLAGS -O2" + ;; + esac +fi + + +dnl Use -Wall if we have gcc. +changequote(,)dnl +if test "x$GCC" = "xyes"; then + case " $CFLAGS " in + *[\ \ ]-Wall[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wall" ;; + esac +fi +changequote([,])dnl + +dnl check for threading model +dnl TODO +AC_DEFINE([HAVE_PTHREADS],1, + [Define if pthreads are present.]) + +dnl libtool versioning for libqalculate + +dnl increment if the interface has additions, changes, removals. +QALCULATE_CURRENT=27 + +dnl increment any time the source changes; set to +dnl 0 if you increment CURRENT +QALCULATE_REVISION=0 + +dnl increment if any interfaces have been added; set to 0 +dnl if any interfaces have been removed. removal has +dnl precedence over adding, so set to 0 if both happened. +QALCULATE_AGE=6 + +AC_SUBST(QALCULATE_CURRENT) +AC_SUBST(QALCULATE_REVISION) +AC_SUBST(QALCULATE_AGE) + + +dnl -------------------------------- +dnl | check for neccessary libraries |----------------------------------------- +dnl -------------------------------- + +AC_CHECK_LIB(pthread, pthread_create, [LIBS="$LIBS -lpthread"]) + +AC_CHECK_HEADERS(mpfr.h, [LIBS="$LIBS -lmpfr -lgmp"], [AC_MSG_ERROR([Unable to find mpfr header])]) + +AC_LANG([C++]) + +AC_CHECK_HEADERS([unordered_map]) +AC_CHECK_FUNCS([pipe2]) + +AC_ARG_WITH([libcurl], AS_HELP_STRING([--with-libcurl], [support for built-in retrieval of exchange rates]), [], [with_libcurl=yes]) +AS_IF([test "x$with_libcurl" = "xyes"], [ + PKG_CHECK_MODULES([LIBCURL], [libcurl]) + AC_DEFINE([HAVE_LIBCURL], [1], [Use libcurl]) + AC_SUBST(LIBCURL_CFLAGS) + AC_SUBST(LIBCURL_LIBS) +]) + +AC_ARG_WITH([icu], AS_HELP_STRING([--with-icu], [support for case-insensitive unicode strings]), [], [with_icu=yes]) +AS_IF([test "x$with_icu" = "xyes"], [ + PKG_CHECK_MODULES([ICU], [icu-uc]) + AC_DEFINE([HAVE_ICU], [1], [Use icu]) + AC_SUBST(ICU_CFLAGS) + AC_SUBST(ICU_LIBS) +]) + +PKG_CHECK_MODULES(LIBXML, [libxml-2.0 >= 2.3.8]) +AC_SUBST(LIBXML_CFLAGS) +AC_SUBST(LIBXML_LIBS) + +AM_ICONV() + +dnl -------------------------------- +dnl | check for readline |----------------------------------------- +dnl -------------------------------- + +QALCULATE_TEXT="" +LN_QALCULATE="" +USE_READLINE="yes" +READLINE_LIBS="" +if test "x$enable_textport" = "xyes" ; then + QALCULATE_TEXT="qalc$EXEEXT" + LN_QALCULATE="qalc" + + AC_MSG_CHECKING([whether to use readline]) + AC_ARG_WITH(readline, + [ --with-readline turn on readline [default=yes, default tries -lncurses, -lcurses, -ltermcap]], + [case "${withval}" in + yes) USE_READLINE="yes" ; AC_MSG_RESULT([yes]) ;; + no) USE_READLINE="no" ; AC_MSG_RESULT([no]) ;; + only) USE_READLINE="yes" + EXTRA_LIBREADLINE_DEPS=" " + AC_MSG_RESULT([yes (using only readline)]) ;; + *) USE_READLINE="yes" + EXTRA_LIBREADLINE_DEPS="${withval}" + AC_MSG_RESULT([yes (using extra libraries ${withval})]) ;; + esac],[AC_MSG_RESULT([${USE_READLINE}])]) + + dnl Checks for libraries. + dnl When checking readline, check using extra libraries first. + dnl We want to protect against the link somehow succeeding, but only + dnl failing at runtime, as seems to happen on some BSD systems. + if test "$USE_READLINE" = yes ; then + AC_CHECK_HEADERS(readline/readline.h readline/history.h) + if test "x${ac_cv_header_readline_readline_h}" != "xyes" -o "x${ac_cv_header_readline_history_h}" != "xyes"; then + AC_MSG_WARN([Could not find the headers for libreadline.]) + else + if test "$EXTRA_LIBREADLINE_DEPS" = "" ; then + unset ac_cv_lib_readline_readline + AC_CHECK_LIB(readline, readline, HAVE_LIBREADLINE=true, + HAVE_LIBREADLINE=false, -lncurses) + if test x${HAVE_LIBREADLINE} = xtrue ; then + echo " Using -lreadline -lncurses" + EXTRA_LIBREADLINE_DEPS=-lncurses + AC_DEFINE(HAVE_LIBREADLINE, [1], [Define if the text port uses readline]) + else + unset ac_cv_lib_readline_readline + AC_CHECK_LIB(readline, readline, HAVE_LIBREADLINE=true, + HAVE_LIBREADLINE=false, -lcurses) + if test x${HAVE_LIBREADLINE} = xtrue ; then + echo " Using -lreadline -lcurses" + EXTRA_LIBREADLINE_DEPS=-lcurses + AC_DEFINE(HAVE_LIBREADLINE, [1], [Define if the text port uses readline]) + else + unset ac_cv_lib_readline_readline + AC_CHECK_LIB(readline, readline, HAVE_LIBREADLINE=true, + HAVE_LIBREADLINE=false, -ltermcap) + if test x${HAVE_LIBREADLINE} = xtrue ; then + echo " Using -lreadline -ltermcap" + EXTRA_LIBREADLINE_DEPS=-ltermcap + AC_DEFINE(HAVE_LIBREADLINE, [1], [Define if the text port uses readline]) + else + unset ac_cv_lib_readline_readline + AC_CHECK_LIB(readline, readline, HAVE_LIBREADLINE=true, + HAVE_LIBREADLINE=false) + if test x${HAVE_LIBREADLINE} = xtrue ; then + AC_DEFINE(HAVE_LIBREADLINE, [1], [Define if the text port uses readline]) + fi + fi + fi + fi + else + unset ac_cv_lib_readline_readline + AC_CHECK_LIB(readline, readline, HAVE_LIBREADLINE=true, + HAVE_LIBREADLINE=false, ${EXTRA_LIBREADLINE_DEPS}) + if test x${HAVE_LIBREADLINE} = xtrue ; then + echo " Using -lreadline ${EXTRA_LIBREADLINE_DEPS}" + AC_DEFINE(HAVE_LIBREADLINE, [1], [Define if the text port uses readline]) + fi + fi + if test x${HAVE_LIBREADLINE} = xtrue; then + READLINE_LIBS="-lreadline -lhistory ${EXTRA_LIBREADLINE_DEPS}" + else + AC_MSG_WARN([Could not find libreadline.]) + fi + fi + fi +fi + +AC_SUBST(READLINE_LIBS) +AC_SUBST(QALCULATE_TEXT) + +AC_SUBST(LN_QALCULATE) + +QALCULATE_DEFS2DOC="" +if test "x$enable_defs2doc" = "xyes" ; then + QALCULATE_DEFS2DOC="defs2doc$EXEEXT" +fi +AC_SUBST(QALCULATE_DEFS2DOC) + +QALCULATE_TEST="" +if test "x$enable_tests" = "xyes" ; then + QALCULATE_TEST="test$EXEEXT" +fi +AC_SUBST(QALCULATE_TEST) + +AC_SEARCH_LIBS([nanosleep],[rt posix4]) + +dnl ------------------------------------- +dnl | internationalization (i18n) support |------------------------------------ +dnl ------------------------------------- + +GETTEXT_PACKAGE=libqalculate +AC_SUBST(GETTEXT_PACKAGE) +AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[The package name for gettext]) + +dnl Please keep this in alphabetical order +ALL_LINGUAS="fr nl sv zh_CN" +AM_GNU_GETTEXT(external) +AM_GNU_GETTEXT_VERSION([0.19.8]) + +dnl AM_GLIB_GNU_GETTEXT sets $DATADIRNAME +AC_MSG_CHECKING(locale directory) +if test "x$prefix" = "xNONE"; then + PACKAGE_LOCALE_DIR=$ac_default_prefix/share/locale +else + PACKAGE_LOCALE_DIR=$prefix/share/locale +fi + +dnl lconv +AC_CHECK_MEMBERS([struct lconv.int_p_cs_precedes,] dnl +[struct lconv.int_n_cs_precedes],[],[],[AC_INCLUDES_DEFAULT +#include ]) + +AC_DEFINE_UNQUOTED(PACKAGE_LOCALE_DIR, "$PACKAGE_LOCALE_DIR", + [The directory in which qalculate's locale data will be stored]) + AC_MSG_RESULT("$PACKAGE_LOCALE_DIR") + +INTLTOOL_QALCULATE_DEFINITIONS_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po-defs/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po-defs/.intltool-merge-cache $(top_srcdir)/po-defs $< [$]@' +AC_SUBST(INTLTOOL_QALCULATE_DEFINITIONS_RULE) + +dnl -------- +dnl | output |----------------------------------------------------------------- +dnl -------- + +AC_OUTPUT([ + Makefile + src/Makefile + libqalculate/Makefile + data/Makefile + po/Makefile.in + po-defs/Makefile + docs/Makefile + docs/reference/Makefile + man/Makefile + libqalculate.pc +]) + diff -Nru libqalculate-3.6.0/.pc/000-fix_autogen.patch/libqalculate/Makefile.am libqalculate-3.7.0/.pc/000-fix_autogen.patch/libqalculate/Makefile.am --- libqalculate-3.6.0/.pc/000-fix_autogen.patch/libqalculate/Makefile.am 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/.pc/000-fix_autogen.patch/libqalculate/Makefile.am 2020-01-21 22:54:43.000000000 +0000 @@ -0,0 +1,42 @@ +# +# src/libqalculate/Makefile.am for qalculate +# + + +lib_LTLIBRARIES = libqalculate.la + +libqalculate_la_SOURCES = \ + Function.cc Calculator.cc Calculator-plot.cc Calculator-parse.cc \ + Calculator-definitions.cc Calculator-calculate.cc Calculator-convert.cc \ + DataSet.cc Variable.cc ExpressionItem.cc Number.cc MathStructure.cc \ + Prefix.cc support.h util.cc Unit.cc QalculateDateTime.cc \ + BuiltinFunctions-util.cc BuiltinFunctions-trigonometry.cc BuiltinFunctions-matrixvector.cc \ + BuiltinFunctions-datetime.cc BuiltinFunctions-statistics.cc \ + BuiltinFunctions-explog.cc BuiltinFunctions-special.cc BuiltinFunctions-algebra.cc \ + BuiltinFunctions-calculus.cc BuiltinFunctions-number.cc \ + BuiltinFunctions-combinatorics.cc BuiltinFunctions-logical.cc \ + MathStructure-factor.cc MathStructure-gcd.cc MathStructure-integrate.cc \ + MathStructure-isolatex.cc MathStructure-polynomial.cc \ + MathStructure-matrixvector.cc MathStructure-print.cc \ + MathStructure-differentiate.cc MathStructure-calculate.cc MathStructure-eval.cc \ + MathStructure-convert.cc MathStructure-decompose.cc MathStructure-limit.cc + +libqalculateincludedir = $(includedir)/libqalculate + +libqalculateinclude_HEADERS = \ + Function.h Calculator.h DataSet.h Variable.h \ + ExpressionItem.h Number.h MathStructure.h Prefix.h \ + util.h includes.h Unit.h BuiltinFunctions.h \ + QalculateDateTime.h qalculate.h + +noinst_HEADERS = MathStructure-support.h Calculator_p.h bernoulli_numbers.h + +libqalculate_la_LDFLAGS = -version-info $(QALCULATE_CURRENT):$(QALCULATE_REVISION):$(QALCULATE_AGE) -no-undefined + +libqalculate_la_LIBADD = \ + @LIBCURL_LIBS@ @LIBXML_LIBS@ @ICU_LIBS@ @LTLIBINTL@ @LTLIBICONV@ + +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ + @LIBCURL_CFLAGS@ @LIBXML_CFLAGS@ @ICU_CFLAGS@ diff -Nru libqalculate-3.6.0/.pc/000-fix_autogen.patch/src/Makefile.am libqalculate-3.7.0/.pc/000-fix_autogen.patch/src/Makefile.am --- libqalculate-3.6.0/.pc/000-fix_autogen.patch/src/Makefile.am 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/.pc/000-fix_autogen.patch/src/Makefile.am 2020-01-21 22:54:43.000000000 +0000 @@ -0,0 +1,48 @@ +# +# src/Makefile.am for qalculate +# + +AM_CPPFLAGS = \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ + -I$(top_srcdir) \ + -I$(top_srcdir)/libqalculate \ + @LIBCURL_CFLAGS@ @LIBXML_CFLAGS@ @ICU_CFLAGS@ + +bin_PROGRAMS = @QALCULATE_TEXT@ +noinst_PROGRAMS = @QALCULATE_DEFS2DOC@ @QALCULATE_TEST@ +EXTRA_PROGRAMS = qalc defs2doc test + +qalc_SOURCES = qalc.cc + +qalc_LDADD = \ + @LIBXML_LIBS@ \ + @LIBCURL_LIBS@ \ + @ICU_LIBS@ \ + @READLINE_LIBS@ \ + @LTLIBINTL@ \ + @LTLIBICONV@ \ + ../libqalculate/libqalculate.la + +defs2doc_SOURCES = defs2doc.cc + +defs2doc_LDADD = \ + @LIBXML_LIBS@ \ + @LIBCURL_LIBS@ \ + @ICU_LIBS@ \ + @LTLIBINTL@ \ + @LTLIBICONV@ \ + ../libqalculate/libqalculate.la + +test_SOURCES = test.cc + +test_LDADD = \ + @LIBXML_LIBS@ \ + @LIBCURL_LIBS@ \ + @ICU_LIBS@ \ + @LTLIBINTL@ \ + @LTLIBICONV@ \ + ../libqalculate/libqalculate.la + +#install-exec-local: +# cd $(DESTDIR)$(bindir) && rm -f qalculate; $(LN_S) @LN_QALCULATE@ qalculate + diff -Nru libqalculate-3.6.0/.pc/applied-patches libqalculate-3.7.0/.pc/applied-patches --- libqalculate-3.6.0/.pc/applied-patches 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/.pc/applied-patches 2020-01-21 22:54:43.000000000 +0000 @@ -0,0 +1 @@ +000-fix_autogen.patch diff -Nru libqalculate-3.6.0/.pc/.quilt_patches libqalculate-3.7.0/.pc/.quilt_patches --- libqalculate-3.6.0/.pc/.quilt_patches 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/.pc/.quilt_patches 2020-01-21 22:54:43.000000000 +0000 @@ -0,0 +1 @@ +/home/buildd/build-RECIPEBRANCHBUILD-2484949/chroot-autobuild/home/buildd/work/tree/recipe/debian/patches diff -Nru libqalculate-3.6.0/.pc/.quilt_series libqalculate-3.7.0/.pc/.quilt_series --- libqalculate-3.6.0/.pc/.quilt_series 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/.pc/.quilt_series 2020-01-21 22:54:43.000000000 +0000 @@ -0,0 +1 @@ +/home/buildd/build-RECIPEBRANCHBUILD-2484949/chroot-autobuild/home/buildd/work/tree/recipe/debian/patches/series diff -Nru libqalculate-3.6.0/.pc/.version libqalculate-3.7.0/.pc/.version --- libqalculate-3.6.0/.pc/.version 1970-01-01 00:00:00.000000000 +0000 +++ libqalculate-3.7.0/.pc/.version 2020-01-21 22:54:43.000000000 +0000 @@ -0,0 +1 @@ +2 diff -Nru libqalculate-3.6.0/po/fr.po libqalculate-3.7.0/po/fr.po --- libqalculate-3.6.0/po/fr.po 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/po/fr.po 2020-01-21 22:54:40.000000000 +0000 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: fr\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-25 10:28+0100\n" +"POT-Creation-Date: 2020-01-12 11:24+0100\n" "PO-Revision-Date: 2006-11-08 21:13-0500\n" "Last-Translator: Nicolas Laug \n" "Language-Team: Français \n" @@ -17,11 +17,11 @@ "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" -#: ../src/defs2doc.cc:301 ../src/qalc.cc:3298 ../libqalculate/Function.cc:207 +#: ../src/defs2doc.cc:301 ../src/qalc.cc:3299 ../libqalculate/Function.cc:222 msgid "argument" msgstr "" -#: ../src/defs2doc.cc:324 ../src/qalc.cc:3321 +#: ../src/defs2doc.cc:324 ../src/qalc.cc:3322 #, c-format msgid "" "Retrieves data from the %s data set for a given object and property. If " @@ -31,38 +31,38 @@ "propriété donnés. Si \"info\" est tapé pour la propriété, toutes les " "propriétés de l'objet seront listées." -#: ../src/defs2doc.cc:331 ../src/qalc.cc:3330 +#: ../src/defs2doc.cc:331 ../src/qalc.cc:3331 #, fuzzy msgid "Example:" msgstr "Exemple : store var1" -#: ../src/defs2doc.cc:339 ../src/qalc.cc:3339 +#: ../src/defs2doc.cc:339 ../src/qalc.cc:3340 msgid "Arguments" msgstr "" #. optional argument, in description -#: ../src/defs2doc.cc:356 ../src/qalc.cc:3356 +#: ../src/defs2doc.cc:356 ../src/qalc.cc:3357 msgid "optional" msgstr "optionnel" #. argument default, in description -#: ../src/defs2doc.cc:359 ../src/qalc.cc:3360 +#: ../src/defs2doc.cc:359 ../src/qalc.cc:3361 msgid "default: " msgstr "défaut :" -#: ../src/defs2doc.cc:372 ../src/qalc.cc:3371 +#: ../src/defs2doc.cc:372 ../src/qalc.cc:3372 msgid "Requirement" msgstr "Exigences" -#: ../src/defs2doc.cc:381 ../src/qalc.cc:3379 +#: ../src/defs2doc.cc:381 ../src/qalc.cc:3380 msgid "Properties" msgstr "Propiétés" -#: ../src/defs2doc.cc:397 ../src/qalc.cc:3394 +#: ../src/defs2doc.cc:397 ../src/qalc.cc:3395 msgid "key" msgstr "touche" -#: ../src/defs2doc.cc:431 ../src/qalc.cc:3509 +#: ../src/defs2doc.cc:431 ../src/qalc.cc:3510 msgid "a previous result" msgstr "un résultat précédent" @@ -71,91 +71,91 @@ msgid "current precision" msgstr "précision de saisie" -#: ../src/defs2doc.cc:438 ../src/defs2doc.cc:539 ../src/qalc.cc:1456 +#: ../src/defs2doc.cc:438 ../src/defs2doc.cc:539 ../src/qalc.cc:1457 msgid "relative uncertainty" msgstr "" -#: ../src/defs2doc.cc:453 ../src/qalc.cc:1478 ../src/qalc.cc:3515 -#: ../libqalculate/Function.cc:2110 +#: ../src/defs2doc.cc:453 ../src/qalc.cc:1479 ../src/qalc.cc:3516 +#: ../libqalculate/Function.cc:2144 msgid "matrix" msgstr "matrice" -#: ../src/defs2doc.cc:455 ../src/qalc.cc:1480 ../src/qalc.cc:3517 -#: ../libqalculate/Function.cc:2049 +#: ../src/defs2doc.cc:455 ../src/qalc.cc:1481 ../src/qalc.cc:3518 +#: ../libqalculate/Function.cc:2083 msgid "vector" msgstr "vecteur" -#: ../src/defs2doc.cc:463 ../src/qalc.cc:249 ../src/qalc.cc:691 -#: ../src/qalc.cc:1497 ../src/qalc.cc:2907 ../src/qalc.cc:3527 -#: ../src/qalc.cc:3646 ../src/qalc.cc:3876 +#: ../src/defs2doc.cc:463 ../src/qalc.cc:250 ../src/qalc.cc:692 +#: ../src/qalc.cc:1498 ../src/qalc.cc:2908 ../src/qalc.cc:3528 +#: ../src/qalc.cc:3647 ../src/qalc.cc:3877 msgid "positive" msgstr "positif" -#: ../src/defs2doc.cc:464 ../src/qalc.cc:255 ../src/qalc.cc:692 -#: ../src/qalc.cc:1498 ../src/qalc.cc:2908 ../src/qalc.cc:3528 -#: ../src/qalc.cc:3650 ../src/qalc.cc:3880 +#: ../src/defs2doc.cc:464 ../src/qalc.cc:256 ../src/qalc.cc:693 +#: ../src/qalc.cc:1499 ../src/qalc.cc:2909 ../src/qalc.cc:3529 +#: ../src/qalc.cc:3651 ../src/qalc.cc:3881 msgid "non-positive" msgstr "non positif" -#: ../src/defs2doc.cc:465 ../src/qalc.cc:253 ../src/qalc.cc:693 -#: ../src/qalc.cc:1499 ../src/qalc.cc:2909 ../src/qalc.cc:3529 -#: ../src/qalc.cc:3648 ../src/qalc.cc:3878 +#: ../src/defs2doc.cc:465 ../src/qalc.cc:254 ../src/qalc.cc:694 +#: ../src/qalc.cc:1500 ../src/qalc.cc:2910 ../src/qalc.cc:3530 +#: ../src/qalc.cc:3649 ../src/qalc.cc:3879 msgid "negative" msgstr "négatif" -#: ../src/defs2doc.cc:466 ../src/qalc.cc:251 ../src/qalc.cc:694 -#: ../src/qalc.cc:1500 ../src/qalc.cc:2910 ../src/qalc.cc:3530 -#: ../src/qalc.cc:3652 ../src/qalc.cc:3882 +#: ../src/defs2doc.cc:466 ../src/qalc.cc:252 ../src/qalc.cc:695 +#: ../src/qalc.cc:1501 ../src/qalc.cc:2911 ../src/qalc.cc:3531 +#: ../src/qalc.cc:3653 ../src/qalc.cc:3883 msgid "non-negative" msgstr "non négatif" -#: ../src/defs2doc.cc:467 ../src/qalc.cc:247 ../src/qalc.cc:695 -#: ../src/qalc.cc:1501 ../src/qalc.cc:2911 ../src/qalc.cc:3531 -#: ../src/qalc.cc:3644 ../src/qalc.cc:3874 +#: ../src/defs2doc.cc:467 ../src/qalc.cc:248 ../src/qalc.cc:696 +#: ../src/qalc.cc:1502 ../src/qalc.cc:2912 ../src/qalc.cc:3532 +#: ../src/qalc.cc:3645 ../src/qalc.cc:3875 msgid "non-zero" msgstr "non nul" -#: ../src/defs2doc.cc:472 ../src/qalc.cc:245 ../src/qalc.cc:700 -#: ../src/qalc.cc:1506 ../src/qalc.cc:2916 ../src/qalc.cc:3536 -#: ../src/qalc.cc:3660 ../src/qalc.cc:3890 ../libqalculate/Function.cc:1905 +#: ../src/defs2doc.cc:472 ../src/qalc.cc:246 ../src/qalc.cc:701 +#: ../src/qalc.cc:1507 ../src/qalc.cc:2917 ../src/qalc.cc:3537 +#: ../src/qalc.cc:3661 ../src/qalc.cc:3891 ../libqalculate/Function.cc:1939 msgid "integer" msgstr "entier" -#: ../src/defs2doc.cc:473 ../src/qalc.cc:243 ../src/qalc.cc:701 -#: ../src/qalc.cc:1507 ../src/qalc.cc:2917 ../src/qalc.cc:3537 -#: ../src/qalc.cc:3658 ../src/qalc.cc:3888 +#: ../src/defs2doc.cc:473 ../src/qalc.cc:244 ../src/qalc.cc:702 +#: ../src/qalc.cc:1508 ../src/qalc.cc:2918 ../src/qalc.cc:3538 +#: ../src/qalc.cc:3659 ../src/qalc.cc:3889 msgid "rational" msgstr "rationnel" -#: ../src/defs2doc.cc:474 ../src/qalc.cc:239 ../src/qalc.cc:702 -#: ../src/qalc.cc:1508 ../src/qalc.cc:2918 ../src/qalc.cc:3538 -#: ../src/qalc.cc:3656 ../src/qalc.cc:3886 +#: ../src/defs2doc.cc:474 ../src/qalc.cc:240 ../src/qalc.cc:703 +#: ../src/qalc.cc:1509 ../src/qalc.cc:2919 ../src/qalc.cc:3539 +#: ../src/qalc.cc:3657 ../src/qalc.cc:3887 msgid "real" msgstr "réel" -#: ../src/defs2doc.cc:475 ../src/qalc.cc:703 ../src/qalc.cc:1509 -#: ../src/qalc.cc:2919 ../src/qalc.cc:3539 +#: ../src/defs2doc.cc:475 ../src/qalc.cc:704 ../src/qalc.cc:1510 +#: ../src/qalc.cc:2920 ../src/qalc.cc:3540 msgid "complex" msgstr "complexe" -#: ../src/defs2doc.cc:476 ../src/qalc.cc:241 ../src/qalc.cc:704 -#: ../src/qalc.cc:1510 ../src/qalc.cc:2920 ../src/qalc.cc:3540 -#: ../src/qalc.cc:3654 ../src/qalc.cc:3884 ../libqalculate/Function.cc:1744 +#: ../src/defs2doc.cc:476 ../src/qalc.cc:242 ../src/qalc.cc:705 +#: ../src/qalc.cc:1511 ../src/qalc.cc:2921 ../src/qalc.cc:3541 +#: ../src/qalc.cc:3655 ../src/qalc.cc:3885 ../libqalculate/Function.cc:1778 msgid "number" msgstr "nombre" -#: ../src/defs2doc.cc:477 ../src/qalc.cc:705 ../src/qalc.cc:1511 -#: ../src/qalc.cc:2921 ../src/qalc.cc:3541 +#: ../src/defs2doc.cc:477 ../src/qalc.cc:706 ../src/qalc.cc:1512 +#: ../src/qalc.cc:2922 ../src/qalc.cc:3542 msgid "non-matrix" msgstr "non-matriciel" -#: ../src/defs2doc.cc:480 ../src/qalc.cc:233 ../src/qalc.cc:708 -#: ../src/qalc.cc:1514 ../src/qalc.cc:2924 ../src/qalc.cc:3544 -#: ../src/qalc.cc:3642 ../src/qalc.cc:3872 +#: ../src/defs2doc.cc:480 ../src/qalc.cc:234 ../src/qalc.cc:709 +#: ../src/qalc.cc:1515 ../src/qalc.cc:2925 ../src/qalc.cc:3545 +#: ../src/qalc.cc:3643 ../src/qalc.cc:3873 msgid "unknown" msgstr "inconnue" -#: ../src/defs2doc.cc:482 ../src/qalc.cc:1516 ../src/qalc.cc:3546 +#: ../src/defs2doc.cc:482 ../src/qalc.cc:1517 ../src/qalc.cc:3547 msgid "default assumptions" msgstr "hypothèses par défaut" @@ -165,47 +165,48 @@ msgstr "précision de saisie" #. qalc command -#: ../src/defs2doc.cc:492 ../src/defs2doc.cc:546 ../src/qalc.cc:900 -#: ../src/qalc.cc:1472 ../src/qalc.cc:1489 ../src/qalc.cc:2559 -#: ../src/qalc.cc:2941 ../src/qalc.cc:3184 ../src/qalc.cc:3458 -#: ../src/qalc.cc:3468 ../src/qalc.cc:3572 ../src/qalc.cc:3668 -#: ../src/qalc.cc:4002 +#: ../src/defs2doc.cc:492 ../src/defs2doc.cc:546 ../src/qalc.cc:901 +#: ../src/qalc.cc:1473 ../src/qalc.cc:1490 ../src/qalc.cc:2560 +#: ../src/qalc.cc:2942 ../src/qalc.cc:3185 ../src/qalc.cc:3459 +#: ../src/qalc.cc:3469 ../src/qalc.cc:3573 ../src/qalc.cc:3669 +#: ../src/qalc.cc:4003 msgid "approximate" msgstr "approximer" -#: ../src/defs2doc.cc:583 ../src/qalc.cc:1892 +#: ../src/defs2doc.cc:583 ../src/qalc.cc:1893 msgid "ans" msgstr "" #: ../src/defs2doc.cc:584 ../src/defs2doc.cc:587 ../src/defs2doc.cc:588 -#: ../src/defs2doc.cc:589 ../src/defs2doc.cc:590 ../src/qalc.cc:1893 -#: ../src/qalc.cc:1896 ../src/qalc.cc:1897 ../src/qalc.cc:1898 -#: ../src/qalc.cc:1899 ../src/qalc.cc:2153 ../libqalculate/Calculator.cc:10674 -#: ../libqalculate/Calculator.cc:10690 +#: ../src/defs2doc.cc:589 ../src/defs2doc.cc:590 ../src/qalc.cc:1894 +#: ../src/qalc.cc:1897 ../src/qalc.cc:1898 ../src/qalc.cc:1899 +#: ../src/qalc.cc:1900 ../src/qalc.cc:2154 +#: ../libqalculate/Calculator-definitions.cc:2225 +#: ../libqalculate/Calculator-definitions.cc:2241 msgid "Temporary" msgstr "Temporaire" -#: ../src/defs2doc.cc:584 ../src/qalc.cc:1893 +#: ../src/defs2doc.cc:584 ../src/qalc.cc:1894 msgid "Last Answer" msgstr "Dernière réponse" -#: ../src/defs2doc.cc:585 ../src/qalc.cc:1894 +#: ../src/defs2doc.cc:585 ../src/qalc.cc:1895 msgid "answer" msgstr "réponse" -#: ../src/defs2doc.cc:587 ../src/qalc.cc:1896 +#: ../src/defs2doc.cc:587 ../src/qalc.cc:1897 msgid "Answer 2" msgstr "Réponse 2" -#: ../src/defs2doc.cc:588 ../src/qalc.cc:1897 +#: ../src/defs2doc.cc:588 ../src/qalc.cc:1898 msgid "Answer 3" msgstr "Réponse 3" -#: ../src/defs2doc.cc:589 ../src/qalc.cc:1898 +#: ../src/defs2doc.cc:589 ../src/qalc.cc:1899 msgid "Answer 4" msgstr "Réponse 4" -#: ../src/defs2doc.cc:590 ../src/qalc.cc:1899 +#: ../src/defs2doc.cc:590 ../src/qalc.cc:1900 msgid "Answer 5" msgstr "Réponse 5" @@ -221,68 +222,68 @@ msgid "Uncategorized" msgstr "factoriser" -#: ../src/qalc.cc:152 ../src/qalc.cc:219 ../src/qalc.cc:3621 +#: ../src/qalc.cc:153 ../src/qalc.cc:220 ../src/qalc.cc:3622 #: ../libqalculate/util.cc:175 msgid "yes" msgstr "oui" -#: ../src/qalc.cc:153 ../src/qalc.cc:221 ../src/qalc.cc:3621 +#: ../src/qalc.cc:154 ../src/qalc.cc:222 ../src/qalc.cc:3622 #: ../libqalculate/util.cc:176 msgid "no" msgstr "non" -#: ../src/qalc.cc:154 ../libqalculate/util.cc:183 +#: ../src/qalc.cc:155 ../libqalculate/util.cc:183 msgid "true" msgstr "vrai" -#: ../src/qalc.cc:155 ../libqalculate/util.cc:184 +#: ../src/qalc.cc:156 ../libqalculate/util.cc:184 msgid "false" msgstr "faux" -#: ../src/qalc.cc:156 ../src/qalc.cc:777 ../src/qalc.cc:797 ../src/qalc.cc:1112 -#: ../src/qalc.cc:1149 ../src/qalc.cc:3028 ../src/qalc.cc:3041 -#: ../src/qalc.cc:3099 ../src/qalc.cc:3620 ../src/qalc.cc:3735 -#: ../src/qalc.cc:3742 ../src/qalc.cc:3793 ../libqalculate/util.cc:191 +#: ../src/qalc.cc:157 ../src/qalc.cc:778 ../src/qalc.cc:798 ../src/qalc.cc:1113 +#: ../src/qalc.cc:1150 ../src/qalc.cc:3029 ../src/qalc.cc:3042 +#: ../src/qalc.cc:3100 ../src/qalc.cc:3621 ../src/qalc.cc:3736 +#: ../src/qalc.cc:3743 ../src/qalc.cc:3794 ../libqalculate/util.cc:191 msgid "on" msgstr "marche" -#: ../src/qalc.cc:157 ../src/qalc.cc:775 ../src/qalc.cc:796 ../src/qalc.cc:1021 -#: ../src/qalc.cc:1085 ../src/qalc.cc:1097 ../src/qalc.cc:1110 -#: ../src/qalc.cc:1147 ../src/qalc.cc:3027 ../src/qalc.cc:3032 -#: ../src/qalc.cc:3039 ../src/qalc.cc:3068 ../src/qalc.cc:3075 -#: ../src/qalc.cc:3082 ../src/qalc.cc:3098 ../src/qalc.cc:3132 -#: ../src/qalc.cc:3620 ../src/qalc.cc:3733 ../src/qalc.cc:3739 -#: ../src/qalc.cc:3742 ../src/qalc.cc:3750 ../src/qalc.cc:3757 -#: ../src/qalc.cc:3767 ../src/qalc.cc:3791 ../src/qalc.cc:3826 +#: ../src/qalc.cc:158 ../src/qalc.cc:776 ../src/qalc.cc:797 ../src/qalc.cc:1022 +#: ../src/qalc.cc:1086 ../src/qalc.cc:1098 ../src/qalc.cc:1111 +#: ../src/qalc.cc:1148 ../src/qalc.cc:3028 ../src/qalc.cc:3033 +#: ../src/qalc.cc:3040 ../src/qalc.cc:3069 ../src/qalc.cc:3076 +#: ../src/qalc.cc:3083 ../src/qalc.cc:3099 ../src/qalc.cc:3133 +#: ../src/qalc.cc:3621 ../src/qalc.cc:3734 ../src/qalc.cc:3740 +#: ../src/qalc.cc:3743 ../src/qalc.cc:3751 ../src/qalc.cc:3758 +#: ../src/qalc.cc:3768 ../src/qalc.cc:3792 ../src/qalc.cc:3827 #: ../libqalculate/util.cc:192 msgid "off" msgstr "arrêt" -#: ../src/qalc.cc:226 +#: ../src/qalc.cc:227 msgid "Please answer yes or no" msgstr "Merci de répondre oui ou non" -#: ../src/qalc.cc:258 +#: ../src/qalc.cc:259 msgid "Unrecognized assumption." msgstr "Hypothèse non reconnue" -#: ../src/qalc.cc:425 ../src/qalc.cc:458 ../libqalculate/Calculator.cc:467 -#: ../libqalculate/Calculator.cc:693 ../libqalculate/DataSet.cc:1072 -#: ../libqalculate/DataSet.cc:1134 ../libqalculate/MathStructure.cc:21595 -#: ../libqalculate/Function.cc:2269 ../libqalculate/Function.cc:2285 +#: ../src/qalc.cc:426 ../src/qalc.cc:459 ../libqalculate/Calculator.cc:245 +#: ../libqalculate/Calculator.cc:473 ../libqalculate/DataSet.cc:1073 +#: ../libqalculate/DataSet.cc:1135 ../libqalculate/MathStructure-print.cc:3190 +#: ../libqalculate/Function.cc:2304 ../libqalculate/Function.cc:2320 msgid "or" msgstr "ou" -#: ../src/qalc.cc:546 ../libqalculate/Calculator.cc:12220 +#: ../src/qalc.cc:547 ../libqalculate/Calculator-definitions.cc:3756 #, fuzzy, c-format msgid "It has been %s day(s) since the exchange rates last were updated." msgstr "La dernière mise à jour des taux d'échange date de plus d'une semaine." -#: ../src/qalc.cc:551 +#: ../src/qalc.cc:552 msgid "Do you wish to update the exchange rates now?" msgstr "" -#: ../src/qalc.cc:565 ../src/qalc.cc:566 +#: ../src/qalc.cc:566 ../src/qalc.cc:567 msgid "" "\n" "Press Enter to continue." @@ -290,677 +291,683 @@ "\n" "Appuyez sur Entrée pour continuer" -#: ../src/qalc.cc:581 ../src/qalc.cc:582 ../src/qalc.cc:583 ../src/qalc.cc:584 -#: ../src/qalc.cc:585 ../src/qalc.cc:586 ../src/qalc.cc:719 ../src/qalc.cc:814 -#: ../src/qalc.cc:817 ../src/qalc.cc:972 ../src/qalc.cc:991 ../src/qalc.cc:1003 -#: ../src/qalc.cc:1012 ../src/qalc.cc:2362 ../src/qalc.cc:2499 +#: ../src/qalc.cc:582 ../src/qalc.cc:583 ../src/qalc.cc:584 ../src/qalc.cc:585 +#: ../src/qalc.cc:586 ../src/qalc.cc:587 ../src/qalc.cc:720 ../src/qalc.cc:815 +#: ../src/qalc.cc:818 ../src/qalc.cc:973 ../src/qalc.cc:992 ../src/qalc.cc:1004 +#: ../src/qalc.cc:1013 ../src/qalc.cc:2363 ../src/qalc.cc:2500 msgid "Illegal value" msgstr "Valeur illégale" #. qalc command -#: ../src/qalc.cc:614 ../src/qalc.cc:934 ../src/qalc.cc:2340 -#: ../src/qalc.cc:2803 ../src/qalc.cc:2809 ../src/qalc.cc:2994 -#: ../src/qalc.cc:3150 ../src/qalc.cc:3186 ../src/qalc.cc:3702 -#: ../src/qalc.cc:3839 ../src/qalc.cc:3994 ../src/qalc.cc:4922 -#: ../src/qalc.cc:4933 ../libqalculate/Calculator.cc:3051 -#: ../libqalculate/Calculator.cc:3055 +#: ../src/qalc.cc:615 ../src/qalc.cc:935 ../src/qalc.cc:2341 +#: ../src/qalc.cc:2804 ../src/qalc.cc:2810 ../src/qalc.cc:2995 +#: ../src/qalc.cc:3151 ../src/qalc.cc:3187 ../src/qalc.cc:3703 +#: ../src/qalc.cc:3840 ../src/qalc.cc:3995 ../src/qalc.cc:4923 +#: ../src/qalc.cc:4934 ../libqalculate/Calculator-calculate.cc:837 +#: ../libqalculate/Calculator-calculate.cc:841 msgid "base" msgstr "" -#: ../src/qalc.cc:614 ../src/qalc.cc:616 ../src/qalc.cc:3108 -#: ../src/qalc.cc:3804 +#: ../src/qalc.cc:615 ../src/qalc.cc:617 ../src/qalc.cc:3109 +#: ../src/qalc.cc:3805 msgid "input base" msgstr "base de saisie" -#: ../src/qalc.cc:614 ../src/qalc.cc:617 +#: ../src/qalc.cc:615 ../src/qalc.cc:618 msgid "output base" msgstr "base de sortie" -#: ../src/qalc.cc:618 ../src/qalc.cc:2606 ../src/qalc.cc:2996 -#: ../src/qalc.cc:3110 ../src/qalc.cc:3714 ../src/qalc.cc:3812 -#: ../src/qalc.cc:4756 ../libqalculate/Calculator.cc:2969 +#: ../src/qalc.cc:619 ../src/qalc.cc:2607 ../src/qalc.cc:2997 +#: ../src/qalc.cc:3111 ../src/qalc.cc:3715 ../src/qalc.cc:3813 +#: ../src/qalc.cc:4757 ../libqalculate/Calculator-calculate.cc:755 msgid "roman" msgstr "" -#: ../src/qalc.cc:619 ../src/qalc.cc:2611 ../src/qalc.cc:2997 -#: ../src/qalc.cc:3111 ../src/qalc.cc:4764 ../libqalculate/Calculator.cc:2972 +#: ../src/qalc.cc:620 ../src/qalc.cc:2612 ../src/qalc.cc:2998 +#: ../src/qalc.cc:3112 ../src/qalc.cc:4765 +#: ../libqalculate/Calculator-calculate.cc:758 #, fuzzy msgid "bijective" msgstr "Objet" -#: ../src/qalc.cc:620 ../src/qalc.cc:2621 ../src/qalc.cc:2999 -#: ../src/qalc.cc:3712 ../src/qalc.cc:4780 ../libqalculate/Calculator.cc:2978 +#: ../src/qalc.cc:621 ../src/qalc.cc:2622 ../src/qalc.cc:3000 +#: ../src/qalc.cc:3713 ../src/qalc.cc:4781 +#: ../libqalculate/Calculator-calculate.cc:764 msgid "time" msgstr "temps" -#: ../src/qalc.cc:621 ../src/qalc.cc:2581 ../src/qalc.cc:4716 -#: ../libqalculate/Calculator.cc:2954 +#: ../src/qalc.cc:622 ../src/qalc.cc:2582 ../src/qalc.cc:4717 +#: ../libqalculate/Calculator-calculate.cc:740 msgid "hexadecimal" msgstr "hexadécimal" -#: ../src/qalc.cc:628 ../src/qalc.cc:2601 ../src/qalc.cc:4748 -#: ../libqalculate/Calculator.cc:2966 +#: ../src/qalc.cc:629 ../src/qalc.cc:2602 ../src/qalc.cc:4749 +#: ../libqalculate/Calculator-calculate.cc:752 msgid "duodecimal" msgstr "duodécimal" -#: ../src/qalc.cc:629 ../src/qalc.cc:2586 ../src/qalc.cc:4724 -#: ../libqalculate/Calculator.cc:2957 +#: ../src/qalc.cc:630 ../src/qalc.cc:2587 ../src/qalc.cc:4725 +#: ../libqalculate/Calculator-calculate.cc:743 msgid "binary" msgstr "binaire" -#: ../src/qalc.cc:630 ../src/qalc.cc:2596 ../src/qalc.cc:4740 -#: ../libqalculate/Calculator.cc:2963 +#: ../src/qalc.cc:631 ../src/qalc.cc:2597 ../src/qalc.cc:4741 +#: ../libqalculate/Calculator-calculate.cc:749 msgid "octal" msgstr "" -#: ../src/qalc.cc:631 ../src/qalc.cc:2591 ../src/qalc.cc:4732 -#: ../libqalculate/Calculator.cc:2960 +#: ../src/qalc.cc:632 ../src/qalc.cc:2592 ../src/qalc.cc:4733 +#: ../libqalculate/Calculator-calculate.cc:746 msgid "decimal" msgstr "décimal" -#: ../src/qalc.cc:632 ../src/qalc.cc:2616 ../src/qalc.cc:2998 -#: ../src/qalc.cc:4772 ../libqalculate/Calculator.cc:2975 +#: ../src/qalc.cc:633 ../src/qalc.cc:2617 ../src/qalc.cc:2999 +#: ../src/qalc.cc:4773 ../libqalculate/Calculator-calculate.cc:761 msgid "sexagesimal" msgstr "sexagésimal" -#: ../src/qalc.cc:643 ../src/qalc.cc:757 ../src/qalc.cc:3010 -#: ../src/qalc.cc:3726 +#: ../src/qalc.cc:644 ../src/qalc.cc:758 ../src/qalc.cc:3011 +#: ../src/qalc.cc:3727 msgid "base display" msgstr "affichage de base" -#: ../src/qalc.cc:673 +#: ../src/qalc.cc:674 msgid "Illegal base." msgstr "Base illégale." -#: ../src/qalc.cc:681 ../src/qalc.cc:709 ../src/qalc.cc:2925 -#: ../src/qalc.cc:3639 +#: ../src/qalc.cc:682 ../src/qalc.cc:710 ../src/qalc.cc:2926 +#: ../src/qalc.cc:3640 msgid "assumptions" msgstr "hypothèses" -#: ../src/qalc.cc:712 ../src/qalc.cc:3141 ../src/qalc.cc:3831 +#: ../src/qalc.cc:713 ../src/qalc.cc:3142 ../src/qalc.cc:3832 msgid "all prefixes" msgstr "tous préfixes" -#: ../src/qalc.cc:713 ../src/qalc.cc:2959 ../src/qalc.cc:3679 +#: ../src/qalc.cc:714 ../src/qalc.cc:2960 ../src/qalc.cc:3680 msgid "complex numbers" msgstr "nombres complexes" -#: ../src/qalc.cc:714 ../src/qalc.cc:2977 ../src/qalc.cc:3691 +#: ../src/qalc.cc:715 ../src/qalc.cc:2978 ../src/qalc.cc:3692 msgid "excessive parentheses" msgstr "parenthèses en excès" -#: ../src/qalc.cc:715 ../src/qalc.cc:2960 ../src/qalc.cc:3240 -#: ../src/qalc.cc:3245 ../src/qalc.cc:3680 +#: ../src/qalc.cc:716 ../src/qalc.cc:2961 ../src/qalc.cc:3241 +#: ../src/qalc.cc:3246 ../src/qalc.cc:3681 msgid "functions" msgstr "fonctions" -#: ../src/qalc.cc:716 ../src/qalc.cc:2961 ../src/qalc.cc:3681 +#: ../src/qalc.cc:717 ../src/qalc.cc:2962 ../src/qalc.cc:3682 msgid "infinite numbers" msgstr "nombres infinis" -#: ../src/qalc.cc:717 ../src/qalc.cc:2986 ../src/qalc.cc:3694 +#: ../src/qalc.cc:718 ../src/qalc.cc:2987 ../src/qalc.cc:3695 msgid "show negative exponents" msgstr "afficher exposants négatifs" -#: ../src/qalc.cc:718 ../src/qalc.cc:2978 ../src/qalc.cc:3692 +#: ../src/qalc.cc:719 ../src/qalc.cc:2979 ../src/qalc.cc:3693 #, fuzzy msgid "minus last" msgstr "moins" -#: ../src/qalc.cc:720 ../src/qalc.cc:2903 ../src/qalc.cc:3636 +#: ../src/qalc.cc:721 ../src/qalc.cc:2904 ../src/qalc.cc:3637 msgid "assume nonzero denominators" msgstr "supposer dénominateurs non nuls" -#: ../src/qalc.cc:721 ../src/qalc.cc:2904 ../src/qalc.cc:3637 +#: ../src/qalc.cc:722 ../src/qalc.cc:2905 ../src/qalc.cc:3638 msgid "warn nonzero denominators" msgstr "avertir dénominateurs non nuls" -#: ../src/qalc.cc:722 ../src/qalc.cc:3158 ../src/qalc.cc:3851 +#: ../src/qalc.cc:723 ../src/qalc.cc:3159 ../src/qalc.cc:3852 msgid "prefixes" msgstr "préfixes" -#: ../src/qalc.cc:723 ../src/qalc.cc:3154 ../src/qalc.cc:3847 +#: ../src/qalc.cc:724 ../src/qalc.cc:3155 ../src/qalc.cc:3848 #, fuzzy msgid "binary prefixes" msgstr "préfixes des dénominateurs" -#: ../src/qalc.cc:730 ../src/qalc.cc:3156 ../src/qalc.cc:3849 +#: ../src/qalc.cc:731 ../src/qalc.cc:3157 ../src/qalc.cc:3850 msgid "denominator prefixes" msgstr "préfixes des dénominateurs" -#: ../src/qalc.cc:731 ../src/qalc.cc:3157 ../src/qalc.cc:3850 +#: ../src/qalc.cc:732 ../src/qalc.cc:3158 ../src/qalc.cc:3851 msgid "place units separately" msgstr "placer unités séparément" -#: ../src/qalc.cc:732 ../src/qalc.cc:2958 ../src/qalc.cc:3678 +#: ../src/qalc.cc:733 ../src/qalc.cc:2959 ../src/qalc.cc:3679 msgid "calculate variables" msgstr "calculer les variables" -#: ../src/qalc.cc:733 ../src/qalc.cc:2957 ../src/qalc.cc:3677 +#: ../src/qalc.cc:734 ../src/qalc.cc:2958 ../src/qalc.cc:3678 msgid "calculate functions" msgstr "calculer les fonctions" -#: ../src/qalc.cc:734 ../src/qalc.cc:3159 ../src/qalc.cc:3852 +#: ../src/qalc.cc:735 ../src/qalc.cc:3160 ../src/qalc.cc:3853 msgid "sync units" msgstr "synchroniser les unités" -#: ../src/qalc.cc:735 ../src/qalc.cc:3079 ../src/qalc.cc:3763 +#: ../src/qalc.cc:736 ../src/qalc.cc:3080 ../src/qalc.cc:3764 msgid "round to even" msgstr "arrondir au inférieur" -#: ../src/qalc.cc:736 ../src/qalc.cc:3137 ../src/qalc.cc:3827 +#: ../src/qalc.cc:737 ../src/qalc.cc:3138 ../src/qalc.cc:3828 msgid "rpn syntax" msgstr "syntaxe npi" #. qalc command -#: ../src/qalc.cc:737 ../src/qalc.cc:2343 ../src/qalc.cc:3171 -#: ../src/qalc.cc:3208 ../src/qalc.cc:3864 ../src/qalc.cc:3944 +#: ../src/qalc.cc:738 ../src/qalc.cc:2344 ../src/qalc.cc:3172 +#: ../src/qalc.cc:3209 ../src/qalc.cc:3865 ../src/qalc.cc:3945 msgid "rpn" msgstr "npi" -#: ../src/qalc.cc:738 ../src/qalc.cc:2987 ../src/qalc.cc:3695 +#: ../src/qalc.cc:739 ../src/qalc.cc:2988 ../src/qalc.cc:3696 msgid "short multiplication" msgstr "multiplication courte" -#: ../src/qalc.cc:739 ../src/qalc.cc:3062 ../src/qalc.cc:3746 +#: ../src/qalc.cc:740 ../src/qalc.cc:3063 ../src/qalc.cc:3747 msgid "lowercase e" msgstr "e minuscule" -#: ../src/qalc.cc:740 ../src/qalc.cc:3063 ../src/qalc.cc:3747 +#: ../src/qalc.cc:741 ../src/qalc.cc:3064 ../src/qalc.cc:3748 msgid "lowercase numbers" msgstr "nombres en minuscules" -#: ../src/qalc.cc:741 ../src/qalc.cc:3046 ../src/qalc.cc:3107 -#: ../src/qalc.cc:3744 ../src/qalc.cc:3803 +#: ../src/qalc.cc:742 ../src/qalc.cc:3047 ../src/qalc.cc:3108 +#: ../src/qalc.cc:3745 ../src/qalc.cc:3804 msgid "imaginary j" msgstr "" -#: ../src/qalc.cc:759 ../src/qalc.cc:776 ../src/qalc.cc:830 ../src/qalc.cc:930 -#: ../src/qalc.cc:956 ../src/qalc.cc:2898 ../src/qalc.cc:2934 -#: ../src/qalc.cc:2947 ../src/qalc.cc:3012 ../src/qalc.cc:3146 -#: ../src/qalc.cc:3667 ../src/qalc.cc:3726 ../src/qalc.cc:3835 +#: ../src/qalc.cc:760 ../src/qalc.cc:777 ../src/qalc.cc:831 ../src/qalc.cc:931 +#: ../src/qalc.cc:957 ../src/qalc.cc:2899 ../src/qalc.cc:2935 +#: ../src/qalc.cc:2948 ../src/qalc.cc:3013 ../src/qalc.cc:3147 +#: ../src/qalc.cc:3668 ../src/qalc.cc:3727 ../src/qalc.cc:3836 msgid "none" msgstr "aucun" -#: ../src/qalc.cc:760 ../src/qalc.cc:3013 ../src/qalc.cc:3726 +#: ../src/qalc.cc:761 ../src/qalc.cc:3014 ../src/qalc.cc:3727 msgid "normal" msgstr "" -#: ../src/qalc.cc:761 ../src/qalc.cc:3014 ../src/qalc.cc:3726 +#: ../src/qalc.cc:762 ../src/qalc.cc:3015 ../src/qalc.cc:3727 msgid "alternative" msgstr "" -#: ../src/qalc.cc:766 ../src/qalc.cc:783 ../src/qalc.cc:803 ../src/qalc.cc:835 -#: ../src/qalc.cc:852 ../src/qalc.cc:877 ../src/qalc.cc:891 ../src/qalc.cc:905 -#: ../src/qalc.cc:922 ../src/qalc.cc:947 ../src/qalc.cc:963 ../src/qalc.cc:1032 -#: ../src/qalc.cc:1038 ../src/qalc.cc:1062 ../src/qalc.cc:1119 -#: ../src/qalc.cc:1138 ../src/qalc.cc:1154 +#: ../src/qalc.cc:767 ../src/qalc.cc:784 ../src/qalc.cc:804 ../src/qalc.cc:836 +#: ../src/qalc.cc:853 ../src/qalc.cc:878 ../src/qalc.cc:892 ../src/qalc.cc:906 +#: ../src/qalc.cc:923 ../src/qalc.cc:948 ../src/qalc.cc:964 ../src/qalc.cc:1033 +#: ../src/qalc.cc:1039 ../src/qalc.cc:1063 ../src/qalc.cc:1120 +#: ../src/qalc.cc:1139 ../src/qalc.cc:1155 msgid "Illegal value." msgstr "Valeur illégale." -#: ../src/qalc.cc:771 ../src/qalc.cc:3091 ../src/qalc.cc:3781 +#: ../src/qalc.cc:772 ../src/qalc.cc:3092 ../src/qalc.cc:3782 msgid "two's complement" msgstr "" -#: ../src/qalc.cc:772 ../src/qalc.cc:3045 ../src/qalc.cc:3743 +#: ../src/qalc.cc:773 ../src/qalc.cc:3046 ../src/qalc.cc:3744 #, fuzzy msgid "hexadecimal two's" msgstr "hexadécimal" -#: ../src/qalc.cc:773 ../src/qalc.cc:3030 ../src/qalc.cc:3739 +#: ../src/qalc.cc:774 ../src/qalc.cc:3031 ../src/qalc.cc:3740 msgid "digit grouping" msgstr "" -#: ../src/qalc.cc:777 ../src/qalc.cc:3033 ../src/qalc.cc:3739 +#: ../src/qalc.cc:778 ../src/qalc.cc:3034 ../src/qalc.cc:3740 msgid "standard" msgstr "" -#: ../src/qalc.cc:778 ../src/qalc.cc:798 ../src/qalc.cc:3026 -#: ../src/qalc.cc:3034 ../src/qalc.cc:3097 ../src/qalc.cc:3731 -#: ../src/qalc.cc:3739 ../src/qalc.cc:3789 +#: ../src/qalc.cc:779 ../src/qalc.cc:799 ../src/qalc.cc:3027 +#: ../src/qalc.cc:3035 ../src/qalc.cc:3098 ../src/qalc.cc:3732 +#: ../src/qalc.cc:3740 ../src/qalc.cc:3790 msgid "locale" msgstr "" -#: ../src/qalc.cc:788 ../src/qalc.cc:2989 ../src/qalc.cc:3697 +#: ../src/qalc.cc:789 ../src/qalc.cc:2990 ../src/qalc.cc:3698 msgid "spell out logical" msgstr "déchiffrement logique" -#: ../src/qalc.cc:789 ../src/qalc.cc:3105 ../src/qalc.cc:3801 +#: ../src/qalc.cc:790 ../src/qalc.cc:3106 ../src/qalc.cc:3802 msgid "ignore dot" msgstr "" -#: ../src/qalc.cc:790 ../src/qalc.cc:3102 ../src/qalc.cc:3798 +#: ../src/qalc.cc:791 ../src/qalc.cc:3103 ../src/qalc.cc:3799 msgid "ignore comma" msgstr "" -#: ../src/qalc.cc:794 ../src/qalc.cc:3025 ../src/qalc.cc:3096 -#: ../src/qalc.cc:3728 ../src/qalc.cc:3786 +#: ../src/qalc.cc:795 ../src/qalc.cc:3026 ../src/qalc.cc:3097 +#: ../src/qalc.cc:3729 ../src/qalc.cc:3787 #, fuzzy msgid "decimal comma" msgstr "décimal" -#: ../src/qalc.cc:813 ../src/qalc.cc:3122 ../src/qalc.cc:3824 +#: ../src/qalc.cc:814 ../src/qalc.cc:3123 ../src/qalc.cc:3825 msgid "limit implicit multiplication" msgstr "limiter multiplications implicites" -#: ../src/qalc.cc:815 ../src/qalc.cc:2988 ../src/qalc.cc:3696 +#: ../src/qalc.cc:816 ../src/qalc.cc:2989 ../src/qalc.cc:3697 msgid "spacious" msgstr "spacieux" -#: ../src/qalc.cc:816 ../src/qalc.cc:2990 ../src/qalc.cc:3698 +#: ../src/qalc.cc:817 ../src/qalc.cc:2991 ../src/qalc.cc:3699 msgid "unicode" msgstr "" -#: ../src/qalc.cc:819 ../src/qalc.cc:2962 ../src/qalc.cc:3242 -#: ../src/qalc.cc:3247 ../src/qalc.cc:3682 +#: ../src/qalc.cc:820 ../src/qalc.cc:2963 ../src/qalc.cc:3243 +#: ../src/qalc.cc:3248 ../src/qalc.cc:3683 msgid "units" msgstr "unités" -#: ../src/qalc.cc:820 ../src/qalc.cc:2963 ../src/qalc.cc:3683 +#: ../src/qalc.cc:821 ../src/qalc.cc:2964 ../src/qalc.cc:3684 msgid "unknowns" msgstr "inconnues" -#: ../src/qalc.cc:821 ../src/qalc.cc:2964 ../src/qalc.cc:3241 -#: ../src/qalc.cc:3246 ../src/qalc.cc:3684 +#: ../src/qalc.cc:822 ../src/qalc.cc:2965 ../src/qalc.cc:3242 +#: ../src/qalc.cc:3247 ../src/qalc.cc:3685 msgid "variables" msgstr "" -#: ../src/qalc.cc:822 ../src/qalc.cc:2969 ../src/qalc.cc:3689 +#: ../src/qalc.cc:823 ../src/qalc.cc:2970 ../src/qalc.cc:3690 msgid "abbreviations" msgstr "abréviations" -#: ../src/qalc.cc:823 ../src/qalc.cc:3090 ../src/qalc.cc:3780 +#: ../src/qalc.cc:824 ../src/qalc.cc:3091 ../src/qalc.cc:3781 msgid "show ending zeroes" msgstr "afficher zéros de fin" -#: ../src/qalc.cc:824 ../src/qalc.cc:3078 ../src/qalc.cc:3762 +#: ../src/qalc.cc:825 ../src/qalc.cc:3079 ../src/qalc.cc:3763 #, fuzzy msgid "repeating decimals" msgstr "décimales min" -#: ../src/qalc.cc:825 ../src/qalc.cc:2929 ../src/qalc.cc:3667 +#: ../src/qalc.cc:826 ../src/qalc.cc:2930 ../src/qalc.cc:3668 msgid "angle unit" msgstr "unité d'angle" -#: ../src/qalc.cc:827 ../src/qalc.cc:2931 ../src/qalc.cc:2932 +#: ../src/qalc.cc:828 ../src/qalc.cc:2932 ../src/qalc.cc:2933 msgid "rad" msgstr "" -#: ../src/qalc.cc:827 ../src/qalc.cc:3667 +#: ../src/qalc.cc:828 ../src/qalc.cc:3668 msgid "radians" msgstr "" -#: ../src/qalc.cc:828 +#: ../src/qalc.cc:829 msgid "deg" msgstr "" -#: ../src/qalc.cc:828 ../src/qalc.cc:3667 +#: ../src/qalc.cc:829 ../src/qalc.cc:3668 msgid "degrees" msgstr "degrés" -#: ../src/qalc.cc:829 ../src/qalc.cc:2933 +#: ../src/qalc.cc:830 ../src/qalc.cc:2934 msgid "gra" msgstr "gr" -#: ../src/qalc.cc:829 ../src/qalc.cc:3667 +#: ../src/qalc.cc:830 ../src/qalc.cc:3668 msgid "gradians" msgstr "grades" -#: ../src/qalc.cc:842 ../src/qalc.cc:3095 ../src/qalc.cc:3785 +#: ../src/qalc.cc:843 ../src/qalc.cc:3096 ../src/qalc.cc:3786 msgid "caret as xor" msgstr "" -#: ../src/qalc.cc:843 ../src/qalc.cc:3123 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4057 +#: ../src/qalc.cc:844 ../src/qalc.cc:3124 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4058 #, fuzzy msgid "parsing mode" msgstr "mode exp" -#: ../src/qalc.cc:845 ../src/qalc.cc:1045 ../src/qalc.cc:3049 -#: ../src/qalc.cc:3125 ../src/qalc.cc:3745 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4065 +#: ../src/qalc.cc:846 ../src/qalc.cc:1046 ../src/qalc.cc:3050 +#: ../src/qalc.cc:3126 ../src/qalc.cc:3746 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4066 #, fuzzy msgid "adaptive" msgstr "strictement positif" -#: ../src/qalc.cc:846 ../src/qalc.cc:3126 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4062 +#: ../src/qalc.cc:847 ../src/qalc.cc:3127 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4063 msgid "implicit first" msgstr "" -#: ../src/qalc.cc:847 ../src/qalc.cc:3127 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4059 +#: ../src/qalc.cc:848 ../src/qalc.cc:3128 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4060 #, fuzzy msgid "conventional" msgstr "optionnel" -#: ../src/qalc.cc:857 ../src/qalc.cc:1696 ../src/qalc.cc:3160 -#: ../src/qalc.cc:3853 +#: ../src/qalc.cc:858 ../src/qalc.cc:1697 ../src/qalc.cc:3161 +#: ../src/qalc.cc:3854 msgid "update exchange rates" msgstr "" -#: ../src/qalc.cc:858 ../src/qalc.cc:3163 ../src/qalc.cc:3855 +#: ../src/qalc.cc:859 ../src/qalc.cc:3164 ../src/qalc.cc:3856 msgid "never" msgstr "" -#: ../src/qalc.cc:860 ../src/qalc.cc:3162 ../src/qalc.cc:3854 +#: ../src/qalc.cc:861 ../src/qalc.cc:3163 ../src/qalc.cc:3855 msgid "ask" msgstr "" -#: ../src/qalc.cc:868 ../src/qalc.cc:2979 ../src/qalc.cc:3693 +#: ../src/qalc.cc:869 ../src/qalc.cc:2980 ../src/qalc.cc:3694 msgid "multiplication sign" msgstr "signe de multiplication" -#: ../src/qalc.cc:882 ../src/qalc.cc:2970 ../src/qalc.cc:3690 +#: ../src/qalc.cc:883 ../src/qalc.cc:2971 ../src/qalc.cc:3691 msgid "division sign" msgstr "signe de division" -#: ../src/qalc.cc:896 ../src/qalc.cc:2937 ../src/qalc.cc:3668 +#: ../src/qalc.cc:897 ../src/qalc.cc:2938 ../src/qalc.cc:3669 msgid "approximation" msgstr "approximation" #. qalc command -#: ../src/qalc.cc:898 ../src/qalc.cc:969 ../src/qalc.cc:1111 -#: ../src/qalc.cc:2549 ../src/qalc.cc:2939 ../src/qalc.cc:3040 -#: ../src/qalc.cc:3188 ../src/qalc.cc:3668 ../src/qalc.cc:3742 -#: ../src/qalc.cc:3998 +#: ../src/qalc.cc:899 ../src/qalc.cc:970 ../src/qalc.cc:1112 +#: ../src/qalc.cc:2550 ../src/qalc.cc:2940 ../src/qalc.cc:3041 +#: ../src/qalc.cc:3189 ../src/qalc.cc:3669 ../src/qalc.cc:3743 +#: ../src/qalc.cc:3999 msgid "exact" msgstr "" -#: ../src/qalc.cc:899 ../src/qalc.cc:2940 ../src/qalc.cc:3668 +#: ../src/qalc.cc:900 ../src/qalc.cc:2941 ../src/qalc.cc:3669 msgid "try exact" msgstr "essayez exact" -#: ../src/qalc.cc:914 ../src/qalc.cc:2945 ../src/qalc.cc:3670 +#: ../src/qalc.cc:915 ../src/qalc.cc:2946 ../src/qalc.cc:3671 #, fuzzy msgid "interval calculation" msgstr "calculs en cours..." -#: ../src/qalc.cc:914 +#: ../src/qalc.cc:915 msgid "uncertainty propagation" msgstr "" -#: ../src/qalc.cc:916 ../src/qalc.cc:2948 ../src/qalc.cc:3670 +#: ../src/qalc.cc:917 ../src/qalc.cc:2949 ../src/qalc.cc:3671 msgid "variance formula" msgstr "" -#: ../src/qalc.cc:916 +#: ../src/qalc.cc:917 msgid "variance" msgstr "" -#: ../src/qalc.cc:917 ../src/qalc.cc:1069 ../src/qalc.cc:2944 -#: ../src/qalc.cc:2949 ../src/qalc.cc:3669 ../src/qalc.cc:3670 +#: ../src/qalc.cc:918 ../src/qalc.cc:1070 ../src/qalc.cc:2945 +#: ../src/qalc.cc:2950 ../src/qalc.cc:3670 ../src/qalc.cc:3671 msgid "interval arithmetic" msgstr "" -#: ../src/qalc.cc:927 ../src/qalc.cc:3142 ../src/qalc.cc:3832 +#: ../src/qalc.cc:928 ../src/qalc.cc:3143 ../src/qalc.cc:3833 msgid "autoconversion" msgstr "" -#: ../src/qalc.cc:931 ../src/qalc.cc:2797 +#: ../src/qalc.cc:932 ../src/qalc.cc:2798 msgid "best" msgstr "meilleur" -#: ../src/qalc.cc:932 ../src/qalc.cc:3151 ../src/qalc.cc:3841 +#: ../src/qalc.cc:933 ../src/qalc.cc:3152 ../src/qalc.cc:3842 #, fuzzy msgid "optimalsi" msgstr "optionnel" -#: ../src/qalc.cc:933 ../src/qalc.cc:2797 ../src/qalc.cc:3149 -#: ../src/qalc.cc:3837 ../src/qalc.cc:4911 ../libqalculate/Calculator.cc:3047 +#: ../src/qalc.cc:934 ../src/qalc.cc:2798 ../src/qalc.cc:3150 +#: ../src/qalc.cc:3838 ../src/qalc.cc:4912 +#: ../libqalculate/Calculator-calculate.cc:833 #, fuzzy msgid "optimal" msgstr "optionnel" -#: ../src/qalc.cc:935 ../src/qalc.cc:1113 ../src/qalc.cc:3042 -#: ../src/qalc.cc:3145 ../src/qalc.cc:3742 ../src/qalc.cc:3843 -#: ../src/qalc.cc:4966 ../libqalculate/Calculator.cc:3076 +#: ../src/qalc.cc:936 ../src/qalc.cc:1114 ../src/qalc.cc:3043 +#: ../src/qalc.cc:3146 ../src/qalc.cc:3743 ../src/qalc.cc:3844 +#: ../src/qalc.cc:4967 ../libqalculate/Calculator-calculate.cc:862 msgid "mixed" msgstr "" -#: ../src/qalc.cc:953 ../src/qalc.cc:3155 ../src/qalc.cc:3848 +#: ../src/qalc.cc:954 ../src/qalc.cc:3156 ../src/qalc.cc:3849 #, fuzzy msgid "currency conversion" msgstr "Devise" -#: ../src/qalc.cc:954 ../src/qalc.cc:2896 ../src/qalc.cc:3635 +#: ../src/qalc.cc:955 ../src/qalc.cc:2897 ../src/qalc.cc:3636 msgid "algebra mode" msgstr "mode algébrique" #. qalc command -#: ../src/qalc.cc:957 ../src/qalc.cc:2884 ../src/qalc.cc:3612 +#: ../src/qalc.cc:958 ../src/qalc.cc:2885 ../src/qalc.cc:3613 msgid "simplify" msgstr "simplifier" -#: ../src/qalc.cc:957 ../src/qalc.cc:2884 ../src/qalc.cc:2900 -#: ../src/qalc.cc:3203 ../src/qalc.cc:3612 ../src/qalc.cc:3635 -#: ../src/qalc.cc:5015 ../libqalculate/Calculator.cc:3101 +#: ../src/qalc.cc:958 ../src/qalc.cc:2885 ../src/qalc.cc:2901 +#: ../src/qalc.cc:3204 ../src/qalc.cc:3613 ../src/qalc.cc:3636 +#: ../src/qalc.cc:5016 ../libqalculate/Calculator-calculate.cc:891 msgid "expand" msgstr "" -#: ../src/qalc.cc:958 ../src/qalc.cc:2899 ../src/qalc.cc:3635 -#: ../src/qalc.cc:5012 ../libqalculate/Calculator.cc:3097 +#: ../src/qalc.cc:959 ../src/qalc.cc:2900 ../src/qalc.cc:3636 +#: ../src/qalc.cc:5013 ../libqalculate/Calculator-calculate.cc:887 msgid "factorize" msgstr "factoriser" -#: ../src/qalc.cc:988 ../src/qalc.cc:3170 ../src/qalc.cc:3863 +#: ../src/qalc.cc:989 ../src/qalc.cc:3171 ../src/qalc.cc:3864 msgid "ignore locale" msgstr "" -#: ../src/qalc.cc:1000 ../src/qalc.cc:3173 ../src/qalc.cc:3201 -#: ../src/qalc.cc:3866 +#: ../src/qalc.cc:1001 ../src/qalc.cc:3174 ../src/qalc.cc:3202 +#: ../src/qalc.cc:3867 msgid "save mode" msgstr "enregistrer le mode" -#: ../src/qalc.cc:1009 ../src/qalc.cc:3172 ../src/qalc.cc:3200 -#: ../src/qalc.cc:3865 +#: ../src/qalc.cc:1010 ../src/qalc.cc:3173 ../src/qalc.cc:3201 +#: ../src/qalc.cc:3866 msgid "save definitions" msgstr "enregistrer les définitions" -#: ../src/qalc.cc:1018 ../src/qalc.cc:3080 ../src/qalc.cc:3764 +#: ../src/qalc.cc:1019 ../src/qalc.cc:3081 ../src/qalc.cc:3765 #, fuzzy msgid "scientific notation" msgstr "scientifique" -#: ../src/qalc.cc:1022 ../src/qalc.cc:3083 ../src/qalc.cc:3769 +#: ../src/qalc.cc:1023 ../src/qalc.cc:3084 ../src/qalc.cc:3770 msgid "auto" msgstr "" -#: ../src/qalc.cc:1023 ../src/qalc.cc:3084 ../src/qalc.cc:3773 +#: ../src/qalc.cc:1024 ../src/qalc.cc:3085 ../src/qalc.cc:3774 msgid "pure" msgstr "pur" -#: ../src/qalc.cc:1024 ../src/qalc.cc:3085 ../src/qalc.cc:3775 +#: ../src/qalc.cc:1025 ../src/qalc.cc:3086 ../src/qalc.cc:3776 msgid "scientific" msgstr "scientifique" -#: ../src/qalc.cc:1025 ../src/qalc.cc:3086 ../src/qalc.cc:3771 +#: ../src/qalc.cc:1026 ../src/qalc.cc:3087 ../src/qalc.cc:3772 msgid "engineering" msgstr "" -#: ../src/qalc.cc:1034 ../src/qalc.cc:2953 ../src/qalc.cc:3671 +#: ../src/qalc.cc:1035 ../src/qalc.cc:2954 ../src/qalc.cc:3672 msgid "precision" msgstr "précision" -#: ../src/qalc.cc:1043 ../src/qalc.cc:3047 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1044 ../src/qalc.cc:3048 ../src/qalc.cc:3746 #, fuzzy msgid "interval display" msgstr "affichage de la base" -#: ../src/qalc.cc:1046 ../src/qalc.cc:3052 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1047 ../src/qalc.cc:3053 ../src/qalc.cc:3746 #, fuzzy msgid "significant" msgstr "scientifique" -#: ../src/qalc.cc:1047 ../src/qalc.cc:3053 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1048 ../src/qalc.cc:3054 ../src/qalc.cc:3746 #, fuzzy msgid "interval" msgstr "entier" -#: ../src/qalc.cc:1048 ../src/qalc.cc:3054 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1049 ../src/qalc.cc:3055 ../src/qalc.cc:3746 #, fuzzy msgid "plusminus" msgstr "moins" -#: ../src/qalc.cc:1049 ../src/qalc.cc:3055 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1050 ../src/qalc.cc:3056 ../src/qalc.cc:3746 msgid "midpoint" msgstr "" -#: ../src/qalc.cc:1050 ../src/qalc.cc:3057 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1051 ../src/qalc.cc:3058 ../src/qalc.cc:3746 msgid "upper" msgstr "" -#: ../src/qalc.cc:1051 ../src/qalc.cc:3056 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1052 ../src/qalc.cc:3057 ../src/qalc.cc:3746 #, fuzzy msgid "lower" msgstr "e minuscule" -#: ../src/qalc.cc:1076 ../src/qalc.cc:2965 ../src/qalc.cc:3685 +#: ../src/qalc.cc:1077 ../src/qalc.cc:2966 ../src/qalc.cc:3686 #, fuzzy msgid "variable units" msgstr "unité d'angle" -#: ../src/qalc.cc:1083 ../src/qalc.cc:3064 ../src/qalc.cc:3748 +#: ../src/qalc.cc:1084 ../src/qalc.cc:3065 ../src/qalc.cc:3749 msgid "max decimals" msgstr "décimales max" -#: ../src/qalc.cc:1095 ../src/qalc.cc:3071 ../src/qalc.cc:3755 +#: ../src/qalc.cc:1096 ../src/qalc.cc:3072 ../src/qalc.cc:3756 msgid "min decimals" msgstr "décimales min" -#: ../src/qalc.cc:1108 ../src/qalc.cc:3037 ../src/qalc.cc:3742 +#: ../src/qalc.cc:1109 ../src/qalc.cc:3038 ../src/qalc.cc:3743 msgid "fractions" msgstr "" -#: ../src/qalc.cc:1113 +#: ../src/qalc.cc:1114 msgid "combined" msgstr "combiné" -#: ../src/qalc.cc:1114 ../src/qalc.cc:3041 ../src/qalc.cc:3742 +#: ../src/qalc.cc:1115 ../src/qalc.cc:3042 ../src/qalc.cc:3743 msgid "long" msgstr "" -#: ../src/qalc.cc:1127 ../src/qalc.cc:3017 ../src/qalc.cc:3727 +#: ../src/qalc.cc:1128 ../src/qalc.cc:3018 ../src/qalc.cc:3728 #, fuzzy msgid "complex form" msgstr "complexe" -#: ../src/qalc.cc:1129 ../src/qalc.cc:2667 ../src/qalc.cc:3019 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4856 ../libqalculate/Calculator.cc:3015 +#: ../src/qalc.cc:1130 ../src/qalc.cc:2668 ../src/qalc.cc:3020 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4857 +#: ../libqalculate/Calculator-calculate.cc:801 msgid "rectangular" msgstr "" -#: ../src/qalc.cc:1129 ../src/qalc.cc:2667 ../src/qalc.cc:4856 -#: ../libqalculate/Calculator.cc:3015 +#: ../src/qalc.cc:1130 ../src/qalc.cc:2668 ../src/qalc.cc:4857 +#: ../libqalculate/Calculator-calculate.cc:801 msgid "cartesian" msgstr "" -#: ../src/qalc.cc:1130 ../src/qalc.cc:2679 ../src/qalc.cc:3020 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4867 ../libqalculate/Calculator.cc:3018 +#: ../src/qalc.cc:1131 ../src/qalc.cc:2680 ../src/qalc.cc:3021 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4868 +#: ../libqalculate/Calculator-calculate.cc:804 #, fuzzy msgid "exponential" msgstr "optionnel" -#: ../src/qalc.cc:1131 ../src/qalc.cc:2691 ../src/qalc.cc:3021 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4878 ../libqalculate/Calculator.cc:3021 +#: ../src/qalc.cc:1132 ../src/qalc.cc:2692 ../src/qalc.cc:3022 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4879 +#: ../libqalculate/Calculator-calculate.cc:807 msgid "polar" msgstr "" -#: ../src/qalc.cc:1132 ../src/qalc.cc:2703 ../src/qalc.cc:3022 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4889 ../libqalculate/Calculator.cc:3024 -#: ../libqalculate/Function.cc:2211 +#: ../src/qalc.cc:1133 ../src/qalc.cc:2704 ../src/qalc.cc:3023 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4890 +#: ../libqalculate/Calculator-calculate.cc:810 ../libqalculate/Function.cc:2245 msgid "angle" msgstr "" -#: ../src/qalc.cc:1132 ../src/qalc.cc:2703 ../src/qalc.cc:4889 -#: ../libqalculate/Calculator.cc:3024 +#: ../src/qalc.cc:1133 ../src/qalc.cc:2704 ../src/qalc.cc:4890 +#: ../libqalculate/Calculator-calculate.cc:810 msgid "phasor" msgstr "" -#: ../src/qalc.cc:1145 ../src/qalc.cc:3130 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1146 ../src/qalc.cc:3131 ../src/qalc.cc:3827 msgid "read precision" msgstr "précision de saisie" -#: ../src/qalc.cc:1148 ../src/qalc.cc:3133 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1149 ../src/qalc.cc:3134 ../src/qalc.cc:3827 msgid "always" msgstr "toujours" -#: ../src/qalc.cc:1149 ../src/qalc.cc:3134 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1150 ../src/qalc.cc:3135 ../src/qalc.cc:3827 msgid "when decimals" msgstr "si décimales" -#: ../src/qalc.cc:1180 +#: ../src/qalc.cc:1181 msgid "Unrecognized option." msgstr "Option inconnue" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Calendar" msgstr "" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Day" msgstr "" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Month" msgstr "" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Year" msgstr "" -#: ../src/qalc.cc:1315 ../libqalculate/Calculator.cc:3124 +#: ../src/qalc.cc:1316 ../libqalculate/Calculator-calculate.cc:934 msgid "failed" msgstr "" -#: ../src/qalc.cc:1316 ../libqalculate/Calculator.cc:3125 +#: ../src/qalc.cc:1317 ../libqalculate/Calculator-calculate.cc:935 msgid "Gregorian:" msgstr "" -#: ../src/qalc.cc:1317 ../libqalculate/Calculator.cc:3126 +#: ../src/qalc.cc:1318 ../libqalculate/Calculator-calculate.cc:936 msgid "Hebrew:" msgstr "" -#: ../src/qalc.cc:1318 ../libqalculate/Calculator.cc:3127 +#: ../src/qalc.cc:1319 ../libqalculate/Calculator-calculate.cc:937 msgid "Islamic:" msgstr "" -#: ../src/qalc.cc:1319 ../libqalculate/Calculator.cc:3128 +#: ../src/qalc.cc:1320 ../libqalculate/Calculator-calculate.cc:938 msgid "Persian:" msgstr "" -#: ../src/qalc.cc:1320 ../libqalculate/Calculator.cc:3129 +#: ../src/qalc.cc:1321 ../libqalculate/Calculator-calculate.cc:939 msgid "Indian national:" msgstr "" -#: ../src/qalc.cc:1321 ../libqalculate/Calculator.cc:3130 +#: ../src/qalc.cc:1322 ../libqalculate/Calculator-calculate.cc:940 msgid "Chinese:" msgstr "" -#: ../src/qalc.cc:1326 ../libqalculate/Calculator.cc:3134 +#: ../src/qalc.cc:1327 ../libqalculate/Calculator-calculate.cc:944 msgid "Julian:" msgstr "" -#: ../src/qalc.cc:1327 ../libqalculate/Calculator.cc:3135 +#: ../src/qalc.cc:1328 ../libqalculate/Calculator-calculate.cc:945 msgid "Revised julian:" msgstr "" -#: ../src/qalc.cc:1328 ../libqalculate/Calculator.cc:3136 +#: ../src/qalc.cc:1329 ../libqalculate/Calculator-calculate.cc:946 #, fuzzy msgid "Coptic:" msgstr "optionnel" -#: ../src/qalc.cc:1329 ../libqalculate/Calculator.cc:3137 +#: ../src/qalc.cc:1330 ../libqalculate/Calculator-calculate.cc:947 msgid "Ethiopian:" msgstr "" -#: ../src/qalc.cc:1396 ../libqalculate/BuiltinFunctions.cc:6237 -#: ../libqalculate/BuiltinFunctions.cc:6267 +#: ../src/qalc.cc:1397 ../libqalculate/BuiltinFunctions-matrixvector.cc:567 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:597 msgid "No matching item found." msgstr "Aucun élément correspondant trouvé." -#: ../src/qalc.cc:1427 ../src/qalc.cc:1428 ../src/qalc.cc:1558 -#: ../src/qalc.cc:1559 ../src/qalc.cc:1626 ../src/qalc.cc:1627 +#: ../src/qalc.cc:1428 ../src/qalc.cc:1429 ../src/qalc.cc:1559 +#: ../src/qalc.cc:1560 ../src/qalc.cc:1627 ../src/qalc.cc:1628 #, fuzzy msgid "" "For more information about a specific function, variable or unit, please use " @@ -969,153 +976,153 @@ "Tapez info NOM pour obtenir de l'information sur une fonction, variable ou " "unité (exemple : info sin)." -#: ../src/qalc.cc:1441 +#: ../src/qalc.cc:1442 msgid "Variables:" msgstr "" -#: ../src/qalc.cc:1443 +#: ../src/qalc.cc:1444 msgid "Name" msgstr "Nom" -#: ../src/qalc.cc:1444 ../src/qalc.cc:3552 ../src/qalc.cc:3559 +#: ../src/qalc.cc:1445 ../src/qalc.cc:3553 ../src/qalc.cc:3560 msgid "Value" msgstr "Valeur" -#: ../src/qalc.cc:1532 +#: ../src/qalc.cc:1533 msgid "Functions:" msgstr "Fonctions:" -#: ../src/qalc.cc:1546 +#: ../src/qalc.cc:1547 msgid "Units:" msgstr "Unités:" -#: ../src/qalc.cc:1553 +#: ../src/qalc.cc:1554 msgid "No local variables, functions or units have been defined." msgstr "" -#: ../src/qalc.cc:1689 +#: ../src/qalc.cc:1690 msgid "usage: qalc [options] [expression]" msgstr "" -#: ../src/qalc.cc:1691 +#: ../src/qalc.cc:1692 msgid "where options are:" msgstr "où les options sont :" -#: ../src/qalc.cc:1692 ../src/qalc.cc:1724 ../src/qalc.cc:3186 +#: ../src/qalc.cc:1693 ../src/qalc.cc:1725 ../src/qalc.cc:3187 msgid "BASE" msgstr "" -#: ../src/qalc.cc:1693 +#: ../src/qalc.cc:1694 msgid "set the number base for results and, optionally, expressions" msgstr "" -#: ../src/qalc.cc:1698 +#: ../src/qalc.cc:1699 msgid "FILE" msgstr "FICHIER" -#: ../src/qalc.cc:1699 +#: ../src/qalc.cc:1700 msgid "execute commands from a file first" msgstr "commencer par exécuter les commandes dans un fichier" -#: ../src/qalc.cc:1701 +#: ../src/qalc.cc:1702 msgid "start in interactive mode" msgstr "" -#: ../src/qalc.cc:1702 ../src/qalc.cc:1704 ../src/qalc.cc:1706 -#: ../src/qalc.cc:1708 +#: ../src/qalc.cc:1703 ../src/qalc.cc:1705 ../src/qalc.cc:1707 +#: ../src/qalc.cc:1709 msgid "SEARCH TERM" msgstr "" -#: ../src/qalc.cc:1703 +#: ../src/qalc.cc:1704 #, fuzzy msgid "" "displays a list of all user-defined or matching variables, functions and " "units" msgstr "\"%s\" n'est pas une variable/fonction/unité valide." -#: ../src/qalc.cc:1705 +#: ../src/qalc.cc:1706 #, fuzzy msgid "displays a list of all or matching functions" msgstr "Exemple : info sin" -#: ../src/qalc.cc:1707 +#: ../src/qalc.cc:1708 #, fuzzy msgid "displays a list of all or matching units" msgstr "Exemple : info sin" -#: ../src/qalc.cc:1709 +#: ../src/qalc.cc:1710 #, fuzzy msgid "displays a list of all or matching variables" msgstr "\"%s\" n'est pas une variable/fonction/unité valide." -#: ../src/qalc.cc:1710 +#: ../src/qalc.cc:1711 msgid "MILLISECONDS" msgstr "" -#: ../src/qalc.cc:1711 +#: ../src/qalc.cc:1712 msgid "" "terminate calculation and display of result after specified amount of time" msgstr "" -#: ../src/qalc.cc:1713 +#: ../src/qalc.cc:1714 #, fuzzy msgid "do not load any functions, units, or variables from file" msgstr "une fonction, une unité ou un nom de variable valide" -#: ../src/qalc.cc:1715 +#: ../src/qalc.cc:1716 msgid "do not load any global currencies from file" msgstr "" -#: ../src/qalc.cc:1717 +#: ../src/qalc.cc:1718 msgid "do not load any global data sets from file" msgstr "" -#: ../src/qalc.cc:1719 +#: ../src/qalc.cc:1720 #, fuzzy msgid "do not load any global functions from file" msgstr "Échec du chargement des définitions globales!" -#: ../src/qalc.cc:1721 +#: ../src/qalc.cc:1722 msgid "do not load any global units from file" msgstr "" -#: ../src/qalc.cc:1723 +#: ../src/qalc.cc:1724 msgid "do not load any global variables from file" msgstr "" -#: ../src/qalc.cc:1725 +#: ../src/qalc.cc:1726 msgid "" "start in programming mode (same as -b \"BASE BASE\" -s \"xor^\", with base " "conversion)" msgstr "" -#: ../src/qalc.cc:1726 ../src/qalc.cc:3202 +#: ../src/qalc.cc:1727 ../src/qalc.cc:3203 msgid "OPTION" msgstr "" -#: ../src/qalc.cc:1726 ../src/qalc.cc:3202 +#: ../src/qalc.cc:1727 ../src/qalc.cc:3203 msgid "VALUE" msgstr "VALEUR" -#: ../src/qalc.cc:1727 +#: ../src/qalc.cc:1728 msgid "as set command in interactive program session (e.g. -set \"base 16\")" msgstr "" "comme une commande set (définir) dans une session de programme interactive " "(ex. -set \"base 16\")" -#: ../src/qalc.cc:1729 +#: ../src/qalc.cc:1730 msgid "reduce output to just the result of the input expression" msgstr "" -#: ../src/qalc.cc:1731 +#: ../src/qalc.cc:1732 msgid "switch unicode support on/off" msgstr "activer/désactiver le support de l'unicode" -#: ../src/qalc.cc:1733 +#: ../src/qalc.cc:1734 msgid "show application version and exit" msgstr "" -#: ../src/qalc.cc:1735 +#: ../src/qalc.cc:1736 msgid "" "The program will start in interactive mode if no expression and no file is " "specified (or interactive mode is explicitly selected)." @@ -1123,67 +1130,67 @@ "Le programme démarrera en mode interactif si aucune expression n'est " "indiquée." -#: ../src/qalc.cc:1835 +#: ../src/qalc.cc:1836 msgid "No option and value specified for set command." msgstr "Pas de fonction et valeur spécifiée pour une commande set." -#: ../src/qalc.cc:1843 +#: ../src/qalc.cc:1844 msgid "No file specified." msgstr "Aucun fichier indiqué." -#: ../src/qalc.cc:1910 +#: ../src/qalc.cc:1911 msgid "Failed to load global definitions!" msgstr "Échec du chargement des définitions globales!" -#: ../src/qalc.cc:1956 +#: ../src/qalc.cc:1957 #, c-format msgid "Could not open \"%s\".\n" msgstr "Impossible d'ouvrir \"%s\".\n" -#: ../src/qalc.cc:1996 ../src/qalc.cc:2048 ../src/qalc.cc:4087 +#: ../src/qalc.cc:1997 ../src/qalc.cc:2049 ../src/qalc.cc:4088 #, c-format msgid "Illegal character, '%c', in expression." msgstr "Caractère illégal, '%c', dans l'expression" #. The qalc command "set" as in "set precision 10". The original text string for commands is kept in addition to the translation. -#: ../src/qalc.cc:2115 ../src/qalc.cc:3202 ../src/qalc.cc:3616 +#: ../src/qalc.cc:2116 ../src/qalc.cc:3203 ../src/qalc.cc:3617 msgid "set" msgstr "définir" #. qalc command -#: ../src/qalc.cc:2119 ../src/qalc.cc:3199 ../src/qalc.cc:3895 +#: ../src/qalc.cc:2120 ../src/qalc.cc:3200 ../src/qalc.cc:3896 msgid "save" msgstr "enregistrer" -#: ../src/qalc.cc:2119 ../src/qalc.cc:3199 ../src/qalc.cc:3895 +#: ../src/qalc.cc:2120 ../src/qalc.cc:3200 ../src/qalc.cc:3896 msgid "store" msgstr "stocker" #. qalc command -#: ../src/qalc.cc:2122 ../src/qalc.cc:2887 ../src/qalc.cc:3197 -#: ../src/qalc.cc:3921 +#: ../src/qalc.cc:2123 ../src/qalc.cc:2888 ../src/qalc.cc:3198 +#: ../src/qalc.cc:3922 msgid "mode" msgstr "" -#: ../src/qalc.cc:2124 +#: ../src/qalc.cc:2125 msgid "mode saved" msgstr "mode enregistré" -#: ../src/qalc.cc:2126 +#: ../src/qalc.cc:2127 msgid "definitions" msgstr "définitions" -#: ../src/qalc.cc:2128 +#: ../src/qalc.cc:2129 msgid "definitions saved" msgstr "définitions enregistrées" -#: ../src/qalc.cc:2175 ../src/qalc.cc:2177 ../src/qalc.cc:2235 -#: ../src/qalc.cc:2237 ../src/qalc.cc:2292 ../src/qalc.cc:2294 +#: ../src/qalc.cc:2176 ../src/qalc.cc:2178 ../src/qalc.cc:2236 +#: ../src/qalc.cc:2238 ../src/qalc.cc:2293 ../src/qalc.cc:2295 #, c-format msgid "Illegal name. Save as %s instead (default: no)?" msgstr "Nom illégal. Enregistrer comme %s à la place (défaut : non)?" -#: ../src/qalc.cc:2184 ../src/qalc.cc:2244 +#: ../src/qalc.cc:2185 ../src/qalc.cc:2245 msgid "" "An unit or variable with the same name already exists.\n" "Do you want to overwrite it (default: no)?" @@ -1192,18 +1199,18 @@ "Voulez-vous l'écraser? (défaut : non)" #. qalc command -#: ../src/qalc.cc:2207 ../src/qalc.cc:3205 ../src/qalc.cc:3902 -#: ../libqalculate/Function.cc:2172 +#: ../src/qalc.cc:2208 ../src/qalc.cc:3206 ../src/qalc.cc:3903 +#: ../libqalculate/Function.cc:2206 msgid "variable" msgstr "" #. qalc command -#: ../src/qalc.cc:2264 ../src/qalc.cc:3195 ../src/qalc.cc:3908 -#: ../libqalculate/Function.cc:2144 +#: ../src/qalc.cc:2265 ../src/qalc.cc:3196 ../src/qalc.cc:3909 +#: ../libqalculate/Function.cc:2178 msgid "function" msgstr "fonction" -#: ../src/qalc.cc:2301 +#: ../src/qalc.cc:2302 #, fuzzy msgid "" "An function with the same name already exists.\n" @@ -1213,283 +1220,292 @@ "Voulez-vous l'écraser? (défaut : non)" #. qalc command -#: ../src/qalc.cc:2321 ../src/qalc.cc:3187 ../src/qalc.cc:3915 +#: ../src/qalc.cc:2322 ../src/qalc.cc:3188 ../src/qalc.cc:3916 msgid "delete" msgstr "effacer" -#: ../src/qalc.cc:2332 +#: ../src/qalc.cc:2333 #, fuzzy msgid "No user-defined variable or function with the specified name exist." msgstr "Aucune fonction, variable ou unité avec le nom indiqué n'existe." #. qalc command -#: ../src/qalc.cc:2336 ../src/qalc.cc:3185 ../src/qalc.cc:3868 +#: ../src/qalc.cc:2337 ../src/qalc.cc:3186 ../src/qalc.cc:3869 msgid "assume" msgstr "supposer" -#: ../src/qalc.cc:2346 +#: ../src/qalc.cc:2347 msgid "syntax" msgstr "syntaxe" #. qalc command -#: ../src/qalc.cc:2353 ../src/qalc.cc:2388 ../src/qalc.cc:3209 -#: ../src/qalc.cc:3960 +#: ../src/qalc.cc:2354 ../src/qalc.cc:2389 ../src/qalc.cc:3210 +#: ../src/qalc.cc:3961 msgid "stack" msgstr "pile" #. qalc command -#: ../src/qalc.cc:2373 ../src/qalc.cc:3190 ../src/qalc.cc:3940 +#: ../src/qalc.cc:2374 ../src/qalc.cc:3191 ../src/qalc.cc:3941 msgid "exrates" msgstr "taux d'échange" -#: ../src/qalc.cc:2390 ../src/qalc.cc:2408 ../src/qalc.cc:2417 -#: ../src/qalc.cc:2450 ../src/qalc.cc:2479 ../src/qalc.cc:2488 -#: ../src/qalc.cc:2505 ../src/qalc.cc:2512 ../src/qalc.cc:2530 -#: ../src/qalc.cc:2537 +#: ../src/qalc.cc:2391 ../src/qalc.cc:2409 ../src/qalc.cc:2418 +#: ../src/qalc.cc:2451 ../src/qalc.cc:2480 ../src/qalc.cc:2489 +#: ../src/qalc.cc:2506 ../src/qalc.cc:2513 ../src/qalc.cc:2531 +#: ../src/qalc.cc:2538 msgid "The RPN stack is empty." msgstr "La pile NPI est vide." #. qalc command -#: ../src/qalc.cc:2406 ../src/qalc.cc:2415 ../src/qalc.cc:3215 -#: ../src/qalc.cc:3964 +#: ../src/qalc.cc:2407 ../src/qalc.cc:2416 ../src/qalc.cc:3216 +#: ../src/qalc.cc:3965 msgid "swap" msgstr "" -#: ../src/qalc.cc:2410 ../src/qalc.cc:2419 ../src/qalc.cc:2452 -#: ../src/qalc.cc:2481 ../src/qalc.cc:2490 +#: ../src/qalc.cc:2411 ../src/qalc.cc:2420 ../src/qalc.cc:2453 +#: ../src/qalc.cc:2482 ../src/qalc.cc:2491 #, fuzzy msgid "The RPN stack only contains one value." msgstr "La pile NPI est vide." -#: ../src/qalc.cc:2438 ../src/qalc.cc:2471 ../src/qalc.cc:2519 -#: ../src/qalc.cc:2543 +#: ../src/qalc.cc:2439 ../src/qalc.cc:2472 ../src/qalc.cc:2520 +#: ../src/qalc.cc:2544 msgid "The specified RPN stack index does not exist." msgstr "" #. qalc command -#: ../src/qalc.cc:2448 ../src/qalc.cc:3212 ../src/qalc.cc:3986 +#: ../src/qalc.cc:2449 ../src/qalc.cc:3213 ../src/qalc.cc:3987 msgid "move" msgstr "" #. qalc command -#: ../src/qalc.cc:2477 ../src/qalc.cc:2486 ../src/qalc.cc:3214 -#: ../src/qalc.cc:3982 +#: ../src/qalc.cc:2478 ../src/qalc.cc:2487 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3983 msgid "rotate" msgstr "" -#: ../src/qalc.cc:2494 +#: ../src/qalc.cc:2495 msgid "up" msgstr "" -#: ../src/qalc.cc:2496 +#: ../src/qalc.cc:2497 msgid "down" msgstr "" #. qalc command -#: ../src/qalc.cc:2503 ../src/qalc.cc:2510 ../src/qalc.cc:3211 -#: ../src/qalc.cc:3974 +#: ../src/qalc.cc:2504 ../src/qalc.cc:2511 ../src/qalc.cc:3212 +#: ../src/qalc.cc:3975 msgid "copy" msgstr "" #. qalc command -#: ../src/qalc.cc:2525 ../src/qalc.cc:3210 ../src/qalc.cc:3950 +#: ../src/qalc.cc:2526 ../src/qalc.cc:3211 ../src/qalc.cc:3951 msgid "clear stack" msgstr "vider la pile" #. qalc command -#: ../src/qalc.cc:2528 ../src/qalc.cc:2535 ../src/qalc.cc:3213 -#: ../src/qalc.cc:3954 +#: ../src/qalc.cc:2529 ../src/qalc.cc:2536 ../src/qalc.cc:3214 +#: ../src/qalc.cc:3955 msgid "pop" msgstr "" #. qalc command -#: ../src/qalc.cc:2569 ../src/qalc.cc:3204 ../src/qalc.cc:4006 +#: ../src/qalc.cc:2570 ../src/qalc.cc:3205 ../src/qalc.cc:4007 msgid "convert" msgstr "convertir" #. "to"-operator -#: ../src/qalc.cc:2569 ../src/qalc.cc:3204 ../src/qalc.cc:4006 -#: ../src/qalc.cc:4049 ../libqalculate/Calculator.cc:518 -#: ../libqalculate/Calculator.cc:744 ../libqalculate/Calculator.cc:1540 -#: ../libqalculate/Calculator.cc:1541 ../libqalculate/Calculator.cc:3233 -#: ../libqalculate/Calculator.cc:3235 ../libqalculate/Calculator.cc:3248 -#: ../libqalculate/Calculator.cc:3250 ../libqalculate/Calculator.cc:3264 -#: ../libqalculate/Calculator.cc:3266 +#: ../src/qalc.cc:2570 ../src/qalc.cc:3205 ../src/qalc.cc:4007 +#: ../src/qalc.cc:4050 ../libqalculate/Calculator-calculate.cc:1065 +#: ../libqalculate/Calculator-calculate.cc:1067 +#: ../libqalculate/Calculator-calculate.cc:1080 +#: ../libqalculate/Calculator-calculate.cc:1082 +#: ../libqalculate/Calculator-calculate.cc:1096 +#: ../libqalculate/Calculator-calculate.cc:1098 +#: ../libqalculate/Calculator.cc:296 ../libqalculate/Calculator.cc:524 +#: ../libqalculate/Calculator.cc:1322 ../libqalculate/Calculator.cc:1323 msgid "to" msgstr "vers" -#: ../src/qalc.cc:2654 ../src/qalc.cc:4822 ../libqalculate/Calculator.cc:3006 +#: ../src/qalc.cc:2655 ../src/qalc.cc:4823 +#: ../libqalculate/Calculator-calculate.cc:792 #, fuzzy msgid "Time zone parsing failed." msgstr "La comparaison a échoué." -#: ../src/qalc.cc:2727 ../src/qalc.cc:4850 ../libqalculate/Calculator.cc:3041 +#: ../src/qalc.cc:2728 ../src/qalc.cc:4851 +#: ../libqalculate/Calculator-calculate.cc:827 msgid "bases" msgstr "" -#: ../src/qalc.cc:2774 ../src/qalc.cc:4853 ../libqalculate/Calculator.cc:3044 +#: ../src/qalc.cc:2775 ../src/qalc.cc:4854 +#: ../libqalculate/Calculator-calculate.cc:830 msgid "calendars" msgstr "calendriers" -#: ../src/qalc.cc:2784 ../src/qalc.cc:4841 ../libqalculate/Calculator.cc:3031 +#: ../src/qalc.cc:2785 ../src/qalc.cc:4842 +#: ../libqalculate/Calculator-calculate.cc:817 msgid "fraction" msgstr "" -#: ../src/qalc.cc:2793 ../src/qalc.cc:4844 ../libqalculate/Calculator.cc:3034 +#: ../src/qalc.cc:2794 ../src/qalc.cc:4845 +#: ../libqalculate/Calculator-calculate.cc:820 msgid "factors" msgstr "facteurs" #. qalc command -#: ../src/qalc.cc:2795 ../src/qalc.cc:2881 ../src/qalc.cc:3198 -#: ../src/qalc.cc:3608 ../src/qalc.cc:4847 ../libqalculate/Calculator.cc:3038 +#: ../src/qalc.cc:2796 ../src/qalc.cc:2882 ../src/qalc.cc:3199 +#: ../src/qalc.cc:3609 ../src/qalc.cc:4848 +#: ../libqalculate/Calculator-calculate.cc:824 msgid "partial fraction" msgstr "fraction partielle" #. qalc command -#: ../src/qalc.cc:2878 ../src/qalc.cc:3193 ../src/qalc.cc:3604 +#: ../src/qalc.cc:2879 ../src/qalc.cc:3194 ../src/qalc.cc:3605 msgid "factor" msgstr "facteur" -#: ../src/qalc.cc:2892 ../src/qalc.cc:3633 +#: ../src/qalc.cc:2893 ../src/qalc.cc:3634 #, fuzzy msgid "Algebraic Mode" msgstr "mode algébrique" -#: ../src/qalc.cc:2927 ../src/qalc.cc:3665 +#: ../src/qalc.cc:2928 ../src/qalc.cc:3666 #, fuzzy msgid "Calculation" msgstr "calculs en cours..." -#: ../src/qalc.cc:2950 +#: ../src/qalc.cc:2951 #, fuzzy msgid "simplified" msgstr "simplifier" -#: ../src/qalc.cc:2955 ../src/qalc.cc:3675 +#: ../src/qalc.cc:2956 ../src/qalc.cc:3676 msgid "Enabled Objects" msgstr "" -#: ../src/qalc.cc:2967 ../src/qalc.cc:3687 +#: ../src/qalc.cc:2968 ../src/qalc.cc:3688 msgid "Generic Display Options" msgstr "" -#: ../src/qalc.cc:2992 ../src/qalc.cc:3700 +#: ../src/qalc.cc:2993 ../src/qalc.cc:3701 #, fuzzy msgid "Numerical Display" msgstr "affichage de la base" -#: ../src/qalc.cc:3093 ../src/qalc.cc:3783 +#: ../src/qalc.cc:3094 ../src/qalc.cc:3784 #, fuzzy msgid "Parsing" msgstr "mode exp" -#: ../src/qalc.cc:3139 ../src/qalc.cc:3829 +#: ../src/qalc.cc:3140 ../src/qalc.cc:3830 #, fuzzy msgid "Units" msgstr "Unité" -#: ../src/qalc.cc:3168 ../src/qalc.cc:3861 +#: ../src/qalc.cc:3169 ../src/qalc.cc:3862 msgid "Other" msgstr "" #. qalc command -#: ../src/qalc.cc:3176 ../src/qalc.cc:3600 +#: ../src/qalc.cc:3177 ../src/qalc.cc:3601 msgid "help" msgstr "aide" -#: ../src/qalc.cc:3179 +#: ../src/qalc.cc:3180 msgid "Enter a mathematical expression or a command and press enter." msgstr "" "Entrez une expression mathématique ou une commande et appuyez sur Entrée." -#: ../src/qalc.cc:3180 +#: ../src/qalc.cc:3181 msgid "Complete functions, units and variables with the tabulator key." msgstr "Fonctions, unités et variables complètes avec la touche de tabulation." -#: ../src/qalc.cc:3182 +#: ../src/qalc.cc:3183 msgid "Available commands are:" msgstr "Les commandes disponibles sont :" -#: ../src/qalc.cc:3185 +#: ../src/qalc.cc:3186 msgid "ASSUMPTIONS" msgstr "HYPOTHÈSES" -#: ../src/qalc.cc:3187 ../src/qalc.cc:3194 ../src/qalc.cc:3195 -#: ../src/qalc.cc:3199 ../src/qalc.cc:3205 +#: ../src/qalc.cc:3188 ../src/qalc.cc:3195 ../src/qalc.cc:3196 +#: ../src/qalc.cc:3200 ../src/qalc.cc:3206 msgid "NAME" msgstr "NOM" -#: ../src/qalc.cc:3194 ../src/qalc.cc:3226 ../src/qalc.cc:3925 +#: ../src/qalc.cc:3195 ../src/qalc.cc:3227 ../src/qalc.cc:3926 msgid "find" msgstr "rechercher" #. qalc command -#: ../src/qalc.cc:3194 ../src/qalc.cc:3224 ../src/qalc.cc:3226 -#: ../src/qalc.cc:3925 +#: ../src/qalc.cc:3195 ../src/qalc.cc:3225 ../src/qalc.cc:3227 +#: ../src/qalc.cc:3926 msgid "list" msgstr "énumérer" -#: ../src/qalc.cc:3195 ../src/qalc.cc:3205 +#: ../src/qalc.cc:3196 ../src/qalc.cc:3206 msgid "EXPRESSION" msgstr "" #. qalc command -#: ../src/qalc.cc:3196 ../src/qalc.cc:3252 ../src/qalc.cc:3934 -#: ../libqalculate/Calculator.cc:11336 ../libqalculate/DataSet.cc:364 -#: ../libqalculate/DataSet.cc:391 ../libqalculate/DataSet.cc:1038 +#: ../src/qalc.cc:3197 ../src/qalc.cc:3253 ../src/qalc.cc:3935 +#: ../libqalculate/Calculator-definitions.cc:2887 +#: ../libqalculate/DataSet.cc:365 ../libqalculate/DataSet.cc:392 +#: ../libqalculate/DataSet.cc:1039 msgid "info" msgstr "" -#: ../src/qalc.cc:3199 +#: ../src/qalc.cc:3200 msgid "CATEGORY" msgstr "CATÉGORIE" -#: ../src/qalc.cc:3199 +#: ../src/qalc.cc:3200 msgid "TITLE" msgstr "TITRE" -#: ../src/qalc.cc:3204 +#: ../src/qalc.cc:3205 msgid "UNIT or \"TO\" COMMAND" msgstr "UNITÉ et \"TO\" COMMANDE" #. qalc command -#: ../src/qalc.cc:3206 ../src/qalc.cc:4053 ../src/qalc.cc:4074 +#: ../src/qalc.cc:3207 ../src/qalc.cc:4054 ../src/qalc.cc:4075 msgid "quit" msgstr "quitter" -#: ../src/qalc.cc:3206 ../src/qalc.cc:4053 ../src/qalc.cc:4074 +#: ../src/qalc.cc:3207 ../src/qalc.cc:4054 ../src/qalc.cc:4075 msgid "exit" msgstr "sortir" -#: ../src/qalc.cc:3207 +#: ../src/qalc.cc:3208 msgid "Commands for RPN mode:" msgstr "" -#: ../src/qalc.cc:3208 +#: ../src/qalc.cc:3209 msgid "STATE" msgstr "" -#: ../src/qalc.cc:3211 ../src/qalc.cc:3213 +#: ../src/qalc.cc:3212 ../src/qalc.cc:3214 msgid "INDEX" msgstr "" -#: ../src/qalc.cc:3212 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3213 ../src/qalc.cc:3216 msgid "INDEX 1" msgstr "" -#: ../src/qalc.cc:3212 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3213 ../src/qalc.cc:3216 msgid "INDEX 2" msgstr "" -#: ../src/qalc.cc:3214 +#: ../src/qalc.cc:3215 msgid "DIRECTION" msgstr "" -#: ../src/qalc.cc:3217 +#: ../src/qalc.cc:3218 msgid "Type help COMMAND for more information (example: help save)." msgstr "Tapez help COMMANDE pour plus d'aide (exemple : help save)." -#: ../src/qalc.cc:3218 +#: ../src/qalc.cc:3219 msgid "" "Type info NAME for information about a function, variable or unit (example: " "info sin)." @@ -1497,13 +1513,13 @@ "Tapez info NOM pour obtenir de l'information sur une fonction, variable ou " "unité (exemple : info sin)." -#: ../src/qalc.cc:3219 +#: ../src/qalc.cc:3220 msgid "" "When a line begins with '/', the following text is always interpreted as a " "command." msgstr "" -#: ../src/qalc.cc:3221 +#: ../src/qalc.cc:3222 msgid "" "For more information about mathematical expression, different options, and a " "complete list of functions, variables and units, see the relevant sections " @@ -1511,318 +1527,318 @@ "qalculate.github.io/manual/index.html)." msgstr "" -#: ../src/qalc.cc:3239 ../src/qalc.cc:3244 +#: ../src/qalc.cc:3240 ../src/qalc.cc:3245 msgid "currencies" msgstr "monnaies" -#: ../src/qalc.cc:3261 +#: ../src/qalc.cc:3262 msgid "No function, variable or unit with specified name exist." msgstr "Aucune fonction, variable ou unité avec le nom indiqué n'existe." -#: ../src/qalc.cc:3271 +#: ../src/qalc.cc:3272 msgid "Function" msgstr "Fonction" -#: ../src/qalc.cc:3408 +#: ../src/qalc.cc:3409 msgid "Expression:" msgstr "" -#: ../src/qalc.cc:3417 ../src/qalc.cc:3420 ../src/qalc.cc:3587 +#: ../src/qalc.cc:3418 ../src/qalc.cc:3421 ../src/qalc.cc:3588 msgid "Unit" msgstr "Unité" -#: ../src/qalc.cc:3423 ../src/qalc.cc:3497 +#: ../src/qalc.cc:3424 ../src/qalc.cc:3498 msgid "Names" msgstr "Noms" -#: ../src/qalc.cc:3441 +#: ../src/qalc.cc:3442 msgid "Base Unit" msgstr "Unité de base" -#: ../src/qalc.cc:3448 +#: ../src/qalc.cc:3449 msgid "Relation" msgstr "" -#: ../src/qalc.cc:3453 ../src/qalc.cc:3555 +#: ../src/qalc.cc:3454 ../src/qalc.cc:3556 msgid "Relative uncertainty" msgstr "" -#: ../src/qalc.cc:3454 ../src/qalc.cc:3556 +#: ../src/qalc.cc:3455 ../src/qalc.cc:3557 msgid "Uncertainty" msgstr "" -#: ../src/qalc.cc:3464 +#: ../src/qalc.cc:3465 msgid "Inverse Relation" msgstr "Relation Inverse" -#: ../src/qalc.cc:3476 +#: ../src/qalc.cc:3477 msgid "Base Units" msgstr "Unités de base" -#: ../src/qalc.cc:3491 ../src/qalc.cc:3494 +#: ../src/qalc.cc:3492 ../src/qalc.cc:3495 msgid "Variable" msgstr "" -#: ../src/qalc.cc:3606 +#: ../src/qalc.cc:3607 msgid "Factorizes the current result." msgstr "Factorise le résultat courant." -#: ../src/qalc.cc:3610 +#: ../src/qalc.cc:3611 msgid "Applies partial fraction decomposition to the current result." msgstr "" -#: ../src/qalc.cc:3614 +#: ../src/qalc.cc:3615 #, fuzzy msgid "Expands the current result." msgstr "Factorise le résultat courant." -#: ../src/qalc.cc:3628 +#: ../src/qalc.cc:3629 msgid "Sets the value of an option." msgstr "Définit la valeur d'une option." -#: ../src/qalc.cc:3629 +#: ../src/qalc.cc:3630 msgid "Example: set base 16." msgstr "Exemple : set base 16." -#: ../src/qalc.cc:3631 +#: ../src/qalc.cc:3632 #, fuzzy msgid "" "Available options and accepted values are (the current value is marked with " "'*'):" msgstr "Les options disponibles et les valeurs acceptées sont :" -#: ../src/qalc.cc:3635 +#: ../src/qalc.cc:3636 msgid "Determines if the expression is factorized or not after calculation." msgstr "" -#: ../src/qalc.cc:3636 +#: ../src/qalc.cc:3637 msgid "Determines if unknown values will be assumed non-zero (x/x=1)." msgstr "" -#: ../src/qalc.cc:3637 +#: ../src/qalc.cc:3638 msgid "Display a message after a value has been assumed non-zero." msgstr "" -#: ../src/qalc.cc:3640 +#: ../src/qalc.cc:3641 #, fuzzy msgid "Default assumptions for unknown variables." msgstr "Définit les hypothèses par défaut pour les variables inconnues." -#: ../src/qalc.cc:3668 +#: ../src/qalc.cc:3669 msgid "" "How approximate variables and calculations are handled. In exact mode " "approximate values will not be calculated." msgstr "" -#: ../src/qalc.cc:3669 +#: ../src/qalc.cc:3670 msgid "" "If activated, interval arithmetic determines the final precision of " "calculations (avoids wrong results after loss of significance) with " "approximate functions and/or irrational numbers." msgstr "" -#: ../src/qalc.cc:3670 +#: ../src/qalc.cc:3671 msgid "" "Determines the method used for interval calculation / uncertainty " "propagation." msgstr "" -#: ../src/qalc.cc:3672 +#: ../src/qalc.cc:3673 msgid "" "Specifies the default number of significant digits displayed and determines " "the precision used for approximate calculations." msgstr "" -#: ../src/qalc.cc:3683 +#: ../src/qalc.cc:3684 #, fuzzy msgid "Interprete undefined symbols in expressions as unknown variables." msgstr "Définit les hypothèses par défaut pour les variables inconnues." -#: ../src/qalc.cc:3685 +#: ../src/qalc.cc:3686 msgid "" "If activated physical constants include units (e.g. c = 299 792 458 m∕s)." msgstr "" -#: ../src/qalc.cc:3689 +#: ../src/qalc.cc:3690 #, fuzzy msgid "Use abbreviated names for units and variables." msgstr "Définit les hypothèses par défaut pour les variables inconnues." -#: ../src/qalc.cc:3692 +#: ../src/qalc.cc:3693 msgid "Always place negative values last." msgstr "" -#: ../src/qalc.cc:3694 +#: ../src/qalc.cc:3695 msgid "Use negative exponents instead of division in result (x/y = xy^-1)." msgstr "" -#: ../src/qalc.cc:3696 +#: ../src/qalc.cc:3697 msgid "Add extra space around operators." msgstr "" -#: ../src/qalc.cc:3698 +#: ../src/qalc.cc:3699 msgid "Display Unicode characters." msgstr "" -#: ../src/qalc.cc:3702 ../src/qalc.cc:3804 +#: ../src/qalc.cc:3703 ../src/qalc.cc:3805 msgid "bin" msgstr "" -#: ../src/qalc.cc:3704 ../src/qalc.cc:3806 +#: ../src/qalc.cc:3705 ../src/qalc.cc:3807 msgid "oct" msgstr "" -#: ../src/qalc.cc:3706 ../src/qalc.cc:3808 +#: ../src/qalc.cc:3707 ../src/qalc.cc:3809 msgid "dec" msgstr "" -#: ../src/qalc.cc:3708 ../src/qalc.cc:3810 +#: ../src/qalc.cc:3709 ../src/qalc.cc:3811 msgid "hex" msgstr "" -#: ../src/qalc.cc:3710 +#: ../src/qalc.cc:3711 msgid "sexa" msgstr "" -#: ../src/qalc.cc:3729 ../src/qalc.cc:3787 +#: ../src/qalc.cc:3730 ../src/qalc.cc:3788 msgid "Determines the default decimal separator." msgstr "" -#: ../src/qalc.cc:3742 +#: ../src/qalc.cc:3743 msgid "" "Determines how rational numbers are displayed (e.g. 5/4 = 1 + 1/4 = 1.25). " "'long' removes limits on the size of the numerator and denonimator." msgstr "" -#: ../src/qalc.cc:3743 +#: ../src/qalc.cc:3744 msgid "" "Enables two's complement representation for display of negative hexadecimal " "numbers." msgstr "" -#: ../src/qalc.cc:3744 ../src/qalc.cc:3803 +#: ../src/qalc.cc:3745 ../src/qalc.cc:3804 msgid "Use 'j' (instead of 'i') as default symbol for the imaginary unit." msgstr "" -#: ../src/qalc.cc:3746 +#: ../src/qalc.cc:3747 msgid "Use lowercase e for E-notation (5e2 = 5 * 10^2)." msgstr "" -#: ../src/qalc.cc:3747 +#: ../src/qalc.cc:3748 msgid "Use lowercase letters for number bases > 10." msgstr "" -#: ../src/qalc.cc:3762 +#: ../src/qalc.cc:3763 msgid "" "If activated, 1/6 is displayed as '0.1 666...', otherwise as '0.166667'." msgstr "" -#: ../src/qalc.cc:3763 +#: ../src/qalc.cc:3764 msgid "" "Determines whether halfway numbers are rounded upwards or towards the " "nearest even integer." msgstr "" -#: ../src/qalc.cc:3765 +#: ../src/qalc.cc:3766 msgid "Determines how scientific notation are used (e.g. 5 543 000 = 5.543E6)." msgstr "" -#: ../src/qalc.cc:3780 +#: ../src/qalc.cc:3781 msgid "If actived, zeroes are kept at the end of approximate numbers." msgstr "" -#: ../src/qalc.cc:3781 +#: ../src/qalc.cc:3782 msgid "" "Enables two's complement representation for display of negative binary " "numbers." msgstr "" -#: ../src/qalc.cc:3785 +#: ../src/qalc.cc:3786 msgid "Use ^ as bitwise exclusive OR operator." msgstr "" -#: ../src/qalc.cc:3798 +#: ../src/qalc.cc:3799 msgid "Allows use of ',' as thousands separator." msgstr "" -#: ../src/qalc.cc:3801 +#: ../src/qalc.cc:3802 msgid "Allows use of '.' as thousands separator." msgstr "" -#: ../src/qalc.cc:3825 +#: ../src/qalc.cc:3826 #, fuzzy msgid "See 'help parsing mode'." msgstr "mode exp" -#: ../src/qalc.cc:3826 +#: ../src/qalc.cc:3827 msgid "" "If activated, numbers be interpreted as approximate with precision equal to " "the number of significant digits (3.20 = 3.20+/-0.005)." msgstr "" -#: ../src/qalc.cc:3831 +#: ../src/qalc.cc:3832 msgid "Enables automatic use of hecto, deca, deci, and centi." msgstr "" -#: ../src/qalc.cc:3833 +#: ../src/qalc.cc:3834 msgid "" "Controls automatic unit conversion of the result. 'optimalsi' always " "converts non-SI units, while 'optimal' only converts to more optimal unit " "expressions, with less units and exponents." msgstr "" -#: ../src/qalc.cc:3847 +#: ../src/qalc.cc:3848 msgid "" "If activated, binary prefixes are used by default for information units." msgstr "" -#: ../src/qalc.cc:3848 +#: ../src/qalc.cc:3849 msgid "" "Enables automatic conversion to the local currency when optimal unit " "conversion is enabled." msgstr "" -#: ../src/qalc.cc:3849 +#: ../src/qalc.cc:3850 msgid "" "Enables automatic use of prefixes in the denominator of unit expressions." msgstr "" -#: ../src/qalc.cc:3850 +#: ../src/qalc.cc:3851 msgid "" "If activated, units are separated from variables at the end of the result." msgstr "" -#: ../src/qalc.cc:3851 +#: ../src/qalc.cc:3852 msgid "Enables automatic use of prefixes in the result." msgstr "" -#: ../src/qalc.cc:3856 +#: ../src/qalc.cc:3857 msgid "days" msgstr "" -#: ../src/qalc.cc:3863 +#: ../src/qalc.cc:3864 msgid "Ignore system language and use English (requires restart)." msgstr "" -#: ../src/qalc.cc:3864 +#: ../src/qalc.cc:3865 #, fuzzy msgid "Activates the Reverse Polish Notation stack." msgstr "(Dés)active le mode Notation Polonaise Inversée." -#: ../src/qalc.cc:3865 +#: ../src/qalc.cc:3866 #, fuzzy msgid "Save functions, units, and variables on exit." msgstr "une fonction, une unité ou un nom de variable valide" -#: ../src/qalc.cc:3866 +#: ../src/qalc.cc:3867 msgid "Save settings on exit." msgstr "" -#: ../src/qalc.cc:3870 +#: ../src/qalc.cc:3871 msgid "Set default assumptions for unknown variables." msgstr "Définit les hypothèses par défaut pour les variables inconnues." -#: ../src/qalc.cc:3897 +#: ../src/qalc.cc:3898 msgid "" "Saves the current result in a variable with the specified name. You may " "optionally also provide a category (default \"Temporary\") and a title." @@ -1831,7 +1847,7 @@ "pouvez éventuellement préciser aussi une catégorie (défaut \"Temporaire\") " "et un titre." -#: ../src/qalc.cc:3898 +#: ../src/qalc.cc:3899 msgid "" "If name equals \"mode\" or \"definitions\", the current mode and " "definitions, respectively, will be saved." @@ -1839,54 +1855,54 @@ "Si le nom est \"mode\" ou \"définitions\", le mode ou la définition " "courants, respectivement, seront enregistrés." -#: ../src/qalc.cc:3900 +#: ../src/qalc.cc:3901 msgid "Example: store var1." msgstr "Exemple : store var1" -#: ../src/qalc.cc:3904 +#: ../src/qalc.cc:3905 #, fuzzy msgid "Create a variables with the specified name and expression." msgstr "Aucune fonction, variable ou unité avec le nom indiqué n'existe." -#: ../src/qalc.cc:3906 +#: ../src/qalc.cc:3907 #, fuzzy msgid "Example: variable var1 pi / 2." msgstr "Exemple : store var1" -#: ../src/qalc.cc:3910 +#: ../src/qalc.cc:3911 #, fuzzy msgid "Creates a function with the specified name and expression." msgstr "Aucune fonction, variable ou unité avec le nom indiqué n'existe." -#: ../src/qalc.cc:3911 +#: ../src/qalc.cc:3912 msgid "Use '\\x', '\\y', '\\z', '\\a', etc. for arguments in the expression." msgstr "" -#: ../src/qalc.cc:3913 +#: ../src/qalc.cc:3914 #, fuzzy msgid "Example: function func1 5*\\x." msgstr "Exemple : info sin" -#: ../src/qalc.cc:3917 +#: ../src/qalc.cc:3918 #, fuzzy msgid "Removes the user-defined variable or function with the specified name." msgstr "Aucune fonction, variable ou unité avec le nom indiqué n'existe." -#: ../src/qalc.cc:3919 +#: ../src/qalc.cc:3920 #, fuzzy msgid "Example: delete var1." msgstr "Exemple : store var1" -#: ../src/qalc.cc:3923 +#: ../src/qalc.cc:3924 msgid "Displays the current mode." msgstr "Affiche le mode courant." -#: ../src/qalc.cc:3927 +#: ../src/qalc.cc:3928 #, fuzzy msgid "Displays a list of variables, functions and units." msgstr "\"%s\" n'est pas une variable/fonction/unité valide." -#: ../src/qalc.cc:3928 +#: ../src/qalc.cc:3929 msgid "" "Enter with argument 'currencies', 'functions', 'variables' or 'units' to " "show a list of all currencies, functions, variables or units. Enter a search " @@ -1894,272 +1910,272 @@ "called with no argument all user-definied objects are listed." msgstr "" -#: ../src/qalc.cc:3930 +#: ../src/qalc.cc:3931 #, fuzzy msgid "Example: list functions." msgstr "Exemple : info sin" -#: ../src/qalc.cc:3931 +#: ../src/qalc.cc:3932 #, fuzzy msgid "Example: find dinar." msgstr "Exemple : info sin" -#: ../src/qalc.cc:3932 +#: ../src/qalc.cc:3933 #, fuzzy msgid "Example: find variables planck." msgstr "Exemple : store var1" -#: ../src/qalc.cc:3936 +#: ../src/qalc.cc:3937 msgid "Displays information about a function, variable or unit." msgstr "Affiche l'information sur une fonction, une variable ou une unité." -#: ../src/qalc.cc:3938 +#: ../src/qalc.cc:3939 msgid "Example: info sin." msgstr "Exemple : info sin" -#: ../src/qalc.cc:3942 +#: ../src/qalc.cc:3943 msgid "Downloads current exchange rates from the Internet." msgstr "Télécharge les taux d'échange courants sur Internet." -#: ../src/qalc.cc:3946 +#: ../src/qalc.cc:3947 #, fuzzy msgid "(De)activates the Reverse Polish Notation stack and syntax." msgstr "(Dés)active le mode Notation Polonaise Inversée." -#: ../src/qalc.cc:3948 +#: ../src/qalc.cc:3949 msgid "" "\"syntax\" activates only the RPN syntax and \"stack\" enables the RPN stack." msgstr "" -#: ../src/qalc.cc:3952 +#: ../src/qalc.cc:3953 #, fuzzy msgid "Clears the entire RPN stack." msgstr "Vide la pile NPI." -#: ../src/qalc.cc:3956 +#: ../src/qalc.cc:3957 #, fuzzy msgid "Removes the top of the RPN stack or the value at the specified index." msgstr "Aucune fonction, variable ou unité avec le nom indiqué n'existe." -#: ../src/qalc.cc:3958 ../src/qalc.cc:3970 ../src/qalc.cc:3980 -#: ../src/qalc.cc:3990 +#: ../src/qalc.cc:3959 ../src/qalc.cc:3971 ../src/qalc.cc:3981 +#: ../src/qalc.cc:3991 msgid "" "Index 1 is the top of stack and negative index values counts from the bottom " "of the stack." msgstr "" -#: ../src/qalc.cc:3962 +#: ../src/qalc.cc:3963 msgid "Displays the RPN stack." msgstr "Affiche la pile NPI." -#: ../src/qalc.cc:3966 +#: ../src/qalc.cc:3967 msgid "Swaps position of values on the RPN stack." msgstr "" -#: ../src/qalc.cc:3968 +#: ../src/qalc.cc:3969 msgid "" "If no index is specified, the values on the top of the stack (index 1 and " "index 2) will be swapped and if only one index is specified, the value at " "this index will be swapped with the top value." msgstr "" -#: ../src/qalc.cc:3972 +#: ../src/qalc.cc:3973 #, fuzzy msgid "Example: swap 2 4" msgstr "Exemple : store var1" -#: ../src/qalc.cc:3976 +#: ../src/qalc.cc:3977 msgid "Duplicates a value on the RPN stack to the top of the stack." msgstr "" -#: ../src/qalc.cc:3978 +#: ../src/qalc.cc:3979 msgid "If no index is specified, the top of the stack is duplicated." msgstr "" -#: ../src/qalc.cc:3984 +#: ../src/qalc.cc:3985 msgid "Rotates the RPN stack up (default) or down." msgstr "" -#: ../src/qalc.cc:3988 +#: ../src/qalc.cc:3989 msgid "Changes the position of a value on the RPN stack." msgstr "" -#: ../src/qalc.cc:3992 +#: ../src/qalc.cc:3993 #, fuzzy msgid "Example: move 2 4" msgstr "Exemple : store var1" -#: ../src/qalc.cc:3996 +#: ../src/qalc.cc:3997 msgid "Sets the result number base (equivalent to set base)." msgstr "" -#: ../src/qalc.cc:4000 +#: ../src/qalc.cc:4001 msgid "Equivalent to set approximation exact." msgstr "" -#: ../src/qalc.cc:4004 +#: ../src/qalc.cc:4005 msgid "Equivalent to set approximation try exact." msgstr "" -#: ../src/qalc.cc:4009 +#: ../src/qalc.cc:4010 #, fuzzy msgid "Converts units or changes number base in current result." msgstr "Convertit les unités dans le résultat courant." -#: ../src/qalc.cc:4011 +#: ../src/qalc.cc:4012 #, fuzzy msgid "Possible values:" msgstr "Les valeurs d'unité possibles sont :" -#: ../src/qalc.cc:4013 +#: ../src/qalc.cc:4014 #, fuzzy msgid "- a unit or unit expression (e.g. meter or km/h)" msgstr "une expression d'unités (exemple : km/h)" -#: ../src/qalc.cc:4014 +#: ../src/qalc.cc:4015 msgid "prepend with ? to request the optimal prefix" msgstr "" -#: ../src/qalc.cc:4015 +#: ../src/qalc.cc:4016 msgid "prepend with b? to request the optimal binary prefix" msgstr "" -#: ../src/qalc.cc:4016 +#: ../src/qalc.cc:4017 msgid "prepend with + or - to force/disable use of mixed units" msgstr "" -#: ../src/qalc.cc:4017 +#: ../src/qalc.cc:4018 msgid "- a variable or physical constant (e.g. c)" msgstr "" -#: ../src/qalc.cc:4018 +#: ../src/qalc.cc:4019 #, fuzzy msgid "- base (convert to base units)" msgstr "base (convertit en unités de base)" -#: ../src/qalc.cc:4019 +#: ../src/qalc.cc:4020 #, fuzzy msgid "- optimal (convert to optimal unit)" msgstr "base (convertit en unités de base)" -#: ../src/qalc.cc:4020 +#: ../src/qalc.cc:4021 msgid "- mixed (convert to mixed units, e.g. hours + minutes)" msgstr "" -#: ../src/qalc.cc:4022 +#: ../src/qalc.cc:4023 msgid "- bin / binary (show as binary number)" msgstr "" -#: ../src/qalc.cc:4023 +#: ../src/qalc.cc:4024 msgid "- oct / octal (show as octal number)" msgstr "" -#: ../src/qalc.cc:4024 +#: ../src/qalc.cc:4025 msgid "- duo / duodecimal (show as duodecimal number)" msgstr "" -#: ../src/qalc.cc:4025 +#: ../src/qalc.cc:4026 msgid "- hex / hexadecimal (show as hexadecimal number)" msgstr "" -#: ../src/qalc.cc:4026 +#: ../src/qalc.cc:4027 msgid "- sex / sexagesimal (show as sexagesimal number)" msgstr "" -#: ../src/qalc.cc:4027 +#: ../src/qalc.cc:4028 msgid "- bijective (shown in bijective base-26)" msgstr "" -#: ../src/qalc.cc:4028 +#: ../src/qalc.cc:4029 #, fuzzy msgid "- roman (show as roman numerals)" msgstr "Erreur dans les chiffres romains : %s." -#: ../src/qalc.cc:4029 +#: ../src/qalc.cc:4030 msgid "- time (show in time format)" msgstr "" -#: ../src/qalc.cc:4030 +#: ../src/qalc.cc:4031 msgid "- unicode" msgstr "" -#: ../src/qalc.cc:4031 +#: ../src/qalc.cc:4032 msgid "- base # (show in specified number base)" msgstr "" -#: ../src/qalc.cc:4032 +#: ../src/qalc.cc:4033 msgid "- bases (show as binary, octal, decimal and hexadecimal number)" msgstr "" -#: ../src/qalc.cc:4034 +#: ../src/qalc.cc:4035 msgid "- rectangular / cartesian (show complex numbers in rectangular form)" msgstr "" -#: ../src/qalc.cc:4035 +#: ../src/qalc.cc:4036 msgid "- exponential (show complex numbers in exponential form)" msgstr "" -#: ../src/qalc.cc:4036 +#: ../src/qalc.cc:4037 msgid "- polar (show complex numbers in polar form)" msgstr "" -#: ../src/qalc.cc:4037 +#: ../src/qalc.cc:4038 msgid "- cis (show complex numbers in cis form)" msgstr "" -#: ../src/qalc.cc:4038 +#: ../src/qalc.cc:4039 msgid "- angle / phasor (show complex numbers in angle/phasor notation)" msgstr "" -#: ../src/qalc.cc:4040 +#: ../src/qalc.cc:4041 msgid "- fraction (show result as mixed fraction)" msgstr "" -#: ../src/qalc.cc:4041 +#: ../src/qalc.cc:4042 #, fuzzy msgid "- factors (factorize result)" msgstr "Factorise le résultat courant." -#: ../src/qalc.cc:4043 +#: ../src/qalc.cc:4044 msgid "- UTC (show date and time in UTC time zone)" msgstr "" -#: ../src/qalc.cc:4044 +#: ../src/qalc.cc:4045 msgid "- UTC+/-hh[:mm] (show date and time in specified time zone)" msgstr "" -#: ../src/qalc.cc:4045 +#: ../src/qalc.cc:4046 msgid "- calendars" msgstr "" -#: ../src/qalc.cc:4047 +#: ../src/qalc.cc:4048 #, fuzzy msgid "Example: to ?g" msgstr "Exemple : store var1" -#: ../src/qalc.cc:4050 +#: ../src/qalc.cc:4051 msgid "" "This command can also be typed directly at the end of the mathematical " "expression (e.g. 5 ft + 2 in to meter)." msgstr "" -#: ../src/qalc.cc:4055 +#: ../src/qalc.cc:4056 msgid "Terminates this program." msgstr "Termine ce programme." -#: ../src/qalc.cc:4060 +#: ../src/qalc.cc:4061 msgid "" "Implicit multiplication does not differ from explicit multiplication " "(\"12/2(1+2) = 12/2*3 = 18\", \"5x/5y = 5*x/5*y = xy\")." msgstr "" -#: ../src/qalc.cc:4063 +#: ../src/qalc.cc:4064 msgid "" "Implicit multiplication is parsed before explicit multiplication " "(\"12/2(1+2) = 12/(2*3) = 2\", \"5x/5y = (5*x)/(5*y) = x/y\")." msgstr "" -#: ../src/qalc.cc:4066 +#: ../src/qalc.cc:4067 msgid "" "The default adaptive mode works as the \"implicit first\" mode, unless " "spaces are found (\"1/5x = 1/(5*x)\", but \"1/5 x = (1/5)*x\"). In the " @@ -2167,67 +2183,67 @@ "(5*(m/s)) = 1 s\")." msgstr "" -#: ../src/qalc.cc:4068 +#: ../src/qalc.cc:4069 msgid "" "Function arguments without parentheses are an exception, where implicit " "multiplication in front of variables and units is parsed first regardless of " "mode (\"sqrt 2x = sqrt(2x)\")." msgstr "" -#: ../src/qalc.cc:4082 +#: ../src/qalc.cc:4083 #, fuzzy msgid "Unknown command." msgstr "Chiffre romain inconnu : %c." -#: ../src/qalc.cc:4131 +#: ../src/qalc.cc:4132 msgid "error" msgstr "erreur" -#: ../src/qalc.cc:4133 +#: ../src/qalc.cc:4134 msgid "warning" msgstr "avertissement" -#: ../src/qalc.cc:4156 ../src/qalc.cc:4441 ../src/qalc.cc:5320 +#: ../src/qalc.cc:4157 ../src/qalc.cc:4442 ../src/qalc.cc:5347 msgid "approx." msgstr "" -#: ../src/qalc.cc:4240 ../src/qalc.cc:4278 ../src/qalc.cc:4598 -#: ../src/qalc.cc:5173 ../libqalculate/Calculator.cc:11754 -#: ../libqalculate/MathStructure.cc:780 +#: ../src/qalc.cc:4241 ../src/qalc.cc:4279 ../src/qalc.cc:4599 +#: ../src/qalc.cc:5178 ../libqalculate/Calculator-calculate.cc:1615 +#: ../libqalculate/MathStructure.cc:448 #, c-format msgid "aborted" msgstr "interrompu" -#: ../src/qalc.cc:4290 +#: ../src/qalc.cc:4291 msgid "RPN Register Moved" msgstr "Registre NPI déplacé" -#: ../src/qalc.cc:4346 +#: ../src/qalc.cc:4347 msgid "Processing (press Enter to abort)" msgstr "Calcul en cours (appuyez sur Entrée pour interrompre)" -#: ../src/qalc.cc:4615 +#: ../src/qalc.cc:4616 msgid "Factorizing (press Enter to abort)" msgstr "Factorisation en cours (appuyez sur Entrée pour interrompre)" -#: ../src/qalc.cc:4619 +#: ../src/qalc.cc:4620 msgid "Expanding partial fractions…" msgstr "" -#: ../src/qalc.cc:4623 +#: ../src/qalc.cc:4624 #, fuzzy msgid "Expanding (press Enter to abort)" msgstr "Factorisation en cours (appuyez sur Entrée pour interrompre)" -#: ../src/qalc.cc:4627 ../src/qalc.cc:5187 +#: ../src/qalc.cc:4628 ../src/qalc.cc:5192 msgid "Calculating (press Enter to abort)" msgstr "Calcul en cours (appuyez sur Entrée pour interrompre)" -#: ../src/qalc.cc:5273 +#: ../src/qalc.cc:5300 msgid "RPN Operation" msgstr "Opération NPI" -#: ../src/qalc.cc:5805 +#: ../src/qalc.cc:5832 #, c-format msgid "" "Couldn't write preferences to\n" @@ -2236,122 +2252,208 @@ "Impossible d'écrire les préférences pour\n" " %s" -#: ../src/qalc.cc:5913 +#: ../src/qalc.cc:5940 msgid "Couldn't write definitions" msgstr "Impossible d'écrire les définitions" -#: ../src/test.cc:13 ../src/test.cc:28 ../libqalculate/Calculator.cc:2229 +#. thread cancellation is not safe +#: ../src/test.cc:13 ../src/test.cc:28 +#: ../libqalculate/Calculator-calculate.cc:172 msgid "" "The calculation has been forcibly terminated. Please restart the application " "and report this as a bug." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:109 +#: ../libqalculate/BuiltinFunctions-algebra.cc:359 +msgid "" +"No equality or inequality to solve. The entered expression to solve is not " +"correct (ex. \"x + 5 = 3\" is correct)" +msgstr "" +"Pas d'égalité ou d'inégalité à résoudre. L'expression à résoudre que vous " +"avez entrée est incorrecte (ex : \"x + 5 = 3\" est correcte)" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:406 #, c-format -msgid "Too many elements (%s) for the dimensions (%sx%s) of the matrix." -msgstr "Trop d'éléments (%s) pour les dimensions (%sx%s) de la matrice." +msgid "The comparison is true for all %s (with current assumptions)." +msgstr "" +"La comparaison est vraie pour tous les %s (avec les hypothèses courantes)." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:410 +msgid "No possible solution was found (with current assumptions)." +msgstr "" +"Aucune solution possible n'a été trouvée (avec les hypothèses courantes)." -#: ../libqalculate/BuiltinFunctions.cc:172 -#: ../libqalculate/BuiltinFunctions.cc:234 +#: ../libqalculate/BuiltinFunctions-algebra.cc:414 #, c-format -msgid "Row %s does not exist in matrix." -msgstr "La ligne %s n'existe pas dans la matrice." +msgid "Was unable to completely isolate %s." +msgstr "Impossible d'isoler complètement %s." -#: ../libqalculate/BuiltinFunctions.cc:185 -#: ../libqalculate/BuiltinFunctions.cc:230 +#: ../libqalculate/BuiltinFunctions-algebra.cc:418 +#: ../libqalculate/BuiltinFunctions-algebra.cc:581 +#: ../libqalculate/BuiltinFunctions-algebra.cc:673 #, c-format -msgid "Column %s does not exist in matrix." -msgstr "La colonne %s n'existe pas dans la matrice." +msgid "The comparison is true for all %s if %s." +msgstr "La comparaison est vraie pour tous les %s si %s." -#: ../libqalculate/BuiltinFunctions.cc:245 +#: ../libqalculate/BuiltinFunctions-algebra.cc:422 #, c-format -msgid "Argument 3, %s, is ignored for vectors." -msgstr "Le troisième argument, %s, est ignoré pour les vecteurs." +msgid "Was unable to isolate %s." +msgstr "Impossible d'isoler %s." -#: ../libqalculate/BuiltinFunctions.cc:249 -#: ../libqalculate/BuiltinFunctions.cc:270 +#: ../libqalculate/BuiltinFunctions-algebra.cc:542 +#: ../libqalculate/BuiltinFunctions-algebra.cc:569 +#: ../libqalculate/BuiltinFunctions-algebra.cc:650 #, c-format -msgid "Element %s does not exist in vector." -msgstr "L'élément %s n'existe pas dans le vecteur." +msgid "" +"Was unable to isolate %s with the current assumptions. The assumed sign was " +"therefore temporarily set as unknown." +msgstr "" +"Impossible d'isoler %s avec les hypothèses courantes. Le signe supposé a été " +"temporairement défini comme inconnu." -#: ../libqalculate/BuiltinFunctions.cc:411 -#: ../libqalculate/BuiltinFunctions.cc:415 -#: ../libqalculate/BuiltinFunctions.cc:447 -#: ../libqalculate/BuiltinFunctions.cc:451 +#: ../libqalculate/BuiltinFunctions-algebra.cc:545 +#: ../libqalculate/BuiltinFunctions-algebra.cc:572 +#: ../libqalculate/BuiltinFunctions-algebra.cc:653 #, c-format -msgid "%s() requires that all matrices/vectors have the same dimensions." +msgid "" +"Was unable to isolate %s with the current assumptions. The assumed type and " +"sign was therefore temporarily set as unknown." +msgstr "" +"Impossible d'isoler %s avec les hypothèses courantes. Le type et le signe " +"supposés ont été temporairement définis comme inconnus." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:577 +#: ../libqalculate/BuiltinFunctions-algebra.cc:660 +#, c-format +msgid "The solution requires that %s." +msgstr "La solution exige que %s." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:667 +#, c-format +msgid "Solution %s requires that %s." +msgstr "La solution %s exige que %s." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:738 +#, c-format +msgid "" +"Unable to isolate %s.\n" +"\n" +"You might need to place the equations and variables in an appropriate order " +"so that each equation at least contains the corresponding variable (if " +"automatic reordering failed)." msgstr "" +"Impossible d'isoler %s.\n" +"\n" +"Vous pourriez placer les équations et les variables dans un ordre approprié " +"pour que chaque équation contienne au moins la variable correspondante (si " +"le réordonnement automatique a échoué)." -#: ../libqalculate/BuiltinFunctions.cc:4759 -#: ../libqalculate/BuiltinFunctions.cc:4802 +#: ../libqalculate/BuiltinFunctions-algebra.cc:740 +#: ../libqalculate/BuiltinFunctions-algebra.cc:754 +#: ../libqalculate/BuiltinFunctions-algebra.cc:763 #, c-format -msgid "Unsolvable comparison in %s()." -msgstr "Comparaison impossible à résoudre dans %s()." +msgid "Unable to isolate %s." +msgstr "Impossible d'isoler %s." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:747 +#, c-format +msgid "Inequalities is not allowed in %s()." +msgstr "Les inégalités ne sont pas autorisées dans %s." -#: ../libqalculate/BuiltinFunctions.cc:4972 -#: ../libqalculate/BuiltinFunctions.cc:5006 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1089 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1094 +msgid "No differential equation found." +msgstr "" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:1098 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1127 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1133 +msgid "Unable to solve differential equation." +msgstr "" + +#: ../libqalculate/BuiltinFunctions-datetime.cc:33 +#: ../libqalculate/BuiltinFunctions-datetime.cc:67 msgid "gregorian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4973 +#: ../libqalculate/BuiltinFunctions-datetime.cc:34 msgid "milankovic" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4974 +#: ../libqalculate/BuiltinFunctions-datetime.cc:35 msgid "julian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4975 +#: ../libqalculate/BuiltinFunctions-datetime.cc:36 msgid "islamic" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4976 +#: ../libqalculate/BuiltinFunctions-datetime.cc:37 msgid "hebrew" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4977 +#: ../libqalculate/BuiltinFunctions-datetime.cc:38 msgid "egyptian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4978 +#: ../libqalculate/BuiltinFunctions-datetime.cc:39 msgid "persian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4979 +#: ../libqalculate/BuiltinFunctions-datetime.cc:40 #, fuzzy msgid "coptic" msgstr "optionnel" -#: ../libqalculate/BuiltinFunctions.cc:4980 +#: ../libqalculate/BuiltinFunctions-datetime.cc:41 msgid "ethiopian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4981 +#: ../libqalculate/BuiltinFunctions-datetime.cc:42 msgid "indian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4982 +#: ../libqalculate/BuiltinFunctions-datetime.cc:43 msgid "chinese" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:5408 -#: ../libqalculate/BuiltinFunctions.cc:5438 ../libqalculate/Number.cc:429 -#: ../libqalculate/Number.cc:900 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:57 #, c-format -msgid "Character '%s' was ignored in the number \"%s\" with base %s." -msgstr "Le caractère '%s' a été ignoré dans le nombre \"%s\" avec la base %s." +msgid "Too many elements (%s) for the dimensions (%sx%s) of the matrix." +msgstr "Trop d'éléments (%s) pour les dimensions (%sx%s) de la matrice." -#: ../libqalculate/BuiltinFunctions.cc:5703 -#: ../libqalculate/BuiltinFunctions.cc:5708 -#: ../libqalculate/BuiltinFunctions.cc:5710 -#: ../libqalculate/BuiltinFunctions.cc:5726 ../libqalculate/Calculator.cc:3409 -#: ../libqalculate/Calculator.cc:3416 ../libqalculate/Calculator.cc:3418 -#: ../libqalculate/Calculator.cc:3482 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:120 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:182 #, c-format -msgid "Original value (%s) was not found." +msgid "Row %s does not exist in matrix." +msgstr "La ligne %s n'existe pas dans la matrice." + +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:133 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:178 +#, c-format +msgid "Column %s does not exist in matrix." +msgstr "La colonne %s n'existe pas dans la matrice." + +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:193 +#, c-format +msgid "Argument 3, %s, is ignored for vectors." +msgstr "Le troisième argument, %s, est ignoré pour les vecteurs." + +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:197 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:218 +#, c-format +msgid "Element %s does not exist in vector." +msgstr "L'élément %s n'existe pas dans le vecteur." + +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:359 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:363 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:395 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:399 +#, c-format +msgid "%s() requires that all matrices/vectors have the same dimensions." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:5862 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:539 msgid "" "The number of requested elements in generate vector function must be a " "positive integer." @@ -2359,280 +2461,195 @@ "Le nombre d'éléments requis pour générer une fonction vectorielle doit être " "un entier positif." -#: ../libqalculate/BuiltinFunctions.cc:6179 -#: ../libqalculate/BuiltinFunctions.cc:6183 -#, c-format -msgid "Too few elements (%s) in vector (%s required)" -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:6232 -#: ../libqalculate/BuiltinFunctions.cc:6249 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:562 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:579 msgid "Comparison failed." msgstr "La comparaison a échoué." -#: ../libqalculate/BuiltinFunctions.cc:6392 -#, c-format -msgid "Object %s does not exist." -msgstr "L'objet %s n'existe pas." - -#: ../libqalculate/BuiltinFunctions.cc:6410 -#, fuzzy, c-format -msgid "Invalid variable name (%s)." -msgstr "un nom de variable valide" - -#: ../libqalculate/BuiltinFunctions.cc:6427 -msgid "" -"A global unit or variable was deactivated. It will be restored after the new " -"variable has been removed." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:6442 +#: ../libqalculate/BuiltinFunctions-statistics.cc:178 +#: ../libqalculate/BuiltinFunctions-statistics.cc:221 #, c-format -msgid "Register %s does not exist. Returning zero." -msgstr "Le registre %s n'existe pas. Valeur renvoyée : zéro." - -#: ../libqalculate/BuiltinFunctions.cc:7390 -#: ../libqalculate/MathStructure.cc:284 ../libqalculate/MathStructure.cc:306 -#: ../libqalculate/MathStructure.cc:337 -#, c-format -msgid "To avoid division by zero, the following must be true: %s." -msgstr "Pour éviter la division par zéro, ce qui suit doit être vrai : %s" +msgid "Unsolvable comparison in %s()." +msgstr "Comparaison impossible à résoudre dans %s()." -#: ../libqalculate/BuiltinFunctions.cc:7598 -#: ../libqalculate/BuiltinFunctions.cc:7617 -#: ../libqalculate/BuiltinFunctions.cc:7650 -#: ../libqalculate/BuiltinFunctions.cc:7672 -#: ../libqalculate/BuiltinFunctions.cc:7721 -#: ../libqalculate/BuiltinFunctions.cc:7756 -#: ../libqalculate/BuiltinFunctions.cc:7871 -#: ../libqalculate/BuiltinFunctions.cc:7921 -#: ../libqalculate/BuiltinFunctions.cc:7955 -#: ../libqalculate/BuiltinFunctions.cc:7998 -#: ../libqalculate/BuiltinFunctions.cc:8030 +#: ../libqalculate/BuiltinFunctions-calculus.cc:314 #, fuzzy -msgid "Unable to integrate the expression." +msgid "Unable to find limit." msgstr "Impossible d'isoler %s." -#: ../libqalculate/BuiltinFunctions.cc:7878 -#: ../libqalculate/BuiltinFunctions.cc:7948 +#: ../libqalculate/BuiltinFunctions-calculus.cc:409 +#: ../libqalculate/BuiltinFunctions-calculus.cc:441 +#: ../libqalculate/MathStructure-integrate.cc:7294 +#: ../libqalculate/MathStructure-integrate.cc:7314 +#: ../libqalculate/MathStructure-integrate.cc:7349 +#: ../libqalculate/MathStructure-integrate.cc:7373 +#: ../libqalculate/MathStructure-integrate.cc:7423 +#: ../libqalculate/MathStructure-integrate.cc:7462 +#: ../libqalculate/MathStructure-integrate.cc:7658 +#: ../libqalculate/MathStructure-integrate.cc:7712 +#: ../libqalculate/MathStructure-integrate.cc:7754 #, fuzzy -msgid "Unable to integrate the expression exact." +msgid "Unable to integrate the expression." msgstr "Impossible d'isoler %s." -#: ../libqalculate/BuiltinFunctions.cc:7915 -msgid "Definite integral was approximated." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:8245 -msgid "" -"No equality or inequality to solve. The entered expression to solve is not " -"correct (ex. \"x + 5 = 3\" is correct)" -msgstr "" -"Pas d'égalité ou d'inégalité à résoudre. L'expression à résoudre que vous " -"avez entrée est incorrecte (ex : \"x + 5 = 3\" est correcte)" - -#: ../libqalculate/BuiltinFunctions.cc:8292 -#, c-format -msgid "The comparison is true for all %s (with current assumptions)." -msgstr "" -"La comparaison est vraie pour tous les %s (avec les hypothèses courantes)." - -#: ../libqalculate/BuiltinFunctions.cc:8296 -msgid "No possible solution was found (with current assumptions)." -msgstr "" -"Aucune solution possible n'a été trouvée (avec les hypothèses courantes)." - -#: ../libqalculate/BuiltinFunctions.cc:8300 +#: ../libqalculate/BuiltinFunctions-number.cc:684 +#: ../libqalculate/BuiltinFunctions-number.cc:714 ../libqalculate/Number.cc:459 +#: ../libqalculate/Number.cc:970 #, c-format -msgid "Was unable to completely isolate %s." -msgstr "Impossible d'isoler complètement %s." - -#: ../libqalculate/BuiltinFunctions.cc:8304 -#: ../libqalculate/BuiltinFunctions.cc:8467 -#: ../libqalculate/BuiltinFunctions.cc:8559 -#, c-format -msgid "The comparison is true for all %s if %s." -msgstr "La comparaison est vraie pour tous les %s si %s." - -#: ../libqalculate/BuiltinFunctions.cc:8308 -#, c-format -msgid "Was unable to isolate %s." -msgstr "Impossible d'isoler %s." +msgid "Character '%s' was ignored in the number \"%s\" with base %s." +msgstr "Le caractère '%s' a été ignoré dans le nombre \"%s\" avec la base %s." -#: ../libqalculate/BuiltinFunctions.cc:8428 -#: ../libqalculate/BuiltinFunctions.cc:8455 -#: ../libqalculate/BuiltinFunctions.cc:8536 +#. if left value is a function without any arguments, do function replacement +#: ../libqalculate/BuiltinFunctions-util.cc:414 +#: ../libqalculate/BuiltinFunctions-util.cc:419 +#: ../libqalculate/BuiltinFunctions-util.cc:421 +#: ../libqalculate/BuiltinFunctions-util.cc:437 +#: ../libqalculate/Calculator-calculate.cc:1239 +#: ../libqalculate/Calculator-calculate.cc:1251 +#: ../libqalculate/Calculator-calculate.cc:1253 +#: ../libqalculate/Calculator-calculate.cc:1256 +#: ../libqalculate/Calculator-calculate.cc:1327 #, c-format -msgid "" -"Was unable to isolate %s with the current assumptions. The assumed sign was " -"therefore temporarily set as unknown." +msgid "Original value (%s) was not found." msgstr "" -"Impossible d'isoler %s avec les hypothèses courantes. Le signe supposé a été " -"temporairement défini comme inconnu." -#: ../libqalculate/BuiltinFunctions.cc:8431 -#: ../libqalculate/BuiltinFunctions.cc:8458 -#: ../libqalculate/BuiltinFunctions.cc:8539 +#: ../libqalculate/BuiltinFunctions-util.cc:627 +#: ../libqalculate/BuiltinFunctions-util.cc:631 #, c-format -msgid "" -"Was unable to isolate %s with the current assumptions. The assumed type and " -"sign was therefore temporarily set as unknown." +msgid "Too few elements (%s) in vector (%s required)" msgstr "" -"Impossible d'isoler %s avec les hypothèses courantes. Le type et le signe " -"supposés ont été temporairement définis comme inconnus." -#: ../libqalculate/BuiltinFunctions.cc:8463 -#: ../libqalculate/BuiltinFunctions.cc:8546 +#: ../libqalculate/BuiltinFunctions-util.cc:677 #, c-format -msgid "The solution requires that %s." -msgstr "La solution exige que %s." +msgid "Object %s does not exist." +msgstr "L'objet %s n'existe pas." -#: ../libqalculate/BuiltinFunctions.cc:8553 -#, c-format -msgid "Solution %s requires that %s." -msgstr "La solution %s exige que %s." +#: ../libqalculate/BuiltinFunctions-util.cc:695 +#, fuzzy, c-format +msgid "Invalid variable name (%s)." +msgstr "un nom de variable valide" -#: ../libqalculate/BuiltinFunctions.cc:8624 -#, c-format +#: ../libqalculate/BuiltinFunctions-util.cc:712 msgid "" -"Unable to isolate %s.\n" -"\n" -"You might need to place the equations and variables in an appropriate order " -"so that each equation at least contains the corresponding variable (if " -"automatic reordering failed)." +"A global unit or variable was deactivated. It will be restored after the new " +"variable has been removed." msgstr "" -"Impossible d'isoler %s.\n" -"\n" -"Vous pourriez placer les équations et les variables dans un ordre approprié " -"pour que chaque équation contienne au moins la variable correspondante (si " -"le réordonnement automatique a échoué)." - -#: ../libqalculate/BuiltinFunctions.cc:8626 -#: ../libqalculate/BuiltinFunctions.cc:8640 -#: ../libqalculate/BuiltinFunctions.cc:8649 -#, c-format -msgid "Unable to isolate %s." -msgstr "Impossible d'isoler %s." -#: ../libqalculate/BuiltinFunctions.cc:8633 +#: ../libqalculate/BuiltinFunctions-util.cc:727 #, c-format -msgid "Inequalities is not allowed in %s()." -msgstr "Les inégalités ne sont pas autorisées dans %s." - -#: ../libqalculate/BuiltinFunctions.cc:8975 -#: ../libqalculate/BuiltinFunctions.cc:8980 -msgid "No differential equation found." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:8984 -#: ../libqalculate/BuiltinFunctions.cc:9013 -#: ../libqalculate/BuiltinFunctions.cc:9019 -msgid "Unable to solve differential equation." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:9045 -#, fuzzy -msgid "Unable to find limit." -msgstr "Impossible d'isoler %s." +msgid "Register %s does not exist. Returning zero." +msgstr "Le registre %s n'existe pas. Valeur renvoyée : zéro." -#: ../libqalculate/BuiltinFunctions.cc:9099 -#: ../libqalculate/BuiltinFunctions.cc:9113 +#: ../libqalculate/BuiltinFunctions-util.cc:794 +#: ../libqalculate/BuiltinFunctions-util.cc:808 #, fuzzy msgid "Matrix" msgstr "matrice" -#: ../libqalculate/BuiltinFunctions.cc:9124 -#: ../libqalculate/BuiltinFunctions.cc:9174 +#: ../libqalculate/BuiltinFunctions-util.cc:819 +#: ../libqalculate/BuiltinFunctions-util.cc:869 #, fuzzy msgid "Vector" msgstr "vecteur" -#: ../libqalculate/BuiltinFunctions.cc:9139 -#: ../libqalculate/BuiltinFunctions.cc:9185 ../libqalculate/Calculator.cc:12320 +#: ../libqalculate/BuiltinFunctions-util.cc:834 +#: ../libqalculate/BuiltinFunctions-util.cc:880 +#: ../libqalculate/Calculator-plot.cc:135 msgid "Unable to generate plot data with current min, max and step size." msgstr "" "Impossible de générer des données graphiques avec les valeurs actuelles min, " "max et pas." -#: ../libqalculate/BuiltinFunctions.cc:9141 -#: ../libqalculate/BuiltinFunctions.cc:9187 +#: ../libqalculate/BuiltinFunctions-util.cc:836 +#: ../libqalculate/BuiltinFunctions-util.cc:882 msgid "Sampling rate must be a positive integer." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:9150 -#: ../libqalculate/BuiltinFunctions.cc:9196 ../libqalculate/Calculator.cc:12290 +#: ../libqalculate/BuiltinFunctions-util.cc:845 +#: ../libqalculate/BuiltinFunctions-util.cc:891 +#: ../libqalculate/Calculator-plot.cc:105 msgid "Unable to generate plot data with current min, max and sampling rate." msgstr "" "Impossible de générer des données graphiques avec les valeurs actuelles min, " "max et taux d'échantillonage." -#: ../libqalculate/Calculator.cc:454 ../libqalculate/Calculator.cc:680 +#: ../libqalculate/Calculator-calculate.cc:303 +#: ../libqalculate/Calculator-calculate.cc:428 +msgid "Stack is empty. Filling remaining function arguments with zeroes." +msgstr "" + +#: ../libqalculate/Calculator-calculate.cc:1004 +msgid "calculating..." +msgstr "calculs en cours..." + +#. "where"-operator +#: ../libqalculate/Calculator-calculate.cc:1130 +#: ../libqalculate/Calculator-calculate.cc:1132 +#: ../libqalculate/Calculator-calculate.cc:1151 +#: ../libqalculate/Calculator-calculate.cc:1153 +#: ../libqalculate/Calculator.cc:1326 +msgid "where" +msgstr "" + +#: ../libqalculate/Calculator-calculate.cc:1349 +#, c-format +msgid "Unhandled \"where\" expression: %s" +msgstr "" + +#: ../libqalculate/Calculator-calculate.cc:1567 +#: ../libqalculate/Calculator-calculate.cc:1614 +msgid "timed out" +msgstr "délai expiré" + +#: ../libqalculate/Calculator.cc:232 ../libqalculate/Calculator.cc:460 msgid "per" msgstr "par" -#: ../libqalculate/Calculator.cc:456 ../libqalculate/Calculator.cc:682 +#: ../libqalculate/Calculator.cc:234 ../libqalculate/Calculator.cc:462 msgid "times" msgstr "fois" -#: ../libqalculate/Calculator.cc:458 ../libqalculate/Calculator.cc:684 +#: ../libqalculate/Calculator.cc:236 ../libqalculate/Calculator.cc:464 msgid "plus" msgstr "" -#: ../libqalculate/Calculator.cc:460 ../libqalculate/Calculator.cc:686 +#: ../libqalculate/Calculator.cc:238 ../libqalculate/Calculator.cc:466 msgid "minus" msgstr "moins" -#: ../libqalculate/Calculator.cc:462 ../libqalculate/Calculator.cc:688 -#: ../libqalculate/MathStructure.cc:21575 ../libqalculate/Function.cc:1331 -#: ../libqalculate/Function.cc:1339 ../libqalculate/Function.cc:1768 -#: ../libqalculate/Function.cc:1930 ../libqalculate/Function.cc:1938 +#: ../libqalculate/Calculator.cc:240 ../libqalculate/Calculator.cc:468 +#: ../libqalculate/MathStructure-print.cc:3170 ../libqalculate/Function.cc:1361 +#: ../libqalculate/Function.cc:1369 ../libqalculate/Function.cc:1802 +#: ../libqalculate/Function.cc:1964 ../libqalculate/Function.cc:1972 msgid "and" msgstr "et" -#: ../libqalculate/Calculator.cc:831 +#: ../libqalculate/Calculator.cc:611 msgid "Gradians unit is missing. Creating one for this session." msgstr "L'unité grade manque. Création pour cette session." -#: ../libqalculate/Calculator.cc:832 ../libqalculate/Calculator.cc:840 -#: ../libqalculate/Calculator.cc:848 +#: ../libqalculate/Calculator.cc:612 ../libqalculate/Calculator.cc:620 +#: ../libqalculate/Calculator.cc:628 msgid "Angle/Plane Angle" msgstr "Angle Plan/Solide" -#: ../libqalculate/Calculator.cc:839 +#: ../libqalculate/Calculator.cc:619 msgid "Radians unit is missing. Creating one for this session." msgstr "L'unité radian manque. Création pour cette session." -#: ../libqalculate/Calculator.cc:847 +#: ../libqalculate/Calculator.cc:627 msgid "Degrees unit is missing. Creating one for this session." msgstr "L'unité degré manque. Création pour cette session." -#. "where"-operator -#: ../libqalculate/Calculator.cc:1544 ../libqalculate/Calculator.cc:3298 -#: ../libqalculate/Calculator.cc:3300 ../libqalculate/Calculator.cc:3319 -#: ../libqalculate/Calculator.cc:3321 -msgid "where" -msgstr "" - -#: ../libqalculate/Calculator.cc:2027 ../libqalculate/Calculator.cc:2028 -#: ../libqalculate/Calculator.cc:11818 ../libqalculate/Calculator.cc:11955 -#: ../libqalculate/Calculator.cc:12013 +#: ../libqalculate/Calculator.cc:1695 ../libqalculate/Calculator.cc:1696 +#: ../libqalculate/Calculator.cc:1700 +#: ../libqalculate/Calculator-definitions.cc:3285 +#: ../libqalculate/Calculator-definitions.cc:3455 +#: ../libqalculate/Calculator-definitions.cc:3513 msgid "Currency" msgstr "Devise" -#: ../libqalculate/Calculator.cc:2563 ../libqalculate/Calculator.cc:2688 -msgid "Stack is empty. Filling remaining function arguments with zeroes." -msgstr "" - -#: ../libqalculate/Calculator.cc:3180 -msgid "calculating..." -msgstr "calculs en cours..." - -#: ../libqalculate/Calculator.cc:3502 -#, c-format -msgid "Unhandled \"where\" expression: %s" -msgstr "" - -#: ../libqalculate/Calculator.cc:5259 +#: ../libqalculate/Calculator.cc:2635 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name of \"%s\", or " @@ -2641,7 +2658,7 @@ "\"%s\" n'est plus autorisé dans les noms. Changez s'il vous plaît le nom de " "\"%s\", ou la variable sera perdue." -#: ../libqalculate/Calculator.cc:5277 +#: ../libqalculate/Calculator.cc:2653 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name \"%s\", or " @@ -2650,7 +2667,7 @@ "\"%s\" n'est plus autorisé dans les noms. Changez s'il vous plaît le nom \"%s" "\", ou la fonction sera perdue." -#: ../libqalculate/Calculator.cc:5294 +#: ../libqalculate/Calculator.cc:2670 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name \"%s\", or " @@ -2659,32 +2676,84 @@ "\"%s\" n'est plus autorisé dans les noms. Changez s'il vous plaît le nom \"%s" "\", ou l'unité sera perdue." -#: ../libqalculate/Calculator.cc:6883 ../libqalculate/Calculator.cc:6927 -#: ../libqalculate/Calculator.cc:6930 ../libqalculate/Calculator.cc:8101 -#: ../libqalculate/Calculator.cc:8110 ../libqalculate/Calculator.cc:8165 -#: ../libqalculate/Calculator.cc:8227 ../libqalculate/Calculator.cc:8248 -#: ../libqalculate/Calculator.cc:8249 +#: ../libqalculate/Calculator.cc:2877 +#, c-format +msgid "Name \"%s\" is in use. Replacing with \"%s\"." +msgstr "Le nom \"%s\" est utilisé. Remplacement par \"%s\"." + +#: ../libqalculate/Calculator-definitions.cc:763 ../libqalculate/DataSet.cc:540 +#, c-format +msgid "File not identified as Qalculate! definitions file: %s." +msgstr "Fichier non identifié comme fichier de définitions Qalculate! : %s." + +#: ../libqalculate/Calculator-definitions.cc:2870 +#: ../libqalculate/DataSet.cc:363 +msgid "Object" +msgstr "Objet" + +#: ../libqalculate/Calculator-definitions.cc:2879 +#: ../libqalculate/DataSet.cc:364 +msgid "Property" +msgstr "Propriété" + +#: ../libqalculate/Calculator-definitions.cc:3178 +msgid "column" +msgstr "colonne" + +#: ../libqalculate/Calculator-definitions.cc:3181 +msgid "Column " +msgstr "Colonne" + +#: ../libqalculate/Calculator-definitions.cc:3632 +#: ../libqalculate/Calculator-definitions.cc:3633 +#: ../libqalculate/Calculator-definitions.cc:3637 +#: ../libqalculate/Calculator-definitions.cc:3640 +#: ../libqalculate/Calculator-definitions.cc:3672 +#: ../libqalculate/Calculator-definitions.cc:3673 +#: ../libqalculate/Calculator-definitions.cc:3676 +#: ../libqalculate/Calculator-definitions.cc:3695 +#: ../libqalculate/Calculator-definitions.cc:3696 +#: ../libqalculate/Calculator-definitions.cc:3699 +#: ../libqalculate/Calculator-definitions.cc:3719 +#: ../libqalculate/Calculator-definitions.cc:3720 +#: ../libqalculate/Calculator-definitions.cc:3723 +#, c-format +msgid "Failed to download exchange rates from %s: %s." +msgstr "Échec du téléchargement des taux d'échange sur %s: %s." + +#. ignore operators +#: ../libqalculate/Calculator-parse.cc:1668 +#: ../libqalculate/Calculator-parse.cc:1721 +#: ../libqalculate/Calculator-parse.cc:1725 +#: ../libqalculate/Calculator-parse.cc:2926 +#: ../libqalculate/Calculator-parse.cc:2935 +#: ../libqalculate/Calculator-parse.cc:2990 +#: ../libqalculate/Calculator-parse.cc:3055 +#: ../libqalculate/Calculator-parse.cc:3077 +#: ../libqalculate/Calculator-parse.cc:3078 #, c-format msgid "Misplaced operator(s) \"%s\" ignored" msgstr "Opérateur(s) mal placé(s), \"%s\" ignoré" -#: ../libqalculate/Calculator.cc:6924 ../libqalculate/Calculator.cc:8250 +#. ignore operators +#: ../libqalculate/Calculator-parse.cc:1717 +#: ../libqalculate/Calculator-parse.cc:3079 #, c-format msgid "Misplaced '%c' ignored" msgstr "L'élément mal placé '%c' ignoré" -#: ../libqalculate/Calculator.cc:6962 ../libqalculate/Function.cc:1489 -#: ../libqalculate/Function.cc:1520 +#: ../libqalculate/Calculator-parse.cc:1759 ../libqalculate/Function.cc:1519 +#: ../libqalculate/Function.cc:1550 #, c-format msgid "Internal id %s does not exist." msgstr "L'identificateur interne %s n'existe pas." -#: ../libqalculate/Calculator.cc:6980 +#: ../libqalculate/Calculator-parse.cc:1779 #, c-format msgid "\"%s\" is not a valid variable/function/unit." msgstr "\"%s\" n'est pas une variable/fonction/unité valide." -#: ../libqalculate/Calculator.cc:6995 +#: ../libqalculate/Calculator-parse.cc:1794 #, c-format msgid "" "Trailing characters \"%s\" (not a valid variable/function/unit) in number " @@ -2693,90 +2762,55 @@ "Les caractères de fin \"%s\" (variable/fonction/unité non valide) dans le " "nombre \"%s\" ont été ignorés." -#: ../libqalculate/Calculator.cc:7261 +#: ../libqalculate/Calculator-parse.cc:2072 msgid "RPN syntax error. Values left at the end of the RPN expression." msgstr "" "Erreur de syntaxe NPI. Des valeurs subsistent à la fin de l'expression NPI." -#: ../libqalculate/Calculator.cc:7264 ../libqalculate/Calculator.cc:7355 +#: ../libqalculate/Calculator-parse.cc:2075 +#: ../libqalculate/Calculator-parse.cc:2166 msgid "Unused stack values." msgstr "Valeurs de pile inutilisées." -#: ../libqalculate/Calculator.cc:7397 ../libqalculate/Calculator.cc:7605 +#: ../libqalculate/Calculator-parse.cc:2208 +#: ../libqalculate/Calculator-parse.cc:2416 #, fuzzy, c-format msgid "RPN syntax error. Operator '%c' not supported." msgstr "Erreur de syntaxe NPI. La pile est vide." -#: ../libqalculate/Calculator.cc:7443 +#: ../libqalculate/Calculator-parse.cc:2254 msgid "RPN syntax error. Stack is empty." msgstr "Erreur de syntaxe NPI. La pile est vide." -#: ../libqalculate/Calculator.cc:7464 +#: ../libqalculate/Calculator-parse.cc:2275 msgid "RPN syntax error. Operator ignored as there where only one stack value." msgstr "" "Erreur de syntaxe NPI. L'opérateur a été ignoré comme si il n'y avait qu'une " "seule valeur de pile." -#: ../libqalculate/Calculator.cc:8525 -#, c-format -msgid "Name \"%s\" is in use. Replacing with \"%s\"." -msgstr "Le nom \"%s\" est utilisé. Remplacement par \"%s\"." - -#: ../libqalculate/Calculator.cc:9212 ../libqalculate/DataSet.cc:539 -#, c-format -msgid "File not identified as Qalculate! definitions file: %s." -msgstr "Fichier non identifié comme fichier de définitions Qalculate! : %s." - -#: ../libqalculate/Calculator.cc:11319 ../libqalculate/DataSet.cc:362 -msgid "Object" -msgstr "Objet" - -#: ../libqalculate/Calculator.cc:11328 ../libqalculate/DataSet.cc:363 -msgid "Property" -msgstr "Propriété" - -#: ../libqalculate/Calculator.cc:11627 -msgid "column" -msgstr "colonne" - -#: ../libqalculate/Calculator.cc:11630 -msgid "Column " -msgstr "Colonne" - -#: ../libqalculate/Calculator.cc:11706 ../libqalculate/Calculator.cc:11753 -msgid "timed out" -msgstr "délai expiré" - -#: ../libqalculate/Calculator.cc:12125 ../libqalculate/Calculator.cc:12126 -#: ../libqalculate/Calculator.cc:12130 ../libqalculate/Calculator.cc:12133 -#: ../libqalculate/Calculator.cc:12165 ../libqalculate/Calculator.cc:12166 -#: ../libqalculate/Calculator.cc:12169 ../libqalculate/Calculator.cc:12188 -#: ../libqalculate/Calculator.cc:12189 ../libqalculate/Calculator.cc:12192 -#, c-format -msgid "Failed to download exchange rates from %s: %s." -msgstr "Échec du téléchargement des taux d'échange sur %s: %s." - -#: ../libqalculate/Calculator.cc:12286 ../libqalculate/Calculator.cc:12316 -#: ../libqalculate/Calculator.cc:12346 ../libqalculate/Calculator.cc:12685 +#: ../libqalculate/Calculator-plot.cc:101 +#: ../libqalculate/Calculator-plot.cc:131 +#: ../libqalculate/Calculator-plot.cc:161 +#: ../libqalculate/Calculator-plot.cc:498 msgid "It took too long to generate the plot data." msgstr "" -#: ../libqalculate/Calculator.cc:12380 +#: ../libqalculate/Calculator-plot.cc:193 msgid "No extension in file name. Saving as PNG image." msgstr "" "Pas d'extension dans le nom de fichier. Enregistrement comme image PNG." -#: ../libqalculate/Calculator.cc:12399 +#: ../libqalculate/Calculator-plot.cc:212 msgid "Unknown extension in file name. Saving as PNG image." msgstr "" "Extension inconnu dans le nom de fichier. Enregistrement comme fichier PNG." -#: ../libqalculate/Calculator.cc:12616 +#: ../libqalculate/Calculator-plot.cc:429 #, c-format msgid "Could not create temporary file %s" msgstr "Impossible de créer le fichier temporaire %s" -#: ../libqalculate/Calculator.cc:12732 +#: ../libqalculate/Calculator-plot.cc:545 msgid "" "Failed to invoke gnuplot. Make sure that you have gnuplot installed in your " "path." @@ -2784,39 +2818,39 @@ "Impossible d'appeler gnuplot. Assurez vous que gnuplot est installé dans " "votre path." -#: ../libqalculate/DataSet.cc:388 +#: ../libqalculate/DataSet.cc:389 #, c-format msgid "Object %s not available in data set." msgstr "L'objet %s n'est pas disponible dans l'ensemble de données." -#: ../libqalculate/DataSet.cc:398 +#: ../libqalculate/DataSet.cc:399 #, c-format msgid "Property %s not available in data set." msgstr "La propriété %s n'est pas disponible dans l'ensemble de données." -#: ../libqalculate/DataSet.cc:403 +#: ../libqalculate/DataSet.cc:404 #, c-format msgid "Property %s not defined for object %s." msgstr "La propriété %s n'est pas définie pour l'objet %s." -#: ../libqalculate/DataSet.cc:516 ../libqalculate/DataSet.cc:524 +#: ../libqalculate/DataSet.cc:517 ../libqalculate/DataSet.cc:525 #, c-format msgid "Unable to load data objects in %s." msgstr "Impossible de charger les objets de données dans %s." -#: ../libqalculate/DataSet.cc:1042 +#: ../libqalculate/DataSet.cc:1043 msgid "data property" msgstr "propriété des données" -#: ../libqalculate/DataSet.cc:1044 +#: ../libqalculate/DataSet.cc:1045 msgid "name of a data property" msgstr "nom d'une propriété de données" -#: ../libqalculate/DataSet.cc:1052 ../libqalculate/DataSet.cc:1068 +#: ../libqalculate/DataSet.cc:1053 ../libqalculate/DataSet.cc:1069 msgid "no properties available" msgstr "aucune propriété n'est disponible" -#: ../libqalculate/DataSet.cc:1102 +#: ../libqalculate/DataSet.cc:1103 #, c-format msgid "" "Data set \"%s\" has no object key that supports the provided argument type." @@ -2824,24 +2858,33 @@ "L'ensemble de données \"%s\" n'a pas de clé d'objet qui supporte le type " "d'argument entré." -#: ../libqalculate/DataSet.cc:1107 +#: ../libqalculate/DataSet.cc:1108 msgid "data object" msgstr "objet de données" -#: ../libqalculate/DataSet.cc:1110 +#: ../libqalculate/DataSet.cc:1111 msgid "an object from" msgstr "un objet de" -#: ../libqalculate/DataSet.cc:1137 +#: ../libqalculate/DataSet.cc:1138 msgid "use" msgstr "utilisation" -#: ../libqalculate/MathStructure.cc:265 +#: ../libqalculate/MathStructure-calculate.cc:76 #, fuzzy, c-format msgid "Required assumption: %s." msgstr "Hypothèse non reconnue" -#: ../libqalculate/MathStructure.cc:4031 ../libqalculate/MathStructure.cc:4052 +#: ../libqalculate/MathStructure-calculate.cc:95 +#: ../libqalculate/MathStructure-calculate.cc:117 +#: ../libqalculate/MathStructure-calculate.cc:148 +#: ../libqalculate/MathStructure-integrate.cc:7086 +#, c-format +msgid "To avoid division by zero, the following must be true: %s." +msgstr "Pour éviter la division par zéro, ce qui suit doit être vrai : %s" + +#: ../libqalculate/MathStructure-calculate.cc:1653 +#: ../libqalculate/MathStructure-calculate.cc:1675 #, c-format msgid "" "The second matrix must have as many rows (was %s) as the first has columns " @@ -2851,131 +2894,147 @@ "première a de colonnes (valeur actuelle : %s) pour la multiplication " "matricielle." -#: ../libqalculate/MathStructure.cc:8936 ../libqalculate/MathStructure.cc:8977 -#: ../libqalculate/MathStructure.cc:9010 ../libqalculate/MathStructure.cc:9077 -#: ../libqalculate/MathStructure.cc:9105 ../libqalculate/MathStructure.cc:9124 -#: ../libqalculate/MathStructure.cc:9143 ../libqalculate/MathStructure.cc:9162 -#: ../libqalculate/MathStructure.cc:9270 ../libqalculate/MathStructure.cc:16270 -#: ../libqalculate/MathStructure.cc:16661 +#: ../libqalculate/MathStructure-calculate.cc:6072 +#: ../libqalculate/MathStructure-calculate.cc:6113 +#: ../libqalculate/MathStructure-calculate.cc:6146 +#: ../libqalculate/MathStructure-calculate.cc:6213 +#: ../libqalculate/MathStructure-calculate.cc:6241 +#: ../libqalculate/MathStructure-calculate.cc:6260 +#: ../libqalculate/MathStructure-calculate.cc:6279 +#: ../libqalculate/MathStructure-calculate.cc:6298 +#: ../libqalculate/MathStructure-calculate.cc:6406 +#: ../libqalculate/MathStructure-factor.cc:413 +#: ../libqalculate/MathStructure-factor.cc:1304 msgid "This is a bug. Please report it." msgstr "Ceci est un bogue. Merci de le reporter." -#: ../libqalculate/MathStructure.cc:9353 ../libqalculate/Function.cc:527 +#: ../libqalculate/MathStructure-calculate.cc:6495 +#: ../libqalculate/Function.cc:557 #, fuzzy msgid "No unknown variable/symbol was found." msgstr "une variable / un symbole inconnu" -#: ../libqalculate/MathStructure.cc:11752 -#: ../libqalculate/MathStructure.cc:11757 -#, c-format -msgid "Limit for %s determined graphically." +#: ../libqalculate/MathStructure-convert.cc:262 +msgid "" +"Calculations involving conversion of units without proportional linear " +"relationship (e.g. with multiple temperature units), might give unexpected " +"results and is not recommended." msgstr "" -#: ../libqalculate/MathStructure.cc:12582 +#: ../libqalculate/MathStructure-eval.cc:754 msgid "Interval potentially calculated wide." msgstr "" -#: ../libqalculate/MathStructure.cc:13500 +#: ../libqalculate/MathStructure-eval.cc:2024 msgid "" "Calculation of uncertainty propagation partially failed (using interval " "arithmetic instead when necessary)." msgstr "" -#: ../libqalculate/MathStructure.cc:13638 +#: ../libqalculate/MathStructure-eval.cc:2170 msgid "" "Calculation of uncertainty propagation failed (using interval arithmetic " "instead)." msgstr "" -#: ../libqalculate/MathStructure.cc:18517 +#: ../libqalculate/MathStructure-factor.cc:3160 msgid "" "Because of time constraints only a limited number of combinations of terms " "were tried during factorization. Repeat factorization to try other random " "combinations." msgstr "" -#: ../libqalculate/MathStructure.cc:21769 -msgid "undefined" -msgstr "indéfini" +#: ../libqalculate/MathStructure-integrate.cc:7668 +#: ../libqalculate/MathStructure-integrate.cc:7743 +#, fuzzy +msgid "Unable to integrate the expression exact." +msgstr "Impossible d'isoler %s." + +#: ../libqalculate/MathStructure-integrate.cc:7707 +msgid "Definite integral was approximated." +msgstr "" + +#: ../libqalculate/MathStructure-isolatex.cc:999 +#: ../libqalculate/MathStructure-isolatex.cc:1176 +#: ../libqalculate/MathStructure-isolatex.cc:1815 +#: ../libqalculate/MathStructure-isolatex.cc:2335 +#: ../libqalculate/MathStructure-isolatex.cc:2401 +#: ../libqalculate/MathStructure-isolatex.cc:2451 +#: ../libqalculate/MathStructure-isolatex.cc:2472 +#: ../libqalculate/MathStructure-isolatex.cc:2530 +#: ../libqalculate/MathStructure-isolatex.cc:2656 +#: ../libqalculate/MathStructure-isolatex.cc:2801 +#, c-format +msgid "Interval arithmetic was disabled during calculation of %s." +msgstr "" + +#: ../libqalculate/MathStructure-isolatex.cc:2800 +#, c-format +msgid "Not all complex roots were calculated for %s." +msgstr "" + +#: ../libqalculate/MathStructure-isolatex.cc:4394 +#, c-format +msgid "Only one or two of the roots where calculated for %s." +msgstr "" + +#: ../libqalculate/MathStructure-limit.cc:967 +#: ../libqalculate/MathStructure-limit.cc:972 +#, c-format +msgid "Limit for %s determined graphically." +msgstr "" -#: ../libqalculate/MathStructure.cc:21810 +#: ../libqalculate/MathStructure-matrixvector.cc:62 #, c-format msgid "Unsolvable comparison at element %s when trying to rank vector." msgstr "" "Comparaison impossible à l'élément %s en essayant de classer le vecteur." -#: ../libqalculate/MathStructure.cc:21860 +#: ../libqalculate/MathStructure-matrixvector.cc:112 #, c-format msgid "Unsolvable comparison at element %s when trying to sort vector." msgstr "Comparaison impossible à l'élément %s en essayant de trier le vecteur." -#: ../libqalculate/MathStructure.cc:22285 +#: ../libqalculate/MathStructure-matrixvector.cc:537 msgid "The determinant can only be calculated for square matrices." msgstr "Le déterminant ne peut être calculé que pour les matrices carrées." -#: ../libqalculate/MathStructure.cc:22348 +#: ../libqalculate/MathStructure-matrixvector.cc:600 msgid "The permanent can only be calculated for square matrices." msgstr "Le permanent ne peut être calculé que pour les matrice carrées." -#: ../libqalculate/MathStructure.cc:22435 +#: ../libqalculate/MathStructure-matrixvector.cc:687 msgid "Inverse of singular matrix." msgstr "Inverse d'une matrice singulière." -#: ../libqalculate/MathStructure.cc:22789 -msgid "" -"Calculations involving conversion of units without proportional linear " -"relationship (e.g. with multiple temperature units), might give unexpected " -"results and is not recommended." -msgstr "" - -#: ../libqalculate/MathStructure.cc:24092 -#: ../libqalculate/MathStructure.cc:24135 +#: ../libqalculate/MathStructure-matrixvector.cc:817 +#: ../libqalculate/MathStructure-matrixvector.cc:860 msgid "Too many data points" msgstr "" -#: ../libqalculate/MathStructure.cc:24099 +#: ../libqalculate/MathStructure-matrixvector.cc:824 msgid "" "The selected min and max do not result in a positive, finite number of data " "points" msgstr "" -#: ../libqalculate/MathStructure.cc:24132 +#: ../libqalculate/MathStructure-matrixvector.cc:857 msgid "" "The selected min, max and step size do not result in a positive, finite " "number of data points" msgstr "" -#: ../libqalculate/MathStructure.cc:32190 -#: ../libqalculate/MathStructure.cc:32368 -#: ../libqalculate/MathStructure.cc:33005 -#: ../libqalculate/MathStructure.cc:33525 -#: ../libqalculate/MathStructure.cc:33591 -#: ../libqalculate/MathStructure.cc:33641 -#: ../libqalculate/MathStructure.cc:33662 -#: ../libqalculate/MathStructure.cc:33720 -#: ../libqalculate/MathStructure.cc:33846 -#: ../libqalculate/MathStructure.cc:33990 -#, c-format -msgid "Interval arithmetic was disabled during calculation of %s." -msgstr "" - -#: ../libqalculate/MathStructure.cc:33989 -#, c-format -msgid "Not all complex roots were calculated for %s." -msgstr "" - -#: ../libqalculate/MathStructure.cc:35479 -#, c-format -msgid "Only one or two of the roots where calculated for %s." -msgstr "" +#: ../libqalculate/MathStructure-print.cc:3364 +msgid "undefined" +msgstr "indéfini" -#: ../libqalculate/Function.cc:171 +#: ../libqalculate/Function.cc:185 #, c-format msgid "%s() requires that %s" msgstr "%s() exige que %s" -#: ../libqalculate/Function.cc:326 ../libqalculate/Function.cc:385 -#: ../libqalculate/Function.cc:445 +#: ../libqalculate/Function.cc:351 ../libqalculate/Function.cc:413 +#: ../libqalculate/Function.cc:474 #, c-format msgid "" "Additional arguments for function %s() was ignored. Function can only use %s " @@ -2984,166 +3043,166 @@ "Les arguments supplémentaires de la fonction %s() ont été ignorés. La " "fonction ne peut utiliser que %s argument(s)." -#: ../libqalculate/Function.cc:466 +#: ../libqalculate/Function.cc:495 #, c-format msgid "You need at least %s argument(s) (%s) in function %s()." msgstr "" "Vous devez utiliser au moins %s argument(s) (%s) dans la fonction %s()." -#: ../libqalculate/Function.cc:468 +#: ../libqalculate/Function.cc:497 #, c-format msgid "You need at least %s argument(s) in function %s()." msgstr "Vous devez utiliser au moins %s argument(s) dans la fonction %s()." -#: ../libqalculate/Function.cc:1321 +#: ../libqalculate/Function.cc:1351 msgid "a free value" msgstr "une valeur libre" -#: ../libqalculate/Function.cc:1326 +#: ../libqalculate/Function.cc:1356 msgid "that is nonzero" msgstr "ceci est non nul" -#: ../libqalculate/Function.cc:1334 +#: ../libqalculate/Function.cc:1364 msgid "that is rational (polynomial)" msgstr "ceci est rationnel (polynomial)" -#: ../libqalculate/Function.cc:1342 +#: ../libqalculate/Function.cc:1372 msgid "that fulfills the condition:" msgstr "ceci remplit la condition :" -#: ../libqalculate/Function.cc:1345 +#: ../libqalculate/Function.cc:1375 msgid "Argument" msgstr "" -#: ../libqalculate/Function.cc:1409 +#: ../libqalculate/Function.cc:1439 #, c-format msgid "Argument %s in %s() must be %s." msgstr "L'argument %s de %s() doit être %s." -#: ../libqalculate/Function.cc:1411 +#: ../libqalculate/Function.cc:1441 #, c-format msgid "Argument %s, %s, in %s() must be %s." msgstr "L'argument %s, %s, de %s() doit être %s." -#: ../libqalculate/Function.cc:1749 +#: ../libqalculate/Function.cc:1783 msgid "a rational number" msgstr "un nombre rationnel" -#: ../libqalculate/Function.cc:1751 +#: ../libqalculate/Function.cc:1785 msgid "a number" msgstr "un nombre" -#: ../libqalculate/Function.cc:1753 +#: ../libqalculate/Function.cc:1787 msgid "a real number" msgstr "un nombre réel" -#: ../libqalculate/Function.cc:1758 ../libqalculate/Function.cc:1911 -#: ../libqalculate/Function.cc:1916 +#: ../libqalculate/Function.cc:1792 ../libqalculate/Function.cc:1945 +#: ../libqalculate/Function.cc:1950 msgid ">=" msgstr "" -#: ../libqalculate/Function.cc:1760 +#: ../libqalculate/Function.cc:1794 msgid ">" msgstr "" -#: ../libqalculate/Function.cc:1772 ../libqalculate/Function.cc:1933 -#: ../libqalculate/Function.cc:1940 +#: ../libqalculate/Function.cc:1806 ../libqalculate/Function.cc:1967 +#: ../libqalculate/Function.cc:1974 msgid "<=" msgstr "" -#: ../libqalculate/Function.cc:1774 +#: ../libqalculate/Function.cc:1808 msgid "<" msgstr "" -#: ../libqalculate/Function.cc:1908 +#: ../libqalculate/Function.cc:1942 msgid "an integer" msgstr "un entier" -#: ../libqalculate/Function.cc:1965 +#: ../libqalculate/Function.cc:1999 msgid "symbol" msgstr "symbole" -#: ../libqalculate/Function.cc:1966 +#: ../libqalculate/Function.cc:2000 msgid "an unknown variable/symbol" msgstr "une variable / un symbole inconnu" -#: ../libqalculate/Function.cc:1979 +#: ../libqalculate/Function.cc:2013 msgid "text" msgstr "texte" -#: ../libqalculate/Function.cc:1980 +#: ../libqalculate/Function.cc:2014 msgid "a text string" msgstr "une chaîne de caractères" -#: ../libqalculate/Function.cc:2002 +#: ../libqalculate/Function.cc:2036 msgid "date" msgstr "" -#: ../libqalculate/Function.cc:2003 +#: ../libqalculate/Function.cc:2037 msgid "a date" msgstr "une date" -#: ../libqalculate/Function.cc:2052 +#: ../libqalculate/Function.cc:2086 msgid "a vector with " msgstr "en vecteur avec" -#: ../libqalculate/Function.cc:2064 +#: ../libqalculate/Function.cc:2098 msgid "a vector" msgstr "un vecteur" -#: ../libqalculate/Function.cc:2113 +#: ../libqalculate/Function.cc:2147 msgid "a square matrix" msgstr "une matrice carrée" -#: ../libqalculate/Function.cc:2115 +#: ../libqalculate/Function.cc:2149 msgid "a matrix" msgstr "une matrice" -#: ../libqalculate/Function.cc:2130 +#: ../libqalculate/Function.cc:2164 msgid "object" msgstr "objet" -#: ../libqalculate/Function.cc:2131 +#: ../libqalculate/Function.cc:2165 msgid "a valid function, unit or variable name" msgstr "une fonction, une unité ou un nom de variable valide" -#: ../libqalculate/Function.cc:2145 +#: ../libqalculate/Function.cc:2179 msgid "a valid function name" msgstr "un nom de fonction valide" -#: ../libqalculate/Function.cc:2158 +#: ../libqalculate/Function.cc:2192 msgid "unit" msgstr "unité" -#: ../libqalculate/Function.cc:2159 +#: ../libqalculate/Function.cc:2193 msgid "a valid unit name" msgstr "un nom d'unité valide" -#: ../libqalculate/Function.cc:2173 +#: ../libqalculate/Function.cc:2207 msgid "a valid variable name" msgstr "un nom de variable valide" -#: ../libqalculate/Function.cc:2186 +#: ../libqalculate/Function.cc:2220 msgid "file" msgstr "fichier" -#: ../libqalculate/Function.cc:2187 +#: ../libqalculate/Function.cc:2221 msgid "a valid file name" msgstr "un nom de fichier valide" -#: ../libqalculate/Function.cc:2200 +#: ../libqalculate/Function.cc:2234 msgid "boolean" msgstr "booléen" -#: ../libqalculate/Function.cc:2201 +#: ../libqalculate/Function.cc:2235 msgid "a boolean (0 or 1)" msgstr "un booléen (0 ou 1)" -#: ../libqalculate/Function.cc:2212 +#: ../libqalculate/Function.cc:2246 msgid "an angle or a number (using the default angle unit)" msgstr "un angle ou un nombre (en utilisant l'unité d'angle par défaut)" -#: ../libqalculate/Number.cc:254 ../libqalculate/Number.cc:8251 +#: ../libqalculate/Number.cc:263 ../libqalculate/Number.cc:10175 msgid "" "Cannot display numbers greater than 9999 or less than -9999 as roman " "numerals." @@ -3151,18 +3210,20 @@ "Impossible 'afficher des nombres plus grands que 9999 ou plus petits que " "-9999 en chiffres romains." -#: ../libqalculate/Number.cc:351 +#: ../libqalculate/Number.cc:363 #, fuzzy, c-format msgid "Character '%s' was ignored in the number \"%s\" in bijective base-26." msgstr "Le caractère '%s' a été ignoré dans le nombre \"%s\" avec la base %s." -#: ../libqalculate/Number.cc:433 ../libqalculate/Number.cc:474 -#: ../libqalculate/Number.cc:501 +#. digit value is higher than allowed by the base: show a warning, but use anyway +#. digit value is higher than allowed by base: show a warning, but use anyway +#: ../libqalculate/Number.cc:464 ../libqalculate/Number.cc:514 +#: ../libqalculate/Number.cc:544 #, c-format msgid "Digit '%s' is too high for number base." msgstr "" -#: ../libqalculate/Number.cc:551 +#: ../libqalculate/Number.cc:601 msgid "" "Assuming the unusual practice of letting a last capital I mean 2 in a roman " "numeral." @@ -3170,18 +3231,18 @@ "Hypothèse qu'on applique la pratique inhabituelle de laisser I comme " "capitale finale signifie 2 en chiffres romains." -#: ../libqalculate/Number.cc:635 ../libqalculate/Number.cc:662 -#: ../libqalculate/Number.cc:667 +#: ../libqalculate/Number.cc:685 ../libqalculate/Number.cc:712 +#: ../libqalculate/Number.cc:717 #, c-format msgid "Error in roman numerals: %s." msgstr "Erreur dans les chiffres romains : %s." -#: ../libqalculate/Number.cc:672 +#: ../libqalculate/Number.cc:722 #, c-format msgid "Unknown roman numeral: %c." msgstr "Chiffre romain inconnu : %c." -#: ../libqalculate/Number.cc:730 +#: ../libqalculate/Number.cc:780 #, c-format msgid "" "Errors in roman numerals: \"%s\". Interpreted as %s, which should be written " @@ -3190,82 +3251,83 @@ "Erreurs dans les chiffres romains : \"%s\". Interprété comme %s, qui devrait " "être écrit %s." -#: ../libqalculate/Number.cc:818 +#: ../libqalculate/Number.cc:881 #, fuzzy msgid "Too large exponent." msgstr "afficher les exposants négatifs" -#: ../libqalculate/Number.cc:850 +#. only allow decimals after last ":" +#: ../libqalculate/Number.cc:917 msgid "':' in decimal number ignored (decimal point detected)." msgstr "':' dans les nombres décimaux ignoré (point décimal détecté)" -#: ../libqalculate/Number.cc:1950 ../libqalculate/Number.cc:2072 +#. test calculated floating point value and show mpfr errors (show as errors if error_level > 1, show as warnings if error_level = 1, do not generate message if error_level is zero) +#: ../libqalculate/Number.cc:2035 ../libqalculate/Number.cc:2160 msgid "Floating point underflow" msgstr "" -#: ../libqalculate/Number.cc:1951 ../libqalculate/Number.cc:2073 +#: ../libqalculate/Number.cc:2036 ../libqalculate/Number.cc:2161 msgid "Floating point overflow" msgstr "" -#: ../libqalculate/Number.cc:1952 ../libqalculate/Number.cc:2074 +#: ../libqalculate/Number.cc:2037 ../libqalculate/Number.cc:2162 msgid "Floating point division by zero exception" msgstr "" -#: ../libqalculate/Number.cc:1953 ../libqalculate/Number.cc:2077 +#: ../libqalculate/Number.cc:2038 ../libqalculate/Number.cc:2165 msgid "Floating point not a number exception" msgstr "" -#: ../libqalculate/Number.cc:1954 ../libqalculate/Number.cc:2075 +#: ../libqalculate/Number.cc:2039 ../libqalculate/Number.cc:2163 msgid "Floating point range exception" msgstr "" -#: ../libqalculate/Number.cc:3528 +#: ../libqalculate/Number.cc:3637 msgid "Division by zero." msgstr "Division par zéro." #. 0^0 -#: ../libqalculate/Number.cc:3534 +#: ../libqalculate/Number.cc:3643 msgid "0^0 might be considered undefined" msgstr "0^0 sera considéré comme indéfini" -#: ../libqalculate/Number.cc:3541 +#: ../libqalculate/Number.cc:3650 msgid "The result of 0^i is possibly undefined" msgstr "" -#: ../libqalculate/Number.cc:3590 ../libqalculate/Number.cc:5389 -#: ../libqalculate/Number.cc:5500 ../libqalculate/Number.cc:5824 -#: ../libqalculate/Number.cc:5832 ../libqalculate/Number.cc:5865 -#: ../libqalculate/Number.cc:5962 ../libqalculate/Number.cc:6111 -#: ../libqalculate/Number.cc:6223 +#: ../libqalculate/Number.cc:3699 ../libqalculate/Number.cc:6103 +#: ../libqalculate/Number.cc:6214 ../libqalculate/Number.cc:6538 +#: ../libqalculate/Number.cc:6546 ../libqalculate/Number.cc:6579 +#: ../libqalculate/Number.cc:6676 ../libqalculate/Number.cc:6825 +#: ../libqalculate/Number.cc:6937 msgid "Interval calculated wide." msgstr "" -#: ../libqalculate/Number.cc:4942 -msgid "Cannot handle an argument (s) that large for Riemann Zeta." -msgstr "" -"Impossible de supporter la fonction Zeta de Riemann pour un argument aussi " -"grand." - -#: ../libqalculate/Number.cc:5017 ../libqalculate/Number.cc:5119 -#: ../libqalculate/Number.cc:5150 ../libqalculate/Number.cc:5181 -#: ../libqalculate/Number.cc:6568 +#: ../libqalculate/Number.cc:5126 ../libqalculate/Number.cc:5352 +#: ../libqalculate/Number.cc:5439 ../libqalculate/Number.cc:5723 +#: ../libqalculate/Number.cc:5809 ../libqalculate/Number.cc:5895 +#: ../libqalculate/Number.cc:7142 ../libqalculate/Number.cc:7160 +#: ../libqalculate/Number.cc:7179 ../libqalculate/Number.cc:7515 +#: ../libqalculate/Number.cc:7562 ../libqalculate/Number.cc:7707 +#: ../libqalculate/Number.cc:8040 ../libqalculate/Number.cc:8196 +#: ../libqalculate/Number.cc:8628 ../libqalculate/Number.cc:9023 #, c-format msgid "%s() lacks proper support interval arithmetic." msgstr "" -#: ../libqalculate/Number.cc:7816 +#: ../libqalculate/Number.cc:9706 #, fuzzy msgid "Unsupported base" msgstr "base de saisie" -#: ../libqalculate/Number.cc:8248 +#: ../libqalculate/Number.cc:10172 #, fuzzy msgid "Can only display rational numbers as roman numerals." msgstr "" "Impossible 'afficher des nombres plus grands que 9999 ou plus petits que " "-9999 en chiffres romains." -#: ../libqalculate/Number.cc:8693 ../libqalculate/Number.cc:8701 +#: ../libqalculate/Number.cc:10659 ../libqalculate/Number.cc:10667 msgid "infinity" msgstr "infini" @@ -3654,11 +3716,11 @@ msgid "leap month" msgstr "" -#: ../libqalculate/Unit.cc:1096 +#: ../libqalculate/Unit.cc:1100 msgid "Error(s) in unitexpression." msgstr "Erreur(s) dans l'expression d'unités." -#: ../libqalculate/Variable.cc:501 +#: ../libqalculate/Variable.cc:502 #, c-format msgid "Recursive variable: %s = %s" msgstr "" @@ -3687,6 +3749,11 @@ msgid "Off" msgstr "Arrêt" +#~ msgid "Cannot handle an argument (s) that large for Riemann Zeta." +#~ msgstr "" +#~ "Impossible de supporter la fonction Zeta de Riemann pour un argument " +#~ "aussi grand." + #, fuzzy #~ msgid "No was unknown variable/symbol found." #~ msgstr "une variable / un symbole inconnu" diff -Nru libqalculate-3.6.0/po/libqalculate.pot libqalculate-3.7.0/po/libqalculate.pot --- libqalculate-3.6.0/po/libqalculate.pot 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/po/libqalculate.pot 2020-01-21 22:54:40.000000000 +0000 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-25 10:28+0100\n" +"POT-Creation-Date: 2020-01-12 11:24+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,48 +17,48 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../src/defs2doc.cc:301 ../src/qalc.cc:3298 ../libqalculate/Function.cc:207 +#: ../src/defs2doc.cc:301 ../src/qalc.cc:3299 ../libqalculate/Function.cc:222 msgid "argument" msgstr "" -#: ../src/defs2doc.cc:324 ../src/qalc.cc:3321 +#: ../src/defs2doc.cc:324 ../src/qalc.cc:3322 #, c-format msgid "" "Retrieves data from the %s data set for a given object and property. If " "\"info\" is typed as property, all properties of the object will be listed." msgstr "" -#: ../src/defs2doc.cc:331 ../src/qalc.cc:3330 +#: ../src/defs2doc.cc:331 ../src/qalc.cc:3331 msgid "Example:" msgstr "" -#: ../src/defs2doc.cc:339 ../src/qalc.cc:3339 +#: ../src/defs2doc.cc:339 ../src/qalc.cc:3340 msgid "Arguments" msgstr "" #. optional argument, in description -#: ../src/defs2doc.cc:356 ../src/qalc.cc:3356 +#: ../src/defs2doc.cc:356 ../src/qalc.cc:3357 msgid "optional" msgstr "" #. argument default, in description -#: ../src/defs2doc.cc:359 ../src/qalc.cc:3360 +#: ../src/defs2doc.cc:359 ../src/qalc.cc:3361 msgid "default: " msgstr "" -#: ../src/defs2doc.cc:372 ../src/qalc.cc:3371 +#: ../src/defs2doc.cc:372 ../src/qalc.cc:3372 msgid "Requirement" msgstr "" -#: ../src/defs2doc.cc:381 ../src/qalc.cc:3379 +#: ../src/defs2doc.cc:381 ../src/qalc.cc:3380 msgid "Properties" msgstr "" -#: ../src/defs2doc.cc:397 ../src/qalc.cc:3394 +#: ../src/defs2doc.cc:397 ../src/qalc.cc:3395 msgid "key" msgstr "" -#: ../src/defs2doc.cc:431 ../src/qalc.cc:3509 +#: ../src/defs2doc.cc:431 ../src/qalc.cc:3510 msgid "a previous result" msgstr "" @@ -66,91 +66,91 @@ msgid "current precision" msgstr "" -#: ../src/defs2doc.cc:438 ../src/defs2doc.cc:539 ../src/qalc.cc:1456 +#: ../src/defs2doc.cc:438 ../src/defs2doc.cc:539 ../src/qalc.cc:1457 msgid "relative uncertainty" msgstr "" -#: ../src/defs2doc.cc:453 ../src/qalc.cc:1478 ../src/qalc.cc:3515 -#: ../libqalculate/Function.cc:2110 +#: ../src/defs2doc.cc:453 ../src/qalc.cc:1479 ../src/qalc.cc:3516 +#: ../libqalculate/Function.cc:2144 msgid "matrix" msgstr "" -#: ../src/defs2doc.cc:455 ../src/qalc.cc:1480 ../src/qalc.cc:3517 -#: ../libqalculate/Function.cc:2049 +#: ../src/defs2doc.cc:455 ../src/qalc.cc:1481 ../src/qalc.cc:3518 +#: ../libqalculate/Function.cc:2083 msgid "vector" msgstr "" -#: ../src/defs2doc.cc:463 ../src/qalc.cc:249 ../src/qalc.cc:691 -#: ../src/qalc.cc:1497 ../src/qalc.cc:2907 ../src/qalc.cc:3527 -#: ../src/qalc.cc:3646 ../src/qalc.cc:3876 +#: ../src/defs2doc.cc:463 ../src/qalc.cc:250 ../src/qalc.cc:692 +#: ../src/qalc.cc:1498 ../src/qalc.cc:2908 ../src/qalc.cc:3528 +#: ../src/qalc.cc:3647 ../src/qalc.cc:3877 msgid "positive" msgstr "" -#: ../src/defs2doc.cc:464 ../src/qalc.cc:255 ../src/qalc.cc:692 -#: ../src/qalc.cc:1498 ../src/qalc.cc:2908 ../src/qalc.cc:3528 -#: ../src/qalc.cc:3650 ../src/qalc.cc:3880 +#: ../src/defs2doc.cc:464 ../src/qalc.cc:256 ../src/qalc.cc:693 +#: ../src/qalc.cc:1499 ../src/qalc.cc:2909 ../src/qalc.cc:3529 +#: ../src/qalc.cc:3651 ../src/qalc.cc:3881 msgid "non-positive" msgstr "" -#: ../src/defs2doc.cc:465 ../src/qalc.cc:253 ../src/qalc.cc:693 -#: ../src/qalc.cc:1499 ../src/qalc.cc:2909 ../src/qalc.cc:3529 -#: ../src/qalc.cc:3648 ../src/qalc.cc:3878 +#: ../src/defs2doc.cc:465 ../src/qalc.cc:254 ../src/qalc.cc:694 +#: ../src/qalc.cc:1500 ../src/qalc.cc:2910 ../src/qalc.cc:3530 +#: ../src/qalc.cc:3649 ../src/qalc.cc:3879 msgid "negative" msgstr "" -#: ../src/defs2doc.cc:466 ../src/qalc.cc:251 ../src/qalc.cc:694 -#: ../src/qalc.cc:1500 ../src/qalc.cc:2910 ../src/qalc.cc:3530 -#: ../src/qalc.cc:3652 ../src/qalc.cc:3882 +#: ../src/defs2doc.cc:466 ../src/qalc.cc:252 ../src/qalc.cc:695 +#: ../src/qalc.cc:1501 ../src/qalc.cc:2911 ../src/qalc.cc:3531 +#: ../src/qalc.cc:3653 ../src/qalc.cc:3883 msgid "non-negative" msgstr "" -#: ../src/defs2doc.cc:467 ../src/qalc.cc:247 ../src/qalc.cc:695 -#: ../src/qalc.cc:1501 ../src/qalc.cc:2911 ../src/qalc.cc:3531 -#: ../src/qalc.cc:3644 ../src/qalc.cc:3874 +#: ../src/defs2doc.cc:467 ../src/qalc.cc:248 ../src/qalc.cc:696 +#: ../src/qalc.cc:1502 ../src/qalc.cc:2912 ../src/qalc.cc:3532 +#: ../src/qalc.cc:3645 ../src/qalc.cc:3875 msgid "non-zero" msgstr "" -#: ../src/defs2doc.cc:472 ../src/qalc.cc:245 ../src/qalc.cc:700 -#: ../src/qalc.cc:1506 ../src/qalc.cc:2916 ../src/qalc.cc:3536 -#: ../src/qalc.cc:3660 ../src/qalc.cc:3890 ../libqalculate/Function.cc:1905 +#: ../src/defs2doc.cc:472 ../src/qalc.cc:246 ../src/qalc.cc:701 +#: ../src/qalc.cc:1507 ../src/qalc.cc:2917 ../src/qalc.cc:3537 +#: ../src/qalc.cc:3661 ../src/qalc.cc:3891 ../libqalculate/Function.cc:1939 msgid "integer" msgstr "" -#: ../src/defs2doc.cc:473 ../src/qalc.cc:243 ../src/qalc.cc:701 -#: ../src/qalc.cc:1507 ../src/qalc.cc:2917 ../src/qalc.cc:3537 -#: ../src/qalc.cc:3658 ../src/qalc.cc:3888 +#: ../src/defs2doc.cc:473 ../src/qalc.cc:244 ../src/qalc.cc:702 +#: ../src/qalc.cc:1508 ../src/qalc.cc:2918 ../src/qalc.cc:3538 +#: ../src/qalc.cc:3659 ../src/qalc.cc:3889 msgid "rational" msgstr "" -#: ../src/defs2doc.cc:474 ../src/qalc.cc:239 ../src/qalc.cc:702 -#: ../src/qalc.cc:1508 ../src/qalc.cc:2918 ../src/qalc.cc:3538 -#: ../src/qalc.cc:3656 ../src/qalc.cc:3886 +#: ../src/defs2doc.cc:474 ../src/qalc.cc:240 ../src/qalc.cc:703 +#: ../src/qalc.cc:1509 ../src/qalc.cc:2919 ../src/qalc.cc:3539 +#: ../src/qalc.cc:3657 ../src/qalc.cc:3887 msgid "real" msgstr "" -#: ../src/defs2doc.cc:475 ../src/qalc.cc:703 ../src/qalc.cc:1509 -#: ../src/qalc.cc:2919 ../src/qalc.cc:3539 +#: ../src/defs2doc.cc:475 ../src/qalc.cc:704 ../src/qalc.cc:1510 +#: ../src/qalc.cc:2920 ../src/qalc.cc:3540 msgid "complex" msgstr "" -#: ../src/defs2doc.cc:476 ../src/qalc.cc:241 ../src/qalc.cc:704 -#: ../src/qalc.cc:1510 ../src/qalc.cc:2920 ../src/qalc.cc:3540 -#: ../src/qalc.cc:3654 ../src/qalc.cc:3884 ../libqalculate/Function.cc:1744 +#: ../src/defs2doc.cc:476 ../src/qalc.cc:242 ../src/qalc.cc:705 +#: ../src/qalc.cc:1511 ../src/qalc.cc:2921 ../src/qalc.cc:3541 +#: ../src/qalc.cc:3655 ../src/qalc.cc:3885 ../libqalculate/Function.cc:1778 msgid "number" msgstr "" -#: ../src/defs2doc.cc:477 ../src/qalc.cc:705 ../src/qalc.cc:1511 -#: ../src/qalc.cc:2921 ../src/qalc.cc:3541 +#: ../src/defs2doc.cc:477 ../src/qalc.cc:706 ../src/qalc.cc:1512 +#: ../src/qalc.cc:2922 ../src/qalc.cc:3542 msgid "non-matrix" msgstr "" -#: ../src/defs2doc.cc:480 ../src/qalc.cc:233 ../src/qalc.cc:708 -#: ../src/qalc.cc:1514 ../src/qalc.cc:2924 ../src/qalc.cc:3544 -#: ../src/qalc.cc:3642 ../src/qalc.cc:3872 +#: ../src/defs2doc.cc:480 ../src/qalc.cc:234 ../src/qalc.cc:709 +#: ../src/qalc.cc:1515 ../src/qalc.cc:2925 ../src/qalc.cc:3545 +#: ../src/qalc.cc:3643 ../src/qalc.cc:3873 msgid "unknown" msgstr "" -#: ../src/defs2doc.cc:482 ../src/qalc.cc:1516 ../src/qalc.cc:3546 +#: ../src/defs2doc.cc:482 ../src/qalc.cc:1517 ../src/qalc.cc:3547 msgid "default assumptions" msgstr "" @@ -159,47 +159,48 @@ msgstr "" #. qalc command -#: ../src/defs2doc.cc:492 ../src/defs2doc.cc:546 ../src/qalc.cc:900 -#: ../src/qalc.cc:1472 ../src/qalc.cc:1489 ../src/qalc.cc:2559 -#: ../src/qalc.cc:2941 ../src/qalc.cc:3184 ../src/qalc.cc:3458 -#: ../src/qalc.cc:3468 ../src/qalc.cc:3572 ../src/qalc.cc:3668 -#: ../src/qalc.cc:4002 +#: ../src/defs2doc.cc:492 ../src/defs2doc.cc:546 ../src/qalc.cc:901 +#: ../src/qalc.cc:1473 ../src/qalc.cc:1490 ../src/qalc.cc:2560 +#: ../src/qalc.cc:2942 ../src/qalc.cc:3185 ../src/qalc.cc:3459 +#: ../src/qalc.cc:3469 ../src/qalc.cc:3573 ../src/qalc.cc:3669 +#: ../src/qalc.cc:4003 msgid "approximate" msgstr "" -#: ../src/defs2doc.cc:583 ../src/qalc.cc:1892 +#: ../src/defs2doc.cc:583 ../src/qalc.cc:1893 msgid "ans" msgstr "" #: ../src/defs2doc.cc:584 ../src/defs2doc.cc:587 ../src/defs2doc.cc:588 -#: ../src/defs2doc.cc:589 ../src/defs2doc.cc:590 ../src/qalc.cc:1893 -#: ../src/qalc.cc:1896 ../src/qalc.cc:1897 ../src/qalc.cc:1898 -#: ../src/qalc.cc:1899 ../src/qalc.cc:2153 ../libqalculate/Calculator.cc:10674 -#: ../libqalculate/Calculator.cc:10690 +#: ../src/defs2doc.cc:589 ../src/defs2doc.cc:590 ../src/qalc.cc:1894 +#: ../src/qalc.cc:1897 ../src/qalc.cc:1898 ../src/qalc.cc:1899 +#: ../src/qalc.cc:1900 ../src/qalc.cc:2154 +#: ../libqalculate/Calculator-definitions.cc:2225 +#: ../libqalculate/Calculator-definitions.cc:2241 msgid "Temporary" msgstr "" -#: ../src/defs2doc.cc:584 ../src/qalc.cc:1893 +#: ../src/defs2doc.cc:584 ../src/qalc.cc:1894 msgid "Last Answer" msgstr "" -#: ../src/defs2doc.cc:585 ../src/qalc.cc:1894 +#: ../src/defs2doc.cc:585 ../src/qalc.cc:1895 msgid "answer" msgstr "" -#: ../src/defs2doc.cc:587 ../src/qalc.cc:1896 +#: ../src/defs2doc.cc:587 ../src/qalc.cc:1897 msgid "Answer 2" msgstr "" -#: ../src/defs2doc.cc:588 ../src/qalc.cc:1897 +#: ../src/defs2doc.cc:588 ../src/qalc.cc:1898 msgid "Answer 3" msgstr "" -#: ../src/defs2doc.cc:589 ../src/qalc.cc:1898 +#: ../src/defs2doc.cc:589 ../src/qalc.cc:1899 msgid "Answer 4" msgstr "" -#: ../src/defs2doc.cc:590 ../src/qalc.cc:1899 +#: ../src/defs2doc.cc:590 ../src/qalc.cc:1900 msgid "Answer 5" msgstr "" @@ -214,1234 +215,1249 @@ msgid "Uncategorized" msgstr "" -#: ../src/qalc.cc:152 ../src/qalc.cc:219 ../src/qalc.cc:3621 +#: ../src/qalc.cc:153 ../src/qalc.cc:220 ../src/qalc.cc:3622 #: ../libqalculate/util.cc:175 msgid "yes" msgstr "" -#: ../src/qalc.cc:153 ../src/qalc.cc:221 ../src/qalc.cc:3621 +#: ../src/qalc.cc:154 ../src/qalc.cc:222 ../src/qalc.cc:3622 #: ../libqalculate/util.cc:176 msgid "no" msgstr "" -#: ../src/qalc.cc:154 ../libqalculate/util.cc:183 +#: ../src/qalc.cc:155 ../libqalculate/util.cc:183 msgid "true" msgstr "" -#: ../src/qalc.cc:155 ../libqalculate/util.cc:184 +#: ../src/qalc.cc:156 ../libqalculate/util.cc:184 msgid "false" msgstr "" -#: ../src/qalc.cc:156 ../src/qalc.cc:777 ../src/qalc.cc:797 ../src/qalc.cc:1112 -#: ../src/qalc.cc:1149 ../src/qalc.cc:3028 ../src/qalc.cc:3041 -#: ../src/qalc.cc:3099 ../src/qalc.cc:3620 ../src/qalc.cc:3735 -#: ../src/qalc.cc:3742 ../src/qalc.cc:3793 ../libqalculate/util.cc:191 +#: ../src/qalc.cc:157 ../src/qalc.cc:778 ../src/qalc.cc:798 ../src/qalc.cc:1113 +#: ../src/qalc.cc:1150 ../src/qalc.cc:3029 ../src/qalc.cc:3042 +#: ../src/qalc.cc:3100 ../src/qalc.cc:3621 ../src/qalc.cc:3736 +#: ../src/qalc.cc:3743 ../src/qalc.cc:3794 ../libqalculate/util.cc:191 msgid "on" msgstr "" -#: ../src/qalc.cc:157 ../src/qalc.cc:775 ../src/qalc.cc:796 ../src/qalc.cc:1021 -#: ../src/qalc.cc:1085 ../src/qalc.cc:1097 ../src/qalc.cc:1110 -#: ../src/qalc.cc:1147 ../src/qalc.cc:3027 ../src/qalc.cc:3032 -#: ../src/qalc.cc:3039 ../src/qalc.cc:3068 ../src/qalc.cc:3075 -#: ../src/qalc.cc:3082 ../src/qalc.cc:3098 ../src/qalc.cc:3132 -#: ../src/qalc.cc:3620 ../src/qalc.cc:3733 ../src/qalc.cc:3739 -#: ../src/qalc.cc:3742 ../src/qalc.cc:3750 ../src/qalc.cc:3757 -#: ../src/qalc.cc:3767 ../src/qalc.cc:3791 ../src/qalc.cc:3826 +#: ../src/qalc.cc:158 ../src/qalc.cc:776 ../src/qalc.cc:797 ../src/qalc.cc:1022 +#: ../src/qalc.cc:1086 ../src/qalc.cc:1098 ../src/qalc.cc:1111 +#: ../src/qalc.cc:1148 ../src/qalc.cc:3028 ../src/qalc.cc:3033 +#: ../src/qalc.cc:3040 ../src/qalc.cc:3069 ../src/qalc.cc:3076 +#: ../src/qalc.cc:3083 ../src/qalc.cc:3099 ../src/qalc.cc:3133 +#: ../src/qalc.cc:3621 ../src/qalc.cc:3734 ../src/qalc.cc:3740 +#: ../src/qalc.cc:3743 ../src/qalc.cc:3751 ../src/qalc.cc:3758 +#: ../src/qalc.cc:3768 ../src/qalc.cc:3792 ../src/qalc.cc:3827 #: ../libqalculate/util.cc:192 msgid "off" msgstr "" -#: ../src/qalc.cc:226 +#: ../src/qalc.cc:227 msgid "Please answer yes or no" msgstr "" -#: ../src/qalc.cc:258 +#: ../src/qalc.cc:259 msgid "Unrecognized assumption." msgstr "" -#: ../src/qalc.cc:425 ../src/qalc.cc:458 ../libqalculate/Calculator.cc:467 -#: ../libqalculate/Calculator.cc:693 ../libqalculate/DataSet.cc:1072 -#: ../libqalculate/DataSet.cc:1134 ../libqalculate/MathStructure.cc:21595 -#: ../libqalculate/Function.cc:2269 ../libqalculate/Function.cc:2285 +#: ../src/qalc.cc:426 ../src/qalc.cc:459 ../libqalculate/Calculator.cc:245 +#: ../libqalculate/Calculator.cc:473 ../libqalculate/DataSet.cc:1073 +#: ../libqalculate/DataSet.cc:1135 ../libqalculate/MathStructure-print.cc:3190 +#: ../libqalculate/Function.cc:2304 ../libqalculate/Function.cc:2320 msgid "or" msgstr "" -#: ../src/qalc.cc:546 ../libqalculate/Calculator.cc:12220 +#: ../src/qalc.cc:547 ../libqalculate/Calculator-definitions.cc:3756 #, c-format msgid "It has been %s day(s) since the exchange rates last were updated." msgstr "" -#: ../src/qalc.cc:551 +#: ../src/qalc.cc:552 msgid "Do you wish to update the exchange rates now?" msgstr "" -#: ../src/qalc.cc:565 ../src/qalc.cc:566 +#: ../src/qalc.cc:566 ../src/qalc.cc:567 msgid "" "\n" "Press Enter to continue." msgstr "" -#: ../src/qalc.cc:581 ../src/qalc.cc:582 ../src/qalc.cc:583 ../src/qalc.cc:584 -#: ../src/qalc.cc:585 ../src/qalc.cc:586 ../src/qalc.cc:719 ../src/qalc.cc:814 -#: ../src/qalc.cc:817 ../src/qalc.cc:972 ../src/qalc.cc:991 ../src/qalc.cc:1003 -#: ../src/qalc.cc:1012 ../src/qalc.cc:2362 ../src/qalc.cc:2499 +#: ../src/qalc.cc:582 ../src/qalc.cc:583 ../src/qalc.cc:584 ../src/qalc.cc:585 +#: ../src/qalc.cc:586 ../src/qalc.cc:587 ../src/qalc.cc:720 ../src/qalc.cc:815 +#: ../src/qalc.cc:818 ../src/qalc.cc:973 ../src/qalc.cc:992 ../src/qalc.cc:1004 +#: ../src/qalc.cc:1013 ../src/qalc.cc:2363 ../src/qalc.cc:2500 msgid "Illegal value" msgstr "" #. qalc command -#: ../src/qalc.cc:614 ../src/qalc.cc:934 ../src/qalc.cc:2340 -#: ../src/qalc.cc:2803 ../src/qalc.cc:2809 ../src/qalc.cc:2994 -#: ../src/qalc.cc:3150 ../src/qalc.cc:3186 ../src/qalc.cc:3702 -#: ../src/qalc.cc:3839 ../src/qalc.cc:3994 ../src/qalc.cc:4922 -#: ../src/qalc.cc:4933 ../libqalculate/Calculator.cc:3051 -#: ../libqalculate/Calculator.cc:3055 +#: ../src/qalc.cc:615 ../src/qalc.cc:935 ../src/qalc.cc:2341 +#: ../src/qalc.cc:2804 ../src/qalc.cc:2810 ../src/qalc.cc:2995 +#: ../src/qalc.cc:3151 ../src/qalc.cc:3187 ../src/qalc.cc:3703 +#: ../src/qalc.cc:3840 ../src/qalc.cc:3995 ../src/qalc.cc:4923 +#: ../src/qalc.cc:4934 ../libqalculate/Calculator-calculate.cc:837 +#: ../libqalculate/Calculator-calculate.cc:841 msgid "base" msgstr "" -#: ../src/qalc.cc:614 ../src/qalc.cc:616 ../src/qalc.cc:3108 -#: ../src/qalc.cc:3804 +#: ../src/qalc.cc:615 ../src/qalc.cc:617 ../src/qalc.cc:3109 +#: ../src/qalc.cc:3805 msgid "input base" msgstr "" -#: ../src/qalc.cc:614 ../src/qalc.cc:617 +#: ../src/qalc.cc:615 ../src/qalc.cc:618 msgid "output base" msgstr "" -#: ../src/qalc.cc:618 ../src/qalc.cc:2606 ../src/qalc.cc:2996 -#: ../src/qalc.cc:3110 ../src/qalc.cc:3714 ../src/qalc.cc:3812 -#: ../src/qalc.cc:4756 ../libqalculate/Calculator.cc:2969 +#: ../src/qalc.cc:619 ../src/qalc.cc:2607 ../src/qalc.cc:2997 +#: ../src/qalc.cc:3111 ../src/qalc.cc:3715 ../src/qalc.cc:3813 +#: ../src/qalc.cc:4757 ../libqalculate/Calculator-calculate.cc:755 msgid "roman" msgstr "" -#: ../src/qalc.cc:619 ../src/qalc.cc:2611 ../src/qalc.cc:2997 -#: ../src/qalc.cc:3111 ../src/qalc.cc:4764 ../libqalculate/Calculator.cc:2972 +#: ../src/qalc.cc:620 ../src/qalc.cc:2612 ../src/qalc.cc:2998 +#: ../src/qalc.cc:3112 ../src/qalc.cc:4765 +#: ../libqalculate/Calculator-calculate.cc:758 msgid "bijective" msgstr "" -#: ../src/qalc.cc:620 ../src/qalc.cc:2621 ../src/qalc.cc:2999 -#: ../src/qalc.cc:3712 ../src/qalc.cc:4780 ../libqalculate/Calculator.cc:2978 +#: ../src/qalc.cc:621 ../src/qalc.cc:2622 ../src/qalc.cc:3000 +#: ../src/qalc.cc:3713 ../src/qalc.cc:4781 +#: ../libqalculate/Calculator-calculate.cc:764 msgid "time" msgstr "" -#: ../src/qalc.cc:621 ../src/qalc.cc:2581 ../src/qalc.cc:4716 -#: ../libqalculate/Calculator.cc:2954 +#: ../src/qalc.cc:622 ../src/qalc.cc:2582 ../src/qalc.cc:4717 +#: ../libqalculate/Calculator-calculate.cc:740 msgid "hexadecimal" msgstr "" -#: ../src/qalc.cc:628 ../src/qalc.cc:2601 ../src/qalc.cc:4748 -#: ../libqalculate/Calculator.cc:2966 +#: ../src/qalc.cc:629 ../src/qalc.cc:2602 ../src/qalc.cc:4749 +#: ../libqalculate/Calculator-calculate.cc:752 msgid "duodecimal" msgstr "" -#: ../src/qalc.cc:629 ../src/qalc.cc:2586 ../src/qalc.cc:4724 -#: ../libqalculate/Calculator.cc:2957 +#: ../src/qalc.cc:630 ../src/qalc.cc:2587 ../src/qalc.cc:4725 +#: ../libqalculate/Calculator-calculate.cc:743 msgid "binary" msgstr "" -#: ../src/qalc.cc:630 ../src/qalc.cc:2596 ../src/qalc.cc:4740 -#: ../libqalculate/Calculator.cc:2963 +#: ../src/qalc.cc:631 ../src/qalc.cc:2597 ../src/qalc.cc:4741 +#: ../libqalculate/Calculator-calculate.cc:749 msgid "octal" msgstr "" -#: ../src/qalc.cc:631 ../src/qalc.cc:2591 ../src/qalc.cc:4732 -#: ../libqalculate/Calculator.cc:2960 +#: ../src/qalc.cc:632 ../src/qalc.cc:2592 ../src/qalc.cc:4733 +#: ../libqalculate/Calculator-calculate.cc:746 msgid "decimal" msgstr "" -#: ../src/qalc.cc:632 ../src/qalc.cc:2616 ../src/qalc.cc:2998 -#: ../src/qalc.cc:4772 ../libqalculate/Calculator.cc:2975 +#: ../src/qalc.cc:633 ../src/qalc.cc:2617 ../src/qalc.cc:2999 +#: ../src/qalc.cc:4773 ../libqalculate/Calculator-calculate.cc:761 msgid "sexagesimal" msgstr "" -#: ../src/qalc.cc:643 ../src/qalc.cc:757 ../src/qalc.cc:3010 -#: ../src/qalc.cc:3726 +#: ../src/qalc.cc:644 ../src/qalc.cc:758 ../src/qalc.cc:3011 +#: ../src/qalc.cc:3727 msgid "base display" msgstr "" -#: ../src/qalc.cc:673 +#: ../src/qalc.cc:674 msgid "Illegal base." msgstr "" -#: ../src/qalc.cc:681 ../src/qalc.cc:709 ../src/qalc.cc:2925 -#: ../src/qalc.cc:3639 +#: ../src/qalc.cc:682 ../src/qalc.cc:710 ../src/qalc.cc:2926 +#: ../src/qalc.cc:3640 msgid "assumptions" msgstr "" -#: ../src/qalc.cc:712 ../src/qalc.cc:3141 ../src/qalc.cc:3831 +#: ../src/qalc.cc:713 ../src/qalc.cc:3142 ../src/qalc.cc:3832 msgid "all prefixes" msgstr "" -#: ../src/qalc.cc:713 ../src/qalc.cc:2959 ../src/qalc.cc:3679 +#: ../src/qalc.cc:714 ../src/qalc.cc:2960 ../src/qalc.cc:3680 msgid "complex numbers" msgstr "" -#: ../src/qalc.cc:714 ../src/qalc.cc:2977 ../src/qalc.cc:3691 +#: ../src/qalc.cc:715 ../src/qalc.cc:2978 ../src/qalc.cc:3692 msgid "excessive parentheses" msgstr "" -#: ../src/qalc.cc:715 ../src/qalc.cc:2960 ../src/qalc.cc:3240 -#: ../src/qalc.cc:3245 ../src/qalc.cc:3680 +#: ../src/qalc.cc:716 ../src/qalc.cc:2961 ../src/qalc.cc:3241 +#: ../src/qalc.cc:3246 ../src/qalc.cc:3681 msgid "functions" msgstr "" -#: ../src/qalc.cc:716 ../src/qalc.cc:2961 ../src/qalc.cc:3681 +#: ../src/qalc.cc:717 ../src/qalc.cc:2962 ../src/qalc.cc:3682 msgid "infinite numbers" msgstr "" -#: ../src/qalc.cc:717 ../src/qalc.cc:2986 ../src/qalc.cc:3694 +#: ../src/qalc.cc:718 ../src/qalc.cc:2987 ../src/qalc.cc:3695 msgid "show negative exponents" msgstr "" -#: ../src/qalc.cc:718 ../src/qalc.cc:2978 ../src/qalc.cc:3692 +#: ../src/qalc.cc:719 ../src/qalc.cc:2979 ../src/qalc.cc:3693 msgid "minus last" msgstr "" -#: ../src/qalc.cc:720 ../src/qalc.cc:2903 ../src/qalc.cc:3636 +#: ../src/qalc.cc:721 ../src/qalc.cc:2904 ../src/qalc.cc:3637 msgid "assume nonzero denominators" msgstr "" -#: ../src/qalc.cc:721 ../src/qalc.cc:2904 ../src/qalc.cc:3637 +#: ../src/qalc.cc:722 ../src/qalc.cc:2905 ../src/qalc.cc:3638 msgid "warn nonzero denominators" msgstr "" -#: ../src/qalc.cc:722 ../src/qalc.cc:3158 ../src/qalc.cc:3851 +#: ../src/qalc.cc:723 ../src/qalc.cc:3159 ../src/qalc.cc:3852 msgid "prefixes" msgstr "" -#: ../src/qalc.cc:723 ../src/qalc.cc:3154 ../src/qalc.cc:3847 +#: ../src/qalc.cc:724 ../src/qalc.cc:3155 ../src/qalc.cc:3848 msgid "binary prefixes" msgstr "" -#: ../src/qalc.cc:730 ../src/qalc.cc:3156 ../src/qalc.cc:3849 +#: ../src/qalc.cc:731 ../src/qalc.cc:3157 ../src/qalc.cc:3850 msgid "denominator prefixes" msgstr "" -#: ../src/qalc.cc:731 ../src/qalc.cc:3157 ../src/qalc.cc:3850 +#: ../src/qalc.cc:732 ../src/qalc.cc:3158 ../src/qalc.cc:3851 msgid "place units separately" msgstr "" -#: ../src/qalc.cc:732 ../src/qalc.cc:2958 ../src/qalc.cc:3678 +#: ../src/qalc.cc:733 ../src/qalc.cc:2959 ../src/qalc.cc:3679 msgid "calculate variables" msgstr "" -#: ../src/qalc.cc:733 ../src/qalc.cc:2957 ../src/qalc.cc:3677 +#: ../src/qalc.cc:734 ../src/qalc.cc:2958 ../src/qalc.cc:3678 msgid "calculate functions" msgstr "" -#: ../src/qalc.cc:734 ../src/qalc.cc:3159 ../src/qalc.cc:3852 +#: ../src/qalc.cc:735 ../src/qalc.cc:3160 ../src/qalc.cc:3853 msgid "sync units" msgstr "" -#: ../src/qalc.cc:735 ../src/qalc.cc:3079 ../src/qalc.cc:3763 +#: ../src/qalc.cc:736 ../src/qalc.cc:3080 ../src/qalc.cc:3764 msgid "round to even" msgstr "" -#: ../src/qalc.cc:736 ../src/qalc.cc:3137 ../src/qalc.cc:3827 +#: ../src/qalc.cc:737 ../src/qalc.cc:3138 ../src/qalc.cc:3828 msgid "rpn syntax" msgstr "" #. qalc command -#: ../src/qalc.cc:737 ../src/qalc.cc:2343 ../src/qalc.cc:3171 -#: ../src/qalc.cc:3208 ../src/qalc.cc:3864 ../src/qalc.cc:3944 +#: ../src/qalc.cc:738 ../src/qalc.cc:2344 ../src/qalc.cc:3172 +#: ../src/qalc.cc:3209 ../src/qalc.cc:3865 ../src/qalc.cc:3945 msgid "rpn" msgstr "" -#: ../src/qalc.cc:738 ../src/qalc.cc:2987 ../src/qalc.cc:3695 +#: ../src/qalc.cc:739 ../src/qalc.cc:2988 ../src/qalc.cc:3696 msgid "short multiplication" msgstr "" -#: ../src/qalc.cc:739 ../src/qalc.cc:3062 ../src/qalc.cc:3746 +#: ../src/qalc.cc:740 ../src/qalc.cc:3063 ../src/qalc.cc:3747 msgid "lowercase e" msgstr "" -#: ../src/qalc.cc:740 ../src/qalc.cc:3063 ../src/qalc.cc:3747 +#: ../src/qalc.cc:741 ../src/qalc.cc:3064 ../src/qalc.cc:3748 msgid "lowercase numbers" msgstr "" -#: ../src/qalc.cc:741 ../src/qalc.cc:3046 ../src/qalc.cc:3107 -#: ../src/qalc.cc:3744 ../src/qalc.cc:3803 +#: ../src/qalc.cc:742 ../src/qalc.cc:3047 ../src/qalc.cc:3108 +#: ../src/qalc.cc:3745 ../src/qalc.cc:3804 msgid "imaginary j" msgstr "" -#: ../src/qalc.cc:759 ../src/qalc.cc:776 ../src/qalc.cc:830 ../src/qalc.cc:930 -#: ../src/qalc.cc:956 ../src/qalc.cc:2898 ../src/qalc.cc:2934 -#: ../src/qalc.cc:2947 ../src/qalc.cc:3012 ../src/qalc.cc:3146 -#: ../src/qalc.cc:3667 ../src/qalc.cc:3726 ../src/qalc.cc:3835 +#: ../src/qalc.cc:760 ../src/qalc.cc:777 ../src/qalc.cc:831 ../src/qalc.cc:931 +#: ../src/qalc.cc:957 ../src/qalc.cc:2899 ../src/qalc.cc:2935 +#: ../src/qalc.cc:2948 ../src/qalc.cc:3013 ../src/qalc.cc:3147 +#: ../src/qalc.cc:3668 ../src/qalc.cc:3727 ../src/qalc.cc:3836 msgid "none" msgstr "" -#: ../src/qalc.cc:760 ../src/qalc.cc:3013 ../src/qalc.cc:3726 +#: ../src/qalc.cc:761 ../src/qalc.cc:3014 ../src/qalc.cc:3727 msgid "normal" msgstr "" -#: ../src/qalc.cc:761 ../src/qalc.cc:3014 ../src/qalc.cc:3726 +#: ../src/qalc.cc:762 ../src/qalc.cc:3015 ../src/qalc.cc:3727 msgid "alternative" msgstr "" -#: ../src/qalc.cc:766 ../src/qalc.cc:783 ../src/qalc.cc:803 ../src/qalc.cc:835 -#: ../src/qalc.cc:852 ../src/qalc.cc:877 ../src/qalc.cc:891 ../src/qalc.cc:905 -#: ../src/qalc.cc:922 ../src/qalc.cc:947 ../src/qalc.cc:963 ../src/qalc.cc:1032 -#: ../src/qalc.cc:1038 ../src/qalc.cc:1062 ../src/qalc.cc:1119 -#: ../src/qalc.cc:1138 ../src/qalc.cc:1154 +#: ../src/qalc.cc:767 ../src/qalc.cc:784 ../src/qalc.cc:804 ../src/qalc.cc:836 +#: ../src/qalc.cc:853 ../src/qalc.cc:878 ../src/qalc.cc:892 ../src/qalc.cc:906 +#: ../src/qalc.cc:923 ../src/qalc.cc:948 ../src/qalc.cc:964 ../src/qalc.cc:1033 +#: ../src/qalc.cc:1039 ../src/qalc.cc:1063 ../src/qalc.cc:1120 +#: ../src/qalc.cc:1139 ../src/qalc.cc:1155 msgid "Illegal value." msgstr "" -#: ../src/qalc.cc:771 ../src/qalc.cc:3091 ../src/qalc.cc:3781 +#: ../src/qalc.cc:772 ../src/qalc.cc:3092 ../src/qalc.cc:3782 msgid "two's complement" msgstr "" -#: ../src/qalc.cc:772 ../src/qalc.cc:3045 ../src/qalc.cc:3743 +#: ../src/qalc.cc:773 ../src/qalc.cc:3046 ../src/qalc.cc:3744 msgid "hexadecimal two's" msgstr "" -#: ../src/qalc.cc:773 ../src/qalc.cc:3030 ../src/qalc.cc:3739 +#: ../src/qalc.cc:774 ../src/qalc.cc:3031 ../src/qalc.cc:3740 msgid "digit grouping" msgstr "" -#: ../src/qalc.cc:777 ../src/qalc.cc:3033 ../src/qalc.cc:3739 +#: ../src/qalc.cc:778 ../src/qalc.cc:3034 ../src/qalc.cc:3740 msgid "standard" msgstr "" -#: ../src/qalc.cc:778 ../src/qalc.cc:798 ../src/qalc.cc:3026 -#: ../src/qalc.cc:3034 ../src/qalc.cc:3097 ../src/qalc.cc:3731 -#: ../src/qalc.cc:3739 ../src/qalc.cc:3789 +#: ../src/qalc.cc:779 ../src/qalc.cc:799 ../src/qalc.cc:3027 +#: ../src/qalc.cc:3035 ../src/qalc.cc:3098 ../src/qalc.cc:3732 +#: ../src/qalc.cc:3740 ../src/qalc.cc:3790 msgid "locale" msgstr "" -#: ../src/qalc.cc:788 ../src/qalc.cc:2989 ../src/qalc.cc:3697 +#: ../src/qalc.cc:789 ../src/qalc.cc:2990 ../src/qalc.cc:3698 msgid "spell out logical" msgstr "" -#: ../src/qalc.cc:789 ../src/qalc.cc:3105 ../src/qalc.cc:3801 +#: ../src/qalc.cc:790 ../src/qalc.cc:3106 ../src/qalc.cc:3802 msgid "ignore dot" msgstr "" -#: ../src/qalc.cc:790 ../src/qalc.cc:3102 ../src/qalc.cc:3798 +#: ../src/qalc.cc:791 ../src/qalc.cc:3103 ../src/qalc.cc:3799 msgid "ignore comma" msgstr "" -#: ../src/qalc.cc:794 ../src/qalc.cc:3025 ../src/qalc.cc:3096 -#: ../src/qalc.cc:3728 ../src/qalc.cc:3786 +#: ../src/qalc.cc:795 ../src/qalc.cc:3026 ../src/qalc.cc:3097 +#: ../src/qalc.cc:3729 ../src/qalc.cc:3787 msgid "decimal comma" msgstr "" -#: ../src/qalc.cc:813 ../src/qalc.cc:3122 ../src/qalc.cc:3824 +#: ../src/qalc.cc:814 ../src/qalc.cc:3123 ../src/qalc.cc:3825 msgid "limit implicit multiplication" msgstr "" -#: ../src/qalc.cc:815 ../src/qalc.cc:2988 ../src/qalc.cc:3696 +#: ../src/qalc.cc:816 ../src/qalc.cc:2989 ../src/qalc.cc:3697 msgid "spacious" msgstr "" -#: ../src/qalc.cc:816 ../src/qalc.cc:2990 ../src/qalc.cc:3698 +#: ../src/qalc.cc:817 ../src/qalc.cc:2991 ../src/qalc.cc:3699 msgid "unicode" msgstr "" -#: ../src/qalc.cc:819 ../src/qalc.cc:2962 ../src/qalc.cc:3242 -#: ../src/qalc.cc:3247 ../src/qalc.cc:3682 +#: ../src/qalc.cc:820 ../src/qalc.cc:2963 ../src/qalc.cc:3243 +#: ../src/qalc.cc:3248 ../src/qalc.cc:3683 msgid "units" msgstr "" -#: ../src/qalc.cc:820 ../src/qalc.cc:2963 ../src/qalc.cc:3683 +#: ../src/qalc.cc:821 ../src/qalc.cc:2964 ../src/qalc.cc:3684 msgid "unknowns" msgstr "" -#: ../src/qalc.cc:821 ../src/qalc.cc:2964 ../src/qalc.cc:3241 -#: ../src/qalc.cc:3246 ../src/qalc.cc:3684 +#: ../src/qalc.cc:822 ../src/qalc.cc:2965 ../src/qalc.cc:3242 +#: ../src/qalc.cc:3247 ../src/qalc.cc:3685 msgid "variables" msgstr "" -#: ../src/qalc.cc:822 ../src/qalc.cc:2969 ../src/qalc.cc:3689 +#: ../src/qalc.cc:823 ../src/qalc.cc:2970 ../src/qalc.cc:3690 msgid "abbreviations" msgstr "" -#: ../src/qalc.cc:823 ../src/qalc.cc:3090 ../src/qalc.cc:3780 +#: ../src/qalc.cc:824 ../src/qalc.cc:3091 ../src/qalc.cc:3781 msgid "show ending zeroes" msgstr "" -#: ../src/qalc.cc:824 ../src/qalc.cc:3078 ../src/qalc.cc:3762 +#: ../src/qalc.cc:825 ../src/qalc.cc:3079 ../src/qalc.cc:3763 msgid "repeating decimals" msgstr "" -#: ../src/qalc.cc:825 ../src/qalc.cc:2929 ../src/qalc.cc:3667 +#: ../src/qalc.cc:826 ../src/qalc.cc:2930 ../src/qalc.cc:3668 msgid "angle unit" msgstr "" -#: ../src/qalc.cc:827 ../src/qalc.cc:2931 ../src/qalc.cc:2932 +#: ../src/qalc.cc:828 ../src/qalc.cc:2932 ../src/qalc.cc:2933 msgid "rad" msgstr "" -#: ../src/qalc.cc:827 ../src/qalc.cc:3667 +#: ../src/qalc.cc:828 ../src/qalc.cc:3668 msgid "radians" msgstr "" -#: ../src/qalc.cc:828 +#: ../src/qalc.cc:829 msgid "deg" msgstr "" -#: ../src/qalc.cc:828 ../src/qalc.cc:3667 +#: ../src/qalc.cc:829 ../src/qalc.cc:3668 msgid "degrees" msgstr "" -#: ../src/qalc.cc:829 ../src/qalc.cc:2933 +#: ../src/qalc.cc:830 ../src/qalc.cc:2934 msgid "gra" msgstr "" -#: ../src/qalc.cc:829 ../src/qalc.cc:3667 +#: ../src/qalc.cc:830 ../src/qalc.cc:3668 msgid "gradians" msgstr "" -#: ../src/qalc.cc:842 ../src/qalc.cc:3095 ../src/qalc.cc:3785 +#: ../src/qalc.cc:843 ../src/qalc.cc:3096 ../src/qalc.cc:3786 msgid "caret as xor" msgstr "" -#: ../src/qalc.cc:843 ../src/qalc.cc:3123 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4057 +#: ../src/qalc.cc:844 ../src/qalc.cc:3124 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4058 msgid "parsing mode" msgstr "" -#: ../src/qalc.cc:845 ../src/qalc.cc:1045 ../src/qalc.cc:3049 -#: ../src/qalc.cc:3125 ../src/qalc.cc:3745 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4065 +#: ../src/qalc.cc:846 ../src/qalc.cc:1046 ../src/qalc.cc:3050 +#: ../src/qalc.cc:3126 ../src/qalc.cc:3746 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4066 msgid "adaptive" msgstr "" -#: ../src/qalc.cc:846 ../src/qalc.cc:3126 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4062 +#: ../src/qalc.cc:847 ../src/qalc.cc:3127 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4063 msgid "implicit first" msgstr "" -#: ../src/qalc.cc:847 ../src/qalc.cc:3127 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4059 +#: ../src/qalc.cc:848 ../src/qalc.cc:3128 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4060 msgid "conventional" msgstr "" -#: ../src/qalc.cc:857 ../src/qalc.cc:1696 ../src/qalc.cc:3160 -#: ../src/qalc.cc:3853 +#: ../src/qalc.cc:858 ../src/qalc.cc:1697 ../src/qalc.cc:3161 +#: ../src/qalc.cc:3854 msgid "update exchange rates" msgstr "" -#: ../src/qalc.cc:858 ../src/qalc.cc:3163 ../src/qalc.cc:3855 +#: ../src/qalc.cc:859 ../src/qalc.cc:3164 ../src/qalc.cc:3856 msgid "never" msgstr "" -#: ../src/qalc.cc:860 ../src/qalc.cc:3162 ../src/qalc.cc:3854 +#: ../src/qalc.cc:861 ../src/qalc.cc:3163 ../src/qalc.cc:3855 msgid "ask" msgstr "" -#: ../src/qalc.cc:868 ../src/qalc.cc:2979 ../src/qalc.cc:3693 +#: ../src/qalc.cc:869 ../src/qalc.cc:2980 ../src/qalc.cc:3694 msgid "multiplication sign" msgstr "" -#: ../src/qalc.cc:882 ../src/qalc.cc:2970 ../src/qalc.cc:3690 +#: ../src/qalc.cc:883 ../src/qalc.cc:2971 ../src/qalc.cc:3691 msgid "division sign" msgstr "" -#: ../src/qalc.cc:896 ../src/qalc.cc:2937 ../src/qalc.cc:3668 +#: ../src/qalc.cc:897 ../src/qalc.cc:2938 ../src/qalc.cc:3669 msgid "approximation" msgstr "" #. qalc command -#: ../src/qalc.cc:898 ../src/qalc.cc:969 ../src/qalc.cc:1111 -#: ../src/qalc.cc:2549 ../src/qalc.cc:2939 ../src/qalc.cc:3040 -#: ../src/qalc.cc:3188 ../src/qalc.cc:3668 ../src/qalc.cc:3742 -#: ../src/qalc.cc:3998 +#: ../src/qalc.cc:899 ../src/qalc.cc:970 ../src/qalc.cc:1112 +#: ../src/qalc.cc:2550 ../src/qalc.cc:2940 ../src/qalc.cc:3041 +#: ../src/qalc.cc:3189 ../src/qalc.cc:3669 ../src/qalc.cc:3743 +#: ../src/qalc.cc:3999 msgid "exact" msgstr "" -#: ../src/qalc.cc:899 ../src/qalc.cc:2940 ../src/qalc.cc:3668 +#: ../src/qalc.cc:900 ../src/qalc.cc:2941 ../src/qalc.cc:3669 msgid "try exact" msgstr "" -#: ../src/qalc.cc:914 ../src/qalc.cc:2945 ../src/qalc.cc:3670 +#: ../src/qalc.cc:915 ../src/qalc.cc:2946 ../src/qalc.cc:3671 msgid "interval calculation" msgstr "" -#: ../src/qalc.cc:914 +#: ../src/qalc.cc:915 msgid "uncertainty propagation" msgstr "" -#: ../src/qalc.cc:916 ../src/qalc.cc:2948 ../src/qalc.cc:3670 +#: ../src/qalc.cc:917 ../src/qalc.cc:2949 ../src/qalc.cc:3671 msgid "variance formula" msgstr "" -#: ../src/qalc.cc:916 +#: ../src/qalc.cc:917 msgid "variance" msgstr "" -#: ../src/qalc.cc:917 ../src/qalc.cc:1069 ../src/qalc.cc:2944 -#: ../src/qalc.cc:2949 ../src/qalc.cc:3669 ../src/qalc.cc:3670 +#: ../src/qalc.cc:918 ../src/qalc.cc:1070 ../src/qalc.cc:2945 +#: ../src/qalc.cc:2950 ../src/qalc.cc:3670 ../src/qalc.cc:3671 msgid "interval arithmetic" msgstr "" -#: ../src/qalc.cc:927 ../src/qalc.cc:3142 ../src/qalc.cc:3832 +#: ../src/qalc.cc:928 ../src/qalc.cc:3143 ../src/qalc.cc:3833 msgid "autoconversion" msgstr "" -#: ../src/qalc.cc:931 ../src/qalc.cc:2797 +#: ../src/qalc.cc:932 ../src/qalc.cc:2798 msgid "best" msgstr "" -#: ../src/qalc.cc:932 ../src/qalc.cc:3151 ../src/qalc.cc:3841 +#: ../src/qalc.cc:933 ../src/qalc.cc:3152 ../src/qalc.cc:3842 msgid "optimalsi" msgstr "" -#: ../src/qalc.cc:933 ../src/qalc.cc:2797 ../src/qalc.cc:3149 -#: ../src/qalc.cc:3837 ../src/qalc.cc:4911 ../libqalculate/Calculator.cc:3047 +#: ../src/qalc.cc:934 ../src/qalc.cc:2798 ../src/qalc.cc:3150 +#: ../src/qalc.cc:3838 ../src/qalc.cc:4912 +#: ../libqalculate/Calculator-calculate.cc:833 msgid "optimal" msgstr "" -#: ../src/qalc.cc:935 ../src/qalc.cc:1113 ../src/qalc.cc:3042 -#: ../src/qalc.cc:3145 ../src/qalc.cc:3742 ../src/qalc.cc:3843 -#: ../src/qalc.cc:4966 ../libqalculate/Calculator.cc:3076 +#: ../src/qalc.cc:936 ../src/qalc.cc:1114 ../src/qalc.cc:3043 +#: ../src/qalc.cc:3146 ../src/qalc.cc:3743 ../src/qalc.cc:3844 +#: ../src/qalc.cc:4967 ../libqalculate/Calculator-calculate.cc:862 msgid "mixed" msgstr "" -#: ../src/qalc.cc:953 ../src/qalc.cc:3155 ../src/qalc.cc:3848 +#: ../src/qalc.cc:954 ../src/qalc.cc:3156 ../src/qalc.cc:3849 msgid "currency conversion" msgstr "" -#: ../src/qalc.cc:954 ../src/qalc.cc:2896 ../src/qalc.cc:3635 +#: ../src/qalc.cc:955 ../src/qalc.cc:2897 ../src/qalc.cc:3636 msgid "algebra mode" msgstr "" #. qalc command -#: ../src/qalc.cc:957 ../src/qalc.cc:2884 ../src/qalc.cc:3612 +#: ../src/qalc.cc:958 ../src/qalc.cc:2885 ../src/qalc.cc:3613 msgid "simplify" msgstr "" -#: ../src/qalc.cc:957 ../src/qalc.cc:2884 ../src/qalc.cc:2900 -#: ../src/qalc.cc:3203 ../src/qalc.cc:3612 ../src/qalc.cc:3635 -#: ../src/qalc.cc:5015 ../libqalculate/Calculator.cc:3101 +#: ../src/qalc.cc:958 ../src/qalc.cc:2885 ../src/qalc.cc:2901 +#: ../src/qalc.cc:3204 ../src/qalc.cc:3613 ../src/qalc.cc:3636 +#: ../src/qalc.cc:5016 ../libqalculate/Calculator-calculate.cc:891 msgid "expand" msgstr "" -#: ../src/qalc.cc:958 ../src/qalc.cc:2899 ../src/qalc.cc:3635 -#: ../src/qalc.cc:5012 ../libqalculate/Calculator.cc:3097 +#: ../src/qalc.cc:959 ../src/qalc.cc:2900 ../src/qalc.cc:3636 +#: ../src/qalc.cc:5013 ../libqalculate/Calculator-calculate.cc:887 msgid "factorize" msgstr "" -#: ../src/qalc.cc:988 ../src/qalc.cc:3170 ../src/qalc.cc:3863 +#: ../src/qalc.cc:989 ../src/qalc.cc:3171 ../src/qalc.cc:3864 msgid "ignore locale" msgstr "" -#: ../src/qalc.cc:1000 ../src/qalc.cc:3173 ../src/qalc.cc:3201 -#: ../src/qalc.cc:3866 +#: ../src/qalc.cc:1001 ../src/qalc.cc:3174 ../src/qalc.cc:3202 +#: ../src/qalc.cc:3867 msgid "save mode" msgstr "" -#: ../src/qalc.cc:1009 ../src/qalc.cc:3172 ../src/qalc.cc:3200 -#: ../src/qalc.cc:3865 +#: ../src/qalc.cc:1010 ../src/qalc.cc:3173 ../src/qalc.cc:3201 +#: ../src/qalc.cc:3866 msgid "save definitions" msgstr "" -#: ../src/qalc.cc:1018 ../src/qalc.cc:3080 ../src/qalc.cc:3764 +#: ../src/qalc.cc:1019 ../src/qalc.cc:3081 ../src/qalc.cc:3765 msgid "scientific notation" msgstr "" -#: ../src/qalc.cc:1022 ../src/qalc.cc:3083 ../src/qalc.cc:3769 +#: ../src/qalc.cc:1023 ../src/qalc.cc:3084 ../src/qalc.cc:3770 msgid "auto" msgstr "" -#: ../src/qalc.cc:1023 ../src/qalc.cc:3084 ../src/qalc.cc:3773 +#: ../src/qalc.cc:1024 ../src/qalc.cc:3085 ../src/qalc.cc:3774 msgid "pure" msgstr "" -#: ../src/qalc.cc:1024 ../src/qalc.cc:3085 ../src/qalc.cc:3775 +#: ../src/qalc.cc:1025 ../src/qalc.cc:3086 ../src/qalc.cc:3776 msgid "scientific" msgstr "" -#: ../src/qalc.cc:1025 ../src/qalc.cc:3086 ../src/qalc.cc:3771 +#: ../src/qalc.cc:1026 ../src/qalc.cc:3087 ../src/qalc.cc:3772 msgid "engineering" msgstr "" -#: ../src/qalc.cc:1034 ../src/qalc.cc:2953 ../src/qalc.cc:3671 +#: ../src/qalc.cc:1035 ../src/qalc.cc:2954 ../src/qalc.cc:3672 msgid "precision" msgstr "" -#: ../src/qalc.cc:1043 ../src/qalc.cc:3047 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1044 ../src/qalc.cc:3048 ../src/qalc.cc:3746 msgid "interval display" msgstr "" -#: ../src/qalc.cc:1046 ../src/qalc.cc:3052 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1047 ../src/qalc.cc:3053 ../src/qalc.cc:3746 msgid "significant" msgstr "" -#: ../src/qalc.cc:1047 ../src/qalc.cc:3053 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1048 ../src/qalc.cc:3054 ../src/qalc.cc:3746 msgid "interval" msgstr "" -#: ../src/qalc.cc:1048 ../src/qalc.cc:3054 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1049 ../src/qalc.cc:3055 ../src/qalc.cc:3746 msgid "plusminus" msgstr "" -#: ../src/qalc.cc:1049 ../src/qalc.cc:3055 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1050 ../src/qalc.cc:3056 ../src/qalc.cc:3746 msgid "midpoint" msgstr "" -#: ../src/qalc.cc:1050 ../src/qalc.cc:3057 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1051 ../src/qalc.cc:3058 ../src/qalc.cc:3746 msgid "upper" msgstr "" -#: ../src/qalc.cc:1051 ../src/qalc.cc:3056 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1052 ../src/qalc.cc:3057 ../src/qalc.cc:3746 msgid "lower" msgstr "" -#: ../src/qalc.cc:1076 ../src/qalc.cc:2965 ../src/qalc.cc:3685 +#: ../src/qalc.cc:1077 ../src/qalc.cc:2966 ../src/qalc.cc:3686 msgid "variable units" msgstr "" -#: ../src/qalc.cc:1083 ../src/qalc.cc:3064 ../src/qalc.cc:3748 +#: ../src/qalc.cc:1084 ../src/qalc.cc:3065 ../src/qalc.cc:3749 msgid "max decimals" msgstr "" -#: ../src/qalc.cc:1095 ../src/qalc.cc:3071 ../src/qalc.cc:3755 +#: ../src/qalc.cc:1096 ../src/qalc.cc:3072 ../src/qalc.cc:3756 msgid "min decimals" msgstr "" -#: ../src/qalc.cc:1108 ../src/qalc.cc:3037 ../src/qalc.cc:3742 +#: ../src/qalc.cc:1109 ../src/qalc.cc:3038 ../src/qalc.cc:3743 msgid "fractions" msgstr "" -#: ../src/qalc.cc:1113 +#: ../src/qalc.cc:1114 msgid "combined" msgstr "" -#: ../src/qalc.cc:1114 ../src/qalc.cc:3041 ../src/qalc.cc:3742 +#: ../src/qalc.cc:1115 ../src/qalc.cc:3042 ../src/qalc.cc:3743 msgid "long" msgstr "" -#: ../src/qalc.cc:1127 ../src/qalc.cc:3017 ../src/qalc.cc:3727 +#: ../src/qalc.cc:1128 ../src/qalc.cc:3018 ../src/qalc.cc:3728 msgid "complex form" msgstr "" -#: ../src/qalc.cc:1129 ../src/qalc.cc:2667 ../src/qalc.cc:3019 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4856 ../libqalculate/Calculator.cc:3015 +#: ../src/qalc.cc:1130 ../src/qalc.cc:2668 ../src/qalc.cc:3020 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4857 +#: ../libqalculate/Calculator-calculate.cc:801 msgid "rectangular" msgstr "" -#: ../src/qalc.cc:1129 ../src/qalc.cc:2667 ../src/qalc.cc:4856 -#: ../libqalculate/Calculator.cc:3015 +#: ../src/qalc.cc:1130 ../src/qalc.cc:2668 ../src/qalc.cc:4857 +#: ../libqalculate/Calculator-calculate.cc:801 msgid "cartesian" msgstr "" -#: ../src/qalc.cc:1130 ../src/qalc.cc:2679 ../src/qalc.cc:3020 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4867 ../libqalculate/Calculator.cc:3018 +#: ../src/qalc.cc:1131 ../src/qalc.cc:2680 ../src/qalc.cc:3021 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4868 +#: ../libqalculate/Calculator-calculate.cc:804 msgid "exponential" msgstr "" -#: ../src/qalc.cc:1131 ../src/qalc.cc:2691 ../src/qalc.cc:3021 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4878 ../libqalculate/Calculator.cc:3021 +#: ../src/qalc.cc:1132 ../src/qalc.cc:2692 ../src/qalc.cc:3022 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4879 +#: ../libqalculate/Calculator-calculate.cc:807 msgid "polar" msgstr "" -#: ../src/qalc.cc:1132 ../src/qalc.cc:2703 ../src/qalc.cc:3022 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4889 ../libqalculate/Calculator.cc:3024 -#: ../libqalculate/Function.cc:2211 +#: ../src/qalc.cc:1133 ../src/qalc.cc:2704 ../src/qalc.cc:3023 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4890 +#: ../libqalculate/Calculator-calculate.cc:810 ../libqalculate/Function.cc:2245 msgid "angle" msgstr "" -#: ../src/qalc.cc:1132 ../src/qalc.cc:2703 ../src/qalc.cc:4889 -#: ../libqalculate/Calculator.cc:3024 +#: ../src/qalc.cc:1133 ../src/qalc.cc:2704 ../src/qalc.cc:4890 +#: ../libqalculate/Calculator-calculate.cc:810 msgid "phasor" msgstr "" -#: ../src/qalc.cc:1145 ../src/qalc.cc:3130 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1146 ../src/qalc.cc:3131 ../src/qalc.cc:3827 msgid "read precision" msgstr "" -#: ../src/qalc.cc:1148 ../src/qalc.cc:3133 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1149 ../src/qalc.cc:3134 ../src/qalc.cc:3827 msgid "always" msgstr "" -#: ../src/qalc.cc:1149 ../src/qalc.cc:3134 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1150 ../src/qalc.cc:3135 ../src/qalc.cc:3827 msgid "when decimals" msgstr "" -#: ../src/qalc.cc:1180 +#: ../src/qalc.cc:1181 msgid "Unrecognized option." msgstr "" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Calendar" msgstr "" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Day" msgstr "" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Month" msgstr "" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Year" msgstr "" -#: ../src/qalc.cc:1315 ../libqalculate/Calculator.cc:3124 +#: ../src/qalc.cc:1316 ../libqalculate/Calculator-calculate.cc:934 msgid "failed" msgstr "" -#: ../src/qalc.cc:1316 ../libqalculate/Calculator.cc:3125 +#: ../src/qalc.cc:1317 ../libqalculate/Calculator-calculate.cc:935 msgid "Gregorian:" msgstr "" -#: ../src/qalc.cc:1317 ../libqalculate/Calculator.cc:3126 +#: ../src/qalc.cc:1318 ../libqalculate/Calculator-calculate.cc:936 msgid "Hebrew:" msgstr "" -#: ../src/qalc.cc:1318 ../libqalculate/Calculator.cc:3127 +#: ../src/qalc.cc:1319 ../libqalculate/Calculator-calculate.cc:937 msgid "Islamic:" msgstr "" -#: ../src/qalc.cc:1319 ../libqalculate/Calculator.cc:3128 +#: ../src/qalc.cc:1320 ../libqalculate/Calculator-calculate.cc:938 msgid "Persian:" msgstr "" -#: ../src/qalc.cc:1320 ../libqalculate/Calculator.cc:3129 +#: ../src/qalc.cc:1321 ../libqalculate/Calculator-calculate.cc:939 msgid "Indian national:" msgstr "" -#: ../src/qalc.cc:1321 ../libqalculate/Calculator.cc:3130 +#: ../src/qalc.cc:1322 ../libqalculate/Calculator-calculate.cc:940 msgid "Chinese:" msgstr "" -#: ../src/qalc.cc:1326 ../libqalculate/Calculator.cc:3134 +#: ../src/qalc.cc:1327 ../libqalculate/Calculator-calculate.cc:944 msgid "Julian:" msgstr "" -#: ../src/qalc.cc:1327 ../libqalculate/Calculator.cc:3135 +#: ../src/qalc.cc:1328 ../libqalculate/Calculator-calculate.cc:945 msgid "Revised julian:" msgstr "" -#: ../src/qalc.cc:1328 ../libqalculate/Calculator.cc:3136 +#: ../src/qalc.cc:1329 ../libqalculate/Calculator-calculate.cc:946 msgid "Coptic:" msgstr "" -#: ../src/qalc.cc:1329 ../libqalculate/Calculator.cc:3137 +#: ../src/qalc.cc:1330 ../libqalculate/Calculator-calculate.cc:947 msgid "Ethiopian:" msgstr "" -#: ../src/qalc.cc:1396 ../libqalculate/BuiltinFunctions.cc:6237 -#: ../libqalculate/BuiltinFunctions.cc:6267 +#: ../src/qalc.cc:1397 ../libqalculate/BuiltinFunctions-matrixvector.cc:567 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:597 msgid "No matching item found." msgstr "" -#: ../src/qalc.cc:1427 ../src/qalc.cc:1428 ../src/qalc.cc:1558 -#: ../src/qalc.cc:1559 ../src/qalc.cc:1626 ../src/qalc.cc:1627 +#: ../src/qalc.cc:1428 ../src/qalc.cc:1429 ../src/qalc.cc:1559 +#: ../src/qalc.cc:1560 ../src/qalc.cc:1627 ../src/qalc.cc:1628 msgid "" "For more information about a specific function, variable or unit, please use " "the info command (in interactive mode)." msgstr "" -#: ../src/qalc.cc:1441 +#: ../src/qalc.cc:1442 msgid "Variables:" msgstr "" -#: ../src/qalc.cc:1443 +#: ../src/qalc.cc:1444 msgid "Name" msgstr "" -#: ../src/qalc.cc:1444 ../src/qalc.cc:3552 ../src/qalc.cc:3559 +#: ../src/qalc.cc:1445 ../src/qalc.cc:3553 ../src/qalc.cc:3560 msgid "Value" msgstr "" -#: ../src/qalc.cc:1532 +#: ../src/qalc.cc:1533 msgid "Functions:" msgstr "" -#: ../src/qalc.cc:1546 +#: ../src/qalc.cc:1547 msgid "Units:" msgstr "" -#: ../src/qalc.cc:1553 +#: ../src/qalc.cc:1554 msgid "No local variables, functions or units have been defined." msgstr "" -#: ../src/qalc.cc:1689 +#: ../src/qalc.cc:1690 msgid "usage: qalc [options] [expression]" msgstr "" -#: ../src/qalc.cc:1691 +#: ../src/qalc.cc:1692 msgid "where options are:" msgstr "" -#: ../src/qalc.cc:1692 ../src/qalc.cc:1724 ../src/qalc.cc:3186 +#: ../src/qalc.cc:1693 ../src/qalc.cc:1725 ../src/qalc.cc:3187 msgid "BASE" msgstr "" -#: ../src/qalc.cc:1693 +#: ../src/qalc.cc:1694 msgid "set the number base for results and, optionally, expressions" msgstr "" -#: ../src/qalc.cc:1698 +#: ../src/qalc.cc:1699 msgid "FILE" msgstr "" -#: ../src/qalc.cc:1699 +#: ../src/qalc.cc:1700 msgid "execute commands from a file first" msgstr "" -#: ../src/qalc.cc:1701 +#: ../src/qalc.cc:1702 msgid "start in interactive mode" msgstr "" -#: ../src/qalc.cc:1702 ../src/qalc.cc:1704 ../src/qalc.cc:1706 -#: ../src/qalc.cc:1708 +#: ../src/qalc.cc:1703 ../src/qalc.cc:1705 ../src/qalc.cc:1707 +#: ../src/qalc.cc:1709 msgid "SEARCH TERM" msgstr "" -#: ../src/qalc.cc:1703 +#: ../src/qalc.cc:1704 msgid "" "displays a list of all user-defined or matching variables, functions and " "units" msgstr "" -#: ../src/qalc.cc:1705 +#: ../src/qalc.cc:1706 msgid "displays a list of all or matching functions" msgstr "" -#: ../src/qalc.cc:1707 +#: ../src/qalc.cc:1708 msgid "displays a list of all or matching units" msgstr "" -#: ../src/qalc.cc:1709 +#: ../src/qalc.cc:1710 msgid "displays a list of all or matching variables" msgstr "" -#: ../src/qalc.cc:1710 +#: ../src/qalc.cc:1711 msgid "MILLISECONDS" msgstr "" -#: ../src/qalc.cc:1711 +#: ../src/qalc.cc:1712 msgid "" "terminate calculation and display of result after specified amount of time" msgstr "" -#: ../src/qalc.cc:1713 +#: ../src/qalc.cc:1714 msgid "do not load any functions, units, or variables from file" msgstr "" -#: ../src/qalc.cc:1715 +#: ../src/qalc.cc:1716 msgid "do not load any global currencies from file" msgstr "" -#: ../src/qalc.cc:1717 +#: ../src/qalc.cc:1718 msgid "do not load any global data sets from file" msgstr "" -#: ../src/qalc.cc:1719 +#: ../src/qalc.cc:1720 msgid "do not load any global functions from file" msgstr "" -#: ../src/qalc.cc:1721 +#: ../src/qalc.cc:1722 msgid "do not load any global units from file" msgstr "" -#: ../src/qalc.cc:1723 +#: ../src/qalc.cc:1724 msgid "do not load any global variables from file" msgstr "" -#: ../src/qalc.cc:1725 +#: ../src/qalc.cc:1726 msgid "" "start in programming mode (same as -b \"BASE BASE\" -s \"xor^\", with base " "conversion)" msgstr "" -#: ../src/qalc.cc:1726 ../src/qalc.cc:3202 +#: ../src/qalc.cc:1727 ../src/qalc.cc:3203 msgid "OPTION" msgstr "" -#: ../src/qalc.cc:1726 ../src/qalc.cc:3202 +#: ../src/qalc.cc:1727 ../src/qalc.cc:3203 msgid "VALUE" msgstr "" -#: ../src/qalc.cc:1727 +#: ../src/qalc.cc:1728 msgid "as set command in interactive program session (e.g. -set \"base 16\")" msgstr "" -#: ../src/qalc.cc:1729 +#: ../src/qalc.cc:1730 msgid "reduce output to just the result of the input expression" msgstr "" -#: ../src/qalc.cc:1731 +#: ../src/qalc.cc:1732 msgid "switch unicode support on/off" msgstr "" -#: ../src/qalc.cc:1733 +#: ../src/qalc.cc:1734 msgid "show application version and exit" msgstr "" -#: ../src/qalc.cc:1735 +#: ../src/qalc.cc:1736 msgid "" "The program will start in interactive mode if no expression and no file is " "specified (or interactive mode is explicitly selected)." msgstr "" -#: ../src/qalc.cc:1835 +#: ../src/qalc.cc:1836 msgid "No option and value specified for set command." msgstr "" -#: ../src/qalc.cc:1843 +#: ../src/qalc.cc:1844 msgid "No file specified." msgstr "" -#: ../src/qalc.cc:1910 +#: ../src/qalc.cc:1911 msgid "Failed to load global definitions!" msgstr "" -#: ../src/qalc.cc:1956 +#: ../src/qalc.cc:1957 #, c-format msgid "Could not open \"%s\".\n" msgstr "" -#: ../src/qalc.cc:1996 ../src/qalc.cc:2048 ../src/qalc.cc:4087 +#: ../src/qalc.cc:1997 ../src/qalc.cc:2049 ../src/qalc.cc:4088 #, c-format msgid "Illegal character, '%c', in expression." msgstr "" #. The qalc command "set" as in "set precision 10". The original text string for commands is kept in addition to the translation. -#: ../src/qalc.cc:2115 ../src/qalc.cc:3202 ../src/qalc.cc:3616 +#: ../src/qalc.cc:2116 ../src/qalc.cc:3203 ../src/qalc.cc:3617 msgid "set" msgstr "" #. qalc command -#: ../src/qalc.cc:2119 ../src/qalc.cc:3199 ../src/qalc.cc:3895 +#: ../src/qalc.cc:2120 ../src/qalc.cc:3200 ../src/qalc.cc:3896 msgid "save" msgstr "" -#: ../src/qalc.cc:2119 ../src/qalc.cc:3199 ../src/qalc.cc:3895 +#: ../src/qalc.cc:2120 ../src/qalc.cc:3200 ../src/qalc.cc:3896 msgid "store" msgstr "" #. qalc command -#: ../src/qalc.cc:2122 ../src/qalc.cc:2887 ../src/qalc.cc:3197 -#: ../src/qalc.cc:3921 +#: ../src/qalc.cc:2123 ../src/qalc.cc:2888 ../src/qalc.cc:3198 +#: ../src/qalc.cc:3922 msgid "mode" msgstr "" -#: ../src/qalc.cc:2124 +#: ../src/qalc.cc:2125 msgid "mode saved" msgstr "" -#: ../src/qalc.cc:2126 +#: ../src/qalc.cc:2127 msgid "definitions" msgstr "" -#: ../src/qalc.cc:2128 +#: ../src/qalc.cc:2129 msgid "definitions saved" msgstr "" -#: ../src/qalc.cc:2175 ../src/qalc.cc:2177 ../src/qalc.cc:2235 -#: ../src/qalc.cc:2237 ../src/qalc.cc:2292 ../src/qalc.cc:2294 +#: ../src/qalc.cc:2176 ../src/qalc.cc:2178 ../src/qalc.cc:2236 +#: ../src/qalc.cc:2238 ../src/qalc.cc:2293 ../src/qalc.cc:2295 #, c-format msgid "Illegal name. Save as %s instead (default: no)?" msgstr "" -#: ../src/qalc.cc:2184 ../src/qalc.cc:2244 +#: ../src/qalc.cc:2185 ../src/qalc.cc:2245 msgid "" "An unit or variable with the same name already exists.\n" "Do you want to overwrite it (default: no)?" msgstr "" #. qalc command -#: ../src/qalc.cc:2207 ../src/qalc.cc:3205 ../src/qalc.cc:3902 -#: ../libqalculate/Function.cc:2172 +#: ../src/qalc.cc:2208 ../src/qalc.cc:3206 ../src/qalc.cc:3903 +#: ../libqalculate/Function.cc:2206 msgid "variable" msgstr "" #. qalc command -#: ../src/qalc.cc:2264 ../src/qalc.cc:3195 ../src/qalc.cc:3908 -#: ../libqalculate/Function.cc:2144 +#: ../src/qalc.cc:2265 ../src/qalc.cc:3196 ../src/qalc.cc:3909 +#: ../libqalculate/Function.cc:2178 msgid "function" msgstr "" -#: ../src/qalc.cc:2301 +#: ../src/qalc.cc:2302 msgid "" "An function with the same name already exists.\n" "Do you want to overwrite it (default: no)?" msgstr "" #. qalc command -#: ../src/qalc.cc:2321 ../src/qalc.cc:3187 ../src/qalc.cc:3915 +#: ../src/qalc.cc:2322 ../src/qalc.cc:3188 ../src/qalc.cc:3916 msgid "delete" msgstr "" -#: ../src/qalc.cc:2332 +#: ../src/qalc.cc:2333 msgid "No user-defined variable or function with the specified name exist." msgstr "" #. qalc command -#: ../src/qalc.cc:2336 ../src/qalc.cc:3185 ../src/qalc.cc:3868 +#: ../src/qalc.cc:2337 ../src/qalc.cc:3186 ../src/qalc.cc:3869 msgid "assume" msgstr "" -#: ../src/qalc.cc:2346 +#: ../src/qalc.cc:2347 msgid "syntax" msgstr "" #. qalc command -#: ../src/qalc.cc:2353 ../src/qalc.cc:2388 ../src/qalc.cc:3209 -#: ../src/qalc.cc:3960 +#: ../src/qalc.cc:2354 ../src/qalc.cc:2389 ../src/qalc.cc:3210 +#: ../src/qalc.cc:3961 msgid "stack" msgstr "" #. qalc command -#: ../src/qalc.cc:2373 ../src/qalc.cc:3190 ../src/qalc.cc:3940 +#: ../src/qalc.cc:2374 ../src/qalc.cc:3191 ../src/qalc.cc:3941 msgid "exrates" msgstr "" -#: ../src/qalc.cc:2390 ../src/qalc.cc:2408 ../src/qalc.cc:2417 -#: ../src/qalc.cc:2450 ../src/qalc.cc:2479 ../src/qalc.cc:2488 -#: ../src/qalc.cc:2505 ../src/qalc.cc:2512 ../src/qalc.cc:2530 -#: ../src/qalc.cc:2537 +#: ../src/qalc.cc:2391 ../src/qalc.cc:2409 ../src/qalc.cc:2418 +#: ../src/qalc.cc:2451 ../src/qalc.cc:2480 ../src/qalc.cc:2489 +#: ../src/qalc.cc:2506 ../src/qalc.cc:2513 ../src/qalc.cc:2531 +#: ../src/qalc.cc:2538 msgid "The RPN stack is empty." msgstr "" #. qalc command -#: ../src/qalc.cc:2406 ../src/qalc.cc:2415 ../src/qalc.cc:3215 -#: ../src/qalc.cc:3964 +#: ../src/qalc.cc:2407 ../src/qalc.cc:2416 ../src/qalc.cc:3216 +#: ../src/qalc.cc:3965 msgid "swap" msgstr "" -#: ../src/qalc.cc:2410 ../src/qalc.cc:2419 ../src/qalc.cc:2452 -#: ../src/qalc.cc:2481 ../src/qalc.cc:2490 +#: ../src/qalc.cc:2411 ../src/qalc.cc:2420 ../src/qalc.cc:2453 +#: ../src/qalc.cc:2482 ../src/qalc.cc:2491 msgid "The RPN stack only contains one value." msgstr "" -#: ../src/qalc.cc:2438 ../src/qalc.cc:2471 ../src/qalc.cc:2519 -#: ../src/qalc.cc:2543 +#: ../src/qalc.cc:2439 ../src/qalc.cc:2472 ../src/qalc.cc:2520 +#: ../src/qalc.cc:2544 msgid "The specified RPN stack index does not exist." msgstr "" #. qalc command -#: ../src/qalc.cc:2448 ../src/qalc.cc:3212 ../src/qalc.cc:3986 +#: ../src/qalc.cc:2449 ../src/qalc.cc:3213 ../src/qalc.cc:3987 msgid "move" msgstr "" #. qalc command -#: ../src/qalc.cc:2477 ../src/qalc.cc:2486 ../src/qalc.cc:3214 -#: ../src/qalc.cc:3982 +#: ../src/qalc.cc:2478 ../src/qalc.cc:2487 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3983 msgid "rotate" msgstr "" -#: ../src/qalc.cc:2494 +#: ../src/qalc.cc:2495 msgid "up" msgstr "" -#: ../src/qalc.cc:2496 +#: ../src/qalc.cc:2497 msgid "down" msgstr "" #. qalc command -#: ../src/qalc.cc:2503 ../src/qalc.cc:2510 ../src/qalc.cc:3211 -#: ../src/qalc.cc:3974 +#: ../src/qalc.cc:2504 ../src/qalc.cc:2511 ../src/qalc.cc:3212 +#: ../src/qalc.cc:3975 msgid "copy" msgstr "" #. qalc command -#: ../src/qalc.cc:2525 ../src/qalc.cc:3210 ../src/qalc.cc:3950 +#: ../src/qalc.cc:2526 ../src/qalc.cc:3211 ../src/qalc.cc:3951 msgid "clear stack" msgstr "" #. qalc command -#: ../src/qalc.cc:2528 ../src/qalc.cc:2535 ../src/qalc.cc:3213 -#: ../src/qalc.cc:3954 +#: ../src/qalc.cc:2529 ../src/qalc.cc:2536 ../src/qalc.cc:3214 +#: ../src/qalc.cc:3955 msgid "pop" msgstr "" #. qalc command -#: ../src/qalc.cc:2569 ../src/qalc.cc:3204 ../src/qalc.cc:4006 +#: ../src/qalc.cc:2570 ../src/qalc.cc:3205 ../src/qalc.cc:4007 msgid "convert" msgstr "" #. "to"-operator -#: ../src/qalc.cc:2569 ../src/qalc.cc:3204 ../src/qalc.cc:4006 -#: ../src/qalc.cc:4049 ../libqalculate/Calculator.cc:518 -#: ../libqalculate/Calculator.cc:744 ../libqalculate/Calculator.cc:1540 -#: ../libqalculate/Calculator.cc:1541 ../libqalculate/Calculator.cc:3233 -#: ../libqalculate/Calculator.cc:3235 ../libqalculate/Calculator.cc:3248 -#: ../libqalculate/Calculator.cc:3250 ../libqalculate/Calculator.cc:3264 -#: ../libqalculate/Calculator.cc:3266 +#: ../src/qalc.cc:2570 ../src/qalc.cc:3205 ../src/qalc.cc:4007 +#: ../src/qalc.cc:4050 ../libqalculate/Calculator-calculate.cc:1065 +#: ../libqalculate/Calculator-calculate.cc:1067 +#: ../libqalculate/Calculator-calculate.cc:1080 +#: ../libqalculate/Calculator-calculate.cc:1082 +#: ../libqalculate/Calculator-calculate.cc:1096 +#: ../libqalculate/Calculator-calculate.cc:1098 +#: ../libqalculate/Calculator.cc:296 ../libqalculate/Calculator.cc:524 +#: ../libqalculate/Calculator.cc:1322 ../libqalculate/Calculator.cc:1323 msgid "to" msgstr "" -#: ../src/qalc.cc:2654 ../src/qalc.cc:4822 ../libqalculate/Calculator.cc:3006 +#: ../src/qalc.cc:2655 ../src/qalc.cc:4823 +#: ../libqalculate/Calculator-calculate.cc:792 msgid "Time zone parsing failed." msgstr "" -#: ../src/qalc.cc:2727 ../src/qalc.cc:4850 ../libqalculate/Calculator.cc:3041 +#: ../src/qalc.cc:2728 ../src/qalc.cc:4851 +#: ../libqalculate/Calculator-calculate.cc:827 msgid "bases" msgstr "" -#: ../src/qalc.cc:2774 ../src/qalc.cc:4853 ../libqalculate/Calculator.cc:3044 +#: ../src/qalc.cc:2775 ../src/qalc.cc:4854 +#: ../libqalculate/Calculator-calculate.cc:830 msgid "calendars" msgstr "" -#: ../src/qalc.cc:2784 ../src/qalc.cc:4841 ../libqalculate/Calculator.cc:3031 +#: ../src/qalc.cc:2785 ../src/qalc.cc:4842 +#: ../libqalculate/Calculator-calculate.cc:817 msgid "fraction" msgstr "" -#: ../src/qalc.cc:2793 ../src/qalc.cc:4844 ../libqalculate/Calculator.cc:3034 +#: ../src/qalc.cc:2794 ../src/qalc.cc:4845 +#: ../libqalculate/Calculator-calculate.cc:820 msgid "factors" msgstr "" #. qalc command -#: ../src/qalc.cc:2795 ../src/qalc.cc:2881 ../src/qalc.cc:3198 -#: ../src/qalc.cc:3608 ../src/qalc.cc:4847 ../libqalculate/Calculator.cc:3038 +#: ../src/qalc.cc:2796 ../src/qalc.cc:2882 ../src/qalc.cc:3199 +#: ../src/qalc.cc:3609 ../src/qalc.cc:4848 +#: ../libqalculate/Calculator-calculate.cc:824 msgid "partial fraction" msgstr "" #. qalc command -#: ../src/qalc.cc:2878 ../src/qalc.cc:3193 ../src/qalc.cc:3604 +#: ../src/qalc.cc:2879 ../src/qalc.cc:3194 ../src/qalc.cc:3605 msgid "factor" msgstr "" -#: ../src/qalc.cc:2892 ../src/qalc.cc:3633 +#: ../src/qalc.cc:2893 ../src/qalc.cc:3634 msgid "Algebraic Mode" msgstr "" -#: ../src/qalc.cc:2927 ../src/qalc.cc:3665 +#: ../src/qalc.cc:2928 ../src/qalc.cc:3666 msgid "Calculation" msgstr "" -#: ../src/qalc.cc:2950 +#: ../src/qalc.cc:2951 msgid "simplified" msgstr "" -#: ../src/qalc.cc:2955 ../src/qalc.cc:3675 +#: ../src/qalc.cc:2956 ../src/qalc.cc:3676 msgid "Enabled Objects" msgstr "" -#: ../src/qalc.cc:2967 ../src/qalc.cc:3687 +#: ../src/qalc.cc:2968 ../src/qalc.cc:3688 msgid "Generic Display Options" msgstr "" -#: ../src/qalc.cc:2992 ../src/qalc.cc:3700 +#: ../src/qalc.cc:2993 ../src/qalc.cc:3701 msgid "Numerical Display" msgstr "" -#: ../src/qalc.cc:3093 ../src/qalc.cc:3783 +#: ../src/qalc.cc:3094 ../src/qalc.cc:3784 msgid "Parsing" msgstr "" -#: ../src/qalc.cc:3139 ../src/qalc.cc:3829 +#: ../src/qalc.cc:3140 ../src/qalc.cc:3830 msgid "Units" msgstr "" -#: ../src/qalc.cc:3168 ../src/qalc.cc:3861 +#: ../src/qalc.cc:3169 ../src/qalc.cc:3862 msgid "Other" msgstr "" #. qalc command -#: ../src/qalc.cc:3176 ../src/qalc.cc:3600 +#: ../src/qalc.cc:3177 ../src/qalc.cc:3601 msgid "help" msgstr "" -#: ../src/qalc.cc:3179 +#: ../src/qalc.cc:3180 msgid "Enter a mathematical expression or a command and press enter." msgstr "" -#: ../src/qalc.cc:3180 +#: ../src/qalc.cc:3181 msgid "Complete functions, units and variables with the tabulator key." msgstr "" -#: ../src/qalc.cc:3182 +#: ../src/qalc.cc:3183 msgid "Available commands are:" msgstr "" -#: ../src/qalc.cc:3185 +#: ../src/qalc.cc:3186 msgid "ASSUMPTIONS" msgstr "" -#: ../src/qalc.cc:3187 ../src/qalc.cc:3194 ../src/qalc.cc:3195 -#: ../src/qalc.cc:3199 ../src/qalc.cc:3205 +#: ../src/qalc.cc:3188 ../src/qalc.cc:3195 ../src/qalc.cc:3196 +#: ../src/qalc.cc:3200 ../src/qalc.cc:3206 msgid "NAME" msgstr "" -#: ../src/qalc.cc:3194 ../src/qalc.cc:3226 ../src/qalc.cc:3925 +#: ../src/qalc.cc:3195 ../src/qalc.cc:3227 ../src/qalc.cc:3926 msgid "find" msgstr "" #. qalc command -#: ../src/qalc.cc:3194 ../src/qalc.cc:3224 ../src/qalc.cc:3226 -#: ../src/qalc.cc:3925 +#: ../src/qalc.cc:3195 ../src/qalc.cc:3225 ../src/qalc.cc:3227 +#: ../src/qalc.cc:3926 msgid "list" msgstr "" -#: ../src/qalc.cc:3195 ../src/qalc.cc:3205 +#: ../src/qalc.cc:3196 ../src/qalc.cc:3206 msgid "EXPRESSION" msgstr "" #. qalc command -#: ../src/qalc.cc:3196 ../src/qalc.cc:3252 ../src/qalc.cc:3934 -#: ../libqalculate/Calculator.cc:11336 ../libqalculate/DataSet.cc:364 -#: ../libqalculate/DataSet.cc:391 ../libqalculate/DataSet.cc:1038 +#: ../src/qalc.cc:3197 ../src/qalc.cc:3253 ../src/qalc.cc:3935 +#: ../libqalculate/Calculator-definitions.cc:2887 +#: ../libqalculate/DataSet.cc:365 ../libqalculate/DataSet.cc:392 +#: ../libqalculate/DataSet.cc:1039 msgid "info" msgstr "" -#: ../src/qalc.cc:3199 +#: ../src/qalc.cc:3200 msgid "CATEGORY" msgstr "" -#: ../src/qalc.cc:3199 +#: ../src/qalc.cc:3200 msgid "TITLE" msgstr "" -#: ../src/qalc.cc:3204 +#: ../src/qalc.cc:3205 msgid "UNIT or \"TO\" COMMAND" msgstr "" #. qalc command -#: ../src/qalc.cc:3206 ../src/qalc.cc:4053 ../src/qalc.cc:4074 +#: ../src/qalc.cc:3207 ../src/qalc.cc:4054 ../src/qalc.cc:4075 msgid "quit" msgstr "" -#: ../src/qalc.cc:3206 ../src/qalc.cc:4053 ../src/qalc.cc:4074 +#: ../src/qalc.cc:3207 ../src/qalc.cc:4054 ../src/qalc.cc:4075 msgid "exit" msgstr "" -#: ../src/qalc.cc:3207 +#: ../src/qalc.cc:3208 msgid "Commands for RPN mode:" msgstr "" -#: ../src/qalc.cc:3208 +#: ../src/qalc.cc:3209 msgid "STATE" msgstr "" -#: ../src/qalc.cc:3211 ../src/qalc.cc:3213 +#: ../src/qalc.cc:3212 ../src/qalc.cc:3214 msgid "INDEX" msgstr "" -#: ../src/qalc.cc:3212 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3213 ../src/qalc.cc:3216 msgid "INDEX 1" msgstr "" -#: ../src/qalc.cc:3212 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3213 ../src/qalc.cc:3216 msgid "INDEX 2" msgstr "" -#: ../src/qalc.cc:3214 +#: ../src/qalc.cc:3215 msgid "DIRECTION" msgstr "" -#: ../src/qalc.cc:3217 +#: ../src/qalc.cc:3218 msgid "Type help COMMAND for more information (example: help save)." msgstr "" -#: ../src/qalc.cc:3218 +#: ../src/qalc.cc:3219 msgid "" "Type info NAME for information about a function, variable or unit (example: " "info sin)." msgstr "" -#: ../src/qalc.cc:3219 +#: ../src/qalc.cc:3220 msgid "" "When a line begins with '/', the following text is always interpreted as a " "command." msgstr "" -#: ../src/qalc.cc:3221 +#: ../src/qalc.cc:3222 msgid "" "For more information about mathematical expression, different options, and a " "complete list of functions, variables and units, see the relevant sections " @@ -1449,362 +1465,362 @@ "qalculate.github.io/manual/index.html)." msgstr "" -#: ../src/qalc.cc:3239 ../src/qalc.cc:3244 +#: ../src/qalc.cc:3240 ../src/qalc.cc:3245 msgid "currencies" msgstr "" -#: ../src/qalc.cc:3261 +#: ../src/qalc.cc:3262 msgid "No function, variable or unit with specified name exist." msgstr "" -#: ../src/qalc.cc:3271 +#: ../src/qalc.cc:3272 msgid "Function" msgstr "" -#: ../src/qalc.cc:3408 +#: ../src/qalc.cc:3409 msgid "Expression:" msgstr "" -#: ../src/qalc.cc:3417 ../src/qalc.cc:3420 ../src/qalc.cc:3587 +#: ../src/qalc.cc:3418 ../src/qalc.cc:3421 ../src/qalc.cc:3588 msgid "Unit" msgstr "" -#: ../src/qalc.cc:3423 ../src/qalc.cc:3497 +#: ../src/qalc.cc:3424 ../src/qalc.cc:3498 msgid "Names" msgstr "" -#: ../src/qalc.cc:3441 +#: ../src/qalc.cc:3442 msgid "Base Unit" msgstr "" -#: ../src/qalc.cc:3448 +#: ../src/qalc.cc:3449 msgid "Relation" msgstr "" -#: ../src/qalc.cc:3453 ../src/qalc.cc:3555 +#: ../src/qalc.cc:3454 ../src/qalc.cc:3556 msgid "Relative uncertainty" msgstr "" -#: ../src/qalc.cc:3454 ../src/qalc.cc:3556 +#: ../src/qalc.cc:3455 ../src/qalc.cc:3557 msgid "Uncertainty" msgstr "" -#: ../src/qalc.cc:3464 +#: ../src/qalc.cc:3465 msgid "Inverse Relation" msgstr "" -#: ../src/qalc.cc:3476 +#: ../src/qalc.cc:3477 msgid "Base Units" msgstr "" -#: ../src/qalc.cc:3491 ../src/qalc.cc:3494 +#: ../src/qalc.cc:3492 ../src/qalc.cc:3495 msgid "Variable" msgstr "" -#: ../src/qalc.cc:3606 +#: ../src/qalc.cc:3607 msgid "Factorizes the current result." msgstr "" -#: ../src/qalc.cc:3610 +#: ../src/qalc.cc:3611 msgid "Applies partial fraction decomposition to the current result." msgstr "" -#: ../src/qalc.cc:3614 +#: ../src/qalc.cc:3615 msgid "Expands the current result." msgstr "" -#: ../src/qalc.cc:3628 +#: ../src/qalc.cc:3629 msgid "Sets the value of an option." msgstr "" -#: ../src/qalc.cc:3629 +#: ../src/qalc.cc:3630 msgid "Example: set base 16." msgstr "" -#: ../src/qalc.cc:3631 +#: ../src/qalc.cc:3632 msgid "" "Available options and accepted values are (the current value is marked with " "'*'):" msgstr "" -#: ../src/qalc.cc:3635 +#: ../src/qalc.cc:3636 msgid "Determines if the expression is factorized or not after calculation." msgstr "" -#: ../src/qalc.cc:3636 +#: ../src/qalc.cc:3637 msgid "Determines if unknown values will be assumed non-zero (x/x=1)." msgstr "" -#: ../src/qalc.cc:3637 +#: ../src/qalc.cc:3638 msgid "Display a message after a value has been assumed non-zero." msgstr "" -#: ../src/qalc.cc:3640 +#: ../src/qalc.cc:3641 msgid "Default assumptions for unknown variables." msgstr "" -#: ../src/qalc.cc:3668 +#: ../src/qalc.cc:3669 msgid "" "How approximate variables and calculations are handled. In exact mode " "approximate values will not be calculated." msgstr "" -#: ../src/qalc.cc:3669 +#: ../src/qalc.cc:3670 msgid "" "If activated, interval arithmetic determines the final precision of " "calculations (avoids wrong results after loss of significance) with " "approximate functions and/or irrational numbers." msgstr "" -#: ../src/qalc.cc:3670 +#: ../src/qalc.cc:3671 msgid "" "Determines the method used for interval calculation / uncertainty " "propagation." msgstr "" -#: ../src/qalc.cc:3672 +#: ../src/qalc.cc:3673 msgid "" "Specifies the default number of significant digits displayed and determines " "the precision used for approximate calculations." msgstr "" -#: ../src/qalc.cc:3683 +#: ../src/qalc.cc:3684 msgid "Interprete undefined symbols in expressions as unknown variables." msgstr "" -#: ../src/qalc.cc:3685 +#: ../src/qalc.cc:3686 msgid "" "If activated physical constants include units (e.g. c = 299 792 458 m∕s)." msgstr "" -#: ../src/qalc.cc:3689 +#: ../src/qalc.cc:3690 msgid "Use abbreviated names for units and variables." msgstr "" -#: ../src/qalc.cc:3692 +#: ../src/qalc.cc:3693 msgid "Always place negative values last." msgstr "" -#: ../src/qalc.cc:3694 +#: ../src/qalc.cc:3695 msgid "Use negative exponents instead of division in result (x/y = xy^-1)." msgstr "" -#: ../src/qalc.cc:3696 +#: ../src/qalc.cc:3697 msgid "Add extra space around operators." msgstr "" -#: ../src/qalc.cc:3698 +#: ../src/qalc.cc:3699 msgid "Display Unicode characters." msgstr "" -#: ../src/qalc.cc:3702 ../src/qalc.cc:3804 +#: ../src/qalc.cc:3703 ../src/qalc.cc:3805 msgid "bin" msgstr "" -#: ../src/qalc.cc:3704 ../src/qalc.cc:3806 +#: ../src/qalc.cc:3705 ../src/qalc.cc:3807 msgid "oct" msgstr "" -#: ../src/qalc.cc:3706 ../src/qalc.cc:3808 +#: ../src/qalc.cc:3707 ../src/qalc.cc:3809 msgid "dec" msgstr "" -#: ../src/qalc.cc:3708 ../src/qalc.cc:3810 +#: ../src/qalc.cc:3709 ../src/qalc.cc:3811 msgid "hex" msgstr "" -#: ../src/qalc.cc:3710 +#: ../src/qalc.cc:3711 msgid "sexa" msgstr "" -#: ../src/qalc.cc:3729 ../src/qalc.cc:3787 +#: ../src/qalc.cc:3730 ../src/qalc.cc:3788 msgid "Determines the default decimal separator." msgstr "" -#: ../src/qalc.cc:3742 +#: ../src/qalc.cc:3743 msgid "" "Determines how rational numbers are displayed (e.g. 5/4 = 1 + 1/4 = 1.25). " "'long' removes limits on the size of the numerator and denonimator." msgstr "" -#: ../src/qalc.cc:3743 +#: ../src/qalc.cc:3744 msgid "" "Enables two's complement representation for display of negative hexadecimal " "numbers." msgstr "" -#: ../src/qalc.cc:3744 ../src/qalc.cc:3803 +#: ../src/qalc.cc:3745 ../src/qalc.cc:3804 msgid "Use 'j' (instead of 'i') as default symbol for the imaginary unit." msgstr "" -#: ../src/qalc.cc:3746 +#: ../src/qalc.cc:3747 msgid "Use lowercase e for E-notation (5e2 = 5 * 10^2)." msgstr "" -#: ../src/qalc.cc:3747 +#: ../src/qalc.cc:3748 msgid "Use lowercase letters for number bases > 10." msgstr "" -#: ../src/qalc.cc:3762 +#: ../src/qalc.cc:3763 msgid "" "If activated, 1/6 is displayed as '0.1 666...', otherwise as '0.166667'." msgstr "" -#: ../src/qalc.cc:3763 +#: ../src/qalc.cc:3764 msgid "" "Determines whether halfway numbers are rounded upwards or towards the " "nearest even integer." msgstr "" -#: ../src/qalc.cc:3765 +#: ../src/qalc.cc:3766 msgid "Determines how scientific notation are used (e.g. 5 543 000 = 5.543E6)." msgstr "" -#: ../src/qalc.cc:3780 +#: ../src/qalc.cc:3781 msgid "If actived, zeroes are kept at the end of approximate numbers." msgstr "" -#: ../src/qalc.cc:3781 +#: ../src/qalc.cc:3782 msgid "" "Enables two's complement representation for display of negative binary " "numbers." msgstr "" -#: ../src/qalc.cc:3785 +#: ../src/qalc.cc:3786 msgid "Use ^ as bitwise exclusive OR operator." msgstr "" -#: ../src/qalc.cc:3798 +#: ../src/qalc.cc:3799 msgid "Allows use of ',' as thousands separator." msgstr "" -#: ../src/qalc.cc:3801 +#: ../src/qalc.cc:3802 msgid "Allows use of '.' as thousands separator." msgstr "" -#: ../src/qalc.cc:3825 +#: ../src/qalc.cc:3826 msgid "See 'help parsing mode'." msgstr "" -#: ../src/qalc.cc:3826 +#: ../src/qalc.cc:3827 msgid "" "If activated, numbers be interpreted as approximate with precision equal to " "the number of significant digits (3.20 = 3.20+/-0.005)." msgstr "" -#: ../src/qalc.cc:3831 +#: ../src/qalc.cc:3832 msgid "Enables automatic use of hecto, deca, deci, and centi." msgstr "" -#: ../src/qalc.cc:3833 +#: ../src/qalc.cc:3834 msgid "" "Controls automatic unit conversion of the result. 'optimalsi' always " "converts non-SI units, while 'optimal' only converts to more optimal unit " "expressions, with less units and exponents." msgstr "" -#: ../src/qalc.cc:3847 +#: ../src/qalc.cc:3848 msgid "" "If activated, binary prefixes are used by default for information units." msgstr "" -#: ../src/qalc.cc:3848 +#: ../src/qalc.cc:3849 msgid "" "Enables automatic conversion to the local currency when optimal unit " "conversion is enabled." msgstr "" -#: ../src/qalc.cc:3849 +#: ../src/qalc.cc:3850 msgid "" "Enables automatic use of prefixes in the denominator of unit expressions." msgstr "" -#: ../src/qalc.cc:3850 +#: ../src/qalc.cc:3851 msgid "" "If activated, units are separated from variables at the end of the result." msgstr "" -#: ../src/qalc.cc:3851 +#: ../src/qalc.cc:3852 msgid "Enables automatic use of prefixes in the result." msgstr "" -#: ../src/qalc.cc:3856 +#: ../src/qalc.cc:3857 msgid "days" msgstr "" -#: ../src/qalc.cc:3863 +#: ../src/qalc.cc:3864 msgid "Ignore system language and use English (requires restart)." msgstr "" -#: ../src/qalc.cc:3864 +#: ../src/qalc.cc:3865 msgid "Activates the Reverse Polish Notation stack." msgstr "" -#: ../src/qalc.cc:3865 +#: ../src/qalc.cc:3866 msgid "Save functions, units, and variables on exit." msgstr "" -#: ../src/qalc.cc:3866 +#: ../src/qalc.cc:3867 msgid "Save settings on exit." msgstr "" -#: ../src/qalc.cc:3870 +#: ../src/qalc.cc:3871 msgid "Set default assumptions for unknown variables." msgstr "" -#: ../src/qalc.cc:3897 +#: ../src/qalc.cc:3898 msgid "" "Saves the current result in a variable with the specified name. You may " "optionally also provide a category (default \"Temporary\") and a title." msgstr "" -#: ../src/qalc.cc:3898 +#: ../src/qalc.cc:3899 msgid "" "If name equals \"mode\" or \"definitions\", the current mode and " "definitions, respectively, will be saved." msgstr "" -#: ../src/qalc.cc:3900 +#: ../src/qalc.cc:3901 msgid "Example: store var1." msgstr "" -#: ../src/qalc.cc:3904 +#: ../src/qalc.cc:3905 msgid "Create a variables with the specified name and expression." msgstr "" -#: ../src/qalc.cc:3906 +#: ../src/qalc.cc:3907 msgid "Example: variable var1 pi / 2." msgstr "" -#: ../src/qalc.cc:3910 +#: ../src/qalc.cc:3911 msgid "Creates a function with the specified name and expression." msgstr "" -#: ../src/qalc.cc:3911 +#: ../src/qalc.cc:3912 msgid "Use '\\x', '\\y', '\\z', '\\a', etc. for arguments in the expression." msgstr "" -#: ../src/qalc.cc:3913 +#: ../src/qalc.cc:3914 msgid "Example: function func1 5*\\x." msgstr "" -#: ../src/qalc.cc:3917 +#: ../src/qalc.cc:3918 msgid "Removes the user-defined variable or function with the specified name." msgstr "" -#: ../src/qalc.cc:3919 +#: ../src/qalc.cc:3920 msgid "Example: delete var1." msgstr "" -#: ../src/qalc.cc:3923 +#: ../src/qalc.cc:3924 msgid "Displays the current mode." msgstr "" -#: ../src/qalc.cc:3927 +#: ../src/qalc.cc:3928 msgid "Displays a list of variables, functions and units." msgstr "" -#: ../src/qalc.cc:3928 +#: ../src/qalc.cc:3929 msgid "" "Enter with argument 'currencies', 'functions', 'variables' or 'units' to " "show a list of all currencies, functions, variables or units. Enter a search " @@ -1812,256 +1828,256 @@ "called with no argument all user-definied objects are listed." msgstr "" -#: ../src/qalc.cc:3930 +#: ../src/qalc.cc:3931 msgid "Example: list functions." msgstr "" -#: ../src/qalc.cc:3931 +#: ../src/qalc.cc:3932 msgid "Example: find dinar." msgstr "" -#: ../src/qalc.cc:3932 +#: ../src/qalc.cc:3933 msgid "Example: find variables planck." msgstr "" -#: ../src/qalc.cc:3936 +#: ../src/qalc.cc:3937 msgid "Displays information about a function, variable or unit." msgstr "" -#: ../src/qalc.cc:3938 +#: ../src/qalc.cc:3939 msgid "Example: info sin." msgstr "" -#: ../src/qalc.cc:3942 +#: ../src/qalc.cc:3943 msgid "Downloads current exchange rates from the Internet." msgstr "" -#: ../src/qalc.cc:3946 +#: ../src/qalc.cc:3947 msgid "(De)activates the Reverse Polish Notation stack and syntax." msgstr "" -#: ../src/qalc.cc:3948 +#: ../src/qalc.cc:3949 msgid "" "\"syntax\" activates only the RPN syntax and \"stack\" enables the RPN stack." msgstr "" -#: ../src/qalc.cc:3952 +#: ../src/qalc.cc:3953 msgid "Clears the entire RPN stack." msgstr "" -#: ../src/qalc.cc:3956 +#: ../src/qalc.cc:3957 msgid "Removes the top of the RPN stack or the value at the specified index." msgstr "" -#: ../src/qalc.cc:3958 ../src/qalc.cc:3970 ../src/qalc.cc:3980 -#: ../src/qalc.cc:3990 +#: ../src/qalc.cc:3959 ../src/qalc.cc:3971 ../src/qalc.cc:3981 +#: ../src/qalc.cc:3991 msgid "" "Index 1 is the top of stack and negative index values counts from the bottom " "of the stack." msgstr "" -#: ../src/qalc.cc:3962 +#: ../src/qalc.cc:3963 msgid "Displays the RPN stack." msgstr "" -#: ../src/qalc.cc:3966 +#: ../src/qalc.cc:3967 msgid "Swaps position of values on the RPN stack." msgstr "" -#: ../src/qalc.cc:3968 +#: ../src/qalc.cc:3969 msgid "" "If no index is specified, the values on the top of the stack (index 1 and " "index 2) will be swapped and if only one index is specified, the value at " "this index will be swapped with the top value." msgstr "" -#: ../src/qalc.cc:3972 +#: ../src/qalc.cc:3973 msgid "Example: swap 2 4" msgstr "" -#: ../src/qalc.cc:3976 +#: ../src/qalc.cc:3977 msgid "Duplicates a value on the RPN stack to the top of the stack." msgstr "" -#: ../src/qalc.cc:3978 +#: ../src/qalc.cc:3979 msgid "If no index is specified, the top of the stack is duplicated." msgstr "" -#: ../src/qalc.cc:3984 +#: ../src/qalc.cc:3985 msgid "Rotates the RPN stack up (default) or down." msgstr "" -#: ../src/qalc.cc:3988 +#: ../src/qalc.cc:3989 msgid "Changes the position of a value on the RPN stack." msgstr "" -#: ../src/qalc.cc:3992 +#: ../src/qalc.cc:3993 msgid "Example: move 2 4" msgstr "" -#: ../src/qalc.cc:3996 +#: ../src/qalc.cc:3997 msgid "Sets the result number base (equivalent to set base)." msgstr "" -#: ../src/qalc.cc:4000 +#: ../src/qalc.cc:4001 msgid "Equivalent to set approximation exact." msgstr "" -#: ../src/qalc.cc:4004 +#: ../src/qalc.cc:4005 msgid "Equivalent to set approximation try exact." msgstr "" -#: ../src/qalc.cc:4009 +#: ../src/qalc.cc:4010 msgid "Converts units or changes number base in current result." msgstr "" -#: ../src/qalc.cc:4011 +#: ../src/qalc.cc:4012 msgid "Possible values:" msgstr "" -#: ../src/qalc.cc:4013 +#: ../src/qalc.cc:4014 msgid "- a unit or unit expression (e.g. meter or km/h)" msgstr "" -#: ../src/qalc.cc:4014 +#: ../src/qalc.cc:4015 msgid "prepend with ? to request the optimal prefix" msgstr "" -#: ../src/qalc.cc:4015 +#: ../src/qalc.cc:4016 msgid "prepend with b? to request the optimal binary prefix" msgstr "" -#: ../src/qalc.cc:4016 +#: ../src/qalc.cc:4017 msgid "prepend with + or - to force/disable use of mixed units" msgstr "" -#: ../src/qalc.cc:4017 +#: ../src/qalc.cc:4018 msgid "- a variable or physical constant (e.g. c)" msgstr "" -#: ../src/qalc.cc:4018 +#: ../src/qalc.cc:4019 msgid "- base (convert to base units)" msgstr "" -#: ../src/qalc.cc:4019 +#: ../src/qalc.cc:4020 msgid "- optimal (convert to optimal unit)" msgstr "" -#: ../src/qalc.cc:4020 +#: ../src/qalc.cc:4021 msgid "- mixed (convert to mixed units, e.g. hours + minutes)" msgstr "" -#: ../src/qalc.cc:4022 +#: ../src/qalc.cc:4023 msgid "- bin / binary (show as binary number)" msgstr "" -#: ../src/qalc.cc:4023 +#: ../src/qalc.cc:4024 msgid "- oct / octal (show as octal number)" msgstr "" -#: ../src/qalc.cc:4024 +#: ../src/qalc.cc:4025 msgid "- duo / duodecimal (show as duodecimal number)" msgstr "" -#: ../src/qalc.cc:4025 +#: ../src/qalc.cc:4026 msgid "- hex / hexadecimal (show as hexadecimal number)" msgstr "" -#: ../src/qalc.cc:4026 +#: ../src/qalc.cc:4027 msgid "- sex / sexagesimal (show as sexagesimal number)" msgstr "" -#: ../src/qalc.cc:4027 +#: ../src/qalc.cc:4028 msgid "- bijective (shown in bijective base-26)" msgstr "" -#: ../src/qalc.cc:4028 +#: ../src/qalc.cc:4029 msgid "- roman (show as roman numerals)" msgstr "" -#: ../src/qalc.cc:4029 +#: ../src/qalc.cc:4030 msgid "- time (show in time format)" msgstr "" -#: ../src/qalc.cc:4030 +#: ../src/qalc.cc:4031 msgid "- unicode" msgstr "" -#: ../src/qalc.cc:4031 +#: ../src/qalc.cc:4032 msgid "- base # (show in specified number base)" msgstr "" -#: ../src/qalc.cc:4032 +#: ../src/qalc.cc:4033 msgid "- bases (show as binary, octal, decimal and hexadecimal number)" msgstr "" -#: ../src/qalc.cc:4034 +#: ../src/qalc.cc:4035 msgid "- rectangular / cartesian (show complex numbers in rectangular form)" msgstr "" -#: ../src/qalc.cc:4035 +#: ../src/qalc.cc:4036 msgid "- exponential (show complex numbers in exponential form)" msgstr "" -#: ../src/qalc.cc:4036 +#: ../src/qalc.cc:4037 msgid "- polar (show complex numbers in polar form)" msgstr "" -#: ../src/qalc.cc:4037 +#: ../src/qalc.cc:4038 msgid "- cis (show complex numbers in cis form)" msgstr "" -#: ../src/qalc.cc:4038 +#: ../src/qalc.cc:4039 msgid "- angle / phasor (show complex numbers in angle/phasor notation)" msgstr "" -#: ../src/qalc.cc:4040 +#: ../src/qalc.cc:4041 msgid "- fraction (show result as mixed fraction)" msgstr "" -#: ../src/qalc.cc:4041 +#: ../src/qalc.cc:4042 msgid "- factors (factorize result)" msgstr "" -#: ../src/qalc.cc:4043 +#: ../src/qalc.cc:4044 msgid "- UTC (show date and time in UTC time zone)" msgstr "" -#: ../src/qalc.cc:4044 +#: ../src/qalc.cc:4045 msgid "- UTC+/-hh[:mm] (show date and time in specified time zone)" msgstr "" -#: ../src/qalc.cc:4045 +#: ../src/qalc.cc:4046 msgid "- calendars" msgstr "" -#: ../src/qalc.cc:4047 +#: ../src/qalc.cc:4048 msgid "Example: to ?g" msgstr "" -#: ../src/qalc.cc:4050 +#: ../src/qalc.cc:4051 msgid "" "This command can also be typed directly at the end of the mathematical " "expression (e.g. 5 ft + 2 in to meter)." msgstr "" -#: ../src/qalc.cc:4055 +#: ../src/qalc.cc:4056 msgid "Terminates this program." msgstr "" -#: ../src/qalc.cc:4060 +#: ../src/qalc.cc:4061 msgid "" "Implicit multiplication does not differ from explicit multiplication " "(\"12/2(1+2) = 12/2*3 = 18\", \"5x/5y = 5*x/5*y = xy\")." msgstr "" -#: ../src/qalc.cc:4063 +#: ../src/qalc.cc:4064 msgid "" "Implicit multiplication is parsed before explicit multiplication " "(\"12/2(1+2) = 12/(2*3) = 2\", \"5x/5y = (5*x)/(5*y) = x/y\")." msgstr "" -#: ../src/qalc.cc:4066 +#: ../src/qalc.cc:4067 msgid "" "The default adaptive mode works as the \"implicit first\" mode, unless " "spaces are found (\"1/5x = 1/(5*x)\", but \"1/5 x = (1/5)*x\"). In the " @@ -2069,1038 +2085,1086 @@ "(5*(m/s)) = 1 s\")." msgstr "" -#: ../src/qalc.cc:4068 +#: ../src/qalc.cc:4069 msgid "" "Function arguments without parentheses are an exception, where implicit " "multiplication in front of variables and units is parsed first regardless of " "mode (\"sqrt 2x = sqrt(2x)\")." msgstr "" -#: ../src/qalc.cc:4082 +#: ../src/qalc.cc:4083 msgid "Unknown command." msgstr "" -#: ../src/qalc.cc:4131 +#: ../src/qalc.cc:4132 msgid "error" msgstr "" -#: ../src/qalc.cc:4133 +#: ../src/qalc.cc:4134 msgid "warning" msgstr "" -#: ../src/qalc.cc:4156 ../src/qalc.cc:4441 ../src/qalc.cc:5320 +#: ../src/qalc.cc:4157 ../src/qalc.cc:4442 ../src/qalc.cc:5347 msgid "approx." msgstr "" -#: ../src/qalc.cc:4240 ../src/qalc.cc:4278 ../src/qalc.cc:4598 -#: ../src/qalc.cc:5173 ../libqalculate/Calculator.cc:11754 -#: ../libqalculate/MathStructure.cc:780 +#: ../src/qalc.cc:4241 ../src/qalc.cc:4279 ../src/qalc.cc:4599 +#: ../src/qalc.cc:5178 ../libqalculate/Calculator-calculate.cc:1615 +#: ../libqalculate/MathStructure.cc:448 #, c-format msgid "aborted" msgstr "" -#: ../src/qalc.cc:4290 +#: ../src/qalc.cc:4291 msgid "RPN Register Moved" msgstr "" -#: ../src/qalc.cc:4346 +#: ../src/qalc.cc:4347 msgid "Processing (press Enter to abort)" msgstr "" -#: ../src/qalc.cc:4615 +#: ../src/qalc.cc:4616 msgid "Factorizing (press Enter to abort)" msgstr "" -#: ../src/qalc.cc:4619 +#: ../src/qalc.cc:4620 msgid "Expanding partial fractions…" msgstr "" -#: ../src/qalc.cc:4623 +#: ../src/qalc.cc:4624 msgid "Expanding (press Enter to abort)" msgstr "" -#: ../src/qalc.cc:4627 ../src/qalc.cc:5187 +#: ../src/qalc.cc:4628 ../src/qalc.cc:5192 msgid "Calculating (press Enter to abort)" msgstr "" -#: ../src/qalc.cc:5273 +#: ../src/qalc.cc:5300 msgid "RPN Operation" msgstr "" -#: ../src/qalc.cc:5805 +#: ../src/qalc.cc:5832 #, c-format msgid "" "Couldn't write preferences to\n" "%s" msgstr "" -#: ../src/qalc.cc:5913 +#: ../src/qalc.cc:5940 msgid "Couldn't write definitions" msgstr "" -#: ../src/test.cc:13 ../src/test.cc:28 ../libqalculate/Calculator.cc:2229 +#. thread cancellation is not safe +#: ../src/test.cc:13 ../src/test.cc:28 +#: ../libqalculate/Calculator-calculate.cc:172 msgid "" "The calculation has been forcibly terminated. Please restart the application " "and report this as a bug." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:109 +#: ../libqalculate/BuiltinFunctions-algebra.cc:359 +msgid "" +"No equality or inequality to solve. The entered expression to solve is not " +"correct (ex. \"x + 5 = 3\" is correct)" +msgstr "" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:406 #, c-format -msgid "Too many elements (%s) for the dimensions (%sx%s) of the matrix." +msgid "The comparison is true for all %s (with current assumptions)." +msgstr "" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:410 +msgid "No possible solution was found (with current assumptions)." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:172 -#: ../libqalculate/BuiltinFunctions.cc:234 +#: ../libqalculate/BuiltinFunctions-algebra.cc:414 #, c-format -msgid "Row %s does not exist in matrix." +msgid "Was unable to completely isolate %s." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:185 -#: ../libqalculate/BuiltinFunctions.cc:230 +#: ../libqalculate/BuiltinFunctions-algebra.cc:418 +#: ../libqalculate/BuiltinFunctions-algebra.cc:581 +#: ../libqalculate/BuiltinFunctions-algebra.cc:673 #, c-format -msgid "Column %s does not exist in matrix." +msgid "The comparison is true for all %s if %s." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:245 +#: ../libqalculate/BuiltinFunctions-algebra.cc:422 #, c-format -msgid "Argument 3, %s, is ignored for vectors." +msgid "Was unable to isolate %s." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:249 -#: ../libqalculate/BuiltinFunctions.cc:270 +#: ../libqalculate/BuiltinFunctions-algebra.cc:542 +#: ../libqalculate/BuiltinFunctions-algebra.cc:569 +#: ../libqalculate/BuiltinFunctions-algebra.cc:650 #, c-format -msgid "Element %s does not exist in vector." +msgid "" +"Was unable to isolate %s with the current assumptions. The assumed sign was " +"therefore temporarily set as unknown." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:411 -#: ../libqalculate/BuiltinFunctions.cc:415 -#: ../libqalculate/BuiltinFunctions.cc:447 -#: ../libqalculate/BuiltinFunctions.cc:451 +#: ../libqalculate/BuiltinFunctions-algebra.cc:545 +#: ../libqalculate/BuiltinFunctions-algebra.cc:572 +#: ../libqalculate/BuiltinFunctions-algebra.cc:653 #, c-format -msgid "%s() requires that all matrices/vectors have the same dimensions." +msgid "" +"Was unable to isolate %s with the current assumptions. The assumed type and " +"sign was therefore temporarily set as unknown." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4759 -#: ../libqalculate/BuiltinFunctions.cc:4802 +#: ../libqalculate/BuiltinFunctions-algebra.cc:577 +#: ../libqalculate/BuiltinFunctions-algebra.cc:660 #, c-format -msgid "Unsolvable comparison in %s()." +msgid "The solution requires that %s." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4972 -#: ../libqalculate/BuiltinFunctions.cc:5006 +#: ../libqalculate/BuiltinFunctions-algebra.cc:667 +#, c-format +msgid "Solution %s requires that %s." +msgstr "" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:738 +#, c-format +msgid "" +"Unable to isolate %s.\n" +"\n" +"You might need to place the equations and variables in an appropriate order " +"so that each equation at least contains the corresponding variable (if " +"automatic reordering failed)." +msgstr "" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:740 +#: ../libqalculate/BuiltinFunctions-algebra.cc:754 +#: ../libqalculate/BuiltinFunctions-algebra.cc:763 +#, c-format +msgid "Unable to isolate %s." +msgstr "" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:747 +#, c-format +msgid "Inequalities is not allowed in %s()." +msgstr "" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:1089 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1094 +msgid "No differential equation found." +msgstr "" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:1098 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1127 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1133 +msgid "Unable to solve differential equation." +msgstr "" + +#: ../libqalculate/BuiltinFunctions-datetime.cc:33 +#: ../libqalculate/BuiltinFunctions-datetime.cc:67 msgid "gregorian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4973 +#: ../libqalculate/BuiltinFunctions-datetime.cc:34 msgid "milankovic" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4974 +#: ../libqalculate/BuiltinFunctions-datetime.cc:35 msgid "julian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4975 +#: ../libqalculate/BuiltinFunctions-datetime.cc:36 msgid "islamic" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4976 +#: ../libqalculate/BuiltinFunctions-datetime.cc:37 msgid "hebrew" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4977 +#: ../libqalculate/BuiltinFunctions-datetime.cc:38 msgid "egyptian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4978 +#: ../libqalculate/BuiltinFunctions-datetime.cc:39 msgid "persian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4979 +#: ../libqalculate/BuiltinFunctions-datetime.cc:40 msgid "coptic" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4980 +#: ../libqalculate/BuiltinFunctions-datetime.cc:41 msgid "ethiopian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4981 +#: ../libqalculate/BuiltinFunctions-datetime.cc:42 msgid "indian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4982 +#: ../libqalculate/BuiltinFunctions-datetime.cc:43 msgid "chinese" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:5408 -#: ../libqalculate/BuiltinFunctions.cc:5438 ../libqalculate/Number.cc:429 -#: ../libqalculate/Number.cc:900 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:57 #, c-format -msgid "Character '%s' was ignored in the number \"%s\" with base %s." +msgid "Too many elements (%s) for the dimensions (%sx%s) of the matrix." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:5703 -#: ../libqalculate/BuiltinFunctions.cc:5708 -#: ../libqalculate/BuiltinFunctions.cc:5710 -#: ../libqalculate/BuiltinFunctions.cc:5726 ../libqalculate/Calculator.cc:3409 -#: ../libqalculate/Calculator.cc:3416 ../libqalculate/Calculator.cc:3418 -#: ../libqalculate/Calculator.cc:3482 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:120 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:182 #, c-format -msgid "Original value (%s) was not found." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:5862 -msgid "" -"The number of requested elements in generate vector function must be a " -"positive integer." +msgid "Row %s does not exist in matrix." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:6179 -#: ../libqalculate/BuiltinFunctions.cc:6183 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:133 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:178 #, c-format -msgid "Too few elements (%s) in vector (%s required)" +msgid "Column %s does not exist in matrix." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:6232 -#: ../libqalculate/BuiltinFunctions.cc:6249 -msgid "Comparison failed." +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:193 +#, c-format +msgid "Argument 3, %s, is ignored for vectors." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:6392 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:197 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:218 #, c-format -msgid "Object %s does not exist." +msgid "Element %s does not exist in vector." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:6410 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:359 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:363 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:395 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:399 #, c-format -msgid "Invalid variable name (%s)." +msgid "%s() requires that all matrices/vectors have the same dimensions." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:6427 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:539 msgid "" -"A global unit or variable was deactivated. It will be restored after the new " -"variable has been removed." +"The number of requested elements in generate vector function must be a " +"positive integer." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:6442 -#, c-format -msgid "Register %s does not exist. Returning zero." +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:562 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:579 +msgid "Comparison failed." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:7390 -#: ../libqalculate/MathStructure.cc:284 ../libqalculate/MathStructure.cc:306 -#: ../libqalculate/MathStructure.cc:337 +#: ../libqalculate/BuiltinFunctions-statistics.cc:178 +#: ../libqalculate/BuiltinFunctions-statistics.cc:221 #, c-format -msgid "To avoid division by zero, the following must be true: %s." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:7598 -#: ../libqalculate/BuiltinFunctions.cc:7617 -#: ../libqalculate/BuiltinFunctions.cc:7650 -#: ../libqalculate/BuiltinFunctions.cc:7672 -#: ../libqalculate/BuiltinFunctions.cc:7721 -#: ../libqalculate/BuiltinFunctions.cc:7756 -#: ../libqalculate/BuiltinFunctions.cc:7871 -#: ../libqalculate/BuiltinFunctions.cc:7921 -#: ../libqalculate/BuiltinFunctions.cc:7955 -#: ../libqalculate/BuiltinFunctions.cc:7998 -#: ../libqalculate/BuiltinFunctions.cc:8030 -msgid "Unable to integrate the expression." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:7878 -#: ../libqalculate/BuiltinFunctions.cc:7948 -msgid "Unable to integrate the expression exact." +msgid "Unsolvable comparison in %s()." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:7915 -msgid "Definite integral was approximated." +#: ../libqalculate/BuiltinFunctions-calculus.cc:314 +msgid "Unable to find limit." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:8245 -msgid "" -"No equality or inequality to solve. The entered expression to solve is not " -"correct (ex. \"x + 5 = 3\" is correct)" +#: ../libqalculate/BuiltinFunctions-calculus.cc:409 +#: ../libqalculate/BuiltinFunctions-calculus.cc:441 +#: ../libqalculate/MathStructure-integrate.cc:7294 +#: ../libqalculate/MathStructure-integrate.cc:7314 +#: ../libqalculate/MathStructure-integrate.cc:7349 +#: ../libqalculate/MathStructure-integrate.cc:7373 +#: ../libqalculate/MathStructure-integrate.cc:7423 +#: ../libqalculate/MathStructure-integrate.cc:7462 +#: ../libqalculate/MathStructure-integrate.cc:7658 +#: ../libqalculate/MathStructure-integrate.cc:7712 +#: ../libqalculate/MathStructure-integrate.cc:7754 +msgid "Unable to integrate the expression." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:8292 +#: ../libqalculate/BuiltinFunctions-number.cc:684 +#: ../libqalculate/BuiltinFunctions-number.cc:714 ../libqalculate/Number.cc:459 +#: ../libqalculate/Number.cc:970 #, c-format -msgid "The comparison is true for all %s (with current assumptions)." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:8296 -msgid "No possible solution was found (with current assumptions)." +msgid "Character '%s' was ignored in the number \"%s\" with base %s." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:8300 +#. if left value is a function without any arguments, do function replacement +#: ../libqalculate/BuiltinFunctions-util.cc:414 +#: ../libqalculate/BuiltinFunctions-util.cc:419 +#: ../libqalculate/BuiltinFunctions-util.cc:421 +#: ../libqalculate/BuiltinFunctions-util.cc:437 +#: ../libqalculate/Calculator-calculate.cc:1239 +#: ../libqalculate/Calculator-calculate.cc:1251 +#: ../libqalculate/Calculator-calculate.cc:1253 +#: ../libqalculate/Calculator-calculate.cc:1256 +#: ../libqalculate/Calculator-calculate.cc:1327 #, c-format -msgid "Was unable to completely isolate %s." +msgid "Original value (%s) was not found." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:8304 -#: ../libqalculate/BuiltinFunctions.cc:8467 -#: ../libqalculate/BuiltinFunctions.cc:8559 +#: ../libqalculate/BuiltinFunctions-util.cc:627 +#: ../libqalculate/BuiltinFunctions-util.cc:631 #, c-format -msgid "The comparison is true for all %s if %s." +msgid "Too few elements (%s) in vector (%s required)" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:8308 +#: ../libqalculate/BuiltinFunctions-util.cc:677 #, c-format -msgid "Was unable to isolate %s." +msgid "Object %s does not exist." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:8428 -#: ../libqalculate/BuiltinFunctions.cc:8455 -#: ../libqalculate/BuiltinFunctions.cc:8536 +#: ../libqalculate/BuiltinFunctions-util.cc:695 #, c-format -msgid "" -"Was unable to isolate %s with the current assumptions. The assumed sign was " -"therefore temporarily set as unknown." +msgid "Invalid variable name (%s)." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:8431 -#: ../libqalculate/BuiltinFunctions.cc:8458 -#: ../libqalculate/BuiltinFunctions.cc:8539 -#, c-format +#: ../libqalculate/BuiltinFunctions-util.cc:712 msgid "" -"Was unable to isolate %s with the current assumptions. The assumed type and " -"sign was therefore temporarily set as unknown." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:8463 -#: ../libqalculate/BuiltinFunctions.cc:8546 -#, c-format -msgid "The solution requires that %s." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:8553 -#, c-format -msgid "Solution %s requires that %s." +"A global unit or variable was deactivated. It will be restored after the new " +"variable has been removed." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:8624 +#: ../libqalculate/BuiltinFunctions-util.cc:727 #, c-format -msgid "" -"Unable to isolate %s.\n" -"\n" -"You might need to place the equations and variables in an appropriate order " -"so that each equation at least contains the corresponding variable (if " -"automatic reordering failed)." +msgid "Register %s does not exist. Returning zero." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:8626 -#: ../libqalculate/BuiltinFunctions.cc:8640 -#: ../libqalculate/BuiltinFunctions.cc:8649 -#, c-format -msgid "Unable to isolate %s." +#: ../libqalculate/BuiltinFunctions-util.cc:794 +#: ../libqalculate/BuiltinFunctions-util.cc:808 +msgid "Matrix" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:8633 -#, c-format -msgid "Inequalities is not allowed in %s()." +#: ../libqalculate/BuiltinFunctions-util.cc:819 +#: ../libqalculate/BuiltinFunctions-util.cc:869 +msgid "Vector" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:8975 -#: ../libqalculate/BuiltinFunctions.cc:8980 -msgid "No differential equation found." +#: ../libqalculate/BuiltinFunctions-util.cc:834 +#: ../libqalculate/BuiltinFunctions-util.cc:880 +#: ../libqalculate/Calculator-plot.cc:135 +msgid "Unable to generate plot data with current min, max and step size." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:8984 -#: ../libqalculate/BuiltinFunctions.cc:9013 -#: ../libqalculate/BuiltinFunctions.cc:9019 -msgid "Unable to solve differential equation." +#: ../libqalculate/BuiltinFunctions-util.cc:836 +#: ../libqalculate/BuiltinFunctions-util.cc:882 +msgid "Sampling rate must be a positive integer." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:9045 -msgid "Unable to find limit." +#: ../libqalculate/BuiltinFunctions-util.cc:845 +#: ../libqalculate/BuiltinFunctions-util.cc:891 +#: ../libqalculate/Calculator-plot.cc:105 +msgid "Unable to generate plot data with current min, max and sampling rate." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:9099 -#: ../libqalculate/BuiltinFunctions.cc:9113 -msgid "Matrix" +#: ../libqalculate/Calculator-calculate.cc:303 +#: ../libqalculate/Calculator-calculate.cc:428 +msgid "Stack is empty. Filling remaining function arguments with zeroes." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:9124 -#: ../libqalculate/BuiltinFunctions.cc:9174 -msgid "Vector" +#: ../libqalculate/Calculator-calculate.cc:1004 +msgid "calculating..." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:9139 -#: ../libqalculate/BuiltinFunctions.cc:9185 ../libqalculate/Calculator.cc:12320 -msgid "Unable to generate plot data with current min, max and step size." +#. "where"-operator +#: ../libqalculate/Calculator-calculate.cc:1130 +#: ../libqalculate/Calculator-calculate.cc:1132 +#: ../libqalculate/Calculator-calculate.cc:1151 +#: ../libqalculate/Calculator-calculate.cc:1153 +#: ../libqalculate/Calculator.cc:1326 +msgid "where" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:9141 -#: ../libqalculate/BuiltinFunctions.cc:9187 -msgid "Sampling rate must be a positive integer." +#: ../libqalculate/Calculator-calculate.cc:1349 +#, c-format +msgid "Unhandled \"where\" expression: %s" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:9150 -#: ../libqalculate/BuiltinFunctions.cc:9196 ../libqalculate/Calculator.cc:12290 -msgid "Unable to generate plot data with current min, max and sampling rate." +#: ../libqalculate/Calculator-calculate.cc:1567 +#: ../libqalculate/Calculator-calculate.cc:1614 +msgid "timed out" msgstr "" -#: ../libqalculate/Calculator.cc:454 ../libqalculate/Calculator.cc:680 +#: ../libqalculate/Calculator.cc:232 ../libqalculate/Calculator.cc:460 msgid "per" msgstr "" -#: ../libqalculate/Calculator.cc:456 ../libqalculate/Calculator.cc:682 +#: ../libqalculate/Calculator.cc:234 ../libqalculate/Calculator.cc:462 msgid "times" msgstr "" -#: ../libqalculate/Calculator.cc:458 ../libqalculate/Calculator.cc:684 +#: ../libqalculate/Calculator.cc:236 ../libqalculate/Calculator.cc:464 msgid "plus" msgstr "" -#: ../libqalculate/Calculator.cc:460 ../libqalculate/Calculator.cc:686 +#: ../libqalculate/Calculator.cc:238 ../libqalculate/Calculator.cc:466 msgid "minus" msgstr "" -#: ../libqalculate/Calculator.cc:462 ../libqalculate/Calculator.cc:688 -#: ../libqalculate/MathStructure.cc:21575 ../libqalculate/Function.cc:1331 -#: ../libqalculate/Function.cc:1339 ../libqalculate/Function.cc:1768 -#: ../libqalculate/Function.cc:1930 ../libqalculate/Function.cc:1938 +#: ../libqalculate/Calculator.cc:240 ../libqalculate/Calculator.cc:468 +#: ../libqalculate/MathStructure-print.cc:3170 ../libqalculate/Function.cc:1361 +#: ../libqalculate/Function.cc:1369 ../libqalculate/Function.cc:1802 +#: ../libqalculate/Function.cc:1964 ../libqalculate/Function.cc:1972 msgid "and" msgstr "" -#: ../libqalculate/Calculator.cc:831 +#: ../libqalculate/Calculator.cc:611 msgid "Gradians unit is missing. Creating one for this session." msgstr "" -#: ../libqalculate/Calculator.cc:832 ../libqalculate/Calculator.cc:840 -#: ../libqalculate/Calculator.cc:848 +#: ../libqalculate/Calculator.cc:612 ../libqalculate/Calculator.cc:620 +#: ../libqalculate/Calculator.cc:628 msgid "Angle/Plane Angle" msgstr "" -#: ../libqalculate/Calculator.cc:839 +#: ../libqalculate/Calculator.cc:619 msgid "Radians unit is missing. Creating one for this session." msgstr "" -#: ../libqalculate/Calculator.cc:847 +#: ../libqalculate/Calculator.cc:627 msgid "Degrees unit is missing. Creating one for this session." msgstr "" -#. "where"-operator -#: ../libqalculate/Calculator.cc:1544 ../libqalculate/Calculator.cc:3298 -#: ../libqalculate/Calculator.cc:3300 ../libqalculate/Calculator.cc:3319 -#: ../libqalculate/Calculator.cc:3321 -msgid "where" -msgstr "" - -#: ../libqalculate/Calculator.cc:2027 ../libqalculate/Calculator.cc:2028 -#: ../libqalculate/Calculator.cc:11818 ../libqalculate/Calculator.cc:11955 -#: ../libqalculate/Calculator.cc:12013 +#: ../libqalculate/Calculator.cc:1695 ../libqalculate/Calculator.cc:1696 +#: ../libqalculate/Calculator.cc:1700 +#: ../libqalculate/Calculator-definitions.cc:3285 +#: ../libqalculate/Calculator-definitions.cc:3455 +#: ../libqalculate/Calculator-definitions.cc:3513 msgid "Currency" msgstr "" -#: ../libqalculate/Calculator.cc:2563 ../libqalculate/Calculator.cc:2688 -msgid "Stack is empty. Filling remaining function arguments with zeroes." -msgstr "" - -#: ../libqalculate/Calculator.cc:3180 -msgid "calculating..." -msgstr "" - -#: ../libqalculate/Calculator.cc:3502 -#, c-format -msgid "Unhandled \"where\" expression: %s" -msgstr "" - -#: ../libqalculate/Calculator.cc:5259 +#: ../libqalculate/Calculator.cc:2635 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name of \"%s\", or " "the variable will be lost." msgstr "" -#: ../libqalculate/Calculator.cc:5277 +#: ../libqalculate/Calculator.cc:2653 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name \"%s\", or " "the function will be lost." msgstr "" -#: ../libqalculate/Calculator.cc:5294 +#: ../libqalculate/Calculator.cc:2670 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name \"%s\", or " "the unit will be lost." msgstr "" -#: ../libqalculate/Calculator.cc:6883 ../libqalculate/Calculator.cc:6927 -#: ../libqalculate/Calculator.cc:6930 ../libqalculate/Calculator.cc:8101 -#: ../libqalculate/Calculator.cc:8110 ../libqalculate/Calculator.cc:8165 -#: ../libqalculate/Calculator.cc:8227 ../libqalculate/Calculator.cc:8248 -#: ../libqalculate/Calculator.cc:8249 -#, c-format -msgid "Misplaced operator(s) \"%s\" ignored" -msgstr "" - -#: ../libqalculate/Calculator.cc:6924 ../libqalculate/Calculator.cc:8250 +#: ../libqalculate/Calculator.cc:2877 #, c-format -msgid "Misplaced '%c' ignored" +msgid "Name \"%s\" is in use. Replacing with \"%s\"." msgstr "" -#: ../libqalculate/Calculator.cc:6962 ../libqalculate/Function.cc:1489 -#: ../libqalculate/Function.cc:1520 +#: ../libqalculate/Calculator-definitions.cc:763 ../libqalculate/DataSet.cc:540 #, c-format -msgid "Internal id %s does not exist." +msgid "File not identified as Qalculate! definitions file: %s." msgstr "" -#: ../libqalculate/Calculator.cc:6980 -#, c-format -msgid "\"%s\" is not a valid variable/function/unit." +#: ../libqalculate/Calculator-definitions.cc:2870 +#: ../libqalculate/DataSet.cc:363 +msgid "Object" msgstr "" -#: ../libqalculate/Calculator.cc:6995 -#, c-format -msgid "" -"Trailing characters \"%s\" (not a valid variable/function/unit) in number " -"\"%s\" was ignored." +#: ../libqalculate/Calculator-definitions.cc:2879 +#: ../libqalculate/DataSet.cc:364 +msgid "Property" msgstr "" -#: ../libqalculate/Calculator.cc:7261 -msgid "RPN syntax error. Values left at the end of the RPN expression." +#: ../libqalculate/Calculator-definitions.cc:3178 +msgid "column" msgstr "" -#: ../libqalculate/Calculator.cc:7264 ../libqalculate/Calculator.cc:7355 -msgid "Unused stack values." +#: ../libqalculate/Calculator-definitions.cc:3181 +msgid "Column " msgstr "" -#: ../libqalculate/Calculator.cc:7397 ../libqalculate/Calculator.cc:7605 +#: ../libqalculate/Calculator-definitions.cc:3632 +#: ../libqalculate/Calculator-definitions.cc:3633 +#: ../libqalculate/Calculator-definitions.cc:3637 +#: ../libqalculate/Calculator-definitions.cc:3640 +#: ../libqalculate/Calculator-definitions.cc:3672 +#: ../libqalculate/Calculator-definitions.cc:3673 +#: ../libqalculate/Calculator-definitions.cc:3676 +#: ../libqalculate/Calculator-definitions.cc:3695 +#: ../libqalculate/Calculator-definitions.cc:3696 +#: ../libqalculate/Calculator-definitions.cc:3699 +#: ../libqalculate/Calculator-definitions.cc:3719 +#: ../libqalculate/Calculator-definitions.cc:3720 +#: ../libqalculate/Calculator-definitions.cc:3723 #, c-format -msgid "RPN syntax error. Operator '%c' not supported." +msgid "Failed to download exchange rates from %s: %s." msgstr "" -#: ../libqalculate/Calculator.cc:7443 -msgid "RPN syntax error. Stack is empty." +#. ignore operators +#: ../libqalculate/Calculator-parse.cc:1668 +#: ../libqalculate/Calculator-parse.cc:1721 +#: ../libqalculate/Calculator-parse.cc:1725 +#: ../libqalculate/Calculator-parse.cc:2926 +#: ../libqalculate/Calculator-parse.cc:2935 +#: ../libqalculate/Calculator-parse.cc:2990 +#: ../libqalculate/Calculator-parse.cc:3055 +#: ../libqalculate/Calculator-parse.cc:3077 +#: ../libqalculate/Calculator-parse.cc:3078 +#, c-format +msgid "Misplaced operator(s) \"%s\" ignored" msgstr "" -#: ../libqalculate/Calculator.cc:7464 -msgid "RPN syntax error. Operator ignored as there where only one stack value." +#. ignore operators +#: ../libqalculate/Calculator-parse.cc:1717 +#: ../libqalculate/Calculator-parse.cc:3079 +#, c-format +msgid "Misplaced '%c' ignored" msgstr "" -#: ../libqalculate/Calculator.cc:8525 +#: ../libqalculate/Calculator-parse.cc:1759 ../libqalculate/Function.cc:1519 +#: ../libqalculate/Function.cc:1550 #, c-format -msgid "Name \"%s\" is in use. Replacing with \"%s\"." +msgid "Internal id %s does not exist." msgstr "" -#: ../libqalculate/Calculator.cc:9212 ../libqalculate/DataSet.cc:539 +#: ../libqalculate/Calculator-parse.cc:1779 #, c-format -msgid "File not identified as Qalculate! definitions file: %s." +msgid "\"%s\" is not a valid variable/function/unit." msgstr "" -#: ../libqalculate/Calculator.cc:11319 ../libqalculate/DataSet.cc:362 -msgid "Object" +#: ../libqalculate/Calculator-parse.cc:1794 +#, c-format +msgid "" +"Trailing characters \"%s\" (not a valid variable/function/unit) in number " +"\"%s\" was ignored." msgstr "" -#: ../libqalculate/Calculator.cc:11328 ../libqalculate/DataSet.cc:363 -msgid "Property" +#: ../libqalculate/Calculator-parse.cc:2072 +msgid "RPN syntax error. Values left at the end of the RPN expression." msgstr "" -#: ../libqalculate/Calculator.cc:11627 -msgid "column" +#: ../libqalculate/Calculator-parse.cc:2075 +#: ../libqalculate/Calculator-parse.cc:2166 +msgid "Unused stack values." msgstr "" -#: ../libqalculate/Calculator.cc:11630 -msgid "Column " +#: ../libqalculate/Calculator-parse.cc:2208 +#: ../libqalculate/Calculator-parse.cc:2416 +#, c-format +msgid "RPN syntax error. Operator '%c' not supported." msgstr "" -#: ../libqalculate/Calculator.cc:11706 ../libqalculate/Calculator.cc:11753 -msgid "timed out" +#: ../libqalculate/Calculator-parse.cc:2254 +msgid "RPN syntax error. Stack is empty." msgstr "" -#: ../libqalculate/Calculator.cc:12125 ../libqalculate/Calculator.cc:12126 -#: ../libqalculate/Calculator.cc:12130 ../libqalculate/Calculator.cc:12133 -#: ../libqalculate/Calculator.cc:12165 ../libqalculate/Calculator.cc:12166 -#: ../libqalculate/Calculator.cc:12169 ../libqalculate/Calculator.cc:12188 -#: ../libqalculate/Calculator.cc:12189 ../libqalculate/Calculator.cc:12192 -#, c-format -msgid "Failed to download exchange rates from %s: %s." +#: ../libqalculate/Calculator-parse.cc:2275 +msgid "RPN syntax error. Operator ignored as there where only one stack value." msgstr "" -#: ../libqalculate/Calculator.cc:12286 ../libqalculate/Calculator.cc:12316 -#: ../libqalculate/Calculator.cc:12346 ../libqalculate/Calculator.cc:12685 +#: ../libqalculate/Calculator-plot.cc:101 +#: ../libqalculate/Calculator-plot.cc:131 +#: ../libqalculate/Calculator-plot.cc:161 +#: ../libqalculate/Calculator-plot.cc:498 msgid "It took too long to generate the plot data." msgstr "" -#: ../libqalculate/Calculator.cc:12380 +#: ../libqalculate/Calculator-plot.cc:193 msgid "No extension in file name. Saving as PNG image." msgstr "" -#: ../libqalculate/Calculator.cc:12399 +#: ../libqalculate/Calculator-plot.cc:212 msgid "Unknown extension in file name. Saving as PNG image." msgstr "" -#: ../libqalculate/Calculator.cc:12616 +#: ../libqalculate/Calculator-plot.cc:429 #, c-format msgid "Could not create temporary file %s" msgstr "" -#: ../libqalculate/Calculator.cc:12732 +#: ../libqalculate/Calculator-plot.cc:545 msgid "" "Failed to invoke gnuplot. Make sure that you have gnuplot installed in your " "path." msgstr "" -#: ../libqalculate/DataSet.cc:388 +#: ../libqalculate/DataSet.cc:389 #, c-format msgid "Object %s not available in data set." msgstr "" -#: ../libqalculate/DataSet.cc:398 +#: ../libqalculate/DataSet.cc:399 #, c-format msgid "Property %s not available in data set." msgstr "" -#: ../libqalculate/DataSet.cc:403 +#: ../libqalculate/DataSet.cc:404 #, c-format msgid "Property %s not defined for object %s." msgstr "" -#: ../libqalculate/DataSet.cc:516 ../libqalculate/DataSet.cc:524 +#: ../libqalculate/DataSet.cc:517 ../libqalculate/DataSet.cc:525 #, c-format msgid "Unable to load data objects in %s." msgstr "" -#: ../libqalculate/DataSet.cc:1042 +#: ../libqalculate/DataSet.cc:1043 msgid "data property" msgstr "" -#: ../libqalculate/DataSet.cc:1044 +#: ../libqalculate/DataSet.cc:1045 msgid "name of a data property" msgstr "" -#: ../libqalculate/DataSet.cc:1052 ../libqalculate/DataSet.cc:1068 +#: ../libqalculate/DataSet.cc:1053 ../libqalculate/DataSet.cc:1069 msgid "no properties available" msgstr "" -#: ../libqalculate/DataSet.cc:1102 +#: ../libqalculate/DataSet.cc:1103 #, c-format msgid "" "Data set \"%s\" has no object key that supports the provided argument type." msgstr "" -#: ../libqalculate/DataSet.cc:1107 +#: ../libqalculate/DataSet.cc:1108 msgid "data object" msgstr "" -#: ../libqalculate/DataSet.cc:1110 +#: ../libqalculate/DataSet.cc:1111 msgid "an object from" msgstr "" -#: ../libqalculate/DataSet.cc:1137 +#: ../libqalculate/DataSet.cc:1138 msgid "use" msgstr "" -#: ../libqalculate/MathStructure.cc:265 +#: ../libqalculate/MathStructure-calculate.cc:76 #, c-format msgid "Required assumption: %s." msgstr "" -#: ../libqalculate/MathStructure.cc:4031 ../libqalculate/MathStructure.cc:4052 +#: ../libqalculate/MathStructure-calculate.cc:95 +#: ../libqalculate/MathStructure-calculate.cc:117 +#: ../libqalculate/MathStructure-calculate.cc:148 +#: ../libqalculate/MathStructure-integrate.cc:7086 +#, c-format +msgid "To avoid division by zero, the following must be true: %s." +msgstr "" + +#: ../libqalculate/MathStructure-calculate.cc:1653 +#: ../libqalculate/MathStructure-calculate.cc:1675 #, c-format msgid "" "The second matrix must have as many rows (was %s) as the first has columns " "(was %s) for matrix multiplication." msgstr "" -#: ../libqalculate/MathStructure.cc:8936 ../libqalculate/MathStructure.cc:8977 -#: ../libqalculate/MathStructure.cc:9010 ../libqalculate/MathStructure.cc:9077 -#: ../libqalculate/MathStructure.cc:9105 ../libqalculate/MathStructure.cc:9124 -#: ../libqalculate/MathStructure.cc:9143 ../libqalculate/MathStructure.cc:9162 -#: ../libqalculate/MathStructure.cc:9270 ../libqalculate/MathStructure.cc:16270 -#: ../libqalculate/MathStructure.cc:16661 +#: ../libqalculate/MathStructure-calculate.cc:6072 +#: ../libqalculate/MathStructure-calculate.cc:6113 +#: ../libqalculate/MathStructure-calculate.cc:6146 +#: ../libqalculate/MathStructure-calculate.cc:6213 +#: ../libqalculate/MathStructure-calculate.cc:6241 +#: ../libqalculate/MathStructure-calculate.cc:6260 +#: ../libqalculate/MathStructure-calculate.cc:6279 +#: ../libqalculate/MathStructure-calculate.cc:6298 +#: ../libqalculate/MathStructure-calculate.cc:6406 +#: ../libqalculate/MathStructure-factor.cc:413 +#: ../libqalculate/MathStructure-factor.cc:1304 msgid "This is a bug. Please report it." msgstr "" -#: ../libqalculate/MathStructure.cc:9353 ../libqalculate/Function.cc:527 +#: ../libqalculate/MathStructure-calculate.cc:6495 +#: ../libqalculate/Function.cc:557 msgid "No unknown variable/symbol was found." msgstr "" -#: ../libqalculate/MathStructure.cc:11752 -#: ../libqalculate/MathStructure.cc:11757 -#, c-format -msgid "Limit for %s determined graphically." +#: ../libqalculate/MathStructure-convert.cc:262 +msgid "" +"Calculations involving conversion of units without proportional linear " +"relationship (e.g. with multiple temperature units), might give unexpected " +"results and is not recommended." msgstr "" -#: ../libqalculate/MathStructure.cc:12582 +#: ../libqalculate/MathStructure-eval.cc:754 msgid "Interval potentially calculated wide." msgstr "" -#: ../libqalculate/MathStructure.cc:13500 +#: ../libqalculate/MathStructure-eval.cc:2024 msgid "" "Calculation of uncertainty propagation partially failed (using interval " "arithmetic instead when necessary)." msgstr "" -#: ../libqalculate/MathStructure.cc:13638 +#: ../libqalculate/MathStructure-eval.cc:2170 msgid "" "Calculation of uncertainty propagation failed (using interval arithmetic " "instead)." msgstr "" -#: ../libqalculate/MathStructure.cc:18517 +#: ../libqalculate/MathStructure-factor.cc:3160 msgid "" "Because of time constraints only a limited number of combinations of terms " "were tried during factorization. Repeat factorization to try other random " "combinations." msgstr "" -#: ../libqalculate/MathStructure.cc:21769 -msgid "undefined" +#: ../libqalculate/MathStructure-integrate.cc:7668 +#: ../libqalculate/MathStructure-integrate.cc:7743 +msgid "Unable to integrate the expression exact." msgstr "" -#: ../libqalculate/MathStructure.cc:21810 +#: ../libqalculate/MathStructure-integrate.cc:7707 +msgid "Definite integral was approximated." +msgstr "" + +#: ../libqalculate/MathStructure-isolatex.cc:999 +#: ../libqalculate/MathStructure-isolatex.cc:1176 +#: ../libqalculate/MathStructure-isolatex.cc:1815 +#: ../libqalculate/MathStructure-isolatex.cc:2335 +#: ../libqalculate/MathStructure-isolatex.cc:2401 +#: ../libqalculate/MathStructure-isolatex.cc:2451 +#: ../libqalculate/MathStructure-isolatex.cc:2472 +#: ../libqalculate/MathStructure-isolatex.cc:2530 +#: ../libqalculate/MathStructure-isolatex.cc:2656 +#: ../libqalculate/MathStructure-isolatex.cc:2801 +#, c-format +msgid "Interval arithmetic was disabled during calculation of %s." +msgstr "" + +#: ../libqalculate/MathStructure-isolatex.cc:2800 +#, c-format +msgid "Not all complex roots were calculated for %s." +msgstr "" + +#: ../libqalculate/MathStructure-isolatex.cc:4394 +#, c-format +msgid "Only one or two of the roots where calculated for %s." +msgstr "" + +#: ../libqalculate/MathStructure-limit.cc:967 +#: ../libqalculate/MathStructure-limit.cc:972 +#, c-format +msgid "Limit for %s determined graphically." +msgstr "" + +#: ../libqalculate/MathStructure-matrixvector.cc:62 #, c-format msgid "Unsolvable comparison at element %s when trying to rank vector." msgstr "" -#: ../libqalculate/MathStructure.cc:21860 +#: ../libqalculate/MathStructure-matrixvector.cc:112 #, c-format msgid "Unsolvable comparison at element %s when trying to sort vector." msgstr "" -#: ../libqalculate/MathStructure.cc:22285 +#: ../libqalculate/MathStructure-matrixvector.cc:537 msgid "The determinant can only be calculated for square matrices." msgstr "" -#: ../libqalculate/MathStructure.cc:22348 +#: ../libqalculate/MathStructure-matrixvector.cc:600 msgid "The permanent can only be calculated for square matrices." msgstr "" -#: ../libqalculate/MathStructure.cc:22435 +#: ../libqalculate/MathStructure-matrixvector.cc:687 msgid "Inverse of singular matrix." msgstr "" -#: ../libqalculate/MathStructure.cc:22789 -msgid "" -"Calculations involving conversion of units without proportional linear " -"relationship (e.g. with multiple temperature units), might give unexpected " -"results and is not recommended." -msgstr "" - -#: ../libqalculate/MathStructure.cc:24092 -#: ../libqalculate/MathStructure.cc:24135 +#: ../libqalculate/MathStructure-matrixvector.cc:817 +#: ../libqalculate/MathStructure-matrixvector.cc:860 msgid "Too many data points" msgstr "" -#: ../libqalculate/MathStructure.cc:24099 +#: ../libqalculate/MathStructure-matrixvector.cc:824 msgid "" "The selected min and max do not result in a positive, finite number of data " "points" msgstr "" -#: ../libqalculate/MathStructure.cc:24132 +#: ../libqalculate/MathStructure-matrixvector.cc:857 msgid "" "The selected min, max and step size do not result in a positive, finite " "number of data points" msgstr "" -#: ../libqalculate/MathStructure.cc:32190 -#: ../libqalculate/MathStructure.cc:32368 -#: ../libqalculate/MathStructure.cc:33005 -#: ../libqalculate/MathStructure.cc:33525 -#: ../libqalculate/MathStructure.cc:33591 -#: ../libqalculate/MathStructure.cc:33641 -#: ../libqalculate/MathStructure.cc:33662 -#: ../libqalculate/MathStructure.cc:33720 -#: ../libqalculate/MathStructure.cc:33846 -#: ../libqalculate/MathStructure.cc:33990 -#, c-format -msgid "Interval arithmetic was disabled during calculation of %s." -msgstr "" - -#: ../libqalculate/MathStructure.cc:33989 -#, c-format -msgid "Not all complex roots were calculated for %s." -msgstr "" - -#: ../libqalculate/MathStructure.cc:35479 -#, c-format -msgid "Only one or two of the roots where calculated for %s." +#: ../libqalculate/MathStructure-print.cc:3364 +msgid "undefined" msgstr "" -#: ../libqalculate/Function.cc:171 +#: ../libqalculate/Function.cc:185 #, c-format msgid "%s() requires that %s" msgstr "" -#: ../libqalculate/Function.cc:326 ../libqalculate/Function.cc:385 -#: ../libqalculate/Function.cc:445 +#: ../libqalculate/Function.cc:351 ../libqalculate/Function.cc:413 +#: ../libqalculate/Function.cc:474 #, c-format msgid "" "Additional arguments for function %s() was ignored. Function can only use %s " "argument(s)." msgstr "" -#: ../libqalculate/Function.cc:466 +#: ../libqalculate/Function.cc:495 #, c-format msgid "You need at least %s argument(s) (%s) in function %s()." msgstr "" -#: ../libqalculate/Function.cc:468 +#: ../libqalculate/Function.cc:497 #, c-format msgid "You need at least %s argument(s) in function %s()." msgstr "" -#: ../libqalculate/Function.cc:1321 +#: ../libqalculate/Function.cc:1351 msgid "a free value" msgstr "" -#: ../libqalculate/Function.cc:1326 +#: ../libqalculate/Function.cc:1356 msgid "that is nonzero" msgstr "" -#: ../libqalculate/Function.cc:1334 +#: ../libqalculate/Function.cc:1364 msgid "that is rational (polynomial)" msgstr "" -#: ../libqalculate/Function.cc:1342 +#: ../libqalculate/Function.cc:1372 msgid "that fulfills the condition:" msgstr "" -#: ../libqalculate/Function.cc:1345 +#: ../libqalculate/Function.cc:1375 msgid "Argument" msgstr "" -#: ../libqalculate/Function.cc:1409 +#: ../libqalculate/Function.cc:1439 #, c-format msgid "Argument %s in %s() must be %s." msgstr "" -#: ../libqalculate/Function.cc:1411 +#: ../libqalculate/Function.cc:1441 #, c-format msgid "Argument %s, %s, in %s() must be %s." msgstr "" -#: ../libqalculate/Function.cc:1749 +#: ../libqalculate/Function.cc:1783 msgid "a rational number" msgstr "" -#: ../libqalculate/Function.cc:1751 +#: ../libqalculate/Function.cc:1785 msgid "a number" msgstr "" -#: ../libqalculate/Function.cc:1753 +#: ../libqalculate/Function.cc:1787 msgid "a real number" msgstr "" -#: ../libqalculate/Function.cc:1758 ../libqalculate/Function.cc:1911 -#: ../libqalculate/Function.cc:1916 +#: ../libqalculate/Function.cc:1792 ../libqalculate/Function.cc:1945 +#: ../libqalculate/Function.cc:1950 msgid ">=" msgstr "" -#: ../libqalculate/Function.cc:1760 +#: ../libqalculate/Function.cc:1794 msgid ">" msgstr "" -#: ../libqalculate/Function.cc:1772 ../libqalculate/Function.cc:1933 -#: ../libqalculate/Function.cc:1940 +#: ../libqalculate/Function.cc:1806 ../libqalculate/Function.cc:1967 +#: ../libqalculate/Function.cc:1974 msgid "<=" msgstr "" -#: ../libqalculate/Function.cc:1774 +#: ../libqalculate/Function.cc:1808 msgid "<" msgstr "" -#: ../libqalculate/Function.cc:1908 +#: ../libqalculate/Function.cc:1942 msgid "an integer" msgstr "" -#: ../libqalculate/Function.cc:1965 +#: ../libqalculate/Function.cc:1999 msgid "symbol" msgstr "" -#: ../libqalculate/Function.cc:1966 +#: ../libqalculate/Function.cc:2000 msgid "an unknown variable/symbol" msgstr "" -#: ../libqalculate/Function.cc:1979 +#: ../libqalculate/Function.cc:2013 msgid "text" msgstr "" -#: ../libqalculate/Function.cc:1980 +#: ../libqalculate/Function.cc:2014 msgid "a text string" msgstr "" -#: ../libqalculate/Function.cc:2002 +#: ../libqalculate/Function.cc:2036 msgid "date" msgstr "" -#: ../libqalculate/Function.cc:2003 +#: ../libqalculate/Function.cc:2037 msgid "a date" msgstr "" -#: ../libqalculate/Function.cc:2052 +#: ../libqalculate/Function.cc:2086 msgid "a vector with " msgstr "" -#: ../libqalculate/Function.cc:2064 +#: ../libqalculate/Function.cc:2098 msgid "a vector" msgstr "" -#: ../libqalculate/Function.cc:2113 +#: ../libqalculate/Function.cc:2147 msgid "a square matrix" msgstr "" -#: ../libqalculate/Function.cc:2115 +#: ../libqalculate/Function.cc:2149 msgid "a matrix" msgstr "" -#: ../libqalculate/Function.cc:2130 +#: ../libqalculate/Function.cc:2164 msgid "object" msgstr "" -#: ../libqalculate/Function.cc:2131 +#: ../libqalculate/Function.cc:2165 msgid "a valid function, unit or variable name" msgstr "" -#: ../libqalculate/Function.cc:2145 +#: ../libqalculate/Function.cc:2179 msgid "a valid function name" msgstr "" -#: ../libqalculate/Function.cc:2158 +#: ../libqalculate/Function.cc:2192 msgid "unit" msgstr "" -#: ../libqalculate/Function.cc:2159 +#: ../libqalculate/Function.cc:2193 msgid "a valid unit name" msgstr "" -#: ../libqalculate/Function.cc:2173 +#: ../libqalculate/Function.cc:2207 msgid "a valid variable name" msgstr "" -#: ../libqalculate/Function.cc:2186 +#: ../libqalculate/Function.cc:2220 msgid "file" msgstr "" -#: ../libqalculate/Function.cc:2187 +#: ../libqalculate/Function.cc:2221 msgid "a valid file name" msgstr "" -#: ../libqalculate/Function.cc:2200 +#: ../libqalculate/Function.cc:2234 msgid "boolean" msgstr "" -#: ../libqalculate/Function.cc:2201 +#: ../libqalculate/Function.cc:2235 msgid "a boolean (0 or 1)" msgstr "" -#: ../libqalculate/Function.cc:2212 +#: ../libqalculate/Function.cc:2246 msgid "an angle or a number (using the default angle unit)" msgstr "" -#: ../libqalculate/Number.cc:254 ../libqalculate/Number.cc:8251 +#: ../libqalculate/Number.cc:263 ../libqalculate/Number.cc:10175 msgid "" "Cannot display numbers greater than 9999 or less than -9999 as roman " "numerals." msgstr "" -#: ../libqalculate/Number.cc:351 +#: ../libqalculate/Number.cc:363 #, c-format msgid "Character '%s' was ignored in the number \"%s\" in bijective base-26." msgstr "" -#: ../libqalculate/Number.cc:433 ../libqalculate/Number.cc:474 -#: ../libqalculate/Number.cc:501 +#. digit value is higher than allowed by the base: show a warning, but use anyway +#. digit value is higher than allowed by base: show a warning, but use anyway +#: ../libqalculate/Number.cc:464 ../libqalculate/Number.cc:514 +#: ../libqalculate/Number.cc:544 #, c-format msgid "Digit '%s' is too high for number base." msgstr "" -#: ../libqalculate/Number.cc:551 +#: ../libqalculate/Number.cc:601 msgid "" "Assuming the unusual practice of letting a last capital I mean 2 in a roman " "numeral." msgstr "" -#: ../libqalculate/Number.cc:635 ../libqalculate/Number.cc:662 -#: ../libqalculate/Number.cc:667 +#: ../libqalculate/Number.cc:685 ../libqalculate/Number.cc:712 +#: ../libqalculate/Number.cc:717 #, c-format msgid "Error in roman numerals: %s." msgstr "" -#: ../libqalculate/Number.cc:672 +#: ../libqalculate/Number.cc:722 #, c-format msgid "Unknown roman numeral: %c." msgstr "" -#: ../libqalculate/Number.cc:730 +#: ../libqalculate/Number.cc:780 #, c-format msgid "" "Errors in roman numerals: \"%s\". Interpreted as %s, which should be written " "as %s." msgstr "" -#: ../libqalculate/Number.cc:818 +#: ../libqalculate/Number.cc:881 msgid "Too large exponent." msgstr "" -#: ../libqalculate/Number.cc:850 +#. only allow decimals after last ":" +#: ../libqalculate/Number.cc:917 msgid "':' in decimal number ignored (decimal point detected)." msgstr "" -#: ../libqalculate/Number.cc:1950 ../libqalculate/Number.cc:2072 +#. test calculated floating point value and show mpfr errors (show as errors if error_level > 1, show as warnings if error_level = 1, do not generate message if error_level is zero) +#: ../libqalculate/Number.cc:2035 ../libqalculate/Number.cc:2160 msgid "Floating point underflow" msgstr "" -#: ../libqalculate/Number.cc:1951 ../libqalculate/Number.cc:2073 +#: ../libqalculate/Number.cc:2036 ../libqalculate/Number.cc:2161 msgid "Floating point overflow" msgstr "" -#: ../libqalculate/Number.cc:1952 ../libqalculate/Number.cc:2074 +#: ../libqalculate/Number.cc:2037 ../libqalculate/Number.cc:2162 msgid "Floating point division by zero exception" msgstr "" -#: ../libqalculate/Number.cc:1953 ../libqalculate/Number.cc:2077 +#: ../libqalculate/Number.cc:2038 ../libqalculate/Number.cc:2165 msgid "Floating point not a number exception" msgstr "" -#: ../libqalculate/Number.cc:1954 ../libqalculate/Number.cc:2075 +#: ../libqalculate/Number.cc:2039 ../libqalculate/Number.cc:2163 msgid "Floating point range exception" msgstr "" -#: ../libqalculate/Number.cc:3528 +#: ../libqalculate/Number.cc:3637 msgid "Division by zero." msgstr "" #. 0^0 -#: ../libqalculate/Number.cc:3534 +#: ../libqalculate/Number.cc:3643 msgid "0^0 might be considered undefined" msgstr "" -#: ../libqalculate/Number.cc:3541 +#: ../libqalculate/Number.cc:3650 msgid "The result of 0^i is possibly undefined" msgstr "" -#: ../libqalculate/Number.cc:3590 ../libqalculate/Number.cc:5389 -#: ../libqalculate/Number.cc:5500 ../libqalculate/Number.cc:5824 -#: ../libqalculate/Number.cc:5832 ../libqalculate/Number.cc:5865 -#: ../libqalculate/Number.cc:5962 ../libqalculate/Number.cc:6111 -#: ../libqalculate/Number.cc:6223 +#: ../libqalculate/Number.cc:3699 ../libqalculate/Number.cc:6103 +#: ../libqalculate/Number.cc:6214 ../libqalculate/Number.cc:6538 +#: ../libqalculate/Number.cc:6546 ../libqalculate/Number.cc:6579 +#: ../libqalculate/Number.cc:6676 ../libqalculate/Number.cc:6825 +#: ../libqalculate/Number.cc:6937 msgid "Interval calculated wide." msgstr "" -#: ../libqalculate/Number.cc:4942 -msgid "Cannot handle an argument (s) that large for Riemann Zeta." -msgstr "" - -#: ../libqalculate/Number.cc:5017 ../libqalculate/Number.cc:5119 -#: ../libqalculate/Number.cc:5150 ../libqalculate/Number.cc:5181 -#: ../libqalculate/Number.cc:6568 +#: ../libqalculate/Number.cc:5126 ../libqalculate/Number.cc:5352 +#: ../libqalculate/Number.cc:5439 ../libqalculate/Number.cc:5723 +#: ../libqalculate/Number.cc:5809 ../libqalculate/Number.cc:5895 +#: ../libqalculate/Number.cc:7142 ../libqalculate/Number.cc:7160 +#: ../libqalculate/Number.cc:7179 ../libqalculate/Number.cc:7515 +#: ../libqalculate/Number.cc:7562 ../libqalculate/Number.cc:7707 +#: ../libqalculate/Number.cc:8040 ../libqalculate/Number.cc:8196 +#: ../libqalculate/Number.cc:8628 ../libqalculate/Number.cc:9023 #, c-format msgid "%s() lacks proper support interval arithmetic." msgstr "" -#: ../libqalculate/Number.cc:7816 +#: ../libqalculate/Number.cc:9706 msgid "Unsupported base" msgstr "" -#: ../libqalculate/Number.cc:8248 +#: ../libqalculate/Number.cc:10172 msgid "Can only display rational numbers as roman numerals." msgstr "" -#: ../libqalculate/Number.cc:8693 ../libqalculate/Number.cc:8701 +#: ../libqalculate/Number.cc:10659 ../libqalculate/Number.cc:10667 msgid "infinity" msgstr "" @@ -3488,11 +3552,11 @@ msgid "leap month" msgstr "" -#: ../libqalculate/Unit.cc:1096 +#: ../libqalculate/Unit.cc:1100 msgid "Error(s) in unitexpression." msgstr "" -#: ../libqalculate/Variable.cc:501 +#: ../libqalculate/Variable.cc:502 #, c-format msgid "Recursive variable: %s = %s" msgstr "" diff -Nru libqalculate-3.6.0/po/nl.po libqalculate-3.7.0/po/nl.po --- libqalculate-3.6.0/po/nl.po 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/po/nl.po 2020-01-21 22:54:40.000000000 +0000 @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: libqalculate\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-25 10:28+0100\n" +"POT-Creation-Date: 2020-01-12 11:24+0100\n" "PO-Revision-Date: 2007-05-18 16:19+0200\n" "Last-Translator: Jaap Woldringh \n" "Language-Team: \n" @@ -26,11 +26,11 @@ "Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../src/defs2doc.cc:301 ../src/qalc.cc:3298 ../libqalculate/Function.cc:207 +#: ../src/defs2doc.cc:301 ../src/qalc.cc:3299 ../libqalculate/Function.cc:222 msgid "argument" msgstr "argument" -#: ../src/defs2doc.cc:324 ../src/qalc.cc:3321 +#: ../src/defs2doc.cc:324 ../src/qalc.cc:3322 #, c-format msgid "" "Retrieves data from the %s data set for a given object and property. If " @@ -40,37 +40,37 @@ "gegevensverzameling %s. Indien als eigenschap \"info\" wordt ingetypt krijgt " "u een lijst van alle eigenschappen van het object." -#: ../src/defs2doc.cc:331 ../src/qalc.cc:3330 +#: ../src/defs2doc.cc:331 ../src/qalc.cc:3331 msgid "Example:" msgstr "bv.:" -#: ../src/defs2doc.cc:339 ../src/qalc.cc:3339 +#: ../src/defs2doc.cc:339 ../src/qalc.cc:3340 msgid "Arguments" msgstr "Argumenten" #. optional argument, in description -#: ../src/defs2doc.cc:356 ../src/qalc.cc:3356 +#: ../src/defs2doc.cc:356 ../src/qalc.cc:3357 msgid "optional" msgstr "optioneel" #. argument default, in description -#: ../src/defs2doc.cc:359 ../src/qalc.cc:3360 +#: ../src/defs2doc.cc:359 ../src/qalc.cc:3361 msgid "default: " msgstr "standaard: " -#: ../src/defs2doc.cc:372 ../src/qalc.cc:3371 +#: ../src/defs2doc.cc:372 ../src/qalc.cc:3372 msgid "Requirement" msgstr "Vereiste" -#: ../src/defs2doc.cc:381 ../src/qalc.cc:3379 +#: ../src/defs2doc.cc:381 ../src/qalc.cc:3380 msgid "Properties" msgstr "Eigenschappen" -#: ../src/defs2doc.cc:397 ../src/qalc.cc:3394 +#: ../src/defs2doc.cc:397 ../src/qalc.cc:3395 msgid "key" msgstr "sleutelwaarde" -#: ../src/defs2doc.cc:431 ../src/qalc.cc:3509 +#: ../src/defs2doc.cc:431 ../src/qalc.cc:3510 msgid "a previous result" msgstr "een vorig antwoord" @@ -79,91 +79,91 @@ msgid "current precision" msgstr "nauwkeurigheid lezen" -#: ../src/defs2doc.cc:438 ../src/defs2doc.cc:539 ../src/qalc.cc:1456 +#: ../src/defs2doc.cc:438 ../src/defs2doc.cc:539 ../src/qalc.cc:1457 msgid "relative uncertainty" msgstr "" -#: ../src/defs2doc.cc:453 ../src/qalc.cc:1478 ../src/qalc.cc:3515 -#: ../libqalculate/Function.cc:2110 +#: ../src/defs2doc.cc:453 ../src/qalc.cc:1479 ../src/qalc.cc:3516 +#: ../libqalculate/Function.cc:2144 msgid "matrix" msgstr "matrix" -#: ../src/defs2doc.cc:455 ../src/qalc.cc:1480 ../src/qalc.cc:3517 -#: ../libqalculate/Function.cc:2049 +#: ../src/defs2doc.cc:455 ../src/qalc.cc:1481 ../src/qalc.cc:3518 +#: ../libqalculate/Function.cc:2083 msgid "vector" msgstr "vector" -#: ../src/defs2doc.cc:463 ../src/qalc.cc:249 ../src/qalc.cc:691 -#: ../src/qalc.cc:1497 ../src/qalc.cc:2907 ../src/qalc.cc:3527 -#: ../src/qalc.cc:3646 ../src/qalc.cc:3876 +#: ../src/defs2doc.cc:463 ../src/qalc.cc:250 ../src/qalc.cc:692 +#: ../src/qalc.cc:1498 ../src/qalc.cc:2908 ../src/qalc.cc:3528 +#: ../src/qalc.cc:3647 ../src/qalc.cc:3877 msgid "positive" msgstr "positief" -#: ../src/defs2doc.cc:464 ../src/qalc.cc:255 ../src/qalc.cc:692 -#: ../src/qalc.cc:1498 ../src/qalc.cc:2908 ../src/qalc.cc:3528 -#: ../src/qalc.cc:3650 ../src/qalc.cc:3880 +#: ../src/defs2doc.cc:464 ../src/qalc.cc:256 ../src/qalc.cc:693 +#: ../src/qalc.cc:1499 ../src/qalc.cc:2909 ../src/qalc.cc:3529 +#: ../src/qalc.cc:3651 ../src/qalc.cc:3881 msgid "non-positive" msgstr "niet-positief" -#: ../src/defs2doc.cc:465 ../src/qalc.cc:253 ../src/qalc.cc:693 -#: ../src/qalc.cc:1499 ../src/qalc.cc:2909 ../src/qalc.cc:3529 -#: ../src/qalc.cc:3648 ../src/qalc.cc:3878 +#: ../src/defs2doc.cc:465 ../src/qalc.cc:254 ../src/qalc.cc:694 +#: ../src/qalc.cc:1500 ../src/qalc.cc:2910 ../src/qalc.cc:3530 +#: ../src/qalc.cc:3649 ../src/qalc.cc:3879 msgid "negative" msgstr "negatief" -#: ../src/defs2doc.cc:466 ../src/qalc.cc:251 ../src/qalc.cc:694 -#: ../src/qalc.cc:1500 ../src/qalc.cc:2910 ../src/qalc.cc:3530 -#: ../src/qalc.cc:3652 ../src/qalc.cc:3882 +#: ../src/defs2doc.cc:466 ../src/qalc.cc:252 ../src/qalc.cc:695 +#: ../src/qalc.cc:1501 ../src/qalc.cc:2911 ../src/qalc.cc:3531 +#: ../src/qalc.cc:3653 ../src/qalc.cc:3883 msgid "non-negative" msgstr "niet-negatief" -#: ../src/defs2doc.cc:467 ../src/qalc.cc:247 ../src/qalc.cc:695 -#: ../src/qalc.cc:1501 ../src/qalc.cc:2911 ../src/qalc.cc:3531 -#: ../src/qalc.cc:3644 ../src/qalc.cc:3874 +#: ../src/defs2doc.cc:467 ../src/qalc.cc:248 ../src/qalc.cc:696 +#: ../src/qalc.cc:1502 ../src/qalc.cc:2912 ../src/qalc.cc:3532 +#: ../src/qalc.cc:3645 ../src/qalc.cc:3875 msgid "non-zero" msgstr "ongelijk nul" -#: ../src/defs2doc.cc:472 ../src/qalc.cc:245 ../src/qalc.cc:700 -#: ../src/qalc.cc:1506 ../src/qalc.cc:2916 ../src/qalc.cc:3536 -#: ../src/qalc.cc:3660 ../src/qalc.cc:3890 ../libqalculate/Function.cc:1905 +#: ../src/defs2doc.cc:472 ../src/qalc.cc:246 ../src/qalc.cc:701 +#: ../src/qalc.cc:1507 ../src/qalc.cc:2917 ../src/qalc.cc:3537 +#: ../src/qalc.cc:3661 ../src/qalc.cc:3891 ../libqalculate/Function.cc:1939 msgid "integer" msgstr "geheel" -#: ../src/defs2doc.cc:473 ../src/qalc.cc:243 ../src/qalc.cc:701 -#: ../src/qalc.cc:1507 ../src/qalc.cc:2917 ../src/qalc.cc:3537 -#: ../src/qalc.cc:3658 ../src/qalc.cc:3888 +#: ../src/defs2doc.cc:473 ../src/qalc.cc:244 ../src/qalc.cc:702 +#: ../src/qalc.cc:1508 ../src/qalc.cc:2918 ../src/qalc.cc:3538 +#: ../src/qalc.cc:3659 ../src/qalc.cc:3889 msgid "rational" msgstr "rationaal" -#: ../src/defs2doc.cc:474 ../src/qalc.cc:239 ../src/qalc.cc:702 -#: ../src/qalc.cc:1508 ../src/qalc.cc:2918 ../src/qalc.cc:3538 -#: ../src/qalc.cc:3656 ../src/qalc.cc:3886 +#: ../src/defs2doc.cc:474 ../src/qalc.cc:240 ../src/qalc.cc:703 +#: ../src/qalc.cc:1509 ../src/qalc.cc:2919 ../src/qalc.cc:3539 +#: ../src/qalc.cc:3657 ../src/qalc.cc:3887 msgid "real" msgstr "reëel" -#: ../src/defs2doc.cc:475 ../src/qalc.cc:703 ../src/qalc.cc:1509 -#: ../src/qalc.cc:2919 ../src/qalc.cc:3539 +#: ../src/defs2doc.cc:475 ../src/qalc.cc:704 ../src/qalc.cc:1510 +#: ../src/qalc.cc:2920 ../src/qalc.cc:3540 msgid "complex" msgstr "complex" -#: ../src/defs2doc.cc:476 ../src/qalc.cc:241 ../src/qalc.cc:704 -#: ../src/qalc.cc:1510 ../src/qalc.cc:2920 ../src/qalc.cc:3540 -#: ../src/qalc.cc:3654 ../src/qalc.cc:3884 ../libqalculate/Function.cc:1744 +#: ../src/defs2doc.cc:476 ../src/qalc.cc:242 ../src/qalc.cc:705 +#: ../src/qalc.cc:1511 ../src/qalc.cc:2921 ../src/qalc.cc:3541 +#: ../src/qalc.cc:3655 ../src/qalc.cc:3885 ../libqalculate/Function.cc:1778 msgid "number" msgstr "getal" -#: ../src/defs2doc.cc:477 ../src/qalc.cc:705 ../src/qalc.cc:1511 -#: ../src/qalc.cc:2921 ../src/qalc.cc:3541 +#: ../src/defs2doc.cc:477 ../src/qalc.cc:706 ../src/qalc.cc:1512 +#: ../src/qalc.cc:2922 ../src/qalc.cc:3542 msgid "non-matrix" msgstr "niet-matrix" -#: ../src/defs2doc.cc:480 ../src/qalc.cc:233 ../src/qalc.cc:708 -#: ../src/qalc.cc:1514 ../src/qalc.cc:2924 ../src/qalc.cc:3544 -#: ../src/qalc.cc:3642 ../src/qalc.cc:3872 +#: ../src/defs2doc.cc:480 ../src/qalc.cc:234 ../src/qalc.cc:709 +#: ../src/qalc.cc:1515 ../src/qalc.cc:2925 ../src/qalc.cc:3545 +#: ../src/qalc.cc:3643 ../src/qalc.cc:3873 msgid "unknown" msgstr "onbekend" -#: ../src/defs2doc.cc:482 ../src/qalc.cc:1516 ../src/qalc.cc:3546 +#: ../src/defs2doc.cc:482 ../src/qalc.cc:1517 ../src/qalc.cc:3547 msgid "default assumptions" msgstr "standaard aannames" @@ -173,47 +173,48 @@ msgstr "nauwkeurigheid lezen" #. qalc command -#: ../src/defs2doc.cc:492 ../src/defs2doc.cc:546 ../src/qalc.cc:900 -#: ../src/qalc.cc:1472 ../src/qalc.cc:1489 ../src/qalc.cc:2559 -#: ../src/qalc.cc:2941 ../src/qalc.cc:3184 ../src/qalc.cc:3458 -#: ../src/qalc.cc:3468 ../src/qalc.cc:3572 ../src/qalc.cc:3668 -#: ../src/qalc.cc:4002 +#: ../src/defs2doc.cc:492 ../src/defs2doc.cc:546 ../src/qalc.cc:901 +#: ../src/qalc.cc:1473 ../src/qalc.cc:1490 ../src/qalc.cc:2560 +#: ../src/qalc.cc:2942 ../src/qalc.cc:3185 ../src/qalc.cc:3459 +#: ../src/qalc.cc:3469 ../src/qalc.cc:3573 ../src/qalc.cc:3669 +#: ../src/qalc.cc:4003 msgid "approximate" msgstr "benaderd" -#: ../src/defs2doc.cc:583 ../src/qalc.cc:1892 +#: ../src/defs2doc.cc:583 ../src/qalc.cc:1893 msgid "ans" msgstr "antw" #: ../src/defs2doc.cc:584 ../src/defs2doc.cc:587 ../src/defs2doc.cc:588 -#: ../src/defs2doc.cc:589 ../src/defs2doc.cc:590 ../src/qalc.cc:1893 -#: ../src/qalc.cc:1896 ../src/qalc.cc:1897 ../src/qalc.cc:1898 -#: ../src/qalc.cc:1899 ../src/qalc.cc:2153 ../libqalculate/Calculator.cc:10674 -#: ../libqalculate/Calculator.cc:10690 +#: ../src/defs2doc.cc:589 ../src/defs2doc.cc:590 ../src/qalc.cc:1894 +#: ../src/qalc.cc:1897 ../src/qalc.cc:1898 ../src/qalc.cc:1899 +#: ../src/qalc.cc:1900 ../src/qalc.cc:2154 +#: ../libqalculate/Calculator-definitions.cc:2225 +#: ../libqalculate/Calculator-definitions.cc:2241 msgid "Temporary" msgstr "Tijdelijk" -#: ../src/defs2doc.cc:584 ../src/qalc.cc:1893 +#: ../src/defs2doc.cc:584 ../src/qalc.cc:1894 msgid "Last Answer" msgstr "Laatste antwoord" -#: ../src/defs2doc.cc:585 ../src/qalc.cc:1894 +#: ../src/defs2doc.cc:585 ../src/qalc.cc:1895 msgid "answer" msgstr "antwoord" -#: ../src/defs2doc.cc:587 ../src/qalc.cc:1896 +#: ../src/defs2doc.cc:587 ../src/qalc.cc:1897 msgid "Answer 2" msgstr "Antwoord 2" -#: ../src/defs2doc.cc:588 ../src/qalc.cc:1897 +#: ../src/defs2doc.cc:588 ../src/qalc.cc:1898 msgid "Answer 3" msgstr "Antwoord 3" -#: ../src/defs2doc.cc:589 ../src/qalc.cc:1898 +#: ../src/defs2doc.cc:589 ../src/qalc.cc:1899 msgid "Answer 4" msgstr "Antwoord 4" -#: ../src/defs2doc.cc:590 ../src/qalc.cc:1899 +#: ../src/defs2doc.cc:590 ../src/qalc.cc:1900 msgid "Answer 5" msgstr "Antwoord 5" @@ -229,69 +230,69 @@ msgid "Uncategorized" msgstr "ontbinden in factoren" -#: ../src/qalc.cc:152 ../src/qalc.cc:219 ../src/qalc.cc:3621 +#: ../src/qalc.cc:153 ../src/qalc.cc:220 ../src/qalc.cc:3622 #: ../libqalculate/util.cc:175 msgid "yes" msgstr "ja" -#: ../src/qalc.cc:153 ../src/qalc.cc:221 ../src/qalc.cc:3621 +#: ../src/qalc.cc:154 ../src/qalc.cc:222 ../src/qalc.cc:3622 #: ../libqalculate/util.cc:176 msgid "no" msgstr "nee" -#: ../src/qalc.cc:154 ../libqalculate/util.cc:183 +#: ../src/qalc.cc:155 ../libqalculate/util.cc:183 msgid "true" msgstr "waar" -#: ../src/qalc.cc:155 ../libqalculate/util.cc:184 +#: ../src/qalc.cc:156 ../libqalculate/util.cc:184 msgid "false" msgstr "onwaar" -#: ../src/qalc.cc:156 ../src/qalc.cc:777 ../src/qalc.cc:797 ../src/qalc.cc:1112 -#: ../src/qalc.cc:1149 ../src/qalc.cc:3028 ../src/qalc.cc:3041 -#: ../src/qalc.cc:3099 ../src/qalc.cc:3620 ../src/qalc.cc:3735 -#: ../src/qalc.cc:3742 ../src/qalc.cc:3793 ../libqalculate/util.cc:191 +#: ../src/qalc.cc:157 ../src/qalc.cc:778 ../src/qalc.cc:798 ../src/qalc.cc:1113 +#: ../src/qalc.cc:1150 ../src/qalc.cc:3029 ../src/qalc.cc:3042 +#: ../src/qalc.cc:3100 ../src/qalc.cc:3621 ../src/qalc.cc:3736 +#: ../src/qalc.cc:3743 ../src/qalc.cc:3794 ../libqalculate/util.cc:191 msgid "on" msgstr "aan" -#: ../src/qalc.cc:157 ../src/qalc.cc:775 ../src/qalc.cc:796 ../src/qalc.cc:1021 -#: ../src/qalc.cc:1085 ../src/qalc.cc:1097 ../src/qalc.cc:1110 -#: ../src/qalc.cc:1147 ../src/qalc.cc:3027 ../src/qalc.cc:3032 -#: ../src/qalc.cc:3039 ../src/qalc.cc:3068 ../src/qalc.cc:3075 -#: ../src/qalc.cc:3082 ../src/qalc.cc:3098 ../src/qalc.cc:3132 -#: ../src/qalc.cc:3620 ../src/qalc.cc:3733 ../src/qalc.cc:3739 -#: ../src/qalc.cc:3742 ../src/qalc.cc:3750 ../src/qalc.cc:3757 -#: ../src/qalc.cc:3767 ../src/qalc.cc:3791 ../src/qalc.cc:3826 +#: ../src/qalc.cc:158 ../src/qalc.cc:776 ../src/qalc.cc:797 ../src/qalc.cc:1022 +#: ../src/qalc.cc:1086 ../src/qalc.cc:1098 ../src/qalc.cc:1111 +#: ../src/qalc.cc:1148 ../src/qalc.cc:3028 ../src/qalc.cc:3033 +#: ../src/qalc.cc:3040 ../src/qalc.cc:3069 ../src/qalc.cc:3076 +#: ../src/qalc.cc:3083 ../src/qalc.cc:3099 ../src/qalc.cc:3133 +#: ../src/qalc.cc:3621 ../src/qalc.cc:3734 ../src/qalc.cc:3740 +#: ../src/qalc.cc:3743 ../src/qalc.cc:3751 ../src/qalc.cc:3758 +#: ../src/qalc.cc:3768 ../src/qalc.cc:3792 ../src/qalc.cc:3827 #: ../libqalculate/util.cc:192 msgid "off" msgstr "uit" -#: ../src/qalc.cc:226 +#: ../src/qalc.cc:227 msgid "Please answer yes or no" msgstr "Antwoord alstublieft met ja of nee" -#: ../src/qalc.cc:258 +#: ../src/qalc.cc:259 msgid "Unrecognized assumption." msgstr "Onbekende aanname." -#: ../src/qalc.cc:425 ../src/qalc.cc:458 ../libqalculate/Calculator.cc:467 -#: ../libqalculate/Calculator.cc:693 ../libqalculate/DataSet.cc:1072 -#: ../libqalculate/DataSet.cc:1134 ../libqalculate/MathStructure.cc:21595 -#: ../libqalculate/Function.cc:2269 ../libqalculate/Function.cc:2285 +#: ../src/qalc.cc:426 ../src/qalc.cc:459 ../libqalculate/Calculator.cc:245 +#: ../libqalculate/Calculator.cc:473 ../libqalculate/DataSet.cc:1073 +#: ../libqalculate/DataSet.cc:1135 ../libqalculate/MathStructure-print.cc:3190 +#: ../libqalculate/Function.cc:2304 ../libqalculate/Function.cc:2320 msgid "or" msgstr "or" -#: ../src/qalc.cc:546 ../libqalculate/Calculator.cc:12220 +#: ../src/qalc.cc:547 ../libqalculate/Calculator-definitions.cc:3756 #, fuzzy, c-format msgid "It has been %s day(s) since the exchange rates last were updated." msgstr "" "Het is al meer dan een week geleden dat de wisselkoersen werden ververst." -#: ../src/qalc.cc:551 +#: ../src/qalc.cc:552 msgid "Do you wish to update the exchange rates now?" msgstr "" -#: ../src/qalc.cc:565 ../src/qalc.cc:566 +#: ../src/qalc.cc:566 ../src/qalc.cc:567 msgid "" "\n" "Press Enter to continue." @@ -299,667 +300,673 @@ "\n" "Druk op Enter om verder te gaan." -#: ../src/qalc.cc:581 ../src/qalc.cc:582 ../src/qalc.cc:583 ../src/qalc.cc:584 -#: ../src/qalc.cc:585 ../src/qalc.cc:586 ../src/qalc.cc:719 ../src/qalc.cc:814 -#: ../src/qalc.cc:817 ../src/qalc.cc:972 ../src/qalc.cc:991 ../src/qalc.cc:1003 -#: ../src/qalc.cc:1012 ../src/qalc.cc:2362 ../src/qalc.cc:2499 +#: ../src/qalc.cc:582 ../src/qalc.cc:583 ../src/qalc.cc:584 ../src/qalc.cc:585 +#: ../src/qalc.cc:586 ../src/qalc.cc:587 ../src/qalc.cc:720 ../src/qalc.cc:815 +#: ../src/qalc.cc:818 ../src/qalc.cc:973 ../src/qalc.cc:992 ../src/qalc.cc:1004 +#: ../src/qalc.cc:1013 ../src/qalc.cc:2363 ../src/qalc.cc:2500 msgid "Illegal value" msgstr "waarde niet toegestaan" #. qalc command -#: ../src/qalc.cc:614 ../src/qalc.cc:934 ../src/qalc.cc:2340 -#: ../src/qalc.cc:2803 ../src/qalc.cc:2809 ../src/qalc.cc:2994 -#: ../src/qalc.cc:3150 ../src/qalc.cc:3186 ../src/qalc.cc:3702 -#: ../src/qalc.cc:3839 ../src/qalc.cc:3994 ../src/qalc.cc:4922 -#: ../src/qalc.cc:4933 ../libqalculate/Calculator.cc:3051 -#: ../libqalculate/Calculator.cc:3055 +#: ../src/qalc.cc:615 ../src/qalc.cc:935 ../src/qalc.cc:2341 +#: ../src/qalc.cc:2804 ../src/qalc.cc:2810 ../src/qalc.cc:2995 +#: ../src/qalc.cc:3151 ../src/qalc.cc:3187 ../src/qalc.cc:3703 +#: ../src/qalc.cc:3840 ../src/qalc.cc:3995 ../src/qalc.cc:4923 +#: ../src/qalc.cc:4934 ../libqalculate/Calculator-calculate.cc:837 +#: ../libqalculate/Calculator-calculate.cc:841 msgid "base" msgstr "grondtal" -#: ../src/qalc.cc:614 ../src/qalc.cc:616 ../src/qalc.cc:3108 -#: ../src/qalc.cc:3804 +#: ../src/qalc.cc:615 ../src/qalc.cc:617 ../src/qalc.cc:3109 +#: ../src/qalc.cc:3805 msgid "input base" msgstr "grondtal in" -#: ../src/qalc.cc:614 ../src/qalc.cc:617 +#: ../src/qalc.cc:615 ../src/qalc.cc:618 msgid "output base" msgstr "grondtal uit" -#: ../src/qalc.cc:618 ../src/qalc.cc:2606 ../src/qalc.cc:2996 -#: ../src/qalc.cc:3110 ../src/qalc.cc:3714 ../src/qalc.cc:3812 -#: ../src/qalc.cc:4756 ../libqalculate/Calculator.cc:2969 +#: ../src/qalc.cc:619 ../src/qalc.cc:2607 ../src/qalc.cc:2997 +#: ../src/qalc.cc:3111 ../src/qalc.cc:3715 ../src/qalc.cc:3813 +#: ../src/qalc.cc:4757 ../libqalculate/Calculator-calculate.cc:755 msgid "roman" msgstr "Romeins" -#: ../src/qalc.cc:619 ../src/qalc.cc:2611 ../src/qalc.cc:2997 -#: ../src/qalc.cc:3111 ../src/qalc.cc:4764 ../libqalculate/Calculator.cc:2972 +#: ../src/qalc.cc:620 ../src/qalc.cc:2612 ../src/qalc.cc:2998 +#: ../src/qalc.cc:3112 ../src/qalc.cc:4765 +#: ../libqalculate/Calculator-calculate.cc:758 #, fuzzy msgid "bijective" msgstr "Object" -#: ../src/qalc.cc:620 ../src/qalc.cc:2621 ../src/qalc.cc:2999 -#: ../src/qalc.cc:3712 ../src/qalc.cc:4780 ../libqalculate/Calculator.cc:2978 +#: ../src/qalc.cc:621 ../src/qalc.cc:2622 ../src/qalc.cc:3000 +#: ../src/qalc.cc:3713 ../src/qalc.cc:4781 +#: ../libqalculate/Calculator-calculate.cc:764 msgid "time" msgstr "tijd" -#: ../src/qalc.cc:621 ../src/qalc.cc:2581 ../src/qalc.cc:4716 -#: ../libqalculate/Calculator.cc:2954 +#: ../src/qalc.cc:622 ../src/qalc.cc:2582 ../src/qalc.cc:4717 +#: ../libqalculate/Calculator-calculate.cc:740 msgid "hexadecimal" msgstr "hexadecimaal" -#: ../src/qalc.cc:628 ../src/qalc.cc:2601 ../src/qalc.cc:4748 -#: ../libqalculate/Calculator.cc:2966 +#: ../src/qalc.cc:629 ../src/qalc.cc:2602 ../src/qalc.cc:4749 +#: ../libqalculate/Calculator-calculate.cc:752 msgid "duodecimal" msgstr "duodecimaal" -#: ../src/qalc.cc:629 ../src/qalc.cc:2586 ../src/qalc.cc:4724 -#: ../libqalculate/Calculator.cc:2957 +#: ../src/qalc.cc:630 ../src/qalc.cc:2587 ../src/qalc.cc:4725 +#: ../libqalculate/Calculator-calculate.cc:743 msgid "binary" msgstr "binair" -#: ../src/qalc.cc:630 ../src/qalc.cc:2596 ../src/qalc.cc:4740 -#: ../libqalculate/Calculator.cc:2963 +#: ../src/qalc.cc:631 ../src/qalc.cc:2597 ../src/qalc.cc:4741 +#: ../libqalculate/Calculator-calculate.cc:749 msgid "octal" msgstr "octaal" -#: ../src/qalc.cc:631 ../src/qalc.cc:2591 ../src/qalc.cc:4732 -#: ../libqalculate/Calculator.cc:2960 +#: ../src/qalc.cc:632 ../src/qalc.cc:2592 ../src/qalc.cc:4733 +#: ../libqalculate/Calculator-calculate.cc:746 msgid "decimal" msgstr "decimaal" -#: ../src/qalc.cc:632 ../src/qalc.cc:2616 ../src/qalc.cc:2998 -#: ../src/qalc.cc:4772 ../libqalculate/Calculator.cc:2975 +#: ../src/qalc.cc:633 ../src/qalc.cc:2617 ../src/qalc.cc:2999 +#: ../src/qalc.cc:4773 ../libqalculate/Calculator-calculate.cc:761 msgid "sexagesimal" msgstr "sexagesimaal" -#: ../src/qalc.cc:643 ../src/qalc.cc:757 ../src/qalc.cc:3010 -#: ../src/qalc.cc:3726 +#: ../src/qalc.cc:644 ../src/qalc.cc:758 ../src/qalc.cc:3011 +#: ../src/qalc.cc:3727 msgid "base display" msgstr "tonen van grondtal" -#: ../src/qalc.cc:673 +#: ../src/qalc.cc:674 msgid "Illegal base." msgstr "Grondtal niet toegestaan." -#: ../src/qalc.cc:681 ../src/qalc.cc:709 ../src/qalc.cc:2925 -#: ../src/qalc.cc:3639 +#: ../src/qalc.cc:682 ../src/qalc.cc:710 ../src/qalc.cc:2926 +#: ../src/qalc.cc:3640 msgid "assumptions" msgstr "aannames" -#: ../src/qalc.cc:712 ../src/qalc.cc:3141 ../src/qalc.cc:3831 +#: ../src/qalc.cc:713 ../src/qalc.cc:3142 ../src/qalc.cc:3832 msgid "all prefixes" msgstr "alle voorvoegsels" -#: ../src/qalc.cc:713 ../src/qalc.cc:2959 ../src/qalc.cc:3679 +#: ../src/qalc.cc:714 ../src/qalc.cc:2960 ../src/qalc.cc:3680 msgid "complex numbers" msgstr "complexe getallen" -#: ../src/qalc.cc:714 ../src/qalc.cc:2977 ../src/qalc.cc:3691 +#: ../src/qalc.cc:715 ../src/qalc.cc:2978 ../src/qalc.cc:3692 msgid "excessive parentheses" msgstr "te veel haakjes" -#: ../src/qalc.cc:715 ../src/qalc.cc:2960 ../src/qalc.cc:3240 -#: ../src/qalc.cc:3245 ../src/qalc.cc:3680 +#: ../src/qalc.cc:716 ../src/qalc.cc:2961 ../src/qalc.cc:3241 +#: ../src/qalc.cc:3246 ../src/qalc.cc:3681 msgid "functions" msgstr "functies" -#: ../src/qalc.cc:716 ../src/qalc.cc:2961 ../src/qalc.cc:3681 +#: ../src/qalc.cc:717 ../src/qalc.cc:2962 ../src/qalc.cc:3682 msgid "infinite numbers" msgstr "oneindige getallen" -#: ../src/qalc.cc:717 ../src/qalc.cc:2986 ../src/qalc.cc:3694 +#: ../src/qalc.cc:718 ../src/qalc.cc:2987 ../src/qalc.cc:3695 msgid "show negative exponents" msgstr "toon negatieve exponenten" -#: ../src/qalc.cc:718 ../src/qalc.cc:2978 ../src/qalc.cc:3692 +#: ../src/qalc.cc:719 ../src/qalc.cc:2979 ../src/qalc.cc:3693 #, fuzzy msgid "minus last" msgstr "minus" -#: ../src/qalc.cc:720 ../src/qalc.cc:2903 ../src/qalc.cc:3636 +#: ../src/qalc.cc:721 ../src/qalc.cc:2904 ../src/qalc.cc:3637 msgid "assume nonzero denominators" msgstr "neem noemers aan ongelijk nul" -#: ../src/qalc.cc:721 ../src/qalc.cc:2904 ../src/qalc.cc:3637 +#: ../src/qalc.cc:722 ../src/qalc.cc:2905 ../src/qalc.cc:3638 msgid "warn nonzero denominators" msgstr "waarschuwen noemers ongelijk nul" -#: ../src/qalc.cc:722 ../src/qalc.cc:3158 ../src/qalc.cc:3851 +#: ../src/qalc.cc:723 ../src/qalc.cc:3159 ../src/qalc.cc:3852 msgid "prefixes" msgstr "voorvoegsels" -#: ../src/qalc.cc:723 ../src/qalc.cc:3154 ../src/qalc.cc:3847 +#: ../src/qalc.cc:724 ../src/qalc.cc:3155 ../src/qalc.cc:3848 #, fuzzy msgid "binary prefixes" msgstr "voorvoegsels voor noemers" -#: ../src/qalc.cc:730 ../src/qalc.cc:3156 ../src/qalc.cc:3849 +#: ../src/qalc.cc:731 ../src/qalc.cc:3157 ../src/qalc.cc:3850 msgid "denominator prefixes" msgstr "voorvoegsels voor noemers" -#: ../src/qalc.cc:731 ../src/qalc.cc:3157 ../src/qalc.cc:3850 +#: ../src/qalc.cc:732 ../src/qalc.cc:3158 ../src/qalc.cc:3851 msgid "place units separately" msgstr "eenheden apart plaatsen" -#: ../src/qalc.cc:732 ../src/qalc.cc:2958 ../src/qalc.cc:3678 +#: ../src/qalc.cc:733 ../src/qalc.cc:2959 ../src/qalc.cc:3679 msgid "calculate variables" msgstr "variabelen berekenen" -#: ../src/qalc.cc:733 ../src/qalc.cc:2957 ../src/qalc.cc:3677 +#: ../src/qalc.cc:734 ../src/qalc.cc:2958 ../src/qalc.cc:3678 msgid "calculate functions" msgstr "functies berekenen" -#: ../src/qalc.cc:734 ../src/qalc.cc:3159 ../src/qalc.cc:3852 +#: ../src/qalc.cc:735 ../src/qalc.cc:3160 ../src/qalc.cc:3853 msgid "sync units" msgstr "sync eenheden" -#: ../src/qalc.cc:735 ../src/qalc.cc:3079 ../src/qalc.cc:3763 +#: ../src/qalc.cc:736 ../src/qalc.cc:3080 ../src/qalc.cc:3764 msgid "round to even" msgstr "afronden naar even" -#: ../src/qalc.cc:736 ../src/qalc.cc:3137 ../src/qalc.cc:3827 +#: ../src/qalc.cc:737 ../src/qalc.cc:3138 ../src/qalc.cc:3828 msgid "rpn syntax" msgstr "rpn-notatie" #. qalc command -#: ../src/qalc.cc:737 ../src/qalc.cc:2343 ../src/qalc.cc:3171 -#: ../src/qalc.cc:3208 ../src/qalc.cc:3864 ../src/qalc.cc:3944 +#: ../src/qalc.cc:738 ../src/qalc.cc:2344 ../src/qalc.cc:3172 +#: ../src/qalc.cc:3209 ../src/qalc.cc:3865 ../src/qalc.cc:3945 msgid "rpn" msgstr "rpn" -#: ../src/qalc.cc:738 ../src/qalc.cc:2987 ../src/qalc.cc:3695 +#: ../src/qalc.cc:739 ../src/qalc.cc:2988 ../src/qalc.cc:3696 msgid "short multiplication" msgstr "korte vermenigvuldiging" -#: ../src/qalc.cc:739 ../src/qalc.cc:3062 ../src/qalc.cc:3746 +#: ../src/qalc.cc:740 ../src/qalc.cc:3063 ../src/qalc.cc:3747 msgid "lowercase e" msgstr "kleine letter e" -#: ../src/qalc.cc:740 ../src/qalc.cc:3063 ../src/qalc.cc:3747 +#: ../src/qalc.cc:741 ../src/qalc.cc:3064 ../src/qalc.cc:3748 msgid "lowercase numbers" msgstr "onderkast getallen" -#: ../src/qalc.cc:741 ../src/qalc.cc:3046 ../src/qalc.cc:3107 -#: ../src/qalc.cc:3744 ../src/qalc.cc:3803 +#: ../src/qalc.cc:742 ../src/qalc.cc:3047 ../src/qalc.cc:3108 +#: ../src/qalc.cc:3745 ../src/qalc.cc:3804 msgid "imaginary j" msgstr "" -#: ../src/qalc.cc:759 ../src/qalc.cc:776 ../src/qalc.cc:830 ../src/qalc.cc:930 -#: ../src/qalc.cc:956 ../src/qalc.cc:2898 ../src/qalc.cc:2934 -#: ../src/qalc.cc:2947 ../src/qalc.cc:3012 ../src/qalc.cc:3146 -#: ../src/qalc.cc:3667 ../src/qalc.cc:3726 ../src/qalc.cc:3835 +#: ../src/qalc.cc:760 ../src/qalc.cc:777 ../src/qalc.cc:831 ../src/qalc.cc:931 +#: ../src/qalc.cc:957 ../src/qalc.cc:2899 ../src/qalc.cc:2935 +#: ../src/qalc.cc:2948 ../src/qalc.cc:3013 ../src/qalc.cc:3147 +#: ../src/qalc.cc:3668 ../src/qalc.cc:3727 ../src/qalc.cc:3836 msgid "none" msgstr "geen" -#: ../src/qalc.cc:760 ../src/qalc.cc:3013 ../src/qalc.cc:3726 +#: ../src/qalc.cc:761 ../src/qalc.cc:3014 ../src/qalc.cc:3727 msgid "normal" msgstr "normaal" -#: ../src/qalc.cc:761 ../src/qalc.cc:3014 ../src/qalc.cc:3726 +#: ../src/qalc.cc:762 ../src/qalc.cc:3015 ../src/qalc.cc:3727 msgid "alternative" msgstr "alternatief" -#: ../src/qalc.cc:766 ../src/qalc.cc:783 ../src/qalc.cc:803 ../src/qalc.cc:835 -#: ../src/qalc.cc:852 ../src/qalc.cc:877 ../src/qalc.cc:891 ../src/qalc.cc:905 -#: ../src/qalc.cc:922 ../src/qalc.cc:947 ../src/qalc.cc:963 ../src/qalc.cc:1032 -#: ../src/qalc.cc:1038 ../src/qalc.cc:1062 ../src/qalc.cc:1119 -#: ../src/qalc.cc:1138 ../src/qalc.cc:1154 +#: ../src/qalc.cc:767 ../src/qalc.cc:784 ../src/qalc.cc:804 ../src/qalc.cc:836 +#: ../src/qalc.cc:853 ../src/qalc.cc:878 ../src/qalc.cc:892 ../src/qalc.cc:906 +#: ../src/qalc.cc:923 ../src/qalc.cc:948 ../src/qalc.cc:964 ../src/qalc.cc:1033 +#: ../src/qalc.cc:1039 ../src/qalc.cc:1063 ../src/qalc.cc:1120 +#: ../src/qalc.cc:1139 ../src/qalc.cc:1155 msgid "Illegal value." msgstr "Waarde niet toegestaan." -#: ../src/qalc.cc:771 ../src/qalc.cc:3091 ../src/qalc.cc:3781 +#: ../src/qalc.cc:772 ../src/qalc.cc:3092 ../src/qalc.cc:3782 msgid "two's complement" msgstr "" -#: ../src/qalc.cc:772 ../src/qalc.cc:3045 ../src/qalc.cc:3743 +#: ../src/qalc.cc:773 ../src/qalc.cc:3046 ../src/qalc.cc:3744 #, fuzzy msgid "hexadecimal two's" msgstr "hexadecimaal" -#: ../src/qalc.cc:773 ../src/qalc.cc:3030 ../src/qalc.cc:3739 +#: ../src/qalc.cc:774 ../src/qalc.cc:3031 ../src/qalc.cc:3740 msgid "digit grouping" msgstr "cijfergroepering" -#: ../src/qalc.cc:777 ../src/qalc.cc:3033 ../src/qalc.cc:3739 +#: ../src/qalc.cc:778 ../src/qalc.cc:3034 ../src/qalc.cc:3740 msgid "standard" msgstr "" -#: ../src/qalc.cc:778 ../src/qalc.cc:798 ../src/qalc.cc:3026 -#: ../src/qalc.cc:3034 ../src/qalc.cc:3097 ../src/qalc.cc:3731 -#: ../src/qalc.cc:3739 ../src/qalc.cc:3789 +#: ../src/qalc.cc:779 ../src/qalc.cc:799 ../src/qalc.cc:3027 +#: ../src/qalc.cc:3035 ../src/qalc.cc:3098 ../src/qalc.cc:3732 +#: ../src/qalc.cc:3740 ../src/qalc.cc:3790 msgid "locale" msgstr "" -#: ../src/qalc.cc:788 ../src/qalc.cc:2989 ../src/qalc.cc:3697 +#: ../src/qalc.cc:789 ../src/qalc.cc:2990 ../src/qalc.cc:3698 msgid "spell out logical" msgstr "logische voluit spellen" -#: ../src/qalc.cc:789 ../src/qalc.cc:3105 ../src/qalc.cc:3801 +#: ../src/qalc.cc:790 ../src/qalc.cc:3106 ../src/qalc.cc:3802 msgid "ignore dot" msgstr "punt negeren" -#: ../src/qalc.cc:790 ../src/qalc.cc:3102 ../src/qalc.cc:3798 +#: ../src/qalc.cc:791 ../src/qalc.cc:3103 ../src/qalc.cc:3799 msgid "ignore comma" msgstr "komma negeren" -#: ../src/qalc.cc:794 ../src/qalc.cc:3025 ../src/qalc.cc:3096 -#: ../src/qalc.cc:3728 ../src/qalc.cc:3786 +#: ../src/qalc.cc:795 ../src/qalc.cc:3026 ../src/qalc.cc:3097 +#: ../src/qalc.cc:3729 ../src/qalc.cc:3787 msgid "decimal comma" msgstr "decimale komma" -#: ../src/qalc.cc:813 ../src/qalc.cc:3122 ../src/qalc.cc:3824 +#: ../src/qalc.cc:814 ../src/qalc.cc:3123 ../src/qalc.cc:3825 msgid "limit implicit multiplication" msgstr "impliciet vermenigvuldigen beperken" -#: ../src/qalc.cc:815 ../src/qalc.cc:2988 ../src/qalc.cc:3696 +#: ../src/qalc.cc:816 ../src/qalc.cc:2989 ../src/qalc.cc:3697 msgid "spacious" msgstr "ruimtelijk" -#: ../src/qalc.cc:816 ../src/qalc.cc:2990 ../src/qalc.cc:3698 +#: ../src/qalc.cc:817 ../src/qalc.cc:2991 ../src/qalc.cc:3699 msgid "unicode" msgstr "unicode" -#: ../src/qalc.cc:819 ../src/qalc.cc:2962 ../src/qalc.cc:3242 -#: ../src/qalc.cc:3247 ../src/qalc.cc:3682 +#: ../src/qalc.cc:820 ../src/qalc.cc:2963 ../src/qalc.cc:3243 +#: ../src/qalc.cc:3248 ../src/qalc.cc:3683 msgid "units" msgstr "eenheden" -#: ../src/qalc.cc:820 ../src/qalc.cc:2963 ../src/qalc.cc:3683 +#: ../src/qalc.cc:821 ../src/qalc.cc:2964 ../src/qalc.cc:3684 msgid "unknowns" msgstr "onbekenden" -#: ../src/qalc.cc:821 ../src/qalc.cc:2964 ../src/qalc.cc:3241 -#: ../src/qalc.cc:3246 ../src/qalc.cc:3684 +#: ../src/qalc.cc:822 ../src/qalc.cc:2965 ../src/qalc.cc:3242 +#: ../src/qalc.cc:3247 ../src/qalc.cc:3685 msgid "variables" msgstr "variabelen" -#: ../src/qalc.cc:822 ../src/qalc.cc:2969 ../src/qalc.cc:3689 +#: ../src/qalc.cc:823 ../src/qalc.cc:2970 ../src/qalc.cc:3690 msgid "abbreviations" msgstr "afkortingen" -#: ../src/qalc.cc:823 ../src/qalc.cc:3090 ../src/qalc.cc:3780 +#: ../src/qalc.cc:824 ../src/qalc.cc:3091 ../src/qalc.cc:3781 msgid "show ending zeroes" msgstr "afsluitende nullen tonen" -#: ../src/qalc.cc:824 ../src/qalc.cc:3078 ../src/qalc.cc:3762 +#: ../src/qalc.cc:825 ../src/qalc.cc:3079 ../src/qalc.cc:3763 msgid "repeating decimals" msgstr "oneindige reeksen" -#: ../src/qalc.cc:825 ../src/qalc.cc:2929 ../src/qalc.cc:3667 +#: ../src/qalc.cc:826 ../src/qalc.cc:2930 ../src/qalc.cc:3668 msgid "angle unit" msgstr "hoekeenheid" -#: ../src/qalc.cc:827 ../src/qalc.cc:2931 ../src/qalc.cc:2932 +#: ../src/qalc.cc:828 ../src/qalc.cc:2932 ../src/qalc.cc:2933 msgid "rad" msgstr "rad" -#: ../src/qalc.cc:827 ../src/qalc.cc:3667 +#: ../src/qalc.cc:828 ../src/qalc.cc:3668 msgid "radians" msgstr "radialen" -#: ../src/qalc.cc:828 +#: ../src/qalc.cc:829 msgid "deg" msgstr "deg" -#: ../src/qalc.cc:828 ../src/qalc.cc:3667 +#: ../src/qalc.cc:829 ../src/qalc.cc:3668 msgid "degrees" msgstr "booggraden" -#: ../src/qalc.cc:829 ../src/qalc.cc:2933 +#: ../src/qalc.cc:830 ../src/qalc.cc:2934 msgid "gra" msgstr "gra" -#: ../src/qalc.cc:829 ../src/qalc.cc:3667 +#: ../src/qalc.cc:830 ../src/qalc.cc:3668 msgid "gradians" msgstr "decimale graden" -#: ../src/qalc.cc:842 ../src/qalc.cc:3095 ../src/qalc.cc:3785 +#: ../src/qalc.cc:843 ../src/qalc.cc:3096 ../src/qalc.cc:3786 msgid "caret as xor" msgstr "" -#: ../src/qalc.cc:843 ../src/qalc.cc:3123 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4057 +#: ../src/qalc.cc:844 ../src/qalc.cc:3124 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4058 msgid "parsing mode" msgstr "interpretatie modus" -#: ../src/qalc.cc:845 ../src/qalc.cc:1045 ../src/qalc.cc:3049 -#: ../src/qalc.cc:3125 ../src/qalc.cc:3745 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4065 +#: ../src/qalc.cc:846 ../src/qalc.cc:1046 ../src/qalc.cc:3050 +#: ../src/qalc.cc:3126 ../src/qalc.cc:3746 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4066 #, fuzzy msgid "adaptive" msgstr "alternatief" -#: ../src/qalc.cc:846 ../src/qalc.cc:3126 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4062 +#: ../src/qalc.cc:847 ../src/qalc.cc:3127 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4063 msgid "implicit first" msgstr "" -#: ../src/qalc.cc:847 ../src/qalc.cc:3127 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4059 +#: ../src/qalc.cc:848 ../src/qalc.cc:3128 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4060 #, fuzzy msgid "conventional" msgstr "optioneel" -#: ../src/qalc.cc:857 ../src/qalc.cc:1696 ../src/qalc.cc:3160 -#: ../src/qalc.cc:3853 +#: ../src/qalc.cc:858 ../src/qalc.cc:1697 ../src/qalc.cc:3161 +#: ../src/qalc.cc:3854 msgid "update exchange rates" msgstr "wisselkoersen bijwerken" -#: ../src/qalc.cc:858 ../src/qalc.cc:3163 ../src/qalc.cc:3855 +#: ../src/qalc.cc:859 ../src/qalc.cc:3164 ../src/qalc.cc:3856 msgid "never" msgstr "nooit" -#: ../src/qalc.cc:860 ../src/qalc.cc:3162 ../src/qalc.cc:3854 +#: ../src/qalc.cc:861 ../src/qalc.cc:3163 ../src/qalc.cc:3855 msgid "ask" msgstr "vragen" -#: ../src/qalc.cc:868 ../src/qalc.cc:2979 ../src/qalc.cc:3693 +#: ../src/qalc.cc:869 ../src/qalc.cc:2980 ../src/qalc.cc:3694 msgid "multiplication sign" msgstr "vermenigvuldigingsteken" -#: ../src/qalc.cc:882 ../src/qalc.cc:2970 ../src/qalc.cc:3690 +#: ../src/qalc.cc:883 ../src/qalc.cc:2971 ../src/qalc.cc:3691 msgid "division sign" msgstr "teken voor delen" -#: ../src/qalc.cc:896 ../src/qalc.cc:2937 ../src/qalc.cc:3668 +#: ../src/qalc.cc:897 ../src/qalc.cc:2938 ../src/qalc.cc:3669 msgid "approximation" msgstr "benadering" #. qalc command -#: ../src/qalc.cc:898 ../src/qalc.cc:969 ../src/qalc.cc:1111 -#: ../src/qalc.cc:2549 ../src/qalc.cc:2939 ../src/qalc.cc:3040 -#: ../src/qalc.cc:3188 ../src/qalc.cc:3668 ../src/qalc.cc:3742 -#: ../src/qalc.cc:3998 +#: ../src/qalc.cc:899 ../src/qalc.cc:970 ../src/qalc.cc:1112 +#: ../src/qalc.cc:2550 ../src/qalc.cc:2940 ../src/qalc.cc:3041 +#: ../src/qalc.cc:3189 ../src/qalc.cc:3669 ../src/qalc.cc:3743 +#: ../src/qalc.cc:3999 msgid "exact" msgstr "exact" -#: ../src/qalc.cc:899 ../src/qalc.cc:2940 ../src/qalc.cc:3668 +#: ../src/qalc.cc:900 ../src/qalc.cc:2941 ../src/qalc.cc:3669 msgid "try exact" msgstr "exact proberen" -#: ../src/qalc.cc:914 ../src/qalc.cc:2945 ../src/qalc.cc:3670 +#: ../src/qalc.cc:915 ../src/qalc.cc:2946 ../src/qalc.cc:3671 msgid "interval calculation" msgstr "interval berekening" -#: ../src/qalc.cc:914 +#: ../src/qalc.cc:915 msgid "uncertainty propagation" msgstr "" -#: ../src/qalc.cc:916 ../src/qalc.cc:2948 ../src/qalc.cc:3670 +#: ../src/qalc.cc:917 ../src/qalc.cc:2949 ../src/qalc.cc:3671 msgid "variance formula" msgstr "" -#: ../src/qalc.cc:916 +#: ../src/qalc.cc:917 #, fuzzy msgid "variance" msgstr "variabele" -#: ../src/qalc.cc:917 ../src/qalc.cc:1069 ../src/qalc.cc:2944 -#: ../src/qalc.cc:2949 ../src/qalc.cc:3669 ../src/qalc.cc:3670 +#: ../src/qalc.cc:918 ../src/qalc.cc:1070 ../src/qalc.cc:2945 +#: ../src/qalc.cc:2950 ../src/qalc.cc:3670 ../src/qalc.cc:3671 msgid "interval arithmetic" msgstr "interval rekenkunde" -#: ../src/qalc.cc:927 ../src/qalc.cc:3142 ../src/qalc.cc:3832 +#: ../src/qalc.cc:928 ../src/qalc.cc:3143 ../src/qalc.cc:3833 msgid "autoconversion" msgstr "autoconversie" -#: ../src/qalc.cc:931 ../src/qalc.cc:2797 +#: ../src/qalc.cc:932 ../src/qalc.cc:2798 msgid "best" msgstr "best" -#: ../src/qalc.cc:932 ../src/qalc.cc:3151 ../src/qalc.cc:3841 +#: ../src/qalc.cc:933 ../src/qalc.cc:3152 ../src/qalc.cc:3842 msgid "optimalsi" msgstr "optimalesi" -#: ../src/qalc.cc:933 ../src/qalc.cc:2797 ../src/qalc.cc:3149 -#: ../src/qalc.cc:3837 ../src/qalc.cc:4911 ../libqalculate/Calculator.cc:3047 +#: ../src/qalc.cc:934 ../src/qalc.cc:2798 ../src/qalc.cc:3150 +#: ../src/qalc.cc:3838 ../src/qalc.cc:4912 +#: ../libqalculate/Calculator-calculate.cc:833 msgid "optimal" msgstr "optimale" -#: ../src/qalc.cc:935 ../src/qalc.cc:1113 ../src/qalc.cc:3042 -#: ../src/qalc.cc:3145 ../src/qalc.cc:3742 ../src/qalc.cc:3843 -#: ../src/qalc.cc:4966 ../libqalculate/Calculator.cc:3076 +#: ../src/qalc.cc:936 ../src/qalc.cc:1114 ../src/qalc.cc:3043 +#: ../src/qalc.cc:3146 ../src/qalc.cc:3743 ../src/qalc.cc:3844 +#: ../src/qalc.cc:4967 ../libqalculate/Calculator-calculate.cc:862 msgid "mixed" msgstr "gemengde" -#: ../src/qalc.cc:953 ../src/qalc.cc:3155 ../src/qalc.cc:3848 +#: ../src/qalc.cc:954 ../src/qalc.cc:3156 ../src/qalc.cc:3849 msgid "currency conversion" msgstr "valutaconversie" -#: ../src/qalc.cc:954 ../src/qalc.cc:2896 ../src/qalc.cc:3635 +#: ../src/qalc.cc:955 ../src/qalc.cc:2897 ../src/qalc.cc:3636 msgid "algebra mode" msgstr "algebraïsche modus" #. qalc command -#: ../src/qalc.cc:957 ../src/qalc.cc:2884 ../src/qalc.cc:3612 +#: ../src/qalc.cc:958 ../src/qalc.cc:2885 ../src/qalc.cc:3613 msgid "simplify" msgstr "vereenvoudigen" -#: ../src/qalc.cc:957 ../src/qalc.cc:2884 ../src/qalc.cc:2900 -#: ../src/qalc.cc:3203 ../src/qalc.cc:3612 ../src/qalc.cc:3635 -#: ../src/qalc.cc:5015 ../libqalculate/Calculator.cc:3101 +#: ../src/qalc.cc:958 ../src/qalc.cc:2885 ../src/qalc.cc:2901 +#: ../src/qalc.cc:3204 ../src/qalc.cc:3613 ../src/qalc.cc:3636 +#: ../src/qalc.cc:5016 ../libqalculate/Calculator-calculate.cc:891 msgid "expand" msgstr "uitwerken" -#: ../src/qalc.cc:958 ../src/qalc.cc:2899 ../src/qalc.cc:3635 -#: ../src/qalc.cc:5012 ../libqalculate/Calculator.cc:3097 +#: ../src/qalc.cc:959 ../src/qalc.cc:2900 ../src/qalc.cc:3636 +#: ../src/qalc.cc:5013 ../libqalculate/Calculator-calculate.cc:887 msgid "factorize" msgstr "factorisatie" -#: ../src/qalc.cc:988 ../src/qalc.cc:3170 ../src/qalc.cc:3863 +#: ../src/qalc.cc:989 ../src/qalc.cc:3171 ../src/qalc.cc:3864 #, fuzzy msgid "ignore locale" msgstr "komma negeren" -#: ../src/qalc.cc:1000 ../src/qalc.cc:3173 ../src/qalc.cc:3201 -#: ../src/qalc.cc:3866 +#: ../src/qalc.cc:1001 ../src/qalc.cc:3174 ../src/qalc.cc:3202 +#: ../src/qalc.cc:3867 msgid "save mode" msgstr "modus opslaan" -#: ../src/qalc.cc:1009 ../src/qalc.cc:3172 ../src/qalc.cc:3200 -#: ../src/qalc.cc:3865 +#: ../src/qalc.cc:1010 ../src/qalc.cc:3173 ../src/qalc.cc:3201 +#: ../src/qalc.cc:3866 msgid "save definitions" msgstr "definities opslaan" -#: ../src/qalc.cc:1018 ../src/qalc.cc:3080 ../src/qalc.cc:3764 +#: ../src/qalc.cc:1019 ../src/qalc.cc:3081 ../src/qalc.cc:3765 msgid "scientific notation" msgstr "wetenschappelijke notatie" -#: ../src/qalc.cc:1022 ../src/qalc.cc:3083 ../src/qalc.cc:3769 +#: ../src/qalc.cc:1023 ../src/qalc.cc:3084 ../src/qalc.cc:3770 msgid "auto" msgstr "auto" -#: ../src/qalc.cc:1023 ../src/qalc.cc:3084 ../src/qalc.cc:3773 +#: ../src/qalc.cc:1024 ../src/qalc.cc:3085 ../src/qalc.cc:3774 msgid "pure" msgstr "zuiver" -#: ../src/qalc.cc:1024 ../src/qalc.cc:3085 ../src/qalc.cc:3775 +#: ../src/qalc.cc:1025 ../src/qalc.cc:3086 ../src/qalc.cc:3776 msgid "scientific" msgstr "wetenschappelijk" -#: ../src/qalc.cc:1025 ../src/qalc.cc:3086 ../src/qalc.cc:3771 +#: ../src/qalc.cc:1026 ../src/qalc.cc:3087 ../src/qalc.cc:3772 msgid "engineering" msgstr "technisch" -#: ../src/qalc.cc:1034 ../src/qalc.cc:2953 ../src/qalc.cc:3671 +#: ../src/qalc.cc:1035 ../src/qalc.cc:2954 ../src/qalc.cc:3672 msgid "precision" msgstr "nauwkeurigheid" -#: ../src/qalc.cc:1043 ../src/qalc.cc:3047 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1044 ../src/qalc.cc:3048 ../src/qalc.cc:3746 msgid "interval display" msgstr "tonen interval" -#: ../src/qalc.cc:1046 ../src/qalc.cc:3052 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1047 ../src/qalc.cc:3053 ../src/qalc.cc:3746 #, fuzzy msgid "significant" msgstr "wetenschappelijk" -#: ../src/qalc.cc:1047 ../src/qalc.cc:3053 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1048 ../src/qalc.cc:3054 ../src/qalc.cc:3746 #, fuzzy msgid "interval" msgstr "geheel" -#: ../src/qalc.cc:1048 ../src/qalc.cc:3054 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1049 ../src/qalc.cc:3055 ../src/qalc.cc:3746 #, fuzzy msgid "plusminus" msgstr "minus" -#: ../src/qalc.cc:1049 ../src/qalc.cc:3055 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1050 ../src/qalc.cc:3056 ../src/qalc.cc:3746 msgid "midpoint" msgstr "" -#: ../src/qalc.cc:1050 ../src/qalc.cc:3057 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1051 ../src/qalc.cc:3058 ../src/qalc.cc:3746 msgid "upper" msgstr "" -#: ../src/qalc.cc:1051 ../src/qalc.cc:3056 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1052 ../src/qalc.cc:3057 ../src/qalc.cc:3746 #, fuzzy msgid "lower" msgstr "kleine letter e" -#: ../src/qalc.cc:1076 ../src/qalc.cc:2965 ../src/qalc.cc:3685 +#: ../src/qalc.cc:1077 ../src/qalc.cc:2966 ../src/qalc.cc:3686 msgid "variable units" msgstr "variabele enheeden" -#: ../src/qalc.cc:1083 ../src/qalc.cc:3064 ../src/qalc.cc:3748 +#: ../src/qalc.cc:1084 ../src/qalc.cc:3065 ../src/qalc.cc:3749 msgid "max decimals" msgstr "max decimalen" -#: ../src/qalc.cc:1095 ../src/qalc.cc:3071 ../src/qalc.cc:3755 +#: ../src/qalc.cc:1096 ../src/qalc.cc:3072 ../src/qalc.cc:3756 msgid "min decimals" msgstr "min decimalen" -#: ../src/qalc.cc:1108 ../src/qalc.cc:3037 ../src/qalc.cc:3742 +#: ../src/qalc.cc:1109 ../src/qalc.cc:3038 ../src/qalc.cc:3743 msgid "fractions" msgstr "breuken" -#: ../src/qalc.cc:1113 +#: ../src/qalc.cc:1114 msgid "combined" msgstr "gemengde" -#: ../src/qalc.cc:1114 ../src/qalc.cc:3041 ../src/qalc.cc:3742 +#: ../src/qalc.cc:1115 ../src/qalc.cc:3042 ../src/qalc.cc:3743 msgid "long" msgstr "" -#: ../src/qalc.cc:1127 ../src/qalc.cc:3017 ../src/qalc.cc:3727 +#: ../src/qalc.cc:1128 ../src/qalc.cc:3018 ../src/qalc.cc:3728 msgid "complex form" msgstr "complexe vorm" -#: ../src/qalc.cc:1129 ../src/qalc.cc:2667 ../src/qalc.cc:3019 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4856 ../libqalculate/Calculator.cc:3015 +#: ../src/qalc.cc:1130 ../src/qalc.cc:2668 ../src/qalc.cc:3020 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4857 +#: ../libqalculate/Calculator-calculate.cc:801 msgid "rectangular" msgstr "rechthoekig" -#: ../src/qalc.cc:1129 ../src/qalc.cc:2667 ../src/qalc.cc:4856 -#: ../libqalculate/Calculator.cc:3015 +#: ../src/qalc.cc:1130 ../src/qalc.cc:2668 ../src/qalc.cc:4857 +#: ../libqalculate/Calculator-calculate.cc:801 msgid "cartesian" msgstr "cartesisch" -#: ../src/qalc.cc:1130 ../src/qalc.cc:2679 ../src/qalc.cc:3020 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4867 ../libqalculate/Calculator.cc:3018 +#: ../src/qalc.cc:1131 ../src/qalc.cc:2680 ../src/qalc.cc:3021 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4868 +#: ../libqalculate/Calculator-calculate.cc:804 msgid "exponential" msgstr "exponentiele" -#: ../src/qalc.cc:1131 ../src/qalc.cc:2691 ../src/qalc.cc:3021 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4878 ../libqalculate/Calculator.cc:3021 +#: ../src/qalc.cc:1132 ../src/qalc.cc:2692 ../src/qalc.cc:3022 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4879 +#: ../libqalculate/Calculator-calculate.cc:807 msgid "polar" msgstr "polair" -#: ../src/qalc.cc:1132 ../src/qalc.cc:2703 ../src/qalc.cc:3022 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4889 ../libqalculate/Calculator.cc:3024 -#: ../libqalculate/Function.cc:2211 +#: ../src/qalc.cc:1133 ../src/qalc.cc:2704 ../src/qalc.cc:3023 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4890 +#: ../libqalculate/Calculator-calculate.cc:810 ../libqalculate/Function.cc:2245 msgid "angle" msgstr "hoek" -#: ../src/qalc.cc:1132 ../src/qalc.cc:2703 ../src/qalc.cc:4889 -#: ../libqalculate/Calculator.cc:3024 +#: ../src/qalc.cc:1133 ../src/qalc.cc:2704 ../src/qalc.cc:4890 +#: ../libqalculate/Calculator-calculate.cc:810 msgid "phasor" msgstr "" -#: ../src/qalc.cc:1145 ../src/qalc.cc:3130 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1146 ../src/qalc.cc:3131 ../src/qalc.cc:3827 msgid "read precision" msgstr "nauwkeurigheid lezen" -#: ../src/qalc.cc:1148 ../src/qalc.cc:3133 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1149 ../src/qalc.cc:3134 ../src/qalc.cc:3827 msgid "always" msgstr "altijd" -#: ../src/qalc.cc:1149 ../src/qalc.cc:3134 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1150 ../src/qalc.cc:3135 ../src/qalc.cc:3827 msgid "when decimals" msgstr "wanneer decimalen" -#: ../src/qalc.cc:1180 +#: ../src/qalc.cc:1181 msgid "Unrecognized option." msgstr "Onbekende optie." -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Calendar" msgstr "" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Day" msgstr "" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Month" msgstr "" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Year" msgstr "" -#: ../src/qalc.cc:1315 ../libqalculate/Calculator.cc:3124 +#: ../src/qalc.cc:1316 ../libqalculate/Calculator-calculate.cc:934 msgid "failed" msgstr "" -#: ../src/qalc.cc:1316 ../libqalculate/Calculator.cc:3125 +#: ../src/qalc.cc:1317 ../libqalculate/Calculator-calculate.cc:935 msgid "Gregorian:" msgstr "" -#: ../src/qalc.cc:1317 ../libqalculate/Calculator.cc:3126 +#: ../src/qalc.cc:1318 ../libqalculate/Calculator-calculate.cc:936 msgid "Hebrew:" msgstr "" -#: ../src/qalc.cc:1318 ../libqalculate/Calculator.cc:3127 +#: ../src/qalc.cc:1319 ../libqalculate/Calculator-calculate.cc:937 msgid "Islamic:" msgstr "" -#: ../src/qalc.cc:1319 ../libqalculate/Calculator.cc:3128 +#: ../src/qalc.cc:1320 ../libqalculate/Calculator-calculate.cc:938 msgid "Persian:" msgstr "" -#: ../src/qalc.cc:1320 ../libqalculate/Calculator.cc:3129 +#: ../src/qalc.cc:1321 ../libqalculate/Calculator-calculate.cc:939 msgid "Indian national:" msgstr "" -#: ../src/qalc.cc:1321 ../libqalculate/Calculator.cc:3130 +#: ../src/qalc.cc:1322 ../libqalculate/Calculator-calculate.cc:940 msgid "Chinese:" msgstr "" -#: ../src/qalc.cc:1326 ../libqalculate/Calculator.cc:3134 +#: ../src/qalc.cc:1327 ../libqalculate/Calculator-calculate.cc:944 msgid "Julian:" msgstr "" -#: ../src/qalc.cc:1327 ../libqalculate/Calculator.cc:3135 +#: ../src/qalc.cc:1328 ../libqalculate/Calculator-calculate.cc:945 msgid "Revised julian:" msgstr "" -#: ../src/qalc.cc:1328 ../libqalculate/Calculator.cc:3136 +#: ../src/qalc.cc:1329 ../libqalculate/Calculator-calculate.cc:946 #, fuzzy msgid "Coptic:" msgstr "optioneel" -#: ../src/qalc.cc:1329 ../libqalculate/Calculator.cc:3137 +#: ../src/qalc.cc:1330 ../libqalculate/Calculator-calculate.cc:947 msgid "Ethiopian:" msgstr "" -#: ../src/qalc.cc:1396 ../libqalculate/BuiltinFunctions.cc:6237 -#: ../libqalculate/BuiltinFunctions.cc:6267 +#: ../src/qalc.cc:1397 ../libqalculate/BuiltinFunctions-matrixvector.cc:567 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:597 msgid "No matching item found." msgstr "Geen overeenkomst gevonden." -#: ../src/qalc.cc:1427 ../src/qalc.cc:1428 ../src/qalc.cc:1558 -#: ../src/qalc.cc:1559 ../src/qalc.cc:1626 ../src/qalc.cc:1627 +#: ../src/qalc.cc:1428 ../src/qalc.cc:1429 ../src/qalc.cc:1559 +#: ../src/qalc.cc:1560 ../src/qalc.cc:1627 ../src/qalc.cc:1628 #, fuzzy msgid "" "For more information about a specific function, variable or unit, please use " @@ -968,150 +975,150 @@ "Type info NAAM voor info over een functie, variabele of eenheid (bv.: info " "sin)." -#: ../src/qalc.cc:1441 +#: ../src/qalc.cc:1442 msgid "Variables:" msgstr "Variabele:" -#: ../src/qalc.cc:1443 +#: ../src/qalc.cc:1444 msgid "Name" msgstr "Naam" -#: ../src/qalc.cc:1444 ../src/qalc.cc:3552 ../src/qalc.cc:3559 +#: ../src/qalc.cc:1445 ../src/qalc.cc:3553 ../src/qalc.cc:3560 msgid "Value" msgstr "Waarde" -#: ../src/qalc.cc:1532 +#: ../src/qalc.cc:1533 msgid "Functions:" msgstr "Functie:" -#: ../src/qalc.cc:1546 +#: ../src/qalc.cc:1547 msgid "Units:" msgstr "Eenheid:" -#: ../src/qalc.cc:1553 +#: ../src/qalc.cc:1554 msgid "No local variables, functions or units have been defined." msgstr "" -#: ../src/qalc.cc:1689 +#: ../src/qalc.cc:1690 msgid "usage: qalc [options] [expression]" msgstr "gebruik: qalc [opties] [expressie]" -#: ../src/qalc.cc:1691 +#: ../src/qalc.cc:1692 msgid "where options are:" msgstr "waarin opties zijn:" -#: ../src/qalc.cc:1692 ../src/qalc.cc:1724 ../src/qalc.cc:3186 +#: ../src/qalc.cc:1693 ../src/qalc.cc:1725 ../src/qalc.cc:3187 msgid "BASE" msgstr "GRONDTAL" -#: ../src/qalc.cc:1693 +#: ../src/qalc.cc:1694 msgid "set the number base for results and, optionally, expressions" msgstr "" -#: ../src/qalc.cc:1698 +#: ../src/qalc.cc:1699 msgid "FILE" msgstr "BESTAND" -#: ../src/qalc.cc:1699 +#: ../src/qalc.cc:1700 msgid "execute commands from a file first" msgstr "voert eerst opdrachten uit vanuit een bestand" -#: ../src/qalc.cc:1701 +#: ../src/qalc.cc:1702 msgid "start in interactive mode" msgstr "" -#: ../src/qalc.cc:1702 ../src/qalc.cc:1704 ../src/qalc.cc:1706 -#: ../src/qalc.cc:1708 +#: ../src/qalc.cc:1703 ../src/qalc.cc:1705 ../src/qalc.cc:1707 +#: ../src/qalc.cc:1709 msgid "SEARCH TERM" msgstr "" -#: ../src/qalc.cc:1703 +#: ../src/qalc.cc:1704 #, fuzzy msgid "" "displays a list of all user-defined or matching variables, functions and " "units" msgstr "\"%s\" is geen geldige variabele/functie/eenheid." -#: ../src/qalc.cc:1705 +#: ../src/qalc.cc:1706 #, fuzzy msgid "displays a list of all or matching functions" msgstr "Voorbeeld: info sin." -#: ../src/qalc.cc:1707 +#: ../src/qalc.cc:1708 #, fuzzy msgid "displays a list of all or matching units" msgstr "Voorbeeld: info sin." -#: ../src/qalc.cc:1709 +#: ../src/qalc.cc:1710 #, fuzzy msgid "displays a list of all or matching variables" msgstr "\"%s\" is geen geldige variabele/functie/eenheid." -#: ../src/qalc.cc:1710 +#: ../src/qalc.cc:1711 msgid "MILLISECONDS" msgstr "" -#: ../src/qalc.cc:1711 +#: ../src/qalc.cc:1712 msgid "" "terminate calculation and display of result after specified amount of time" msgstr "" -#: ../src/qalc.cc:1713 +#: ../src/qalc.cc:1714 msgid "do not load any functions, units, or variables from file" msgstr "lees geen functies, eenheden of variabelen in uit bestand" -#: ../src/qalc.cc:1715 +#: ../src/qalc.cc:1716 msgid "do not load any global currencies from file" msgstr "lees geen globale munteenheden in uit bestand" -#: ../src/qalc.cc:1717 +#: ../src/qalc.cc:1718 msgid "do not load any global data sets from file" msgstr "lees geen globale gegevensverzamelingen in uit bestand" -#: ../src/qalc.cc:1719 +#: ../src/qalc.cc:1720 msgid "do not load any global functions from file" msgstr "lees geen globale functies in uit bestand" -#: ../src/qalc.cc:1721 +#: ../src/qalc.cc:1722 msgid "do not load any global units from file" msgstr "lees geen globale eenheden in uit bestand" -#: ../src/qalc.cc:1723 +#: ../src/qalc.cc:1724 msgid "do not load any global variables from file" msgstr "lees geen globale variabelen in uit bestand" -#: ../src/qalc.cc:1725 +#: ../src/qalc.cc:1726 msgid "" "start in programming mode (same as -b \"BASE BASE\" -s \"xor^\", with base " "conversion)" msgstr "" -#: ../src/qalc.cc:1726 ../src/qalc.cc:3202 +#: ../src/qalc.cc:1727 ../src/qalc.cc:3203 msgid "OPTION" msgstr "OPTIE" -#: ../src/qalc.cc:1726 ../src/qalc.cc:3202 +#: ../src/qalc.cc:1727 ../src/qalc.cc:3203 msgid "VALUE" msgstr "WAARDE" -#: ../src/qalc.cc:1727 +#: ../src/qalc.cc:1728 msgid "as set command in interactive program session (e.g. -set \"base 16\")" msgstr "als set-opdracht bij interactief programmeren (vb. -set \"base 16\")" -#: ../src/qalc.cc:1729 +#: ../src/qalc.cc:1730 msgid "reduce output to just the result of the input expression" msgstr "" "reduceert de uitvoer tot alleen het antwoord op de ingevoerde expressie" -#: ../src/qalc.cc:1731 +#: ../src/qalc.cc:1732 msgid "switch unicode support on/off" msgstr "ondersteuning unicode aan/uit" -#: ../src/qalc.cc:1733 +#: ../src/qalc.cc:1734 msgid "show application version and exit" msgstr "" -#: ../src/qalc.cc:1735 +#: ../src/qalc.cc:1736 msgid "" "The program will start in interactive mode if no expression and no file is " "specified (or interactive mode is explicitly selected)." @@ -1119,67 +1126,67 @@ "Het programma start op in interactieve modus indien geen expressie is " "opgegeven." -#: ../src/qalc.cc:1835 +#: ../src/qalc.cc:1836 msgid "No option and value specified for set command." msgstr "Voor set-opdracht zijn geen optie en waarde opgegeven." -#: ../src/qalc.cc:1843 +#: ../src/qalc.cc:1844 msgid "No file specified." msgstr "Geen bestand opgegeven." -#: ../src/qalc.cc:1910 +#: ../src/qalc.cc:1911 msgid "Failed to load global definitions!" msgstr "Inlezen van globale definities is mislukt!" -#: ../src/qalc.cc:1956 +#: ../src/qalc.cc:1957 #, c-format msgid "Could not open \"%s\".\n" msgstr "Kon \"%s\" niet openen.\n" -#: ../src/qalc.cc:1996 ../src/qalc.cc:2048 ../src/qalc.cc:4087 +#: ../src/qalc.cc:1997 ../src/qalc.cc:2049 ../src/qalc.cc:4088 #, c-format msgid "Illegal character, '%c', in expression." msgstr "Ongeldig teken '%c', in expressie." #. The qalc command "set" as in "set precision 10". The original text string for commands is kept in addition to the translation. -#: ../src/qalc.cc:2115 ../src/qalc.cc:3202 ../src/qalc.cc:3616 +#: ../src/qalc.cc:2116 ../src/qalc.cc:3203 ../src/qalc.cc:3617 msgid "set" msgstr "set" #. qalc command -#: ../src/qalc.cc:2119 ../src/qalc.cc:3199 ../src/qalc.cc:3895 +#: ../src/qalc.cc:2120 ../src/qalc.cc:3200 ../src/qalc.cc:3896 msgid "save" msgstr "opslaan" -#: ../src/qalc.cc:2119 ../src/qalc.cc:3199 ../src/qalc.cc:3895 +#: ../src/qalc.cc:2120 ../src/qalc.cc:3200 ../src/qalc.cc:3896 msgid "store" msgstr "bewaren" #. qalc command -#: ../src/qalc.cc:2122 ../src/qalc.cc:2887 ../src/qalc.cc:3197 -#: ../src/qalc.cc:3921 +#: ../src/qalc.cc:2123 ../src/qalc.cc:2888 ../src/qalc.cc:3198 +#: ../src/qalc.cc:3922 msgid "mode" msgstr "modus" -#: ../src/qalc.cc:2124 +#: ../src/qalc.cc:2125 msgid "mode saved" msgstr "modus opgeslagen" -#: ../src/qalc.cc:2126 +#: ../src/qalc.cc:2127 msgid "definitions" msgstr "definities" -#: ../src/qalc.cc:2128 +#: ../src/qalc.cc:2129 msgid "definitions saved" msgstr "definities opgeslagen" -#: ../src/qalc.cc:2175 ../src/qalc.cc:2177 ../src/qalc.cc:2235 -#: ../src/qalc.cc:2237 ../src/qalc.cc:2292 ../src/qalc.cc:2294 +#: ../src/qalc.cc:2176 ../src/qalc.cc:2178 ../src/qalc.cc:2236 +#: ../src/qalc.cc:2238 ../src/qalc.cc:2293 ../src/qalc.cc:2295 #, c-format msgid "Illegal name. Save as %s instead (default: no)?" msgstr "Ongeldige naam. In plaats daarvan als %s opslaan (standaard is nee)?" -#: ../src/qalc.cc:2184 ../src/qalc.cc:2244 +#: ../src/qalc.cc:2185 ../src/qalc.cc:2245 msgid "" "An unit or variable with the same name already exists.\n" "Do you want to overwrite it (default: no)?" @@ -1188,18 +1195,18 @@ "Wilt u die overschrijven (standaard is nee)?" #. qalc command -#: ../src/qalc.cc:2207 ../src/qalc.cc:3205 ../src/qalc.cc:3902 -#: ../libqalculate/Function.cc:2172 +#: ../src/qalc.cc:2208 ../src/qalc.cc:3206 ../src/qalc.cc:3903 +#: ../libqalculate/Function.cc:2206 msgid "variable" msgstr "variabele" #. qalc command -#: ../src/qalc.cc:2264 ../src/qalc.cc:3195 ../src/qalc.cc:3908 -#: ../libqalculate/Function.cc:2144 +#: ../src/qalc.cc:2265 ../src/qalc.cc:3196 ../src/qalc.cc:3909 +#: ../libqalculate/Function.cc:2178 msgid "function" msgstr "functie" -#: ../src/qalc.cc:2301 +#: ../src/qalc.cc:2302 #, fuzzy msgid "" "An function with the same name already exists.\n" @@ -1209,275 +1216,284 @@ "Wilt u die overschrijven (standaard is nee)?" #. qalc command -#: ../src/qalc.cc:2321 ../src/qalc.cc:3187 ../src/qalc.cc:3915 +#: ../src/qalc.cc:2322 ../src/qalc.cc:3188 ../src/qalc.cc:3916 msgid "delete" msgstr "" -#: ../src/qalc.cc:2332 +#: ../src/qalc.cc:2333 #, fuzzy msgid "No user-defined variable or function with the specified name exist." msgstr "Er bestaat geen functie, variabele of eenheid met de opgegeven naam." #. qalc command -#: ../src/qalc.cc:2336 ../src/qalc.cc:3185 ../src/qalc.cc:3868 +#: ../src/qalc.cc:2337 ../src/qalc.cc:3186 ../src/qalc.cc:3869 msgid "assume" msgstr "aannemen" -#: ../src/qalc.cc:2346 +#: ../src/qalc.cc:2347 msgid "syntax" msgstr "notatie" #. qalc command -#: ../src/qalc.cc:2353 ../src/qalc.cc:2388 ../src/qalc.cc:3209 -#: ../src/qalc.cc:3960 +#: ../src/qalc.cc:2354 ../src/qalc.cc:2389 ../src/qalc.cc:3210 +#: ../src/qalc.cc:3961 msgid "stack" msgstr "" #. qalc command -#: ../src/qalc.cc:2373 ../src/qalc.cc:3190 ../src/qalc.cc:3940 +#: ../src/qalc.cc:2374 ../src/qalc.cc:3191 ../src/qalc.cc:3941 msgid "exrates" msgstr "wisselkoersen" -#: ../src/qalc.cc:2390 ../src/qalc.cc:2408 ../src/qalc.cc:2417 -#: ../src/qalc.cc:2450 ../src/qalc.cc:2479 ../src/qalc.cc:2488 -#: ../src/qalc.cc:2505 ../src/qalc.cc:2512 ../src/qalc.cc:2530 -#: ../src/qalc.cc:2537 +#: ../src/qalc.cc:2391 ../src/qalc.cc:2409 ../src/qalc.cc:2418 +#: ../src/qalc.cc:2451 ../src/qalc.cc:2480 ../src/qalc.cc:2489 +#: ../src/qalc.cc:2506 ../src/qalc.cc:2513 ../src/qalc.cc:2531 +#: ../src/qalc.cc:2538 msgid "The RPN stack is empty." msgstr "Het RPN-stapel is leeg." #. qalc command -#: ../src/qalc.cc:2406 ../src/qalc.cc:2415 ../src/qalc.cc:3215 -#: ../src/qalc.cc:3964 +#: ../src/qalc.cc:2407 ../src/qalc.cc:2416 ../src/qalc.cc:3216 +#: ../src/qalc.cc:3965 msgid "swap" msgstr "" -#: ../src/qalc.cc:2410 ../src/qalc.cc:2419 ../src/qalc.cc:2452 -#: ../src/qalc.cc:2481 ../src/qalc.cc:2490 +#: ../src/qalc.cc:2411 ../src/qalc.cc:2420 ../src/qalc.cc:2453 +#: ../src/qalc.cc:2482 ../src/qalc.cc:2491 msgid "The RPN stack only contains one value." msgstr "" -#: ../src/qalc.cc:2438 ../src/qalc.cc:2471 ../src/qalc.cc:2519 -#: ../src/qalc.cc:2543 +#: ../src/qalc.cc:2439 ../src/qalc.cc:2472 ../src/qalc.cc:2520 +#: ../src/qalc.cc:2544 msgid "The specified RPN stack index does not exist." msgstr "" #. qalc command -#: ../src/qalc.cc:2448 ../src/qalc.cc:3212 ../src/qalc.cc:3986 +#: ../src/qalc.cc:2449 ../src/qalc.cc:3213 ../src/qalc.cc:3987 msgid "move" msgstr "" #. qalc command -#: ../src/qalc.cc:2477 ../src/qalc.cc:2486 ../src/qalc.cc:3214 -#: ../src/qalc.cc:3982 +#: ../src/qalc.cc:2478 ../src/qalc.cc:2487 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3983 msgid "rotate" msgstr "" -#: ../src/qalc.cc:2494 +#: ../src/qalc.cc:2495 msgid "up" msgstr "" -#: ../src/qalc.cc:2496 +#: ../src/qalc.cc:2497 msgid "down" msgstr "" #. qalc command -#: ../src/qalc.cc:2503 ../src/qalc.cc:2510 ../src/qalc.cc:3211 -#: ../src/qalc.cc:3974 +#: ../src/qalc.cc:2504 ../src/qalc.cc:2511 ../src/qalc.cc:3212 +#: ../src/qalc.cc:3975 msgid "copy" msgstr "" #. qalc command -#: ../src/qalc.cc:2525 ../src/qalc.cc:3210 ../src/qalc.cc:3950 +#: ../src/qalc.cc:2526 ../src/qalc.cc:3211 ../src/qalc.cc:3951 msgid "clear stack" msgstr "" #. qalc command -#: ../src/qalc.cc:2528 ../src/qalc.cc:2535 ../src/qalc.cc:3213 -#: ../src/qalc.cc:3954 +#: ../src/qalc.cc:2529 ../src/qalc.cc:2536 ../src/qalc.cc:3214 +#: ../src/qalc.cc:3955 msgid "pop" msgstr "" #. qalc command -#: ../src/qalc.cc:2569 ../src/qalc.cc:3204 ../src/qalc.cc:4006 +#: ../src/qalc.cc:2570 ../src/qalc.cc:3205 ../src/qalc.cc:4007 msgid "convert" msgstr "converteren" #. "to"-operator -#: ../src/qalc.cc:2569 ../src/qalc.cc:3204 ../src/qalc.cc:4006 -#: ../src/qalc.cc:4049 ../libqalculate/Calculator.cc:518 -#: ../libqalculate/Calculator.cc:744 ../libqalculate/Calculator.cc:1540 -#: ../libqalculate/Calculator.cc:1541 ../libqalculate/Calculator.cc:3233 -#: ../libqalculate/Calculator.cc:3235 ../libqalculate/Calculator.cc:3248 -#: ../libqalculate/Calculator.cc:3250 ../libqalculate/Calculator.cc:3264 -#: ../libqalculate/Calculator.cc:3266 +#: ../src/qalc.cc:2570 ../src/qalc.cc:3205 ../src/qalc.cc:4007 +#: ../src/qalc.cc:4050 ../libqalculate/Calculator-calculate.cc:1065 +#: ../libqalculate/Calculator-calculate.cc:1067 +#: ../libqalculate/Calculator-calculate.cc:1080 +#: ../libqalculate/Calculator-calculate.cc:1082 +#: ../libqalculate/Calculator-calculate.cc:1096 +#: ../libqalculate/Calculator-calculate.cc:1098 +#: ../libqalculate/Calculator.cc:296 ../libqalculate/Calculator.cc:524 +#: ../libqalculate/Calculator.cc:1322 ../libqalculate/Calculator.cc:1323 msgid "to" msgstr "naar" -#: ../src/qalc.cc:2654 ../src/qalc.cc:4822 ../libqalculate/Calculator.cc:3006 +#: ../src/qalc.cc:2655 ../src/qalc.cc:4823 +#: ../libqalculate/Calculator-calculate.cc:792 msgid "Time zone parsing failed." msgstr "" -#: ../src/qalc.cc:2727 ../src/qalc.cc:4850 ../libqalculate/Calculator.cc:3041 +#: ../src/qalc.cc:2728 ../src/qalc.cc:4851 +#: ../libqalculate/Calculator-calculate.cc:827 msgid "bases" msgstr "grondtallen" -#: ../src/qalc.cc:2774 ../src/qalc.cc:4853 ../libqalculate/Calculator.cc:3044 +#: ../src/qalc.cc:2775 ../src/qalc.cc:4854 +#: ../libqalculate/Calculator-calculate.cc:830 msgid "calendars" msgstr "kalenders" -#: ../src/qalc.cc:2784 ../src/qalc.cc:4841 ../libqalculate/Calculator.cc:3031 +#: ../src/qalc.cc:2785 ../src/qalc.cc:4842 +#: ../libqalculate/Calculator-calculate.cc:817 msgid "fraction" msgstr "breuk" -#: ../src/qalc.cc:2793 ../src/qalc.cc:4844 ../libqalculate/Calculator.cc:3034 +#: ../src/qalc.cc:2794 ../src/qalc.cc:4845 +#: ../libqalculate/Calculator-calculate.cc:820 msgid "factors" msgstr "factoren" #. qalc command -#: ../src/qalc.cc:2795 ../src/qalc.cc:2881 ../src/qalc.cc:3198 -#: ../src/qalc.cc:3608 ../src/qalc.cc:4847 ../libqalculate/Calculator.cc:3038 +#: ../src/qalc.cc:2796 ../src/qalc.cc:2882 ../src/qalc.cc:3199 +#: ../src/qalc.cc:3609 ../src/qalc.cc:4848 +#: ../libqalculate/Calculator-calculate.cc:824 msgid "partial fraction" msgstr "partiële breuken" #. qalc command -#: ../src/qalc.cc:2878 ../src/qalc.cc:3193 ../src/qalc.cc:3604 +#: ../src/qalc.cc:2879 ../src/qalc.cc:3194 ../src/qalc.cc:3605 msgid "factor" msgstr "factor" -#: ../src/qalc.cc:2892 ../src/qalc.cc:3633 +#: ../src/qalc.cc:2893 ../src/qalc.cc:3634 msgid "Algebraic Mode" msgstr "Algebraïsche modus" -#: ../src/qalc.cc:2927 ../src/qalc.cc:3665 +#: ../src/qalc.cc:2928 ../src/qalc.cc:3666 msgid "Calculation" msgstr "Berekening" -#: ../src/qalc.cc:2950 +#: ../src/qalc.cc:2951 msgid "simplified" msgstr "" -#: ../src/qalc.cc:2955 ../src/qalc.cc:3675 +#: ../src/qalc.cc:2956 ../src/qalc.cc:3676 msgid "Enabled Objects" msgstr "Ingeschakelde objecten" -#: ../src/qalc.cc:2967 ../src/qalc.cc:3687 +#: ../src/qalc.cc:2968 ../src/qalc.cc:3688 msgid "Generic Display Options" msgstr "Algemene weergaveopties" -#: ../src/qalc.cc:2992 ../src/qalc.cc:3700 +#: ../src/qalc.cc:2993 ../src/qalc.cc:3701 msgid "Numerical Display" msgstr "Tonen getal" -#: ../src/qalc.cc:3093 ../src/qalc.cc:3783 +#: ../src/qalc.cc:3094 ../src/qalc.cc:3784 msgid "Parsing" msgstr "Interpretatie" -#: ../src/qalc.cc:3139 ../src/qalc.cc:3829 +#: ../src/qalc.cc:3140 ../src/qalc.cc:3830 msgid "Units" msgstr "Eenheden" -#: ../src/qalc.cc:3168 ../src/qalc.cc:3861 +#: ../src/qalc.cc:3169 ../src/qalc.cc:3862 msgid "Other" msgstr "Overig" #. qalc command -#: ../src/qalc.cc:3176 ../src/qalc.cc:3600 +#: ../src/qalc.cc:3177 ../src/qalc.cc:3601 msgid "help" msgstr "help" -#: ../src/qalc.cc:3179 +#: ../src/qalc.cc:3180 msgid "Enter a mathematical expression or a command and press enter." msgstr "Voer een wiskundige expressie of opdracht in en druk op enter." -#: ../src/qalc.cc:3180 +#: ../src/qalc.cc:3181 msgid "Complete functions, units and variables with the tabulator key." msgstr "" "Invoer namen functies, eenheden en variabelen met de tabtoets voltooien." -#: ../src/qalc.cc:3182 +#: ../src/qalc.cc:3183 msgid "Available commands are:" msgstr "Beschikbare opdrachten zijn:" -#: ../src/qalc.cc:3185 +#: ../src/qalc.cc:3186 msgid "ASSUMPTIONS" msgstr "AANNAMES" -#: ../src/qalc.cc:3187 ../src/qalc.cc:3194 ../src/qalc.cc:3195 -#: ../src/qalc.cc:3199 ../src/qalc.cc:3205 +#: ../src/qalc.cc:3188 ../src/qalc.cc:3195 ../src/qalc.cc:3196 +#: ../src/qalc.cc:3200 ../src/qalc.cc:3206 msgid "NAME" msgstr "NAAM" -#: ../src/qalc.cc:3194 ../src/qalc.cc:3226 ../src/qalc.cc:3925 +#: ../src/qalc.cc:3195 ../src/qalc.cc:3227 ../src/qalc.cc:3926 msgid "find" msgstr "zoeken" #. qalc command -#: ../src/qalc.cc:3194 ../src/qalc.cc:3224 ../src/qalc.cc:3226 -#: ../src/qalc.cc:3925 +#: ../src/qalc.cc:3195 ../src/qalc.cc:3225 ../src/qalc.cc:3227 +#: ../src/qalc.cc:3926 msgid "list" msgstr "lijst" -#: ../src/qalc.cc:3195 ../src/qalc.cc:3205 +#: ../src/qalc.cc:3196 ../src/qalc.cc:3206 msgid "EXPRESSION" msgstr "EXPRESSIE" #. qalc command -#: ../src/qalc.cc:3196 ../src/qalc.cc:3252 ../src/qalc.cc:3934 -#: ../libqalculate/Calculator.cc:11336 ../libqalculate/DataSet.cc:364 -#: ../libqalculate/DataSet.cc:391 ../libqalculate/DataSet.cc:1038 +#: ../src/qalc.cc:3197 ../src/qalc.cc:3253 ../src/qalc.cc:3935 +#: ../libqalculate/Calculator-definitions.cc:2887 +#: ../libqalculate/DataSet.cc:365 ../libqalculate/DataSet.cc:392 +#: ../libqalculate/DataSet.cc:1039 msgid "info" msgstr "info" -#: ../src/qalc.cc:3199 +#: ../src/qalc.cc:3200 msgid "CATEGORY" msgstr "CATEGORIE" -#: ../src/qalc.cc:3199 +#: ../src/qalc.cc:3200 msgid "TITLE" msgstr "TITEL" -#: ../src/qalc.cc:3204 +#: ../src/qalc.cc:3205 msgid "UNIT or \"TO\" COMMAND" msgstr "EENHEID of \"TO\"-OPDRACHT" #. qalc command -#: ../src/qalc.cc:3206 ../src/qalc.cc:4053 ../src/qalc.cc:4074 +#: ../src/qalc.cc:3207 ../src/qalc.cc:4054 ../src/qalc.cc:4075 msgid "quit" msgstr "afsluiten" -#: ../src/qalc.cc:3206 ../src/qalc.cc:4053 ../src/qalc.cc:4074 +#: ../src/qalc.cc:3207 ../src/qalc.cc:4054 ../src/qalc.cc:4075 msgid "exit" msgstr "verlaten" -#: ../src/qalc.cc:3207 +#: ../src/qalc.cc:3208 msgid "Commands for RPN mode:" msgstr "Opdrachten voor de RPN-modues:" -#: ../src/qalc.cc:3208 +#: ../src/qalc.cc:3209 msgid "STATE" msgstr "" -#: ../src/qalc.cc:3211 ../src/qalc.cc:3213 +#: ../src/qalc.cc:3212 ../src/qalc.cc:3214 msgid "INDEX" msgstr "" -#: ../src/qalc.cc:3212 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3213 ../src/qalc.cc:3216 msgid "INDEX 1" msgstr "" -#: ../src/qalc.cc:3212 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3213 ../src/qalc.cc:3216 msgid "INDEX 2" msgstr "" -#: ../src/qalc.cc:3214 +#: ../src/qalc.cc:3215 msgid "DIRECTION" msgstr "" -#: ../src/qalc.cc:3217 +#: ../src/qalc.cc:3218 msgid "Type help COMMAND for more information (example: help save)." msgstr "Type help OPDRACHT voor meer hulp (bv.: help save)." -#: ../src/qalc.cc:3218 +#: ../src/qalc.cc:3219 msgid "" "Type info NAME for information about a function, variable or unit (example: " "info sin)." @@ -1485,13 +1501,13 @@ "Type info NAAM voor info over een functie, variabele of eenheid (bv.: info " "sin)." -#: ../src/qalc.cc:3219 +#: ../src/qalc.cc:3220 msgid "" "When a line begins with '/', the following text is always interpreted as a " "command." msgstr "" -#: ../src/qalc.cc:3221 +#: ../src/qalc.cc:3222 msgid "" "For more information about mathematical expression, different options, and a " "complete list of functions, variables and units, see the relevant sections " @@ -1499,319 +1515,319 @@ "qalculate.github.io/manual/index.html)." msgstr "" -#: ../src/qalc.cc:3239 ../src/qalc.cc:3244 +#: ../src/qalc.cc:3240 ../src/qalc.cc:3245 #, fuzzy msgid "currencies" msgstr "Valuta" -#: ../src/qalc.cc:3261 +#: ../src/qalc.cc:3262 msgid "No function, variable or unit with specified name exist." msgstr "Er bestaat geen functie, variabele of eenheid met de opgegeven naam." -#: ../src/qalc.cc:3271 +#: ../src/qalc.cc:3272 msgid "Function" msgstr "Functie" -#: ../src/qalc.cc:3408 +#: ../src/qalc.cc:3409 #, fuzzy msgid "Expression:" msgstr "nauwkeurigheid" -#: ../src/qalc.cc:3417 ../src/qalc.cc:3420 ../src/qalc.cc:3587 +#: ../src/qalc.cc:3418 ../src/qalc.cc:3421 ../src/qalc.cc:3588 msgid "Unit" msgstr "Eenheid" -#: ../src/qalc.cc:3423 ../src/qalc.cc:3497 +#: ../src/qalc.cc:3424 ../src/qalc.cc:3498 msgid "Names" msgstr "Namen" -#: ../src/qalc.cc:3441 +#: ../src/qalc.cc:3442 msgid "Base Unit" msgstr "Basiseenheid" -#: ../src/qalc.cc:3448 +#: ../src/qalc.cc:3449 msgid "Relation" msgstr "Relatie" -#: ../src/qalc.cc:3453 ../src/qalc.cc:3555 +#: ../src/qalc.cc:3454 ../src/qalc.cc:3556 msgid "Relative uncertainty" msgstr "" -#: ../src/qalc.cc:3454 ../src/qalc.cc:3556 +#: ../src/qalc.cc:3455 ../src/qalc.cc:3557 msgid "Uncertainty" msgstr "" -#: ../src/qalc.cc:3464 +#: ../src/qalc.cc:3465 msgid "Inverse Relation" msgstr "Inverse relatie" -#: ../src/qalc.cc:3476 +#: ../src/qalc.cc:3477 msgid "Base Units" msgstr "Basiseenheden" -#: ../src/qalc.cc:3491 ../src/qalc.cc:3494 +#: ../src/qalc.cc:3492 ../src/qalc.cc:3495 msgid "Variable" msgstr "Variabele" -#: ../src/qalc.cc:3606 +#: ../src/qalc.cc:3607 msgid "Factorizes the current result." msgstr "Het huidige antwoord wordt in factoren ontbonden." -#: ../src/qalc.cc:3610 +#: ../src/qalc.cc:3611 msgid "Applies partial fraction decomposition to the current result." msgstr "" -#: ../src/qalc.cc:3614 +#: ../src/qalc.cc:3615 #, fuzzy msgid "Expands the current result." msgstr "Het huidige antwoord wordt in factoren ontbonden." -#: ../src/qalc.cc:3628 +#: ../src/qalc.cc:3629 msgid "Sets the value of an option." msgstr "Stelt de waarde in van een optie." -#: ../src/qalc.cc:3629 +#: ../src/qalc.cc:3630 msgid "Example: set base 16." msgstr "Voorbeeld: set base 16 (stel grondtal talstelsel in op 16)." -#: ../src/qalc.cc:3631 +#: ../src/qalc.cc:3632 msgid "" "Available options and accepted values are (the current value is marked with " "'*'):" msgstr "Beschikbare opties en geaccepteerde waarden zijn:" -#: ../src/qalc.cc:3635 +#: ../src/qalc.cc:3636 msgid "Determines if the expression is factorized or not after calculation." msgstr "" -#: ../src/qalc.cc:3636 +#: ../src/qalc.cc:3637 msgid "Determines if unknown values will be assumed non-zero (x/x=1)." msgstr "" -#: ../src/qalc.cc:3637 +#: ../src/qalc.cc:3638 msgid "Display a message after a value has been assumed non-zero." msgstr "" -#: ../src/qalc.cc:3640 +#: ../src/qalc.cc:3641 #, fuzzy msgid "Default assumptions for unknown variables." msgstr "Staandaard aannames voor onbekende variabelen." -#: ../src/qalc.cc:3668 +#: ../src/qalc.cc:3669 msgid "" "How approximate variables and calculations are handled. In exact mode " "approximate values will not be calculated." msgstr "" -#: ../src/qalc.cc:3669 +#: ../src/qalc.cc:3670 msgid "" "If activated, interval arithmetic determines the final precision of " "calculations (avoids wrong results after loss of significance) with " "approximate functions and/or irrational numbers." msgstr "" -#: ../src/qalc.cc:3670 +#: ../src/qalc.cc:3671 msgid "" "Determines the method used for interval calculation / uncertainty " "propagation." msgstr "" -#: ../src/qalc.cc:3672 +#: ../src/qalc.cc:3673 msgid "" "Specifies the default number of significant digits displayed and determines " "the precision used for approximate calculations." msgstr "" -#: ../src/qalc.cc:3683 +#: ../src/qalc.cc:3684 #, fuzzy msgid "Interprete undefined symbols in expressions as unknown variables." msgstr "Staandaard aannames instellen voor onbekende variabelen." -#: ../src/qalc.cc:3685 +#: ../src/qalc.cc:3686 msgid "" "If activated physical constants include units (e.g. c = 299 792 458 m∕s)." msgstr "" -#: ../src/qalc.cc:3689 +#: ../src/qalc.cc:3690 #, fuzzy msgid "Use abbreviated names for units and variables." msgstr "Staandaard aannames instellen voor onbekende variabelen." -#: ../src/qalc.cc:3692 +#: ../src/qalc.cc:3693 msgid "Always place negative values last." msgstr "" -#: ../src/qalc.cc:3694 +#: ../src/qalc.cc:3695 msgid "Use negative exponents instead of division in result (x/y = xy^-1)." msgstr "" -#: ../src/qalc.cc:3696 +#: ../src/qalc.cc:3697 msgid "Add extra space around operators." msgstr "" -#: ../src/qalc.cc:3698 +#: ../src/qalc.cc:3699 msgid "Display Unicode characters." msgstr "" -#: ../src/qalc.cc:3702 ../src/qalc.cc:3804 +#: ../src/qalc.cc:3703 ../src/qalc.cc:3805 msgid "bin" msgstr "bin" -#: ../src/qalc.cc:3704 ../src/qalc.cc:3806 +#: ../src/qalc.cc:3705 ../src/qalc.cc:3807 msgid "oct" msgstr "oct" -#: ../src/qalc.cc:3706 ../src/qalc.cc:3808 +#: ../src/qalc.cc:3707 ../src/qalc.cc:3809 msgid "dec" msgstr "dec" -#: ../src/qalc.cc:3708 ../src/qalc.cc:3810 +#: ../src/qalc.cc:3709 ../src/qalc.cc:3811 msgid "hex" msgstr "hex" -#: ../src/qalc.cc:3710 +#: ../src/qalc.cc:3711 msgid "sexa" msgstr "" -#: ../src/qalc.cc:3729 ../src/qalc.cc:3787 +#: ../src/qalc.cc:3730 ../src/qalc.cc:3788 msgid "Determines the default decimal separator." msgstr "" -#: ../src/qalc.cc:3742 +#: ../src/qalc.cc:3743 msgid "" "Determines how rational numbers are displayed (e.g. 5/4 = 1 + 1/4 = 1.25). " "'long' removes limits on the size of the numerator and denonimator." msgstr "" -#: ../src/qalc.cc:3743 +#: ../src/qalc.cc:3744 msgid "" "Enables two's complement representation for display of negative hexadecimal " "numbers." msgstr "" -#: ../src/qalc.cc:3744 ../src/qalc.cc:3803 +#: ../src/qalc.cc:3745 ../src/qalc.cc:3804 msgid "Use 'j' (instead of 'i') as default symbol for the imaginary unit." msgstr "" -#: ../src/qalc.cc:3746 +#: ../src/qalc.cc:3747 msgid "Use lowercase e for E-notation (5e2 = 5 * 10^2)." msgstr "" -#: ../src/qalc.cc:3747 +#: ../src/qalc.cc:3748 msgid "Use lowercase letters for number bases > 10." msgstr "" -#: ../src/qalc.cc:3762 +#: ../src/qalc.cc:3763 msgid "" "If activated, 1/6 is displayed as '0.1 666...', otherwise as '0.166667'." msgstr "" -#: ../src/qalc.cc:3763 +#: ../src/qalc.cc:3764 msgid "" "Determines whether halfway numbers are rounded upwards or towards the " "nearest even integer." msgstr "" -#: ../src/qalc.cc:3765 +#: ../src/qalc.cc:3766 msgid "Determines how scientific notation are used (e.g. 5 543 000 = 5.543E6)." msgstr "" -#: ../src/qalc.cc:3780 +#: ../src/qalc.cc:3781 msgid "If actived, zeroes are kept at the end of approximate numbers." msgstr "" -#: ../src/qalc.cc:3781 +#: ../src/qalc.cc:3782 msgid "" "Enables two's complement representation for display of negative binary " "numbers." msgstr "" -#: ../src/qalc.cc:3785 +#: ../src/qalc.cc:3786 msgid "Use ^ as bitwise exclusive OR operator." msgstr "" -#: ../src/qalc.cc:3798 +#: ../src/qalc.cc:3799 msgid "Allows use of ',' as thousands separator." msgstr "" -#: ../src/qalc.cc:3801 +#: ../src/qalc.cc:3802 msgid "Allows use of '.' as thousands separator." msgstr "" -#: ../src/qalc.cc:3825 +#: ../src/qalc.cc:3826 #, fuzzy msgid "See 'help parsing mode'." msgstr "exp modus" -#: ../src/qalc.cc:3826 +#: ../src/qalc.cc:3827 msgid "" "If activated, numbers be interpreted as approximate with precision equal to " "the number of significant digits (3.20 = 3.20+/-0.005)." msgstr "" -#: ../src/qalc.cc:3831 +#: ../src/qalc.cc:3832 msgid "Enables automatic use of hecto, deca, deci, and centi." msgstr "" -#: ../src/qalc.cc:3833 +#: ../src/qalc.cc:3834 msgid "" "Controls automatic unit conversion of the result. 'optimalsi' always " "converts non-SI units, while 'optimal' only converts to more optimal unit " "expressions, with less units and exponents." msgstr "" -#: ../src/qalc.cc:3847 +#: ../src/qalc.cc:3848 msgid "" "If activated, binary prefixes are used by default for information units." msgstr "" -#: ../src/qalc.cc:3848 +#: ../src/qalc.cc:3849 msgid "" "Enables automatic conversion to the local currency when optimal unit " "conversion is enabled." msgstr "" -#: ../src/qalc.cc:3849 +#: ../src/qalc.cc:3850 msgid "" "Enables automatic use of prefixes in the denominator of unit expressions." msgstr "" -#: ../src/qalc.cc:3850 +#: ../src/qalc.cc:3851 msgid "" "If activated, units are separated from variables at the end of the result." msgstr "" -#: ../src/qalc.cc:3851 +#: ../src/qalc.cc:3852 msgid "Enables automatic use of prefixes in the result." msgstr "" -#: ../src/qalc.cc:3856 +#: ../src/qalc.cc:3857 msgid "days" msgstr "" -#: ../src/qalc.cc:3863 +#: ../src/qalc.cc:3864 msgid "Ignore system language and use English (requires restart)." msgstr "" -#: ../src/qalc.cc:3864 +#: ../src/qalc.cc:3865 #, fuzzy msgid "Activates the Reverse Polish Notation stack." msgstr "(De)activeert de RPN-modus (omgekeerde Poolse notatie)." -#: ../src/qalc.cc:3865 +#: ../src/qalc.cc:3866 #, fuzzy msgid "Save functions, units, and variables on exit." msgstr "een geldige naam voor een functie, eenheid of variabele" -#: ../src/qalc.cc:3866 +#: ../src/qalc.cc:3867 msgid "Save settings on exit." msgstr "" -#: ../src/qalc.cc:3870 +#: ../src/qalc.cc:3871 msgid "Set default assumptions for unknown variables." msgstr "Staandaard aannames instellen voor onbekende variabelen." -#: ../src/qalc.cc:3897 +#: ../src/qalc.cc:3898 msgid "" "Saves the current result in a variable with the specified name. You may " "optionally also provide a category (default \"Temporary\") and a title." @@ -1820,7 +1836,7 @@ "Optioneel kunt u ook een categorie (standaard \"Tijdelijk\") en een titel " "opgeven." -#: ../src/qalc.cc:3898 +#: ../src/qalc.cc:3899 msgid "" "If name equals \"mode\" or \"definitions\", the current mode and " "definitions, respectively, will be saved." @@ -1828,54 +1844,54 @@ "Indien de naam \"modus\" is of \"definities\", worden de huidige modus of " "definities opgeslagen." -#: ../src/qalc.cc:3900 +#: ../src/qalc.cc:3901 msgid "Example: store var1." msgstr "Voorbeeld: store var1 (bewaar var1)." -#: ../src/qalc.cc:3904 +#: ../src/qalc.cc:3905 #, fuzzy msgid "Create a variables with the specified name and expression." msgstr "Er bestaat geen functie, variabele of eenheid met de opgegeven naam." -#: ../src/qalc.cc:3906 +#: ../src/qalc.cc:3907 #, fuzzy msgid "Example: variable var1 pi / 2." msgstr "Voorbeeld: store var1 (bewaar var1)." -#: ../src/qalc.cc:3910 +#: ../src/qalc.cc:3911 #, fuzzy msgid "Creates a function with the specified name and expression." msgstr "Er bestaat geen functie, variabele of eenheid met de opgegeven naam." -#: ../src/qalc.cc:3911 +#: ../src/qalc.cc:3912 msgid "Use '\\x', '\\y', '\\z', '\\a', etc. for arguments in the expression." msgstr "" -#: ../src/qalc.cc:3913 +#: ../src/qalc.cc:3914 #, fuzzy msgid "Example: function func1 5*\\x." msgstr "Voorbeeld: info sin." -#: ../src/qalc.cc:3917 +#: ../src/qalc.cc:3918 #, fuzzy msgid "Removes the user-defined variable or function with the specified name." msgstr "Er bestaat geen functie, variabele of eenheid met de opgegeven naam." -#: ../src/qalc.cc:3919 +#: ../src/qalc.cc:3920 #, fuzzy msgid "Example: delete var1." msgstr "Voorbeeld: store var1 (bewaar var1)." -#: ../src/qalc.cc:3923 +#: ../src/qalc.cc:3924 msgid "Displays the current mode." msgstr "Toont de huidige modus." -#: ../src/qalc.cc:3927 +#: ../src/qalc.cc:3928 #, fuzzy msgid "Displays a list of variables, functions and units." msgstr "\"%s\" is geen geldige variabele/functie/eenheid." -#: ../src/qalc.cc:3928 +#: ../src/qalc.cc:3929 msgid "" "Enter with argument 'currencies', 'functions', 'variables' or 'units' to " "show a list of all currencies, functions, variables or units. Enter a search " @@ -1883,277 +1899,277 @@ "called with no argument all user-definied objects are listed." msgstr "" -#: ../src/qalc.cc:3930 +#: ../src/qalc.cc:3931 #, fuzzy msgid "Example: list functions." msgstr "Voorbeeld: info sin." -#: ../src/qalc.cc:3931 +#: ../src/qalc.cc:3932 #, fuzzy msgid "Example: find dinar." msgstr "Voorbeeld: info sin." -#: ../src/qalc.cc:3932 +#: ../src/qalc.cc:3933 #, fuzzy msgid "Example: find variables planck." msgstr "Voorbeeld: store var1 (bewaar var1)." -#: ../src/qalc.cc:3936 +#: ../src/qalc.cc:3937 msgid "Displays information about a function, variable or unit." msgstr "Toont informatie over een functie, variabele of eenheid." -#: ../src/qalc.cc:3938 +#: ../src/qalc.cc:3939 msgid "Example: info sin." msgstr "Voorbeeld: info sin." -#: ../src/qalc.cc:3942 +#: ../src/qalc.cc:3943 msgid "Downloads current exchange rates from the Internet." msgstr "Haalt de huidige wisselkoersen op van het internet." -#: ../src/qalc.cc:3946 +#: ../src/qalc.cc:3947 #, fuzzy msgid "(De)activates the Reverse Polish Notation stack and syntax." msgstr "(De)activeert de RPN-modus (omgekeerde Poolse notatie)." -#: ../src/qalc.cc:3948 +#: ../src/qalc.cc:3949 msgid "" "\"syntax\" activates only the RPN syntax and \"stack\" enables the RPN stack." msgstr "" -#: ../src/qalc.cc:3952 +#: ../src/qalc.cc:3953 #, fuzzy msgid "Clears the entire RPN stack." msgstr "Maakt het RPN-stapelgeheugen leeg." -#: ../src/qalc.cc:3956 +#: ../src/qalc.cc:3957 #, fuzzy msgid "Removes the top of the RPN stack or the value at the specified index." msgstr "Er bestaat geen functie, variabele of eenheid met de opgegeven naam." -#: ../src/qalc.cc:3958 ../src/qalc.cc:3970 ../src/qalc.cc:3980 -#: ../src/qalc.cc:3990 +#: ../src/qalc.cc:3959 ../src/qalc.cc:3971 ../src/qalc.cc:3981 +#: ../src/qalc.cc:3991 msgid "" "Index 1 is the top of stack and negative index values counts from the bottom " "of the stack." msgstr "" -#: ../src/qalc.cc:3962 +#: ../src/qalc.cc:3963 msgid "Displays the RPN stack." msgstr "" -#: ../src/qalc.cc:3966 +#: ../src/qalc.cc:3967 msgid "Swaps position of values on the RPN stack." msgstr "" -#: ../src/qalc.cc:3968 +#: ../src/qalc.cc:3969 msgid "" "If no index is specified, the values on the top of the stack (index 1 and " "index 2) will be swapped and if only one index is specified, the value at " "this index will be swapped with the top value." msgstr "" -#: ../src/qalc.cc:3972 +#: ../src/qalc.cc:3973 #, fuzzy msgid "Example: swap 2 4" msgstr "Voorbeeld: store var1 (bewaar var1)." -#: ../src/qalc.cc:3976 +#: ../src/qalc.cc:3977 msgid "Duplicates a value on the RPN stack to the top of the stack." msgstr "" -#: ../src/qalc.cc:3978 +#: ../src/qalc.cc:3979 msgid "If no index is specified, the top of the stack is duplicated." msgstr "" -#: ../src/qalc.cc:3984 +#: ../src/qalc.cc:3985 msgid "Rotates the RPN stack up (default) or down." msgstr "" -#: ../src/qalc.cc:3988 +#: ../src/qalc.cc:3989 msgid "Changes the position of a value on the RPN stack." msgstr "" -#: ../src/qalc.cc:3992 +#: ../src/qalc.cc:3993 #, fuzzy msgid "Example: move 2 4" msgstr "Voorbeeld: store var1 (bewaar var1)." -#: ../src/qalc.cc:3996 +#: ../src/qalc.cc:3997 #, fuzzy msgid "Sets the result number base (equivalent to set base)." msgstr "" "Stelt het grondtal in voor het antwoord (gelijkwaardig aan instellen " "grondtal talstelsel)." -#: ../src/qalc.cc:4000 +#: ../src/qalc.cc:4001 msgid "Equivalent to set approximation exact." msgstr "Gelijkwaardig aan benadering instellen op exact." -#: ../src/qalc.cc:4004 +#: ../src/qalc.cc:4005 msgid "Equivalent to set approximation try exact." msgstr "Gelijkwaardig aan benadering instellen op exact proberen." -#: ../src/qalc.cc:4009 +#: ../src/qalc.cc:4010 #, fuzzy msgid "Converts units or changes number base in current result." msgstr "Converteert de eenheden in het huidige antwoord." -#: ../src/qalc.cc:4011 +#: ../src/qalc.cc:4012 #, fuzzy msgid "Possible values:" msgstr "Mogelijke eenheden zijn:" -#: ../src/qalc.cc:4013 +#: ../src/qalc.cc:4014 #, fuzzy msgid "- a unit or unit expression (e.g. meter or km/h)" msgstr "- een uitdrukking voor een eenheid (voorbeeld km/h)" -#: ../src/qalc.cc:4014 +#: ../src/qalc.cc:4015 msgid "prepend with ? to request the optimal prefix" msgstr "" -#: ../src/qalc.cc:4015 +#: ../src/qalc.cc:4016 msgid "prepend with b? to request the optimal binary prefix" msgstr "" -#: ../src/qalc.cc:4016 +#: ../src/qalc.cc:4017 msgid "prepend with + or - to force/disable use of mixed units" msgstr "" -#: ../src/qalc.cc:4017 +#: ../src/qalc.cc:4018 msgid "- a variable or physical constant (e.g. c)" msgstr "" -#: ../src/qalc.cc:4018 +#: ../src/qalc.cc:4019 #, fuzzy msgid "- base (convert to base units)" msgstr "- basis (omzetten naar basiseenheden)" -#: ../src/qalc.cc:4019 +#: ../src/qalc.cc:4020 #, fuzzy msgid "- optimal (convert to optimal unit)" msgstr "- optimale (omzetten naar meest geschikte eenheid)" -#: ../src/qalc.cc:4020 +#: ../src/qalc.cc:4021 #, fuzzy msgid "- mixed (convert to mixed units, e.g. hours + minutes)" msgstr "- gemengde (naar gemengde eenheden, hours + minutues)" -#: ../src/qalc.cc:4022 +#: ../src/qalc.cc:4023 msgid "- bin / binary (show as binary number)" msgstr "" -#: ../src/qalc.cc:4023 +#: ../src/qalc.cc:4024 msgid "- oct / octal (show as octal number)" msgstr "" -#: ../src/qalc.cc:4024 +#: ../src/qalc.cc:4025 msgid "- duo / duodecimal (show as duodecimal number)" msgstr "" -#: ../src/qalc.cc:4025 +#: ../src/qalc.cc:4026 msgid "- hex / hexadecimal (show as hexadecimal number)" msgstr "" -#: ../src/qalc.cc:4026 +#: ../src/qalc.cc:4027 msgid "- sex / sexagesimal (show as sexagesimal number)" msgstr "" -#: ../src/qalc.cc:4027 +#: ../src/qalc.cc:4028 msgid "- bijective (shown in bijective base-26)" msgstr "" -#: ../src/qalc.cc:4028 +#: ../src/qalc.cc:4029 #, fuzzy msgid "- roman (show as roman numerals)" msgstr "Fout in Romeins cijfers: \"%s\"." -#: ../src/qalc.cc:4029 +#: ../src/qalc.cc:4030 msgid "- time (show in time format)" msgstr "" -#: ../src/qalc.cc:4030 +#: ../src/qalc.cc:4031 #, fuzzy msgid "- unicode" msgstr "unicode" -#: ../src/qalc.cc:4031 +#: ../src/qalc.cc:4032 msgid "- base # (show in specified number base)" msgstr "" -#: ../src/qalc.cc:4032 +#: ../src/qalc.cc:4033 msgid "- bases (show as binary, octal, decimal and hexadecimal number)" msgstr "" -#: ../src/qalc.cc:4034 +#: ../src/qalc.cc:4035 msgid "- rectangular / cartesian (show complex numbers in rectangular form)" msgstr "" -#: ../src/qalc.cc:4035 +#: ../src/qalc.cc:4036 msgid "- exponential (show complex numbers in exponential form)" msgstr "" -#: ../src/qalc.cc:4036 +#: ../src/qalc.cc:4037 msgid "- polar (show complex numbers in polar form)" msgstr "" -#: ../src/qalc.cc:4037 +#: ../src/qalc.cc:4038 msgid "- cis (show complex numbers in cis form)" msgstr "" -#: ../src/qalc.cc:4038 +#: ../src/qalc.cc:4039 msgid "- angle / phasor (show complex numbers in angle/phasor notation)" msgstr "" -#: ../src/qalc.cc:4040 +#: ../src/qalc.cc:4041 msgid "- fraction (show result as mixed fraction)" msgstr "" -#: ../src/qalc.cc:4041 +#: ../src/qalc.cc:4042 #, fuzzy msgid "- factors (factorize result)" msgstr "Het huidige antwoord wordt in factoren ontbonden." -#: ../src/qalc.cc:4043 +#: ../src/qalc.cc:4044 msgid "- UTC (show date and time in UTC time zone)" msgstr "" -#: ../src/qalc.cc:4044 +#: ../src/qalc.cc:4045 msgid "- UTC+/-hh[:mm] (show date and time in specified time zone)" msgstr "" -#: ../src/qalc.cc:4045 +#: ../src/qalc.cc:4046 msgid "- calendars" msgstr "" -#: ../src/qalc.cc:4047 +#: ../src/qalc.cc:4048 #, fuzzy msgid "Example: to ?g" msgstr "Voorbeeld: store var1 (bewaar var1)." -#: ../src/qalc.cc:4050 +#: ../src/qalc.cc:4051 msgid "" "This command can also be typed directly at the end of the mathematical " "expression (e.g. 5 ft + 2 in to meter)." msgstr "" -#: ../src/qalc.cc:4055 +#: ../src/qalc.cc:4056 msgid "Terminates this program." msgstr "Sluit het programma af." -#: ../src/qalc.cc:4060 +#: ../src/qalc.cc:4061 msgid "" "Implicit multiplication does not differ from explicit multiplication " "(\"12/2(1+2) = 12/2*3 = 18\", \"5x/5y = 5*x/5*y = xy\")." msgstr "" -#: ../src/qalc.cc:4063 +#: ../src/qalc.cc:4064 msgid "" "Implicit multiplication is parsed before explicit multiplication " "(\"12/2(1+2) = 12/(2*3) = 2\", \"5x/5y = (5*x)/(5*y) = x/y\")." msgstr "" -#: ../src/qalc.cc:4066 +#: ../src/qalc.cc:4067 msgid "" "The default adaptive mode works as the \"implicit first\" mode, unless " "spaces are found (\"1/5x = 1/(5*x)\", but \"1/5 x = (1/5)*x\"). In the " @@ -2161,66 +2177,66 @@ "(5*(m/s)) = 1 s\")." msgstr "" -#: ../src/qalc.cc:4068 +#: ../src/qalc.cc:4069 msgid "" "Function arguments without parentheses are an exception, where implicit " "multiplication in front of variables and units is parsed first regardless of " "mode (\"sqrt 2x = sqrt(2x)\")." msgstr "" -#: ../src/qalc.cc:4082 +#: ../src/qalc.cc:4083 #, fuzzy msgid "Unknown command." msgstr "Onbekend Romeins cijfer: %c." -#: ../src/qalc.cc:4131 +#: ../src/qalc.cc:4132 msgid "error" msgstr "fout" -#: ../src/qalc.cc:4133 +#: ../src/qalc.cc:4134 msgid "warning" msgstr "waarschuwing" -#: ../src/qalc.cc:4156 ../src/qalc.cc:4441 ../src/qalc.cc:5320 +#: ../src/qalc.cc:4157 ../src/qalc.cc:4442 ../src/qalc.cc:5347 msgid "approx." msgstr "benad." -#: ../src/qalc.cc:4240 ../src/qalc.cc:4278 ../src/qalc.cc:4598 -#: ../src/qalc.cc:5173 ../libqalculate/Calculator.cc:11754 -#: ../libqalculate/MathStructure.cc:780 +#: ../src/qalc.cc:4241 ../src/qalc.cc:4279 ../src/qalc.cc:4599 +#: ../src/qalc.cc:5178 ../libqalculate/Calculator-calculate.cc:1615 +#: ../libqalculate/MathStructure.cc:448 #, c-format msgid "aborted" msgstr "afgebroken" -#: ../src/qalc.cc:4290 +#: ../src/qalc.cc:4291 msgid "RPN Register Moved" msgstr "RPN-register is verplaatst" -#: ../src/qalc.cc:4346 +#: ../src/qalc.cc:4347 msgid "Processing (press Enter to abort)" msgstr "Aan het verwerken (afbreken met Enter)" -#: ../src/qalc.cc:4615 +#: ../src/qalc.cc:4616 msgid "Factorizing (press Enter to abort)" msgstr "Aan het ontbinden in factoren (afbreken met Enter)" -#: ../src/qalc.cc:4619 +#: ../src/qalc.cc:4620 msgid "Expanding partial fractions…" msgstr "" -#: ../src/qalc.cc:4623 +#: ../src/qalc.cc:4624 msgid "Expanding (press Enter to abort)" msgstr "Uitwerken (afbreken met Enter)" -#: ../src/qalc.cc:4627 ../src/qalc.cc:5187 +#: ../src/qalc.cc:4628 ../src/qalc.cc:5192 msgid "Calculating (press Enter to abort)" msgstr "Aan het berekenen (afbreken met Enter)" -#: ../src/qalc.cc:5273 +#: ../src/qalc.cc:5300 msgid "RPN Operation" msgstr "RPN-berwerking" -#: ../src/qalc.cc:5805 +#: ../src/qalc.cc:5832 #, c-format msgid "" "Couldn't write preferences to\n" @@ -2229,123 +2245,207 @@ "Kon de voorkeurinstellingen niet schrijven naar\n" "%s" -#: ../src/qalc.cc:5913 +#: ../src/qalc.cc:5940 msgid "Couldn't write definitions" msgstr "Kon definities niet schrijven" -#: ../src/test.cc:13 ../src/test.cc:28 ../libqalculate/Calculator.cc:2229 +#. thread cancellation is not safe +#: ../src/test.cc:13 ../src/test.cc:28 +#: ../libqalculate/Calculator-calculate.cc:172 msgid "" "The calculation has been forcibly terminated. Please restart the application " "and report this as a bug." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:109 +#: ../libqalculate/BuiltinFunctions-algebra.cc:359 +msgid "" +"No equality or inequality to solve. The entered expression to solve is not " +"correct (ex. \"x + 5 = 3\" is correct)" +msgstr "" +"Geen op te lossen vergelijking of ongelijkheid. De ingevoerde op te lossen " +"expressie is onjuist (bv. \"x + 5 = 3\" is juist)" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:406 #, c-format -msgid "Too many elements (%s) for the dimensions (%sx%s) of the matrix." -msgstr "Te veel elementen (%s) voor de dimensies (%sx%s) van de matrix." +msgid "The comparison is true for all %s (with current assumptions)." +msgstr "Het vergelijken geeft waar voor alle %s (met huidige aannames)." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:410 +msgid "No possible solution was found (with current assumptions)." +msgstr "Geen oplossing gevonden (met huidige aannames)." -#: ../libqalculate/BuiltinFunctions.cc:172 -#: ../libqalculate/BuiltinFunctions.cc:234 +#: ../libqalculate/BuiltinFunctions-algebra.cc:414 #, c-format -msgid "Row %s does not exist in matrix." -msgstr "Rij %s bestaat niet in matrix." +msgid "Was unable to completely isolate %s." +msgstr "Kon %s niet volledig isoleren." -#: ../libqalculate/BuiltinFunctions.cc:185 -#: ../libqalculate/BuiltinFunctions.cc:230 +#: ../libqalculate/BuiltinFunctions-algebra.cc:418 +#: ../libqalculate/BuiltinFunctions-algebra.cc:581 +#: ../libqalculate/BuiltinFunctions-algebra.cc:673 #, c-format -msgid "Column %s does not exist in matrix." -msgstr "Kolom %s bestaat niet in matrix." +msgid "The comparison is true for all %s if %s." +msgstr "Het vergelijken geeft waar voor alle %s indien %s." -#: ../libqalculate/BuiltinFunctions.cc:245 +#: ../libqalculate/BuiltinFunctions-algebra.cc:422 #, c-format -msgid "Argument 3, %s, is ignored for vectors." -msgstr "Argument 3, %s, wordt genegeerd voor vectoren." +msgid "Was unable to isolate %s." +msgstr "Kon %s niet isoleren." -#: ../libqalculate/BuiltinFunctions.cc:249 -#: ../libqalculate/BuiltinFunctions.cc:270 +#: ../libqalculate/BuiltinFunctions-algebra.cc:542 +#: ../libqalculate/BuiltinFunctions-algebra.cc:569 +#: ../libqalculate/BuiltinFunctions-algebra.cc:650 #, c-format -msgid "Element %s does not exist in vector." -msgstr "Element %s bestaat niet in vector." +msgid "" +"Was unable to isolate %s with the current assumptions. The assumed sign was " +"therefore temporarily set as unknown." +msgstr "" +"Kon %s niet isoleren met de huidige aannames. Het aangenomen teken werd " +"daarom tijdelijk als onbekend beschouwd." -#: ../libqalculate/BuiltinFunctions.cc:411 -#: ../libqalculate/BuiltinFunctions.cc:415 -#: ../libqalculate/BuiltinFunctions.cc:447 -#: ../libqalculate/BuiltinFunctions.cc:451 +#: ../libqalculate/BuiltinFunctions-algebra.cc:545 +#: ../libqalculate/BuiltinFunctions-algebra.cc:572 +#: ../libqalculate/BuiltinFunctions-algebra.cc:653 #, c-format -msgid "%s() requires that all matrices/vectors have the same dimensions." +msgid "" +"Was unable to isolate %s with the current assumptions. The assumed type and " +"sign was therefore temporarily set as unknown." +msgstr "" +"Kon %s niet isoleren met de huidige aannames. Het aangenomen type en teken " +"werd daarom tijdelijk als onbekend beschouwd." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:577 +#: ../libqalculate/BuiltinFunctions-algebra.cc:660 +#, c-format +msgid "The solution requires that %s." +msgstr "De oplossing vereist dat %s." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:667 +#, c-format +msgid "Solution %s requires that %s." +msgstr "De oplossing %s vereist dat %s." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:738 +#, c-format +msgid "" +"Unable to isolate %s.\n" +"\n" +"You might need to place the equations and variables in an appropriate order " +"so that each equation at least contains the corresponding variable (if " +"automatic reordering failed)." msgstr "" +"Kan %s niet isoleren.\n" +"\n" +"Mogelijk moet u de vergelijkingen en variabelen in een juiste volgorde " +"plaatsen zodat elke vergelijking tenminste de ermee overeenkomende variabele " +"bevat (indien het automatisch op volgorde zetten niet is gelukt)." -#: ../libqalculate/BuiltinFunctions.cc:4759 -#: ../libqalculate/BuiltinFunctions.cc:4802 +#: ../libqalculate/BuiltinFunctions-algebra.cc:740 +#: ../libqalculate/BuiltinFunctions-algebra.cc:754 +#: ../libqalculate/BuiltinFunctions-algebra.cc:763 #, c-format -msgid "Unsolvable comparison in %s()." -msgstr "Vergelijken lukt niet in %s()." +msgid "Unable to isolate %s." +msgstr "Kon %s niet isoleren." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:747 +#, c-format +msgid "Inequalities is not allowed in %s()." +msgstr "Ongelijkheden zijn niet toegestaan in %s()." -#: ../libqalculate/BuiltinFunctions.cc:4972 -#: ../libqalculate/BuiltinFunctions.cc:5006 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1089 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1094 +msgid "No differential equation found." +msgstr "" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:1098 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1127 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1133 +msgid "Unable to solve differential equation." +msgstr "" + +#: ../libqalculate/BuiltinFunctions-datetime.cc:33 +#: ../libqalculate/BuiltinFunctions-datetime.cc:67 msgid "gregorian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4973 +#: ../libqalculate/BuiltinFunctions-datetime.cc:34 msgid "milankovic" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4974 +#: ../libqalculate/BuiltinFunctions-datetime.cc:35 msgid "julian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4975 +#: ../libqalculate/BuiltinFunctions-datetime.cc:36 msgid "islamic" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4976 +#: ../libqalculate/BuiltinFunctions-datetime.cc:37 msgid "hebrew" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4977 +#: ../libqalculate/BuiltinFunctions-datetime.cc:38 msgid "egyptian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4978 +#: ../libqalculate/BuiltinFunctions-datetime.cc:39 msgid "persian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4979 +#: ../libqalculate/BuiltinFunctions-datetime.cc:40 #, fuzzy msgid "coptic" msgstr "optioneel" -#: ../libqalculate/BuiltinFunctions.cc:4980 +#: ../libqalculate/BuiltinFunctions-datetime.cc:41 msgid "ethiopian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4981 +#: ../libqalculate/BuiltinFunctions-datetime.cc:42 #, fuzzy msgid "indian" msgstr "radialen" -#: ../libqalculate/BuiltinFunctions.cc:4982 +#: ../libqalculate/BuiltinFunctions-datetime.cc:43 msgid "chinese" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:5408 -#: ../libqalculate/BuiltinFunctions.cc:5438 ../libqalculate/Number.cc:429 -#: ../libqalculate/Number.cc:900 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:57 #, c-format -msgid "Character '%s' was ignored in the number \"%s\" with base %s." -msgstr "Karakter '%s' werd genegeerd in het getal \"%s\" met grondtal %s." +msgid "Too many elements (%s) for the dimensions (%sx%s) of the matrix." +msgstr "Te veel elementen (%s) voor de dimensies (%sx%s) van de matrix." -#: ../libqalculate/BuiltinFunctions.cc:5703 -#: ../libqalculate/BuiltinFunctions.cc:5708 -#: ../libqalculate/BuiltinFunctions.cc:5710 -#: ../libqalculate/BuiltinFunctions.cc:5726 ../libqalculate/Calculator.cc:3409 -#: ../libqalculate/Calculator.cc:3416 ../libqalculate/Calculator.cc:3418 -#: ../libqalculate/Calculator.cc:3482 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:120 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:182 #, c-format -msgid "Original value (%s) was not found." +msgid "Row %s does not exist in matrix." +msgstr "Rij %s bestaat niet in matrix." + +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:133 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:178 +#, c-format +msgid "Column %s does not exist in matrix." +msgstr "Kolom %s bestaat niet in matrix." + +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:193 +#, c-format +msgid "Argument 3, %s, is ignored for vectors." +msgstr "Argument 3, %s, wordt genegeerd voor vectoren." + +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:197 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:218 +#, c-format +msgid "Element %s does not exist in vector." +msgstr "Element %s bestaat niet in vector." + +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:359 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:363 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:395 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:399 +#, c-format +msgid "%s() requires that all matrices/vectors have the same dimensions." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:5862 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:539 msgid "" "The number of requested elements in generate vector function must be a " "positive integer." @@ -2353,278 +2453,195 @@ "Het aantal gevraagde elementen in de gegenereerde vectorfunctie moet een " "positief geheel getal zijn." -#: ../libqalculate/BuiltinFunctions.cc:6179 -#: ../libqalculate/BuiltinFunctions.cc:6183 -#, c-format -msgid "Too few elements (%s) in vector (%s required)" -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:6232 -#: ../libqalculate/BuiltinFunctions.cc:6249 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:562 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:579 msgid "Comparison failed." msgstr "Vergelijken is mislukt." -#: ../libqalculate/BuiltinFunctions.cc:6392 -#, c-format -msgid "Object %s does not exist." -msgstr "Object %s bestaat niet." - -#: ../libqalculate/BuiltinFunctions.cc:6410 -#, fuzzy, c-format -msgid "Invalid variable name (%s)." -msgstr "een geldige naam voor een variabele" - -#: ../libqalculate/BuiltinFunctions.cc:6427 -msgid "" -"A global unit or variable was deactivated. It will be restored after the new " -"variable has been removed." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:6442 +#: ../libqalculate/BuiltinFunctions-statistics.cc:178 +#: ../libqalculate/BuiltinFunctions-statistics.cc:221 #, c-format -msgid "Register %s does not exist. Returning zero." -msgstr "Register %s bestaat niet. Nul wordt geretourneerd." - -#: ../libqalculate/BuiltinFunctions.cc:7390 -#: ../libqalculate/MathStructure.cc:284 ../libqalculate/MathStructure.cc:306 -#: ../libqalculate/MathStructure.cc:337 -#, c-format -msgid "To avoid division by zero, the following must be true: %s." -msgstr "Om delen door nul te voorkomen moet het volgende waar zijn: %s." +msgid "Unsolvable comparison in %s()." +msgstr "Vergelijken lukt niet in %s()." -#: ../libqalculate/BuiltinFunctions.cc:7598 -#: ../libqalculate/BuiltinFunctions.cc:7617 -#: ../libqalculate/BuiltinFunctions.cc:7650 -#: ../libqalculate/BuiltinFunctions.cc:7672 -#: ../libqalculate/BuiltinFunctions.cc:7721 -#: ../libqalculate/BuiltinFunctions.cc:7756 -#: ../libqalculate/BuiltinFunctions.cc:7871 -#: ../libqalculate/BuiltinFunctions.cc:7921 -#: ../libqalculate/BuiltinFunctions.cc:7955 -#: ../libqalculate/BuiltinFunctions.cc:7998 -#: ../libqalculate/BuiltinFunctions.cc:8030 +#: ../libqalculate/BuiltinFunctions-calculus.cc:314 #, fuzzy -msgid "Unable to integrate the expression." +msgid "Unable to find limit." msgstr "Kon %s niet isoleren." -#: ../libqalculate/BuiltinFunctions.cc:7878 -#: ../libqalculate/BuiltinFunctions.cc:7948 +#: ../libqalculate/BuiltinFunctions-calculus.cc:409 +#: ../libqalculate/BuiltinFunctions-calculus.cc:441 +#: ../libqalculate/MathStructure-integrate.cc:7294 +#: ../libqalculate/MathStructure-integrate.cc:7314 +#: ../libqalculate/MathStructure-integrate.cc:7349 +#: ../libqalculate/MathStructure-integrate.cc:7373 +#: ../libqalculate/MathStructure-integrate.cc:7423 +#: ../libqalculate/MathStructure-integrate.cc:7462 +#: ../libqalculate/MathStructure-integrate.cc:7658 +#: ../libqalculate/MathStructure-integrate.cc:7712 +#: ../libqalculate/MathStructure-integrate.cc:7754 #, fuzzy -msgid "Unable to integrate the expression exact." +msgid "Unable to integrate the expression." msgstr "Kon %s niet isoleren." -#: ../libqalculate/BuiltinFunctions.cc:7915 -msgid "Definite integral was approximated." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:8245 -msgid "" -"No equality or inequality to solve. The entered expression to solve is not " -"correct (ex. \"x + 5 = 3\" is correct)" -msgstr "" -"Geen op te lossen vergelijking of ongelijkheid. De ingevoerde op te lossen " -"expressie is onjuist (bv. \"x + 5 = 3\" is juist)" - -#: ../libqalculate/BuiltinFunctions.cc:8292 -#, c-format -msgid "The comparison is true for all %s (with current assumptions)." -msgstr "Het vergelijken geeft waar voor alle %s (met huidige aannames)." - -#: ../libqalculate/BuiltinFunctions.cc:8296 -msgid "No possible solution was found (with current assumptions)." -msgstr "Geen oplossing gevonden (met huidige aannames)." - -#: ../libqalculate/BuiltinFunctions.cc:8300 +#: ../libqalculate/BuiltinFunctions-number.cc:684 +#: ../libqalculate/BuiltinFunctions-number.cc:714 ../libqalculate/Number.cc:459 +#: ../libqalculate/Number.cc:970 #, c-format -msgid "Was unable to completely isolate %s." -msgstr "Kon %s niet volledig isoleren." - -#: ../libqalculate/BuiltinFunctions.cc:8304 -#: ../libqalculate/BuiltinFunctions.cc:8467 -#: ../libqalculate/BuiltinFunctions.cc:8559 -#, c-format -msgid "The comparison is true for all %s if %s." -msgstr "Het vergelijken geeft waar voor alle %s indien %s." - -#: ../libqalculate/BuiltinFunctions.cc:8308 -#, c-format -msgid "Was unable to isolate %s." -msgstr "Kon %s niet isoleren." +msgid "Character '%s' was ignored in the number \"%s\" with base %s." +msgstr "Karakter '%s' werd genegeerd in het getal \"%s\" met grondtal %s." -#: ../libqalculate/BuiltinFunctions.cc:8428 -#: ../libqalculate/BuiltinFunctions.cc:8455 -#: ../libqalculate/BuiltinFunctions.cc:8536 +#. if left value is a function without any arguments, do function replacement +#: ../libqalculate/BuiltinFunctions-util.cc:414 +#: ../libqalculate/BuiltinFunctions-util.cc:419 +#: ../libqalculate/BuiltinFunctions-util.cc:421 +#: ../libqalculate/BuiltinFunctions-util.cc:437 +#: ../libqalculate/Calculator-calculate.cc:1239 +#: ../libqalculate/Calculator-calculate.cc:1251 +#: ../libqalculate/Calculator-calculate.cc:1253 +#: ../libqalculate/Calculator-calculate.cc:1256 +#: ../libqalculate/Calculator-calculate.cc:1327 #, c-format -msgid "" -"Was unable to isolate %s with the current assumptions. The assumed sign was " -"therefore temporarily set as unknown." +msgid "Original value (%s) was not found." msgstr "" -"Kon %s niet isoleren met de huidige aannames. Het aangenomen teken werd " -"daarom tijdelijk als onbekend beschouwd." -#: ../libqalculate/BuiltinFunctions.cc:8431 -#: ../libqalculate/BuiltinFunctions.cc:8458 -#: ../libqalculate/BuiltinFunctions.cc:8539 +#: ../libqalculate/BuiltinFunctions-util.cc:627 +#: ../libqalculate/BuiltinFunctions-util.cc:631 #, c-format -msgid "" -"Was unable to isolate %s with the current assumptions. The assumed type and " -"sign was therefore temporarily set as unknown." +msgid "Too few elements (%s) in vector (%s required)" msgstr "" -"Kon %s niet isoleren met de huidige aannames. Het aangenomen type en teken " -"werd daarom tijdelijk als onbekend beschouwd." -#: ../libqalculate/BuiltinFunctions.cc:8463 -#: ../libqalculate/BuiltinFunctions.cc:8546 +#: ../libqalculate/BuiltinFunctions-util.cc:677 #, c-format -msgid "The solution requires that %s." -msgstr "De oplossing vereist dat %s." +msgid "Object %s does not exist." +msgstr "Object %s bestaat niet." -#: ../libqalculate/BuiltinFunctions.cc:8553 -#, c-format -msgid "Solution %s requires that %s." -msgstr "De oplossing %s vereist dat %s." +#: ../libqalculate/BuiltinFunctions-util.cc:695 +#, fuzzy, c-format +msgid "Invalid variable name (%s)." +msgstr "een geldige naam voor een variabele" -#: ../libqalculate/BuiltinFunctions.cc:8624 -#, c-format +#: ../libqalculate/BuiltinFunctions-util.cc:712 msgid "" -"Unable to isolate %s.\n" -"\n" -"You might need to place the equations and variables in an appropriate order " -"so that each equation at least contains the corresponding variable (if " -"automatic reordering failed)." +"A global unit or variable was deactivated. It will be restored after the new " +"variable has been removed." msgstr "" -"Kan %s niet isoleren.\n" -"\n" -"Mogelijk moet u de vergelijkingen en variabelen in een juiste volgorde " -"plaatsen zodat elke vergelijking tenminste de ermee overeenkomende variabele " -"bevat (indien het automatisch op volgorde zetten niet is gelukt)." -#: ../libqalculate/BuiltinFunctions.cc:8626 -#: ../libqalculate/BuiltinFunctions.cc:8640 -#: ../libqalculate/BuiltinFunctions.cc:8649 +#: ../libqalculate/BuiltinFunctions-util.cc:727 #, c-format -msgid "Unable to isolate %s." -msgstr "Kon %s niet isoleren." - -#: ../libqalculate/BuiltinFunctions.cc:8633 -#, c-format -msgid "Inequalities is not allowed in %s()." -msgstr "Ongelijkheden zijn niet toegestaan in %s()." - -#: ../libqalculate/BuiltinFunctions.cc:8975 -#: ../libqalculate/BuiltinFunctions.cc:8980 -msgid "No differential equation found." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:8984 -#: ../libqalculate/BuiltinFunctions.cc:9013 -#: ../libqalculate/BuiltinFunctions.cc:9019 -msgid "Unable to solve differential equation." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:9045 -#, fuzzy -msgid "Unable to find limit." -msgstr "Kon %s niet isoleren." +msgid "Register %s does not exist. Returning zero." +msgstr "Register %s bestaat niet. Nul wordt geretourneerd." -#: ../libqalculate/BuiltinFunctions.cc:9099 -#: ../libqalculate/BuiltinFunctions.cc:9113 +#: ../libqalculate/BuiltinFunctions-util.cc:794 +#: ../libqalculate/BuiltinFunctions-util.cc:808 msgid "Matrix" msgstr "Matrix" -#: ../libqalculate/BuiltinFunctions.cc:9124 -#: ../libqalculate/BuiltinFunctions.cc:9174 +#: ../libqalculate/BuiltinFunctions-util.cc:819 +#: ../libqalculate/BuiltinFunctions-util.cc:869 msgid "Vector" msgstr "Vector" -#: ../libqalculate/BuiltinFunctions.cc:9139 -#: ../libqalculate/BuiltinFunctions.cc:9185 ../libqalculate/Calculator.cc:12320 +#: ../libqalculate/BuiltinFunctions-util.cc:834 +#: ../libqalculate/BuiltinFunctions-util.cc:880 +#: ../libqalculate/Calculator-plot.cc:135 msgid "Unable to generate plot data with current min, max and step size." msgstr "" "Het is onmogelijk plotgegevens te genereren met de huidige min, max en " "stapgrootte." -#: ../libqalculate/BuiltinFunctions.cc:9141 -#: ../libqalculate/BuiltinFunctions.cc:9187 +#: ../libqalculate/BuiltinFunctions-util.cc:836 +#: ../libqalculate/BuiltinFunctions-util.cc:882 msgid "Sampling rate must be a positive integer." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:9150 -#: ../libqalculate/BuiltinFunctions.cc:9196 ../libqalculate/Calculator.cc:12290 +#: ../libqalculate/BuiltinFunctions-util.cc:845 +#: ../libqalculate/BuiltinFunctions-util.cc:891 +#: ../libqalculate/Calculator-plot.cc:105 msgid "Unable to generate plot data with current min, max and sampling rate." msgstr "" "Het is onmogelijk plotgegevens te genereren met de huidige min, max en " "bemonsteringsnelheid." -#: ../libqalculate/Calculator.cc:454 ../libqalculate/Calculator.cc:680 +#: ../libqalculate/Calculator-calculate.cc:303 +#: ../libqalculate/Calculator-calculate.cc:428 +msgid "Stack is empty. Filling remaining function arguments with zeroes." +msgstr "" + +#: ../libqalculate/Calculator-calculate.cc:1004 +msgid "calculating..." +msgstr "aan het rekenen..." + +#. "where"-operator +#: ../libqalculate/Calculator-calculate.cc:1130 +#: ../libqalculate/Calculator-calculate.cc:1132 +#: ../libqalculate/Calculator-calculate.cc:1151 +#: ../libqalculate/Calculator-calculate.cc:1153 +#: ../libqalculate/Calculator.cc:1326 +msgid "where" +msgstr "" + +#: ../libqalculate/Calculator-calculate.cc:1349 +#, c-format +msgid "Unhandled \"where\" expression: %s" +msgstr "" + +#: ../libqalculate/Calculator-calculate.cc:1567 +#: ../libqalculate/Calculator-calculate.cc:1614 +msgid "timed out" +msgstr "tijd is verlopen" + +#: ../libqalculate/Calculator.cc:232 ../libqalculate/Calculator.cc:460 msgid "per" msgstr "per" -#: ../libqalculate/Calculator.cc:456 ../libqalculate/Calculator.cc:682 +#: ../libqalculate/Calculator.cc:234 ../libqalculate/Calculator.cc:462 msgid "times" msgstr "keer" -#: ../libqalculate/Calculator.cc:458 ../libqalculate/Calculator.cc:684 +#: ../libqalculate/Calculator.cc:236 ../libqalculate/Calculator.cc:464 msgid "plus" msgstr "plus" -#: ../libqalculate/Calculator.cc:460 ../libqalculate/Calculator.cc:686 +#: ../libqalculate/Calculator.cc:238 ../libqalculate/Calculator.cc:466 msgid "minus" msgstr "minus" -#: ../libqalculate/Calculator.cc:462 ../libqalculate/Calculator.cc:688 -#: ../libqalculate/MathStructure.cc:21575 ../libqalculate/Function.cc:1331 -#: ../libqalculate/Function.cc:1339 ../libqalculate/Function.cc:1768 -#: ../libqalculate/Function.cc:1930 ../libqalculate/Function.cc:1938 +#: ../libqalculate/Calculator.cc:240 ../libqalculate/Calculator.cc:468 +#: ../libqalculate/MathStructure-print.cc:3170 ../libqalculate/Function.cc:1361 +#: ../libqalculate/Function.cc:1369 ../libqalculate/Function.cc:1802 +#: ../libqalculate/Function.cc:1964 ../libqalculate/Function.cc:1972 msgid "and" msgstr "and" -#: ../libqalculate/Calculator.cc:831 +#: ../libqalculate/Calculator.cc:611 msgid "Gradians unit is missing. Creating one for this session." msgstr "" "Eenheid grad (100 grads in rechte hoek) ontbreekt. Voor deze sessie wordt er " "een aangemaakt." -#: ../libqalculate/Calculator.cc:832 ../libqalculate/Calculator.cc:840 -#: ../libqalculate/Calculator.cc:848 +#: ../libqalculate/Calculator.cc:612 ../libqalculate/Calculator.cc:620 +#: ../libqalculate/Calculator.cc:628 msgid "Angle/Plane Angle" msgstr "Hoek/hoek in het platte vlak" -#: ../libqalculate/Calculator.cc:839 +#: ../libqalculate/Calculator.cc:619 msgid "Radians unit is missing. Creating one for this session." msgstr "Eenheid radiaal ontbreekt. Voor deze sessie wordt er een aangemaakt." -#: ../libqalculate/Calculator.cc:847 +#: ../libqalculate/Calculator.cc:627 msgid "Degrees unit is missing. Creating one for this session." msgstr "Eenheid graad ontbreekt. Voor deze sessie wordt er een aangemaakt." -#. "where"-operator -#: ../libqalculate/Calculator.cc:1544 ../libqalculate/Calculator.cc:3298 -#: ../libqalculate/Calculator.cc:3300 ../libqalculate/Calculator.cc:3319 -#: ../libqalculate/Calculator.cc:3321 -msgid "where" -msgstr "" - -#: ../libqalculate/Calculator.cc:2027 ../libqalculate/Calculator.cc:2028 -#: ../libqalculate/Calculator.cc:11818 ../libqalculate/Calculator.cc:11955 -#: ../libqalculate/Calculator.cc:12013 +#: ../libqalculate/Calculator.cc:1695 ../libqalculate/Calculator.cc:1696 +#: ../libqalculate/Calculator.cc:1700 +#: ../libqalculate/Calculator-definitions.cc:3285 +#: ../libqalculate/Calculator-definitions.cc:3455 +#: ../libqalculate/Calculator-definitions.cc:3513 msgid "Currency" msgstr "Valuta" -#: ../libqalculate/Calculator.cc:2563 ../libqalculate/Calculator.cc:2688 -msgid "Stack is empty. Filling remaining function arguments with zeroes." -msgstr "" - -#: ../libqalculate/Calculator.cc:3180 -msgid "calculating..." -msgstr "aan het rekenen..." - -#: ../libqalculate/Calculator.cc:3502 -#, c-format -msgid "Unhandled \"where\" expression: %s" -msgstr "" - -#: ../libqalculate/Calculator.cc:5259 +#: ../libqalculate/Calculator.cc:2635 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name of \"%s\", or " @@ -2633,7 +2650,7 @@ "De naam \"%s\" is niet meer toegestaan. Verander alstublieft de naam \"%s\" " "omdat anders deze variabele verloren gaat." -#: ../libqalculate/Calculator.cc:5277 +#: ../libqalculate/Calculator.cc:2653 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name \"%s\", or " @@ -2642,7 +2659,7 @@ "De naam \"%s\" is niet meer toegestaan. Verander alstublieft de naam \"%s\" " "omdat anders deze functie verloren gaat." -#: ../libqalculate/Calculator.cc:5294 +#: ../libqalculate/Calculator.cc:2670 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name \"%s\", or " @@ -2651,32 +2668,84 @@ "De naam \"%s\" is niet meer toegestaan. Verander alstublieft de naam \"%s\" " "omdat anders deze eenheid verloren gaat." -#: ../libqalculate/Calculator.cc:6883 ../libqalculate/Calculator.cc:6927 -#: ../libqalculate/Calculator.cc:6930 ../libqalculate/Calculator.cc:8101 -#: ../libqalculate/Calculator.cc:8110 ../libqalculate/Calculator.cc:8165 -#: ../libqalculate/Calculator.cc:8227 ../libqalculate/Calculator.cc:8248 -#: ../libqalculate/Calculator.cc:8249 +#: ../libqalculate/Calculator.cc:2877 +#, c-format +msgid "Name \"%s\" is in use. Replacing with \"%s\"." +msgstr "Naam \"%s\" wordt al gebruikt.. Wordt vervangen door \"%s\"." + +#: ../libqalculate/Calculator-definitions.cc:763 ../libqalculate/DataSet.cc:540 +#, c-format +msgid "File not identified as Qalculate! definitions file: %s." +msgstr "Bestand niet gedefinieerd als definitiebestand voor Qalculate!: %s." + +#: ../libqalculate/Calculator-definitions.cc:2870 +#: ../libqalculate/DataSet.cc:363 +msgid "Object" +msgstr "Object" + +#: ../libqalculate/Calculator-definitions.cc:2879 +#: ../libqalculate/DataSet.cc:364 +msgid "Property" +msgstr "Eigenschap" + +#: ../libqalculate/Calculator-definitions.cc:3178 +msgid "column" +msgstr "kolom" + +#: ../libqalculate/Calculator-definitions.cc:3181 +msgid "Column " +msgstr "Kolom " + +#: ../libqalculate/Calculator-definitions.cc:3632 +#: ../libqalculate/Calculator-definitions.cc:3633 +#: ../libqalculate/Calculator-definitions.cc:3637 +#: ../libqalculate/Calculator-definitions.cc:3640 +#: ../libqalculate/Calculator-definitions.cc:3672 +#: ../libqalculate/Calculator-definitions.cc:3673 +#: ../libqalculate/Calculator-definitions.cc:3676 +#: ../libqalculate/Calculator-definitions.cc:3695 +#: ../libqalculate/Calculator-definitions.cc:3696 +#: ../libqalculate/Calculator-definitions.cc:3699 +#: ../libqalculate/Calculator-definitions.cc:3719 +#: ../libqalculate/Calculator-definitions.cc:3720 +#: ../libqalculate/Calculator-definitions.cc:3723 +#, c-format +msgid "Failed to download exchange rates from %s: %s." +msgstr "Het ophalen van wisselkoersen van %s is niet gelukt: %s." + +#. ignore operators +#: ../libqalculate/Calculator-parse.cc:1668 +#: ../libqalculate/Calculator-parse.cc:1721 +#: ../libqalculate/Calculator-parse.cc:1725 +#: ../libqalculate/Calculator-parse.cc:2926 +#: ../libqalculate/Calculator-parse.cc:2935 +#: ../libqalculate/Calculator-parse.cc:2990 +#: ../libqalculate/Calculator-parse.cc:3055 +#: ../libqalculate/Calculator-parse.cc:3077 +#: ../libqalculate/Calculator-parse.cc:3078 #, c-format msgid "Misplaced operator(s) \"%s\" ignored" msgstr "Verkeerd geplaatste bewerking(en) \"%s\" genegeerd" -#: ../libqalculate/Calculator.cc:6924 ../libqalculate/Calculator.cc:8250 +#. ignore operators +#: ../libqalculate/Calculator-parse.cc:1717 +#: ../libqalculate/Calculator-parse.cc:3079 #, c-format msgid "Misplaced '%c' ignored" msgstr "Verkeerd geplaatste '%c' genegeerd" -#: ../libqalculate/Calculator.cc:6962 ../libqalculate/Function.cc:1489 -#: ../libqalculate/Function.cc:1520 +#: ../libqalculate/Calculator-parse.cc:1759 ../libqalculate/Function.cc:1519 +#: ../libqalculate/Function.cc:1550 #, c-format msgid "Internal id %s does not exist." msgstr "Interne id %s bestaat niet." -#: ../libqalculate/Calculator.cc:6980 +#: ../libqalculate/Calculator-parse.cc:1779 #, c-format msgid "\"%s\" is not a valid variable/function/unit." msgstr "\"%s\" is geen geldige variabele/functie/eenheid." -#: ../libqalculate/Calculator.cc:6995 +#: ../libqalculate/Calculator-parse.cc:1794 #, c-format msgid "" "Trailing characters \"%s\" (not a valid variable/function/unit) in number " @@ -2685,131 +2754,96 @@ "Afsluitende karakters \"%s\" (geen geldige variabele/functie/eenheid) in " "getal \"%s\" werden genegeerd." -#: ../libqalculate/Calculator.cc:7261 +#: ../libqalculate/Calculator-parse.cc:2072 msgid "RPN syntax error. Values left at the end of the RPN expression." msgstr "" "RPN-fout. Er zijn nog waarden overgebleven na de verwerking van de RPN-" "opdracht." -#: ../libqalculate/Calculator.cc:7264 ../libqalculate/Calculator.cc:7355 +#: ../libqalculate/Calculator-parse.cc:2075 +#: ../libqalculate/Calculator-parse.cc:2166 msgid "Unused stack values." msgstr "Ongebruikte waarden op de stack (stapelregister)." -#: ../libqalculate/Calculator.cc:7397 ../libqalculate/Calculator.cc:7605 +#: ../libqalculate/Calculator-parse.cc:2208 +#: ../libqalculate/Calculator-parse.cc:2416 #, fuzzy, c-format msgid "RPN syntax error. Operator '%c' not supported." msgstr "RPN-syntaxisfout. Stack (stapelregister) is leeg." -#: ../libqalculate/Calculator.cc:7443 +#: ../libqalculate/Calculator-parse.cc:2254 msgid "RPN syntax error. Stack is empty." msgstr "RPN-syntaxisfout. Stack (stapelregister) is leeg." -#: ../libqalculate/Calculator.cc:7464 +#: ../libqalculate/Calculator-parse.cc:2275 msgid "RPN syntax error. Operator ignored as there where only one stack value." msgstr "" "RPN-syntaxisfout. Bewerking genegeerd omdat er slechts één waarde is op de " "stack (stapelregister)." -#: ../libqalculate/Calculator.cc:8525 -#, c-format -msgid "Name \"%s\" is in use. Replacing with \"%s\"." -msgstr "Naam \"%s\" wordt al gebruikt.. Wordt vervangen door \"%s\"." - -#: ../libqalculate/Calculator.cc:9212 ../libqalculate/DataSet.cc:539 -#, c-format -msgid "File not identified as Qalculate! definitions file: %s." -msgstr "Bestand niet gedefinieerd als definitiebestand voor Qalculate!: %s." - -#: ../libqalculate/Calculator.cc:11319 ../libqalculate/DataSet.cc:362 -msgid "Object" -msgstr "Object" - -#: ../libqalculate/Calculator.cc:11328 ../libqalculate/DataSet.cc:363 -msgid "Property" -msgstr "Eigenschap" - -#: ../libqalculate/Calculator.cc:11627 -msgid "column" -msgstr "kolom" - -#: ../libqalculate/Calculator.cc:11630 -msgid "Column " -msgstr "Kolom " - -#: ../libqalculate/Calculator.cc:11706 ../libqalculate/Calculator.cc:11753 -msgid "timed out" -msgstr "tijd is verlopen" - -#: ../libqalculate/Calculator.cc:12125 ../libqalculate/Calculator.cc:12126 -#: ../libqalculate/Calculator.cc:12130 ../libqalculate/Calculator.cc:12133 -#: ../libqalculate/Calculator.cc:12165 ../libqalculate/Calculator.cc:12166 -#: ../libqalculate/Calculator.cc:12169 ../libqalculate/Calculator.cc:12188 -#: ../libqalculate/Calculator.cc:12189 ../libqalculate/Calculator.cc:12192 -#, c-format -msgid "Failed to download exchange rates from %s: %s." -msgstr "Het ophalen van wisselkoersen van %s is niet gelukt: %s." - -#: ../libqalculate/Calculator.cc:12286 ../libqalculate/Calculator.cc:12316 -#: ../libqalculate/Calculator.cc:12346 ../libqalculate/Calculator.cc:12685 +#: ../libqalculate/Calculator-plot.cc:101 +#: ../libqalculate/Calculator-plot.cc:131 +#: ../libqalculate/Calculator-plot.cc:161 +#: ../libqalculate/Calculator-plot.cc:498 msgid "It took too long to generate the plot data." msgstr "" -#: ../libqalculate/Calculator.cc:12380 +#: ../libqalculate/Calculator-plot.cc:193 msgid "No extension in file name. Saving as PNG image." msgstr "" "Geen extensie opgegeven voor bestandsnaam. Wordt opgeslagen als PNG-" "afbeelding." -#: ../libqalculate/Calculator.cc:12399 +#: ../libqalculate/Calculator-plot.cc:212 msgid "Unknown extension in file name. Saving as PNG image." msgstr "" "Onbekende extensie in bestandsnaam. Wordt opgeslagen als PNG-afbeelding." -#: ../libqalculate/Calculator.cc:12616 +#: ../libqalculate/Calculator-plot.cc:429 #, c-format msgid "Could not create temporary file %s" msgstr "Kon tijdelijk bestand %s niet aanmaken" -#: ../libqalculate/Calculator.cc:12732 +#: ../libqalculate/Calculator-plot.cc:545 msgid "" "Failed to invoke gnuplot. Make sure that you have gnuplot installed in your " "path." msgstr "" "Gnuplot aanroepen mislukt. Controleer uw path of gnuplot daarin is te vinden." -#: ../libqalculate/DataSet.cc:388 +#: ../libqalculate/DataSet.cc:389 #, c-format msgid "Object %s not available in data set." msgstr "Object %s niet beschikbaar in gegevensverzameling." -#: ../libqalculate/DataSet.cc:398 +#: ../libqalculate/DataSet.cc:399 #, c-format msgid "Property %s not available in data set." msgstr "Eigenschap %s niet beschikbaar in gegevensverzameling." -#: ../libqalculate/DataSet.cc:403 +#: ../libqalculate/DataSet.cc:404 #, c-format msgid "Property %s not defined for object %s." msgstr "Eigenschap %s niet gedefinieerd voor object %s." -#: ../libqalculate/DataSet.cc:516 ../libqalculate/DataSet.cc:524 +#: ../libqalculate/DataSet.cc:517 ../libqalculate/DataSet.cc:525 #, c-format msgid "Unable to load data objects in %s." msgstr "Kon gegevensobjecten in %s niet inlezen." -#: ../libqalculate/DataSet.cc:1042 +#: ../libqalculate/DataSet.cc:1043 msgid "data property" msgstr "eigenschap gegevens" -#: ../libqalculate/DataSet.cc:1044 +#: ../libqalculate/DataSet.cc:1045 msgid "name of a data property" msgstr "naam van een eigenschap van gegevens" -#: ../libqalculate/DataSet.cc:1052 ../libqalculate/DataSet.cc:1068 +#: ../libqalculate/DataSet.cc:1053 ../libqalculate/DataSet.cc:1069 msgid "no properties available" msgstr "geen eigenschappen beschikbaar" -#: ../libqalculate/DataSet.cc:1102 +#: ../libqalculate/DataSet.cc:1103 #, c-format msgid "" "Data set \"%s\" has no object key that supports the provided argument type." @@ -2817,24 +2851,33 @@ "Gegevensverzameling \"%s\" heeft geen objectsleutel die het opgegeven " "argumenttype ondersteunt." -#: ../libqalculate/DataSet.cc:1107 +#: ../libqalculate/DataSet.cc:1108 msgid "data object" msgstr "gegevensobject" -#: ../libqalculate/DataSet.cc:1110 +#: ../libqalculate/DataSet.cc:1111 msgid "an object from" msgstr "een object van" -#: ../libqalculate/DataSet.cc:1137 +#: ../libqalculate/DataSet.cc:1138 msgid "use" msgstr "gebruik" -#: ../libqalculate/MathStructure.cc:265 +#: ../libqalculate/MathStructure-calculate.cc:76 #, fuzzy, c-format msgid "Required assumption: %s." msgstr "Onbekende aanname." -#: ../libqalculate/MathStructure.cc:4031 ../libqalculate/MathStructure.cc:4052 +#: ../libqalculate/MathStructure-calculate.cc:95 +#: ../libqalculate/MathStructure-calculate.cc:117 +#: ../libqalculate/MathStructure-calculate.cc:148 +#: ../libqalculate/MathStructure-integrate.cc:7086 +#, c-format +msgid "To avoid division by zero, the following must be true: %s." +msgstr "Om delen door nul te voorkomen moet het volgende waar zijn: %s." + +#: ../libqalculate/MathStructure-calculate.cc:1653 +#: ../libqalculate/MathStructure-calculate.cc:1675 #, c-format msgid "" "The second matrix must have as many rows (was %s) as the first has columns " @@ -2844,131 +2887,147 @@ "tweede (was %s) even groot zijn als het aantal kolommen van de eerste (was " "%s)." -#: ../libqalculate/MathStructure.cc:8936 ../libqalculate/MathStructure.cc:8977 -#: ../libqalculate/MathStructure.cc:9010 ../libqalculate/MathStructure.cc:9077 -#: ../libqalculate/MathStructure.cc:9105 ../libqalculate/MathStructure.cc:9124 -#: ../libqalculate/MathStructure.cc:9143 ../libqalculate/MathStructure.cc:9162 -#: ../libqalculate/MathStructure.cc:9270 ../libqalculate/MathStructure.cc:16270 -#: ../libqalculate/MathStructure.cc:16661 +#: ../libqalculate/MathStructure-calculate.cc:6072 +#: ../libqalculate/MathStructure-calculate.cc:6113 +#: ../libqalculate/MathStructure-calculate.cc:6146 +#: ../libqalculate/MathStructure-calculate.cc:6213 +#: ../libqalculate/MathStructure-calculate.cc:6241 +#: ../libqalculate/MathStructure-calculate.cc:6260 +#: ../libqalculate/MathStructure-calculate.cc:6279 +#: ../libqalculate/MathStructure-calculate.cc:6298 +#: ../libqalculate/MathStructure-calculate.cc:6406 +#: ../libqalculate/MathStructure-factor.cc:413 +#: ../libqalculate/MathStructure-factor.cc:1304 msgid "This is a bug. Please report it." msgstr "Dit is een bug (programmafout). Meld deze alstublieft." -#: ../libqalculate/MathStructure.cc:9353 ../libqalculate/Function.cc:527 +#: ../libqalculate/MathStructure-calculate.cc:6495 +#: ../libqalculate/Function.cc:557 #, fuzzy msgid "No unknown variable/symbol was found." msgstr "een onbekend(e) variabele/symbool" -#: ../libqalculate/MathStructure.cc:11752 -#: ../libqalculate/MathStructure.cc:11757 -#, c-format -msgid "Limit for %s determined graphically." +#: ../libqalculate/MathStructure-convert.cc:262 +msgid "" +"Calculations involving conversion of units without proportional linear " +"relationship (e.g. with multiple temperature units), might give unexpected " +"results and is not recommended." msgstr "" -#: ../libqalculate/MathStructure.cc:12582 +#: ../libqalculate/MathStructure-eval.cc:754 msgid "Interval potentially calculated wide." msgstr "" -#: ../libqalculate/MathStructure.cc:13500 +#: ../libqalculate/MathStructure-eval.cc:2024 msgid "" "Calculation of uncertainty propagation partially failed (using interval " "arithmetic instead when necessary)." msgstr "" -#: ../libqalculate/MathStructure.cc:13638 +#: ../libqalculate/MathStructure-eval.cc:2170 msgid "" "Calculation of uncertainty propagation failed (using interval arithmetic " "instead)." msgstr "" -#: ../libqalculate/MathStructure.cc:18517 +#: ../libqalculate/MathStructure-factor.cc:3160 msgid "" "Because of time constraints only a limited number of combinations of terms " "were tried during factorization. Repeat factorization to try other random " "combinations." msgstr "" -#: ../libqalculate/MathStructure.cc:21769 -msgid "undefined" -msgstr "ongedefinieerd" +#: ../libqalculate/MathStructure-integrate.cc:7668 +#: ../libqalculate/MathStructure-integrate.cc:7743 +#, fuzzy +msgid "Unable to integrate the expression exact." +msgstr "Kon %s niet isoleren." -#: ../libqalculate/MathStructure.cc:21810 +#: ../libqalculate/MathStructure-integrate.cc:7707 +msgid "Definite integral was approximated." +msgstr "" + +#: ../libqalculate/MathStructure-isolatex.cc:999 +#: ../libqalculate/MathStructure-isolatex.cc:1176 +#: ../libqalculate/MathStructure-isolatex.cc:1815 +#: ../libqalculate/MathStructure-isolatex.cc:2335 +#: ../libqalculate/MathStructure-isolatex.cc:2401 +#: ../libqalculate/MathStructure-isolatex.cc:2451 +#: ../libqalculate/MathStructure-isolatex.cc:2472 +#: ../libqalculate/MathStructure-isolatex.cc:2530 +#: ../libqalculate/MathStructure-isolatex.cc:2656 +#: ../libqalculate/MathStructure-isolatex.cc:2801 +#, c-format +msgid "Interval arithmetic was disabled during calculation of %s." +msgstr "" + +#: ../libqalculate/MathStructure-isolatex.cc:2800 +#, c-format +msgid "Not all complex roots were calculated for %s." +msgstr "" + +#: ../libqalculate/MathStructure-isolatex.cc:4394 +#, c-format +msgid "Only one or two of the roots where calculated for %s." +msgstr "" + +#: ../libqalculate/MathStructure-limit.cc:967 +#: ../libqalculate/MathStructure-limit.cc:972 +#, c-format +msgid "Limit for %s determined graphically." +msgstr "" + +#: ../libqalculate/MathStructure-matrixvector.cc:62 #, c-format msgid "Unsolvable comparison at element %s when trying to rank vector." msgstr "" "Vergelijken lukt niet bij element %s bij berekenen van rangvolgorde vector." -#: ../libqalculate/MathStructure.cc:21860 +#: ../libqalculate/MathStructure-matrixvector.cc:112 #, c-format msgid "Unsolvable comparison at element %s when trying to sort vector." msgstr "Vergelijken lukt niet bij element %s bij sorteren vector." -#: ../libqalculate/MathStructure.cc:22285 +#: ../libqalculate/MathStructure-matrixvector.cc:537 msgid "The determinant can only be calculated for square matrices." msgstr "De determinant kan alleen voor een vierkante matrix worden berekend." -#: ../libqalculate/MathStructure.cc:22348 +#: ../libqalculate/MathStructure-matrixvector.cc:600 msgid "The permanent can only be calculated for square matrices." msgstr "De permanent kan alleen voor een vierkante matrix worden berekend." -#: ../libqalculate/MathStructure.cc:22435 +#: ../libqalculate/MathStructure-matrixvector.cc:687 msgid "Inverse of singular matrix." msgstr "Inverse van singuliere matrix." -#: ../libqalculate/MathStructure.cc:22789 -msgid "" -"Calculations involving conversion of units without proportional linear " -"relationship (e.g. with multiple temperature units), might give unexpected " -"results and is not recommended." -msgstr "" - -#: ../libqalculate/MathStructure.cc:24092 -#: ../libqalculate/MathStructure.cc:24135 +#: ../libqalculate/MathStructure-matrixvector.cc:817 +#: ../libqalculate/MathStructure-matrixvector.cc:860 msgid "Too many data points" msgstr "" -#: ../libqalculate/MathStructure.cc:24099 +#: ../libqalculate/MathStructure-matrixvector.cc:824 msgid "" "The selected min and max do not result in a positive, finite number of data " "points" msgstr "" -#: ../libqalculate/MathStructure.cc:24132 +#: ../libqalculate/MathStructure-matrixvector.cc:857 msgid "" "The selected min, max and step size do not result in a positive, finite " "number of data points" msgstr "" -#: ../libqalculate/MathStructure.cc:32190 -#: ../libqalculate/MathStructure.cc:32368 -#: ../libqalculate/MathStructure.cc:33005 -#: ../libqalculate/MathStructure.cc:33525 -#: ../libqalculate/MathStructure.cc:33591 -#: ../libqalculate/MathStructure.cc:33641 -#: ../libqalculate/MathStructure.cc:33662 -#: ../libqalculate/MathStructure.cc:33720 -#: ../libqalculate/MathStructure.cc:33846 -#: ../libqalculate/MathStructure.cc:33990 -#, c-format -msgid "Interval arithmetic was disabled during calculation of %s." -msgstr "" - -#: ../libqalculate/MathStructure.cc:33989 -#, c-format -msgid "Not all complex roots were calculated for %s." -msgstr "" - -#: ../libqalculate/MathStructure.cc:35479 -#, c-format -msgid "Only one or two of the roots where calculated for %s." -msgstr "" +#: ../libqalculate/MathStructure-print.cc:3364 +msgid "undefined" +msgstr "ongedefinieerd" -#: ../libqalculate/Function.cc:171 +#: ../libqalculate/Function.cc:185 #, c-format msgid "%s() requires that %s" msgstr "%s() vereist dat %s" -#: ../libqalculate/Function.cc:326 ../libqalculate/Function.cc:385 -#: ../libqalculate/Function.cc:445 +#: ../libqalculate/Function.cc:351 ../libqalculate/Function.cc:413 +#: ../libqalculate/Function.cc:474 #, c-format msgid "" "Additional arguments for function %s() was ignored. Function can only use %s " @@ -2977,165 +3036,165 @@ "Overtollige argumenten voor functie %s() werden genegeerd. Functie heeft " "slechts %s argument(en) nodig." -#: ../libqalculate/Function.cc:466 +#: ../libqalculate/Function.cc:495 #, c-format msgid "You need at least %s argument(s) (%s) in function %s()." msgstr "Er is/zijn minstens %s argument(en) (%s) nodig in functie %s()." -#: ../libqalculate/Function.cc:468 +#: ../libqalculate/Function.cc:497 #, c-format msgid "You need at least %s argument(s) in function %s()." msgstr "Er is/zijn minstens %s argument(en) nodig in functie %s()." -#: ../libqalculate/Function.cc:1321 +#: ../libqalculate/Function.cc:1351 msgid "a free value" msgstr "een vrije waarde" -#: ../libqalculate/Function.cc:1326 +#: ../libqalculate/Function.cc:1356 msgid "that is nonzero" msgstr "die ongelijk nul is" -#: ../libqalculate/Function.cc:1334 +#: ../libqalculate/Function.cc:1364 msgid "that is rational (polynomial)" msgstr "die rationaal is (polynoom)" -#: ../libqalculate/Function.cc:1342 +#: ../libqalculate/Function.cc:1372 msgid "that fulfills the condition:" msgstr "die aan de conditie voldoet:" -#: ../libqalculate/Function.cc:1345 +#: ../libqalculate/Function.cc:1375 msgid "Argument" msgstr "Argument" -#: ../libqalculate/Function.cc:1409 +#: ../libqalculate/Function.cc:1439 #, c-format msgid "Argument %s in %s() must be %s." msgstr "Argument %s in %s() moet zijn: %s." -#: ../libqalculate/Function.cc:1411 +#: ../libqalculate/Function.cc:1441 #, c-format msgid "Argument %s, %s, in %s() must be %s." msgstr "Argument %s, %s, in %s() moet zijn: %s." -#: ../libqalculate/Function.cc:1749 +#: ../libqalculate/Function.cc:1783 msgid "a rational number" msgstr "een rationaal getal" -#: ../libqalculate/Function.cc:1751 +#: ../libqalculate/Function.cc:1785 msgid "a number" msgstr "een getal" -#: ../libqalculate/Function.cc:1753 +#: ../libqalculate/Function.cc:1787 msgid "a real number" msgstr "een reëel getal" -#: ../libqalculate/Function.cc:1758 ../libqalculate/Function.cc:1911 -#: ../libqalculate/Function.cc:1916 +#: ../libqalculate/Function.cc:1792 ../libqalculate/Function.cc:1945 +#: ../libqalculate/Function.cc:1950 msgid ">=" msgstr ">=" -#: ../libqalculate/Function.cc:1760 +#: ../libqalculate/Function.cc:1794 msgid ">" msgstr ">" -#: ../libqalculate/Function.cc:1772 ../libqalculate/Function.cc:1933 -#: ../libqalculate/Function.cc:1940 +#: ../libqalculate/Function.cc:1806 ../libqalculate/Function.cc:1967 +#: ../libqalculate/Function.cc:1974 msgid "<=" msgstr "<=" -#: ../libqalculate/Function.cc:1774 +#: ../libqalculate/Function.cc:1808 msgid "<" msgstr "<" -#: ../libqalculate/Function.cc:1908 +#: ../libqalculate/Function.cc:1942 msgid "an integer" msgstr "een geheel getal" -#: ../libqalculate/Function.cc:1965 +#: ../libqalculate/Function.cc:1999 msgid "symbol" msgstr "symbool" -#: ../libqalculate/Function.cc:1966 +#: ../libqalculate/Function.cc:2000 msgid "an unknown variable/symbol" msgstr "een onbekend(e) variabele/symbool" -#: ../libqalculate/Function.cc:1979 +#: ../libqalculate/Function.cc:2013 msgid "text" msgstr "tekst" -#: ../libqalculate/Function.cc:1980 +#: ../libqalculate/Function.cc:2014 msgid "a text string" msgstr "een tekenrij" -#: ../libqalculate/Function.cc:2002 +#: ../libqalculate/Function.cc:2036 msgid "date" msgstr "datum" -#: ../libqalculate/Function.cc:2003 +#: ../libqalculate/Function.cc:2037 msgid "a date" msgstr "een datum" -#: ../libqalculate/Function.cc:2052 +#: ../libqalculate/Function.cc:2086 msgid "a vector with " msgstr "een vector met " -#: ../libqalculate/Function.cc:2064 +#: ../libqalculate/Function.cc:2098 msgid "a vector" msgstr "een vector" -#: ../libqalculate/Function.cc:2113 +#: ../libqalculate/Function.cc:2147 msgid "a square matrix" msgstr "een vierkante matrix" -#: ../libqalculate/Function.cc:2115 +#: ../libqalculate/Function.cc:2149 msgid "a matrix" msgstr "een matrix" -#: ../libqalculate/Function.cc:2130 +#: ../libqalculate/Function.cc:2164 msgid "object" msgstr "object" -#: ../libqalculate/Function.cc:2131 +#: ../libqalculate/Function.cc:2165 msgid "a valid function, unit or variable name" msgstr "een geldige naam voor een functie, eenheid of variabele" -#: ../libqalculate/Function.cc:2145 +#: ../libqalculate/Function.cc:2179 msgid "a valid function name" msgstr "een geldige functienaam" -#: ../libqalculate/Function.cc:2158 +#: ../libqalculate/Function.cc:2192 msgid "unit" msgstr "eenheid" -#: ../libqalculate/Function.cc:2159 +#: ../libqalculate/Function.cc:2193 msgid "a valid unit name" msgstr "een geldige naam voor een eenheid" -#: ../libqalculate/Function.cc:2173 +#: ../libqalculate/Function.cc:2207 msgid "a valid variable name" msgstr "een geldige naam voor een variabele" -#: ../libqalculate/Function.cc:2186 +#: ../libqalculate/Function.cc:2220 msgid "file" msgstr "bestand" -#: ../libqalculate/Function.cc:2187 +#: ../libqalculate/Function.cc:2221 msgid "a valid file name" msgstr "een geldige bestandsnaam" -#: ../libqalculate/Function.cc:2200 +#: ../libqalculate/Function.cc:2234 msgid "boolean" msgstr "Booleaanse waarde" -#: ../libqalculate/Function.cc:2201 +#: ../libqalculate/Function.cc:2235 msgid "a boolean (0 or 1)" msgstr "een Booleaanse waarde (0 of 1)" -#: ../libqalculate/Function.cc:2212 +#: ../libqalculate/Function.cc:2246 msgid "an angle or a number (using the default angle unit)" msgstr "een hoek of een getal (in standaard hoekeenheid)" -#: ../libqalculate/Number.cc:254 ../libqalculate/Number.cc:8251 +#: ../libqalculate/Number.cc:263 ../libqalculate/Number.cc:10175 msgid "" "Cannot display numbers greater than 9999 or less than -9999 as roman " "numerals." @@ -3143,18 +3202,20 @@ "Kan getallen groter dan 9999 of kleiner dan -9999 niet weergeven als " "Romeinse getallen." -#: ../libqalculate/Number.cc:351 +#: ../libqalculate/Number.cc:363 #, fuzzy, c-format msgid "Character '%s' was ignored in the number \"%s\" in bijective base-26." msgstr "Karakter '%s' werd genegeerd in het getal \"%s\" met grondtal %s." -#: ../libqalculate/Number.cc:433 ../libqalculate/Number.cc:474 -#: ../libqalculate/Number.cc:501 +#. digit value is higher than allowed by the base: show a warning, but use anyway +#. digit value is higher than allowed by base: show a warning, but use anyway +#: ../libqalculate/Number.cc:464 ../libqalculate/Number.cc:514 +#: ../libqalculate/Number.cc:544 #, c-format msgid "Digit '%s' is too high for number base." msgstr "" -#: ../libqalculate/Number.cc:551 +#: ../libqalculate/Number.cc:601 msgid "" "Assuming the unusual practice of letting a last capital I mean 2 in a roman " "numeral." @@ -3162,18 +3223,18 @@ "Een laatste hoofdletter I in een Romeins getal betekent hier 2, hoewel dit " "ongebruikelijk is." -#: ../libqalculate/Number.cc:635 ../libqalculate/Number.cc:662 -#: ../libqalculate/Number.cc:667 +#: ../libqalculate/Number.cc:685 ../libqalculate/Number.cc:712 +#: ../libqalculate/Number.cc:717 #, c-format msgid "Error in roman numerals: %s." msgstr "Fout in Romeins cijfers: \"%s\"." -#: ../libqalculate/Number.cc:672 +#: ../libqalculate/Number.cc:722 #, c-format msgid "Unknown roman numeral: %c." msgstr "Onbekend Romeins cijfer: %c." -#: ../libqalculate/Number.cc:730 +#: ../libqalculate/Number.cc:780 #, c-format msgid "" "Errors in roman numerals: \"%s\". Interpreted as %s, which should be written " @@ -3182,80 +3243,83 @@ "Fout in Romeinse cijfers: \"%s\". Geïnterpreteerd als %s, wat als %s zou " "moeten worden geschreven." -#: ../libqalculate/Number.cc:818 +#: ../libqalculate/Number.cc:881 #, fuzzy msgid "Too large exponent." msgstr "toon negatieve exponenten" -#: ../libqalculate/Number.cc:850 +#. only allow decimals after last ":" +#: ../libqalculate/Number.cc:917 msgid "':' in decimal number ignored (decimal point detected)." msgstr "':' in decimaal getal genegeerd (decimale komma gevonden)." -#: ../libqalculate/Number.cc:1950 ../libqalculate/Number.cc:2072 +#. test calculated floating point value and show mpfr errors (show as errors if error_level > 1, show as warnings if error_level = 1, do not generate message if error_level is zero) +#: ../libqalculate/Number.cc:2035 ../libqalculate/Number.cc:2160 msgid "Floating point underflow" msgstr "" -#: ../libqalculate/Number.cc:1951 ../libqalculate/Number.cc:2073 +#: ../libqalculate/Number.cc:2036 ../libqalculate/Number.cc:2161 msgid "Floating point overflow" msgstr "" -#: ../libqalculate/Number.cc:1952 ../libqalculate/Number.cc:2074 +#: ../libqalculate/Number.cc:2037 ../libqalculate/Number.cc:2162 msgid "Floating point division by zero exception" msgstr "" -#: ../libqalculate/Number.cc:1953 ../libqalculate/Number.cc:2077 +#: ../libqalculate/Number.cc:2038 ../libqalculate/Number.cc:2165 msgid "Floating point not a number exception" msgstr "" -#: ../libqalculate/Number.cc:1954 ../libqalculate/Number.cc:2075 +#: ../libqalculate/Number.cc:2039 ../libqalculate/Number.cc:2163 msgid "Floating point range exception" msgstr "" -#: ../libqalculate/Number.cc:3528 +#: ../libqalculate/Number.cc:3637 msgid "Division by zero." msgstr "Deling door nul." #. 0^0 -#: ../libqalculate/Number.cc:3534 +#: ../libqalculate/Number.cc:3643 msgid "0^0 might be considered undefined" msgstr "0^0 kan als ongedefinieerd worden beschouwd" -#: ../libqalculate/Number.cc:3541 +#: ../libqalculate/Number.cc:3650 msgid "The result of 0^i is possibly undefined" msgstr "" -#: ../libqalculate/Number.cc:3590 ../libqalculate/Number.cc:5389 -#: ../libqalculate/Number.cc:5500 ../libqalculate/Number.cc:5824 -#: ../libqalculate/Number.cc:5832 ../libqalculate/Number.cc:5865 -#: ../libqalculate/Number.cc:5962 ../libqalculate/Number.cc:6111 -#: ../libqalculate/Number.cc:6223 +#: ../libqalculate/Number.cc:3699 ../libqalculate/Number.cc:6103 +#: ../libqalculate/Number.cc:6214 ../libqalculate/Number.cc:6538 +#: ../libqalculate/Number.cc:6546 ../libqalculate/Number.cc:6579 +#: ../libqalculate/Number.cc:6676 ../libqalculate/Number.cc:6825 +#: ../libqalculate/Number.cc:6937 msgid "Interval calculated wide." msgstr "" -#: ../libqalculate/Number.cc:4942 -msgid "Cannot handle an argument (s) that large for Riemann Zeta." -msgstr "Argument (s) is te groot voor de berekening van Riemann Zeta." - -#: ../libqalculate/Number.cc:5017 ../libqalculate/Number.cc:5119 -#: ../libqalculate/Number.cc:5150 ../libqalculate/Number.cc:5181 -#: ../libqalculate/Number.cc:6568 +#: ../libqalculate/Number.cc:5126 ../libqalculate/Number.cc:5352 +#: ../libqalculate/Number.cc:5439 ../libqalculate/Number.cc:5723 +#: ../libqalculate/Number.cc:5809 ../libqalculate/Number.cc:5895 +#: ../libqalculate/Number.cc:7142 ../libqalculate/Number.cc:7160 +#: ../libqalculate/Number.cc:7179 ../libqalculate/Number.cc:7515 +#: ../libqalculate/Number.cc:7562 ../libqalculate/Number.cc:7707 +#: ../libqalculate/Number.cc:8040 ../libqalculate/Number.cc:8196 +#: ../libqalculate/Number.cc:8628 ../libqalculate/Number.cc:9023 #, c-format msgid "%s() lacks proper support interval arithmetic." msgstr "" -#: ../libqalculate/Number.cc:7816 +#: ../libqalculate/Number.cc:9706 #, fuzzy msgid "Unsupported base" msgstr "grondtal in" -#: ../libqalculate/Number.cc:8248 +#: ../libqalculate/Number.cc:10172 #, fuzzy msgid "Can only display rational numbers as roman numerals." msgstr "" "Kan getallen groter dan 9999 of kleiner dan -9999 niet weergeven als " "Romeinse getallen." -#: ../libqalculate/Number.cc:8693 ../libqalculate/Number.cc:8701 +#: ../libqalculate/Number.cc:10659 ../libqalculate/Number.cc:10667 msgid "infinity" msgstr "oneindigheid" @@ -3645,11 +3709,11 @@ msgid "leap month" msgstr "" -#: ../libqalculate/Unit.cc:1096 +#: ../libqalculate/Unit.cc:1100 msgid "Error(s) in unitexpression." msgstr "Fout(en) in de eenheidexpressie." -#: ../libqalculate/Variable.cc:501 +#: ../libqalculate/Variable.cc:502 #, c-format msgid "Recursive variable: %s = %s" msgstr "" @@ -3678,6 +3742,9 @@ msgid "Off" msgstr "Uit" +#~ msgid "Cannot handle an argument (s) that large for Riemann Zeta." +#~ msgstr "Argument (s) is te groot voor de berekening van Riemann Zeta." + #, fuzzy #~ msgid "No was unknown variable/symbol found." #~ msgstr "een onbekend(e) variabele/symbool" diff -Nru libqalculate-3.6.0/po/POTFILES.in libqalculate-3.7.0/po/POTFILES.in --- libqalculate-3.6.0/po/POTFILES.in 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/po/POTFILES.in 2020-01-21 22:54:40.000000000 +0000 @@ -3,11 +3,40 @@ src/defs2doc.cc src/qalc.cc src/test.cc -libqalculate/BuiltinFunctions.cc +libqalculate/BuiltinFunctions-algebra.cc +libqalculate/BuiltinFunctions-datetime.cc +libqalculate/BuiltinFunctions-matrixvector.cc +libqalculate/BuiltinFunctions-statistics.cc +libqalculate/BuiltinFunctions-calculus.cc +libqalculate/BuiltinFunctions-explog.cc +libqalculate/BuiltinFunctions-number.cc +libqalculate/BuiltinFunctions-trigonometry.cc +libqalculate/BuiltinFunctions-combinatorics.cc +libqalculate/BuiltinFunctions-logical.cc +libqalculate/BuiltinFunctions-special.cc +libqalculate/BuiltinFunctions-util.cc +libqalculate/Calculator-calculate.cc libqalculate/Calculator.cc +libqalculate/Calculator-convert.cc +libqalculate/Calculator-definitions.cc +libqalculate/Calculator-parse.cc +libqalculate/Calculator-plot.cc libqalculate/DataSet.cc libqalculate/ExpressionItem.cc +libqalculate/MathStructure-calculate.cc libqalculate/MathStructure.cc +libqalculate/MathStructure-convert.cc +libqalculate/MathStructure-decompose.cc +libqalculate/MathStructure-differentiate.cc +libqalculate/MathStructure-eval.cc +libqalculate/MathStructure-factor.cc +libqalculate/MathStructure-gcd.cc +libqalculate/MathStructure-integrate.cc +libqalculate/MathStructure-isolatex.cc +libqalculate/MathStructure-limit.cc +libqalculate/MathStructure-matrixvector.cc +libqalculate/MathStructure-polynomial.cc +libqalculate/MathStructure-print.cc libqalculate/Function.cc libqalculate/Number.cc libqalculate/Prefix.cc diff -Nru libqalculate-3.6.0/po/sv.po libqalculate-3.7.0/po/sv.po --- libqalculate-3.6.0/po/sv.po 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/po/sv.po 2020-01-21 22:54:40.000000000 +0000 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: sv\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-25 10:28+0100\n" +"POT-Creation-Date: 2020-01-12 11:24+0100\n" "PO-Revision-Date: 2006-05-04 12:29+0200\n" "Last-Translator: Hanna Knutsson \n" "Language-Team: Swedish\n" @@ -16,11 +16,11 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../src/defs2doc.cc:301 ../src/qalc.cc:3298 ../libqalculate/Function.cc:207 +#: ../src/defs2doc.cc:301 ../src/qalc.cc:3299 ../libqalculate/Function.cc:222 msgid "argument" msgstr "parameter" -#: ../src/defs2doc.cc:324 ../src/qalc.cc:3321 +#: ../src/defs2doc.cc:324 ../src/qalc.cc:3322 #, c-format msgid "" "Retrieves data from the %s data set for a given object and property. If " @@ -29,37 +29,37 @@ "Hämtar data från dataset %s för ett givet objekt och egenskap. Om \"info\" " "är angivet som egenskap, kommer alla objektets egenskaper att listas." -#: ../src/defs2doc.cc:331 ../src/qalc.cc:3330 +#: ../src/defs2doc.cc:331 ../src/qalc.cc:3331 msgid "Example:" msgstr "Exempel:" -#: ../src/defs2doc.cc:339 ../src/qalc.cc:3339 +#: ../src/defs2doc.cc:339 ../src/qalc.cc:3340 msgid "Arguments" msgstr "Parametrar" #. optional argument, in description -#: ../src/defs2doc.cc:356 ../src/qalc.cc:3356 +#: ../src/defs2doc.cc:356 ../src/qalc.cc:3357 msgid "optional" msgstr "frivillig" #. argument default, in description -#: ../src/defs2doc.cc:359 ../src/qalc.cc:3360 +#: ../src/defs2doc.cc:359 ../src/qalc.cc:3361 msgid "default: " msgstr "förval: " -#: ../src/defs2doc.cc:372 ../src/qalc.cc:3371 +#: ../src/defs2doc.cc:372 ../src/qalc.cc:3372 msgid "Requirement" msgstr "Krav" -#: ../src/defs2doc.cc:381 ../src/qalc.cc:3379 +#: ../src/defs2doc.cc:381 ../src/qalc.cc:3380 msgid "Properties" msgstr "Egenskaper" -#: ../src/defs2doc.cc:397 ../src/qalc.cc:3394 +#: ../src/defs2doc.cc:397 ../src/qalc.cc:3395 msgid "key" msgstr "nyckel" -#: ../src/defs2doc.cc:431 ../src/qalc.cc:3509 +#: ../src/defs2doc.cc:431 ../src/qalc.cc:3510 msgid "a previous result" msgstr "ett föregående resultat" @@ -67,91 +67,91 @@ msgid "current precision" msgstr "nuvarande precision" -#: ../src/defs2doc.cc:438 ../src/defs2doc.cc:539 ../src/qalc.cc:1456 +#: ../src/defs2doc.cc:438 ../src/defs2doc.cc:539 ../src/qalc.cc:1457 msgid "relative uncertainty" msgstr "relativt fel" -#: ../src/defs2doc.cc:453 ../src/qalc.cc:1478 ../src/qalc.cc:3515 -#: ../libqalculate/Function.cc:2110 +#: ../src/defs2doc.cc:453 ../src/qalc.cc:1479 ../src/qalc.cc:3516 +#: ../libqalculate/Function.cc:2144 msgid "matrix" msgstr "matris" -#: ../src/defs2doc.cc:455 ../src/qalc.cc:1480 ../src/qalc.cc:3517 -#: ../libqalculate/Function.cc:2049 +#: ../src/defs2doc.cc:455 ../src/qalc.cc:1481 ../src/qalc.cc:3518 +#: ../libqalculate/Function.cc:2083 msgid "vector" msgstr "vektor" -#: ../src/defs2doc.cc:463 ../src/qalc.cc:249 ../src/qalc.cc:691 -#: ../src/qalc.cc:1497 ../src/qalc.cc:2907 ../src/qalc.cc:3527 -#: ../src/qalc.cc:3646 ../src/qalc.cc:3876 +#: ../src/defs2doc.cc:463 ../src/qalc.cc:250 ../src/qalc.cc:692 +#: ../src/qalc.cc:1498 ../src/qalc.cc:2908 ../src/qalc.cc:3528 +#: ../src/qalc.cc:3647 ../src/qalc.cc:3877 msgid "positive" msgstr "positiv" -#: ../src/defs2doc.cc:464 ../src/qalc.cc:255 ../src/qalc.cc:692 -#: ../src/qalc.cc:1498 ../src/qalc.cc:2908 ../src/qalc.cc:3528 -#: ../src/qalc.cc:3650 ../src/qalc.cc:3880 +#: ../src/defs2doc.cc:464 ../src/qalc.cc:256 ../src/qalc.cc:693 +#: ../src/qalc.cc:1499 ../src/qalc.cc:2909 ../src/qalc.cc:3529 +#: ../src/qalc.cc:3651 ../src/qalc.cc:3881 msgid "non-positive" msgstr "ej positiv" -#: ../src/defs2doc.cc:465 ../src/qalc.cc:253 ../src/qalc.cc:693 -#: ../src/qalc.cc:1499 ../src/qalc.cc:2909 ../src/qalc.cc:3529 -#: ../src/qalc.cc:3648 ../src/qalc.cc:3878 +#: ../src/defs2doc.cc:465 ../src/qalc.cc:254 ../src/qalc.cc:694 +#: ../src/qalc.cc:1500 ../src/qalc.cc:2910 ../src/qalc.cc:3530 +#: ../src/qalc.cc:3649 ../src/qalc.cc:3879 msgid "negative" msgstr "negativ" -#: ../src/defs2doc.cc:466 ../src/qalc.cc:251 ../src/qalc.cc:694 -#: ../src/qalc.cc:1500 ../src/qalc.cc:2910 ../src/qalc.cc:3530 -#: ../src/qalc.cc:3652 ../src/qalc.cc:3882 +#: ../src/defs2doc.cc:466 ../src/qalc.cc:252 ../src/qalc.cc:695 +#: ../src/qalc.cc:1501 ../src/qalc.cc:2911 ../src/qalc.cc:3531 +#: ../src/qalc.cc:3653 ../src/qalc.cc:3883 msgid "non-negative" msgstr "ej negativ" -#: ../src/defs2doc.cc:467 ../src/qalc.cc:247 ../src/qalc.cc:695 -#: ../src/qalc.cc:1501 ../src/qalc.cc:2911 ../src/qalc.cc:3531 -#: ../src/qalc.cc:3644 ../src/qalc.cc:3874 +#: ../src/defs2doc.cc:467 ../src/qalc.cc:248 ../src/qalc.cc:696 +#: ../src/qalc.cc:1502 ../src/qalc.cc:2912 ../src/qalc.cc:3532 +#: ../src/qalc.cc:3645 ../src/qalc.cc:3875 msgid "non-zero" msgstr "ej noll" -#: ../src/defs2doc.cc:472 ../src/qalc.cc:245 ../src/qalc.cc:700 -#: ../src/qalc.cc:1506 ../src/qalc.cc:2916 ../src/qalc.cc:3536 -#: ../src/qalc.cc:3660 ../src/qalc.cc:3890 ../libqalculate/Function.cc:1905 +#: ../src/defs2doc.cc:472 ../src/qalc.cc:246 ../src/qalc.cc:701 +#: ../src/qalc.cc:1507 ../src/qalc.cc:2917 ../src/qalc.cc:3537 +#: ../src/qalc.cc:3661 ../src/qalc.cc:3891 ../libqalculate/Function.cc:1939 msgid "integer" msgstr "heltal" -#: ../src/defs2doc.cc:473 ../src/qalc.cc:243 ../src/qalc.cc:701 -#: ../src/qalc.cc:1507 ../src/qalc.cc:2917 ../src/qalc.cc:3537 -#: ../src/qalc.cc:3658 ../src/qalc.cc:3888 +#: ../src/defs2doc.cc:473 ../src/qalc.cc:244 ../src/qalc.cc:702 +#: ../src/qalc.cc:1508 ../src/qalc.cc:2918 ../src/qalc.cc:3538 +#: ../src/qalc.cc:3659 ../src/qalc.cc:3889 msgid "rational" msgstr "rationell" -#: ../src/defs2doc.cc:474 ../src/qalc.cc:239 ../src/qalc.cc:702 -#: ../src/qalc.cc:1508 ../src/qalc.cc:2918 ../src/qalc.cc:3538 -#: ../src/qalc.cc:3656 ../src/qalc.cc:3886 +#: ../src/defs2doc.cc:474 ../src/qalc.cc:240 ../src/qalc.cc:703 +#: ../src/qalc.cc:1509 ../src/qalc.cc:2919 ../src/qalc.cc:3539 +#: ../src/qalc.cc:3657 ../src/qalc.cc:3887 msgid "real" msgstr "reell" -#: ../src/defs2doc.cc:475 ../src/qalc.cc:703 ../src/qalc.cc:1509 -#: ../src/qalc.cc:2919 ../src/qalc.cc:3539 +#: ../src/defs2doc.cc:475 ../src/qalc.cc:704 ../src/qalc.cc:1510 +#: ../src/qalc.cc:2920 ../src/qalc.cc:3540 msgid "complex" msgstr "komplex" -#: ../src/defs2doc.cc:476 ../src/qalc.cc:241 ../src/qalc.cc:704 -#: ../src/qalc.cc:1510 ../src/qalc.cc:2920 ../src/qalc.cc:3540 -#: ../src/qalc.cc:3654 ../src/qalc.cc:3884 ../libqalculate/Function.cc:1744 +#: ../src/defs2doc.cc:476 ../src/qalc.cc:242 ../src/qalc.cc:705 +#: ../src/qalc.cc:1511 ../src/qalc.cc:2921 ../src/qalc.cc:3541 +#: ../src/qalc.cc:3655 ../src/qalc.cc:3885 ../libqalculate/Function.cc:1778 msgid "number" msgstr "nummer" -#: ../src/defs2doc.cc:477 ../src/qalc.cc:705 ../src/qalc.cc:1511 -#: ../src/qalc.cc:2921 ../src/qalc.cc:3541 +#: ../src/defs2doc.cc:477 ../src/qalc.cc:706 ../src/qalc.cc:1512 +#: ../src/qalc.cc:2922 ../src/qalc.cc:3542 msgid "non-matrix" msgstr "ej matris" -#: ../src/defs2doc.cc:480 ../src/qalc.cc:233 ../src/qalc.cc:708 -#: ../src/qalc.cc:1514 ../src/qalc.cc:2924 ../src/qalc.cc:3544 -#: ../src/qalc.cc:3642 ../src/qalc.cc:3872 +#: ../src/defs2doc.cc:480 ../src/qalc.cc:234 ../src/qalc.cc:709 +#: ../src/qalc.cc:1515 ../src/qalc.cc:2925 ../src/qalc.cc:3545 +#: ../src/qalc.cc:3643 ../src/qalc.cc:3873 msgid "unknown" msgstr "okänd" -#: ../src/defs2doc.cc:482 ../src/qalc.cc:1516 ../src/qalc.cc:3546 +#: ../src/defs2doc.cc:482 ../src/qalc.cc:1517 ../src/qalc.cc:3547 msgid "default assumptions" msgstr "förvalda antaganden" @@ -160,47 +160,48 @@ msgstr "variabel precision" #. qalc command -#: ../src/defs2doc.cc:492 ../src/defs2doc.cc:546 ../src/qalc.cc:900 -#: ../src/qalc.cc:1472 ../src/qalc.cc:1489 ../src/qalc.cc:2559 -#: ../src/qalc.cc:2941 ../src/qalc.cc:3184 ../src/qalc.cc:3458 -#: ../src/qalc.cc:3468 ../src/qalc.cc:3572 ../src/qalc.cc:3668 -#: ../src/qalc.cc:4002 +#: ../src/defs2doc.cc:492 ../src/defs2doc.cc:546 ../src/qalc.cc:901 +#: ../src/qalc.cc:1473 ../src/qalc.cc:1490 ../src/qalc.cc:2560 +#: ../src/qalc.cc:2942 ../src/qalc.cc:3185 ../src/qalc.cc:3459 +#: ../src/qalc.cc:3469 ../src/qalc.cc:3573 ../src/qalc.cc:3669 +#: ../src/qalc.cc:4003 msgid "approximate" msgstr "approximerat" -#: ../src/defs2doc.cc:583 ../src/qalc.cc:1892 +#: ../src/defs2doc.cc:583 ../src/qalc.cc:1893 msgid "ans" msgstr "ans" #: ../src/defs2doc.cc:584 ../src/defs2doc.cc:587 ../src/defs2doc.cc:588 -#: ../src/defs2doc.cc:589 ../src/defs2doc.cc:590 ../src/qalc.cc:1893 -#: ../src/qalc.cc:1896 ../src/qalc.cc:1897 ../src/qalc.cc:1898 -#: ../src/qalc.cc:1899 ../src/qalc.cc:2153 ../libqalculate/Calculator.cc:10674 -#: ../libqalculate/Calculator.cc:10690 +#: ../src/defs2doc.cc:589 ../src/defs2doc.cc:590 ../src/qalc.cc:1894 +#: ../src/qalc.cc:1897 ../src/qalc.cc:1898 ../src/qalc.cc:1899 +#: ../src/qalc.cc:1900 ../src/qalc.cc:2154 +#: ../libqalculate/Calculator-definitions.cc:2225 +#: ../libqalculate/Calculator-definitions.cc:2241 msgid "Temporary" msgstr "Temporära" -#: ../src/defs2doc.cc:584 ../src/qalc.cc:1893 +#: ../src/defs2doc.cc:584 ../src/qalc.cc:1894 msgid "Last Answer" msgstr "Senaste svaret" -#: ../src/defs2doc.cc:585 ../src/qalc.cc:1894 +#: ../src/defs2doc.cc:585 ../src/qalc.cc:1895 msgid "answer" msgstr "svar" -#: ../src/defs2doc.cc:587 ../src/qalc.cc:1896 +#: ../src/defs2doc.cc:587 ../src/qalc.cc:1897 msgid "Answer 2" msgstr "Svar 2" -#: ../src/defs2doc.cc:588 ../src/qalc.cc:1897 +#: ../src/defs2doc.cc:588 ../src/qalc.cc:1898 msgid "Answer 3" msgstr "Svar 3" -#: ../src/defs2doc.cc:589 ../src/qalc.cc:1898 +#: ../src/defs2doc.cc:589 ../src/qalc.cc:1899 msgid "Answer 4" msgstr "Svar 4" -#: ../src/defs2doc.cc:590 ../src/qalc.cc:1899 +#: ../src/defs2doc.cc:590 ../src/qalc.cc:1900 msgid "Answer 5" msgstr "Svar 5" @@ -215,68 +216,68 @@ msgid "Uncategorized" msgstr "Okategoriserade" -#: ../src/qalc.cc:152 ../src/qalc.cc:219 ../src/qalc.cc:3621 +#: ../src/qalc.cc:153 ../src/qalc.cc:220 ../src/qalc.cc:3622 #: ../libqalculate/util.cc:175 msgid "yes" msgstr "ja" -#: ../src/qalc.cc:153 ../src/qalc.cc:221 ../src/qalc.cc:3621 +#: ../src/qalc.cc:154 ../src/qalc.cc:222 ../src/qalc.cc:3622 #: ../libqalculate/util.cc:176 msgid "no" msgstr "nej" -#: ../src/qalc.cc:154 ../libqalculate/util.cc:183 +#: ../src/qalc.cc:155 ../libqalculate/util.cc:183 msgid "true" msgstr "sant" -#: ../src/qalc.cc:155 ../libqalculate/util.cc:184 +#: ../src/qalc.cc:156 ../libqalculate/util.cc:184 msgid "false" msgstr "falskt" -#: ../src/qalc.cc:156 ../src/qalc.cc:777 ../src/qalc.cc:797 ../src/qalc.cc:1112 -#: ../src/qalc.cc:1149 ../src/qalc.cc:3028 ../src/qalc.cc:3041 -#: ../src/qalc.cc:3099 ../src/qalc.cc:3620 ../src/qalc.cc:3735 -#: ../src/qalc.cc:3742 ../src/qalc.cc:3793 ../libqalculate/util.cc:191 +#: ../src/qalc.cc:157 ../src/qalc.cc:778 ../src/qalc.cc:798 ../src/qalc.cc:1113 +#: ../src/qalc.cc:1150 ../src/qalc.cc:3029 ../src/qalc.cc:3042 +#: ../src/qalc.cc:3100 ../src/qalc.cc:3621 ../src/qalc.cc:3736 +#: ../src/qalc.cc:3743 ../src/qalc.cc:3794 ../libqalculate/util.cc:191 msgid "on" msgstr "på" -#: ../src/qalc.cc:157 ../src/qalc.cc:775 ../src/qalc.cc:796 ../src/qalc.cc:1021 -#: ../src/qalc.cc:1085 ../src/qalc.cc:1097 ../src/qalc.cc:1110 -#: ../src/qalc.cc:1147 ../src/qalc.cc:3027 ../src/qalc.cc:3032 -#: ../src/qalc.cc:3039 ../src/qalc.cc:3068 ../src/qalc.cc:3075 -#: ../src/qalc.cc:3082 ../src/qalc.cc:3098 ../src/qalc.cc:3132 -#: ../src/qalc.cc:3620 ../src/qalc.cc:3733 ../src/qalc.cc:3739 -#: ../src/qalc.cc:3742 ../src/qalc.cc:3750 ../src/qalc.cc:3757 -#: ../src/qalc.cc:3767 ../src/qalc.cc:3791 ../src/qalc.cc:3826 +#: ../src/qalc.cc:158 ../src/qalc.cc:776 ../src/qalc.cc:797 ../src/qalc.cc:1022 +#: ../src/qalc.cc:1086 ../src/qalc.cc:1098 ../src/qalc.cc:1111 +#: ../src/qalc.cc:1148 ../src/qalc.cc:3028 ../src/qalc.cc:3033 +#: ../src/qalc.cc:3040 ../src/qalc.cc:3069 ../src/qalc.cc:3076 +#: ../src/qalc.cc:3083 ../src/qalc.cc:3099 ../src/qalc.cc:3133 +#: ../src/qalc.cc:3621 ../src/qalc.cc:3734 ../src/qalc.cc:3740 +#: ../src/qalc.cc:3743 ../src/qalc.cc:3751 ../src/qalc.cc:3758 +#: ../src/qalc.cc:3768 ../src/qalc.cc:3792 ../src/qalc.cc:3827 #: ../libqalculate/util.cc:192 msgid "off" msgstr "av" -#: ../src/qalc.cc:226 +#: ../src/qalc.cc:227 msgid "Please answer yes or no" msgstr "Vänligen svara ja eller nej" -#: ../src/qalc.cc:258 +#: ../src/qalc.cc:259 msgid "Unrecognized assumption." msgstr "Okänt antagande." -#: ../src/qalc.cc:425 ../src/qalc.cc:458 ../libqalculate/Calculator.cc:467 -#: ../libqalculate/Calculator.cc:693 ../libqalculate/DataSet.cc:1072 -#: ../libqalculate/DataSet.cc:1134 ../libqalculate/MathStructure.cc:21595 -#: ../libqalculate/Function.cc:2269 ../libqalculate/Function.cc:2285 +#: ../src/qalc.cc:426 ../src/qalc.cc:459 ../libqalculate/Calculator.cc:245 +#: ../libqalculate/Calculator.cc:473 ../libqalculate/DataSet.cc:1073 +#: ../libqalculate/DataSet.cc:1135 ../libqalculate/MathStructure-print.cc:3190 +#: ../libqalculate/Function.cc:2304 ../libqalculate/Function.cc:2320 msgid "or" msgstr "eller" -#: ../src/qalc.cc:546 ../libqalculate/Calculator.cc:12220 +#: ../src/qalc.cc:547 ../libqalculate/Calculator-definitions.cc:3756 #, c-format msgid "It has been %s day(s) since the exchange rates last were updated." msgstr "Det var %s dag(ar) sedan växelkurserna senast updaterades." -#: ../src/qalc.cc:551 +#: ../src/qalc.cc:552 msgid "Do you wish to update the exchange rates now?" msgstr "Vill du uppdatera växelkurserna nu?" -#: ../src/qalc.cc:565 ../src/qalc.cc:566 +#: ../src/qalc.cc:566 ../src/qalc.cc:567 msgid "" "\n" "Press Enter to continue." @@ -284,654 +285,660 @@ "\n" "Tryck Enter för att fortsätta." -#: ../src/qalc.cc:581 ../src/qalc.cc:582 ../src/qalc.cc:583 ../src/qalc.cc:584 -#: ../src/qalc.cc:585 ../src/qalc.cc:586 ../src/qalc.cc:719 ../src/qalc.cc:814 -#: ../src/qalc.cc:817 ../src/qalc.cc:972 ../src/qalc.cc:991 ../src/qalc.cc:1003 -#: ../src/qalc.cc:1012 ../src/qalc.cc:2362 ../src/qalc.cc:2499 +#: ../src/qalc.cc:582 ../src/qalc.cc:583 ../src/qalc.cc:584 ../src/qalc.cc:585 +#: ../src/qalc.cc:586 ../src/qalc.cc:587 ../src/qalc.cc:720 ../src/qalc.cc:815 +#: ../src/qalc.cc:818 ../src/qalc.cc:973 ../src/qalc.cc:992 ../src/qalc.cc:1004 +#: ../src/qalc.cc:1013 ../src/qalc.cc:2363 ../src/qalc.cc:2500 msgid "Illegal value" msgstr "Otillåtet värde" #. qalc command -#: ../src/qalc.cc:614 ../src/qalc.cc:934 ../src/qalc.cc:2340 -#: ../src/qalc.cc:2803 ../src/qalc.cc:2809 ../src/qalc.cc:2994 -#: ../src/qalc.cc:3150 ../src/qalc.cc:3186 ../src/qalc.cc:3702 -#: ../src/qalc.cc:3839 ../src/qalc.cc:3994 ../src/qalc.cc:4922 -#: ../src/qalc.cc:4933 ../libqalculate/Calculator.cc:3051 -#: ../libqalculate/Calculator.cc:3055 +#: ../src/qalc.cc:615 ../src/qalc.cc:935 ../src/qalc.cc:2341 +#: ../src/qalc.cc:2804 ../src/qalc.cc:2810 ../src/qalc.cc:2995 +#: ../src/qalc.cc:3151 ../src/qalc.cc:3187 ../src/qalc.cc:3703 +#: ../src/qalc.cc:3840 ../src/qalc.cc:3995 ../src/qalc.cc:4923 +#: ../src/qalc.cc:4934 ../libqalculate/Calculator-calculate.cc:837 +#: ../libqalculate/Calculator-calculate.cc:841 msgid "base" msgstr "bas" -#: ../src/qalc.cc:614 ../src/qalc.cc:616 ../src/qalc.cc:3108 -#: ../src/qalc.cc:3804 +#: ../src/qalc.cc:615 ../src/qalc.cc:617 ../src/qalc.cc:3109 +#: ../src/qalc.cc:3805 msgid "input base" msgstr "indatabas" -#: ../src/qalc.cc:614 ../src/qalc.cc:617 +#: ../src/qalc.cc:615 ../src/qalc.cc:618 msgid "output base" msgstr "utdatabas" -#: ../src/qalc.cc:618 ../src/qalc.cc:2606 ../src/qalc.cc:2996 -#: ../src/qalc.cc:3110 ../src/qalc.cc:3714 ../src/qalc.cc:3812 -#: ../src/qalc.cc:4756 ../libqalculate/Calculator.cc:2969 +#: ../src/qalc.cc:619 ../src/qalc.cc:2607 ../src/qalc.cc:2997 +#: ../src/qalc.cc:3111 ../src/qalc.cc:3715 ../src/qalc.cc:3813 +#: ../src/qalc.cc:4757 ../libqalculate/Calculator-calculate.cc:755 msgid "roman" msgstr "romersk" -#: ../src/qalc.cc:619 ../src/qalc.cc:2611 ../src/qalc.cc:2997 -#: ../src/qalc.cc:3111 ../src/qalc.cc:4764 ../libqalculate/Calculator.cc:2972 +#: ../src/qalc.cc:620 ../src/qalc.cc:2612 ../src/qalc.cc:2998 +#: ../src/qalc.cc:3112 ../src/qalc.cc:4765 +#: ../libqalculate/Calculator-calculate.cc:758 msgid "bijective" msgstr "bijektiv" -#: ../src/qalc.cc:620 ../src/qalc.cc:2621 ../src/qalc.cc:2999 -#: ../src/qalc.cc:3712 ../src/qalc.cc:4780 ../libqalculate/Calculator.cc:2978 +#: ../src/qalc.cc:621 ../src/qalc.cc:2622 ../src/qalc.cc:3000 +#: ../src/qalc.cc:3713 ../src/qalc.cc:4781 +#: ../libqalculate/Calculator-calculate.cc:764 msgid "time" msgstr "tid" -#: ../src/qalc.cc:621 ../src/qalc.cc:2581 ../src/qalc.cc:4716 -#: ../libqalculate/Calculator.cc:2954 +#: ../src/qalc.cc:622 ../src/qalc.cc:2582 ../src/qalc.cc:4717 +#: ../libqalculate/Calculator-calculate.cc:740 msgid "hexadecimal" msgstr "hexadecimal" -#: ../src/qalc.cc:628 ../src/qalc.cc:2601 ../src/qalc.cc:4748 -#: ../libqalculate/Calculator.cc:2966 +#: ../src/qalc.cc:629 ../src/qalc.cc:2602 ../src/qalc.cc:4749 +#: ../libqalculate/Calculator-calculate.cc:752 msgid "duodecimal" msgstr "duodecimal" -#: ../src/qalc.cc:629 ../src/qalc.cc:2586 ../src/qalc.cc:4724 -#: ../libqalculate/Calculator.cc:2957 +#: ../src/qalc.cc:630 ../src/qalc.cc:2587 ../src/qalc.cc:4725 +#: ../libqalculate/Calculator-calculate.cc:743 msgid "binary" msgstr "binär" -#: ../src/qalc.cc:630 ../src/qalc.cc:2596 ../src/qalc.cc:4740 -#: ../libqalculate/Calculator.cc:2963 +#: ../src/qalc.cc:631 ../src/qalc.cc:2597 ../src/qalc.cc:4741 +#: ../libqalculate/Calculator-calculate.cc:749 msgid "octal" msgstr "oktal" -#: ../src/qalc.cc:631 ../src/qalc.cc:2591 ../src/qalc.cc:4732 -#: ../libqalculate/Calculator.cc:2960 +#: ../src/qalc.cc:632 ../src/qalc.cc:2592 ../src/qalc.cc:4733 +#: ../libqalculate/Calculator-calculate.cc:746 msgid "decimal" msgstr "decimal" -#: ../src/qalc.cc:632 ../src/qalc.cc:2616 ../src/qalc.cc:2998 -#: ../src/qalc.cc:4772 ../libqalculate/Calculator.cc:2975 +#: ../src/qalc.cc:633 ../src/qalc.cc:2617 ../src/qalc.cc:2999 +#: ../src/qalc.cc:4773 ../libqalculate/Calculator-calculate.cc:761 msgid "sexagesimal" msgstr "sexagesimal" -#: ../src/qalc.cc:643 ../src/qalc.cc:757 ../src/qalc.cc:3010 -#: ../src/qalc.cc:3726 +#: ../src/qalc.cc:644 ../src/qalc.cc:758 ../src/qalc.cc:3011 +#: ../src/qalc.cc:3727 msgid "base display" msgstr "basvisning" -#: ../src/qalc.cc:673 +#: ../src/qalc.cc:674 msgid "Illegal base." msgstr "Otillåten bas." -#: ../src/qalc.cc:681 ../src/qalc.cc:709 ../src/qalc.cc:2925 -#: ../src/qalc.cc:3639 +#: ../src/qalc.cc:682 ../src/qalc.cc:710 ../src/qalc.cc:2926 +#: ../src/qalc.cc:3640 msgid "assumptions" msgstr "antaganden" -#: ../src/qalc.cc:712 ../src/qalc.cc:3141 ../src/qalc.cc:3831 +#: ../src/qalc.cc:713 ../src/qalc.cc:3142 ../src/qalc.cc:3832 msgid "all prefixes" msgstr "alla prefix" -#: ../src/qalc.cc:713 ../src/qalc.cc:2959 ../src/qalc.cc:3679 +#: ../src/qalc.cc:714 ../src/qalc.cc:2960 ../src/qalc.cc:3680 msgid "complex numbers" msgstr "komplexa tal" -#: ../src/qalc.cc:714 ../src/qalc.cc:2977 ../src/qalc.cc:3691 +#: ../src/qalc.cc:715 ../src/qalc.cc:2978 ../src/qalc.cc:3692 msgid "excessive parentheses" msgstr "överdrivna parenteser" -#: ../src/qalc.cc:715 ../src/qalc.cc:2960 ../src/qalc.cc:3240 -#: ../src/qalc.cc:3245 ../src/qalc.cc:3680 +#: ../src/qalc.cc:716 ../src/qalc.cc:2961 ../src/qalc.cc:3241 +#: ../src/qalc.cc:3246 ../src/qalc.cc:3681 msgid "functions" msgstr "funktioner" -#: ../src/qalc.cc:716 ../src/qalc.cc:2961 ../src/qalc.cc:3681 +#: ../src/qalc.cc:717 ../src/qalc.cc:2962 ../src/qalc.cc:3682 msgid "infinite numbers" msgstr "oändliga tal" -#: ../src/qalc.cc:717 ../src/qalc.cc:2986 ../src/qalc.cc:3694 +#: ../src/qalc.cc:718 ../src/qalc.cc:2987 ../src/qalc.cc:3695 msgid "show negative exponents" msgstr "visa negativa exponenter" -#: ../src/qalc.cc:718 ../src/qalc.cc:2978 ../src/qalc.cc:3692 +#: ../src/qalc.cc:719 ../src/qalc.cc:2979 ../src/qalc.cc:3693 msgid "minus last" msgstr "minus sist" -#: ../src/qalc.cc:720 ../src/qalc.cc:2903 ../src/qalc.cc:3636 +#: ../src/qalc.cc:721 ../src/qalc.cc:2904 ../src/qalc.cc:3637 msgid "assume nonzero denominators" msgstr "antag nämnare ej noll" -#: ../src/qalc.cc:721 ../src/qalc.cc:2904 ../src/qalc.cc:3637 +#: ../src/qalc.cc:722 ../src/qalc.cc:2905 ../src/qalc.cc:3638 msgid "warn nonzero denominators" msgstr "varna nämnare ej noll" -#: ../src/qalc.cc:722 ../src/qalc.cc:3158 ../src/qalc.cc:3851 +#: ../src/qalc.cc:723 ../src/qalc.cc:3159 ../src/qalc.cc:3852 msgid "prefixes" msgstr "prefix" -#: ../src/qalc.cc:723 ../src/qalc.cc:3154 ../src/qalc.cc:3847 +#: ../src/qalc.cc:724 ../src/qalc.cc:3155 ../src/qalc.cc:3848 msgid "binary prefixes" msgstr "binära prefix" -#: ../src/qalc.cc:730 ../src/qalc.cc:3156 ../src/qalc.cc:3849 +#: ../src/qalc.cc:731 ../src/qalc.cc:3157 ../src/qalc.cc:3850 msgid "denominator prefixes" msgstr "nämnarprefix" -#: ../src/qalc.cc:731 ../src/qalc.cc:3157 ../src/qalc.cc:3850 +#: ../src/qalc.cc:732 ../src/qalc.cc:3158 ../src/qalc.cc:3851 msgid "place units separately" msgstr "placera enheter separat" -#: ../src/qalc.cc:732 ../src/qalc.cc:2958 ../src/qalc.cc:3678 +#: ../src/qalc.cc:733 ../src/qalc.cc:2959 ../src/qalc.cc:3679 msgid "calculate variables" msgstr "beräkna variabler" -#: ../src/qalc.cc:733 ../src/qalc.cc:2957 ../src/qalc.cc:3677 +#: ../src/qalc.cc:734 ../src/qalc.cc:2958 ../src/qalc.cc:3678 msgid "calculate functions" msgstr "beräkna funktioner" -#: ../src/qalc.cc:734 ../src/qalc.cc:3159 ../src/qalc.cc:3852 +#: ../src/qalc.cc:735 ../src/qalc.cc:3160 ../src/qalc.cc:3853 msgid "sync units" msgstr "synkronisera enheter" -#: ../src/qalc.cc:735 ../src/qalc.cc:3079 ../src/qalc.cc:3763 +#: ../src/qalc.cc:736 ../src/qalc.cc:3080 ../src/qalc.cc:3764 msgid "round to even" msgstr "avrunda till jämnt" -#: ../src/qalc.cc:736 ../src/qalc.cc:3137 ../src/qalc.cc:3827 +#: ../src/qalc.cc:737 ../src/qalc.cc:3138 ../src/qalc.cc:3828 msgid "rpn syntax" msgstr "rpnsyntax" #. qalc command -#: ../src/qalc.cc:737 ../src/qalc.cc:2343 ../src/qalc.cc:3171 -#: ../src/qalc.cc:3208 ../src/qalc.cc:3864 ../src/qalc.cc:3944 +#: ../src/qalc.cc:738 ../src/qalc.cc:2344 ../src/qalc.cc:3172 +#: ../src/qalc.cc:3209 ../src/qalc.cc:3865 ../src/qalc.cc:3945 msgid "rpn" msgstr "rpn" -#: ../src/qalc.cc:738 ../src/qalc.cc:2987 ../src/qalc.cc:3695 +#: ../src/qalc.cc:739 ../src/qalc.cc:2988 ../src/qalc.cc:3696 msgid "short multiplication" msgstr "kort multiplikation" -#: ../src/qalc.cc:739 ../src/qalc.cc:3062 ../src/qalc.cc:3746 +#: ../src/qalc.cc:740 ../src/qalc.cc:3063 ../src/qalc.cc:3747 msgid "lowercase e" msgstr "litet e" -#: ../src/qalc.cc:740 ../src/qalc.cc:3063 ../src/qalc.cc:3747 +#: ../src/qalc.cc:741 ../src/qalc.cc:3064 ../src/qalc.cc:3748 msgid "lowercase numbers" msgstr "små nummer" -#: ../src/qalc.cc:741 ../src/qalc.cc:3046 ../src/qalc.cc:3107 -#: ../src/qalc.cc:3744 ../src/qalc.cc:3803 +#: ../src/qalc.cc:742 ../src/qalc.cc:3047 ../src/qalc.cc:3108 +#: ../src/qalc.cc:3745 ../src/qalc.cc:3804 msgid "imaginary j" msgstr "imaginärt j" -#: ../src/qalc.cc:759 ../src/qalc.cc:776 ../src/qalc.cc:830 ../src/qalc.cc:930 -#: ../src/qalc.cc:956 ../src/qalc.cc:2898 ../src/qalc.cc:2934 -#: ../src/qalc.cc:2947 ../src/qalc.cc:3012 ../src/qalc.cc:3146 -#: ../src/qalc.cc:3667 ../src/qalc.cc:3726 ../src/qalc.cc:3835 +#: ../src/qalc.cc:760 ../src/qalc.cc:777 ../src/qalc.cc:831 ../src/qalc.cc:931 +#: ../src/qalc.cc:957 ../src/qalc.cc:2899 ../src/qalc.cc:2935 +#: ../src/qalc.cc:2948 ../src/qalc.cc:3013 ../src/qalc.cc:3147 +#: ../src/qalc.cc:3668 ../src/qalc.cc:3727 ../src/qalc.cc:3836 msgid "none" msgstr "ingen" -#: ../src/qalc.cc:760 ../src/qalc.cc:3013 ../src/qalc.cc:3726 +#: ../src/qalc.cc:761 ../src/qalc.cc:3014 ../src/qalc.cc:3727 msgid "normal" msgstr "normal" -#: ../src/qalc.cc:761 ../src/qalc.cc:3014 ../src/qalc.cc:3726 +#: ../src/qalc.cc:762 ../src/qalc.cc:3015 ../src/qalc.cc:3727 msgid "alternative" msgstr "alternativ" -#: ../src/qalc.cc:766 ../src/qalc.cc:783 ../src/qalc.cc:803 ../src/qalc.cc:835 -#: ../src/qalc.cc:852 ../src/qalc.cc:877 ../src/qalc.cc:891 ../src/qalc.cc:905 -#: ../src/qalc.cc:922 ../src/qalc.cc:947 ../src/qalc.cc:963 ../src/qalc.cc:1032 -#: ../src/qalc.cc:1038 ../src/qalc.cc:1062 ../src/qalc.cc:1119 -#: ../src/qalc.cc:1138 ../src/qalc.cc:1154 +#: ../src/qalc.cc:767 ../src/qalc.cc:784 ../src/qalc.cc:804 ../src/qalc.cc:836 +#: ../src/qalc.cc:853 ../src/qalc.cc:878 ../src/qalc.cc:892 ../src/qalc.cc:906 +#: ../src/qalc.cc:923 ../src/qalc.cc:948 ../src/qalc.cc:964 ../src/qalc.cc:1033 +#: ../src/qalc.cc:1039 ../src/qalc.cc:1063 ../src/qalc.cc:1120 +#: ../src/qalc.cc:1139 ../src/qalc.cc:1155 msgid "Illegal value." msgstr "Otillåtet värde." -#: ../src/qalc.cc:771 ../src/qalc.cc:3091 ../src/qalc.cc:3781 +#: ../src/qalc.cc:772 ../src/qalc.cc:3092 ../src/qalc.cc:3782 msgid "two's complement" msgstr "tvåkomplement" -#: ../src/qalc.cc:772 ../src/qalc.cc:3045 ../src/qalc.cc:3743 +#: ../src/qalc.cc:773 ../src/qalc.cc:3046 ../src/qalc.cc:3744 msgid "hexadecimal two's" msgstr "hexadecimal tvåkomplement" -#: ../src/qalc.cc:773 ../src/qalc.cc:3030 ../src/qalc.cc:3739 +#: ../src/qalc.cc:774 ../src/qalc.cc:3031 ../src/qalc.cc:3740 msgid "digit grouping" msgstr "siffergruppering" -#: ../src/qalc.cc:777 ../src/qalc.cc:3033 ../src/qalc.cc:3739 +#: ../src/qalc.cc:778 ../src/qalc.cc:3034 ../src/qalc.cc:3740 msgid "standard" msgstr "standard" -#: ../src/qalc.cc:778 ../src/qalc.cc:798 ../src/qalc.cc:3026 -#: ../src/qalc.cc:3034 ../src/qalc.cc:3097 ../src/qalc.cc:3731 -#: ../src/qalc.cc:3739 ../src/qalc.cc:3789 +#: ../src/qalc.cc:779 ../src/qalc.cc:799 ../src/qalc.cc:3027 +#: ../src/qalc.cc:3035 ../src/qalc.cc:3098 ../src/qalc.cc:3732 +#: ../src/qalc.cc:3740 ../src/qalc.cc:3790 msgid "locale" msgstr "locale" -#: ../src/qalc.cc:788 ../src/qalc.cc:2989 ../src/qalc.cc:3697 +#: ../src/qalc.cc:789 ../src/qalc.cc:2990 ../src/qalc.cc:3698 msgid "spell out logical" msgstr "skriv ut logiska" -#: ../src/qalc.cc:789 ../src/qalc.cc:3105 ../src/qalc.cc:3801 +#: ../src/qalc.cc:790 ../src/qalc.cc:3106 ../src/qalc.cc:3802 msgid "ignore dot" msgstr "ignorera punkt" -#: ../src/qalc.cc:790 ../src/qalc.cc:3102 ../src/qalc.cc:3798 +#: ../src/qalc.cc:791 ../src/qalc.cc:3103 ../src/qalc.cc:3799 msgid "ignore comma" msgstr "ignorera komma" -#: ../src/qalc.cc:794 ../src/qalc.cc:3025 ../src/qalc.cc:3096 -#: ../src/qalc.cc:3728 ../src/qalc.cc:3786 +#: ../src/qalc.cc:795 ../src/qalc.cc:3026 ../src/qalc.cc:3097 +#: ../src/qalc.cc:3729 ../src/qalc.cc:3787 msgid "decimal comma" msgstr "decimalkomma" -#: ../src/qalc.cc:813 ../src/qalc.cc:3122 ../src/qalc.cc:3824 +#: ../src/qalc.cc:814 ../src/qalc.cc:3123 ../src/qalc.cc:3825 msgid "limit implicit multiplication" msgstr "begränsa implicit multiplikation" -#: ../src/qalc.cc:815 ../src/qalc.cc:2988 ../src/qalc.cc:3696 +#: ../src/qalc.cc:816 ../src/qalc.cc:2989 ../src/qalc.cc:3697 msgid "spacious" msgstr "rymlig" -#: ../src/qalc.cc:816 ../src/qalc.cc:2990 ../src/qalc.cc:3698 +#: ../src/qalc.cc:817 ../src/qalc.cc:2991 ../src/qalc.cc:3699 msgid "unicode" msgstr "unicode" -#: ../src/qalc.cc:819 ../src/qalc.cc:2962 ../src/qalc.cc:3242 -#: ../src/qalc.cc:3247 ../src/qalc.cc:3682 +#: ../src/qalc.cc:820 ../src/qalc.cc:2963 ../src/qalc.cc:3243 +#: ../src/qalc.cc:3248 ../src/qalc.cc:3683 msgid "units" msgstr "enheter" -#: ../src/qalc.cc:820 ../src/qalc.cc:2963 ../src/qalc.cc:3683 +#: ../src/qalc.cc:821 ../src/qalc.cc:2964 ../src/qalc.cc:3684 msgid "unknowns" msgstr "okända" -#: ../src/qalc.cc:821 ../src/qalc.cc:2964 ../src/qalc.cc:3241 -#: ../src/qalc.cc:3246 ../src/qalc.cc:3684 +#: ../src/qalc.cc:822 ../src/qalc.cc:2965 ../src/qalc.cc:3242 +#: ../src/qalc.cc:3247 ../src/qalc.cc:3685 msgid "variables" msgstr "variabler" -#: ../src/qalc.cc:822 ../src/qalc.cc:2969 ../src/qalc.cc:3689 +#: ../src/qalc.cc:823 ../src/qalc.cc:2970 ../src/qalc.cc:3690 msgid "abbreviations" msgstr "förkortningar" -#: ../src/qalc.cc:823 ../src/qalc.cc:3090 ../src/qalc.cc:3780 +#: ../src/qalc.cc:824 ../src/qalc.cc:3091 ../src/qalc.cc:3781 msgid "show ending zeroes" msgstr "visa avslutande nollor" -#: ../src/qalc.cc:824 ../src/qalc.cc:3078 ../src/qalc.cc:3762 +#: ../src/qalc.cc:825 ../src/qalc.cc:3079 ../src/qalc.cc:3763 msgid "repeating decimals" msgstr "upprepande decimaler" -#: ../src/qalc.cc:825 ../src/qalc.cc:2929 ../src/qalc.cc:3667 +#: ../src/qalc.cc:826 ../src/qalc.cc:2930 ../src/qalc.cc:3668 msgid "angle unit" msgstr "vinkelenhet" -#: ../src/qalc.cc:827 ../src/qalc.cc:2931 ../src/qalc.cc:2932 +#: ../src/qalc.cc:828 ../src/qalc.cc:2932 ../src/qalc.cc:2933 msgid "rad" msgstr "rad" -#: ../src/qalc.cc:827 ../src/qalc.cc:3667 +#: ../src/qalc.cc:828 ../src/qalc.cc:3668 msgid "radians" msgstr "radianer" -#: ../src/qalc.cc:828 +#: ../src/qalc.cc:829 msgid "deg" msgstr "deg" -#: ../src/qalc.cc:828 ../src/qalc.cc:3667 +#: ../src/qalc.cc:829 ../src/qalc.cc:3668 msgid "degrees" msgstr "grader" -#: ../src/qalc.cc:829 ../src/qalc.cc:2933 +#: ../src/qalc.cc:830 ../src/qalc.cc:2934 msgid "gra" msgstr "gra" -#: ../src/qalc.cc:829 ../src/qalc.cc:3667 +#: ../src/qalc.cc:830 ../src/qalc.cc:3668 msgid "gradians" msgstr "gradienter" -#: ../src/qalc.cc:842 ../src/qalc.cc:3095 ../src/qalc.cc:3785 +#: ../src/qalc.cc:843 ../src/qalc.cc:3096 ../src/qalc.cc:3786 msgid "caret as xor" msgstr "insättningstecken för xor" -#: ../src/qalc.cc:843 ../src/qalc.cc:3123 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4057 +#: ../src/qalc.cc:844 ../src/qalc.cc:3124 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4058 msgid "parsing mode" msgstr "tolkningsläge" -#: ../src/qalc.cc:845 ../src/qalc.cc:1045 ../src/qalc.cc:3049 -#: ../src/qalc.cc:3125 ../src/qalc.cc:3745 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4065 +#: ../src/qalc.cc:846 ../src/qalc.cc:1046 ../src/qalc.cc:3050 +#: ../src/qalc.cc:3126 ../src/qalc.cc:3746 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4066 msgid "adaptive" msgstr "anpassad" -#: ../src/qalc.cc:846 ../src/qalc.cc:3126 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4062 +#: ../src/qalc.cc:847 ../src/qalc.cc:3127 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4063 msgid "implicit first" msgstr "implicit först" -#: ../src/qalc.cc:847 ../src/qalc.cc:3127 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4059 +#: ../src/qalc.cc:848 ../src/qalc.cc:3128 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4060 msgid "conventional" msgstr "konventionell" -#: ../src/qalc.cc:857 ../src/qalc.cc:1696 ../src/qalc.cc:3160 -#: ../src/qalc.cc:3853 +#: ../src/qalc.cc:858 ../src/qalc.cc:1697 ../src/qalc.cc:3161 +#: ../src/qalc.cc:3854 msgid "update exchange rates" msgstr "updatering av växelkurser" -#: ../src/qalc.cc:858 ../src/qalc.cc:3163 ../src/qalc.cc:3855 +#: ../src/qalc.cc:859 ../src/qalc.cc:3164 ../src/qalc.cc:3856 msgid "never" msgstr "aldrig" -#: ../src/qalc.cc:860 ../src/qalc.cc:3162 ../src/qalc.cc:3854 +#: ../src/qalc.cc:861 ../src/qalc.cc:3163 ../src/qalc.cc:3855 msgid "ask" msgstr "fråga" -#: ../src/qalc.cc:868 ../src/qalc.cc:2979 ../src/qalc.cc:3693 +#: ../src/qalc.cc:869 ../src/qalc.cc:2980 ../src/qalc.cc:3694 msgid "multiplication sign" msgstr "multiplikationstecken" -#: ../src/qalc.cc:882 ../src/qalc.cc:2970 ../src/qalc.cc:3690 +#: ../src/qalc.cc:883 ../src/qalc.cc:2971 ../src/qalc.cc:3691 msgid "division sign" msgstr "divisionstecken" -#: ../src/qalc.cc:896 ../src/qalc.cc:2937 ../src/qalc.cc:3668 +#: ../src/qalc.cc:897 ../src/qalc.cc:2938 ../src/qalc.cc:3669 msgid "approximation" msgstr "approximering" #. qalc command -#: ../src/qalc.cc:898 ../src/qalc.cc:969 ../src/qalc.cc:1111 -#: ../src/qalc.cc:2549 ../src/qalc.cc:2939 ../src/qalc.cc:3040 -#: ../src/qalc.cc:3188 ../src/qalc.cc:3668 ../src/qalc.cc:3742 -#: ../src/qalc.cc:3998 +#: ../src/qalc.cc:899 ../src/qalc.cc:970 ../src/qalc.cc:1112 +#: ../src/qalc.cc:2550 ../src/qalc.cc:2940 ../src/qalc.cc:3041 +#: ../src/qalc.cc:3189 ../src/qalc.cc:3669 ../src/qalc.cc:3743 +#: ../src/qalc.cc:3999 msgid "exact" msgstr "exakt" -#: ../src/qalc.cc:899 ../src/qalc.cc:2940 ../src/qalc.cc:3668 +#: ../src/qalc.cc:900 ../src/qalc.cc:2941 ../src/qalc.cc:3669 msgid "try exact" msgstr "försök exakt" -#: ../src/qalc.cc:914 ../src/qalc.cc:2945 ../src/qalc.cc:3670 +#: ../src/qalc.cc:915 ../src/qalc.cc:2946 ../src/qalc.cc:3671 msgid "interval calculation" msgstr "intervallberäkning" -#: ../src/qalc.cc:914 +#: ../src/qalc.cc:915 msgid "uncertainty propagation" msgstr "felfortplantning" -#: ../src/qalc.cc:916 ../src/qalc.cc:2948 ../src/qalc.cc:3670 +#: ../src/qalc.cc:917 ../src/qalc.cc:2949 ../src/qalc.cc:3671 msgid "variance formula" msgstr "variansformel" -#: ../src/qalc.cc:916 +#: ../src/qalc.cc:917 msgid "variance" msgstr "varians" -#: ../src/qalc.cc:917 ../src/qalc.cc:1069 ../src/qalc.cc:2944 -#: ../src/qalc.cc:2949 ../src/qalc.cc:3669 ../src/qalc.cc:3670 +#: ../src/qalc.cc:918 ../src/qalc.cc:1070 ../src/qalc.cc:2945 +#: ../src/qalc.cc:2950 ../src/qalc.cc:3670 ../src/qalc.cc:3671 msgid "interval arithmetic" msgstr "intervallaritmetik" -#: ../src/qalc.cc:927 ../src/qalc.cc:3142 ../src/qalc.cc:3832 +#: ../src/qalc.cc:928 ../src/qalc.cc:3143 ../src/qalc.cc:3833 msgid "autoconversion" msgstr "autoomvandling" -#: ../src/qalc.cc:931 ../src/qalc.cc:2797 +#: ../src/qalc.cc:932 ../src/qalc.cc:2798 msgid "best" msgstr "bästa" -#: ../src/qalc.cc:932 ../src/qalc.cc:3151 ../src/qalc.cc:3841 +#: ../src/qalc.cc:933 ../src/qalc.cc:3152 ../src/qalc.cc:3842 msgid "optimalsi" msgstr "optimalsi" -#: ../src/qalc.cc:933 ../src/qalc.cc:2797 ../src/qalc.cc:3149 -#: ../src/qalc.cc:3837 ../src/qalc.cc:4911 ../libqalculate/Calculator.cc:3047 +#: ../src/qalc.cc:934 ../src/qalc.cc:2798 ../src/qalc.cc:3150 +#: ../src/qalc.cc:3838 ../src/qalc.cc:4912 +#: ../libqalculate/Calculator-calculate.cc:833 msgid "optimal" msgstr "optimal" -#: ../src/qalc.cc:935 ../src/qalc.cc:1113 ../src/qalc.cc:3042 -#: ../src/qalc.cc:3145 ../src/qalc.cc:3742 ../src/qalc.cc:3843 -#: ../src/qalc.cc:4966 ../libqalculate/Calculator.cc:3076 +#: ../src/qalc.cc:936 ../src/qalc.cc:1114 ../src/qalc.cc:3043 +#: ../src/qalc.cc:3146 ../src/qalc.cc:3743 ../src/qalc.cc:3844 +#: ../src/qalc.cc:4967 ../libqalculate/Calculator-calculate.cc:862 msgid "mixed" msgstr "blandade" -#: ../src/qalc.cc:953 ../src/qalc.cc:3155 ../src/qalc.cc:3848 +#: ../src/qalc.cc:954 ../src/qalc.cc:3156 ../src/qalc.cc:3849 msgid "currency conversion" msgstr "valutaomvandling" -#: ../src/qalc.cc:954 ../src/qalc.cc:2896 ../src/qalc.cc:3635 +#: ../src/qalc.cc:955 ../src/qalc.cc:2897 ../src/qalc.cc:3636 msgid "algebra mode" msgstr "algebraiskt läge" #. qalc command -#: ../src/qalc.cc:957 ../src/qalc.cc:2884 ../src/qalc.cc:3612 +#: ../src/qalc.cc:958 ../src/qalc.cc:2885 ../src/qalc.cc:3613 msgid "simplify" msgstr "förenkla" -#: ../src/qalc.cc:957 ../src/qalc.cc:2884 ../src/qalc.cc:2900 -#: ../src/qalc.cc:3203 ../src/qalc.cc:3612 ../src/qalc.cc:3635 -#: ../src/qalc.cc:5015 ../libqalculate/Calculator.cc:3101 +#: ../src/qalc.cc:958 ../src/qalc.cc:2885 ../src/qalc.cc:2901 +#: ../src/qalc.cc:3204 ../src/qalc.cc:3613 ../src/qalc.cc:3636 +#: ../src/qalc.cc:5016 ../libqalculate/Calculator-calculate.cc:891 msgid "expand" msgstr "expandera" -#: ../src/qalc.cc:958 ../src/qalc.cc:2899 ../src/qalc.cc:3635 -#: ../src/qalc.cc:5012 ../libqalculate/Calculator.cc:3097 +#: ../src/qalc.cc:959 ../src/qalc.cc:2900 ../src/qalc.cc:3636 +#: ../src/qalc.cc:5013 ../libqalculate/Calculator-calculate.cc:887 msgid "factorize" msgstr "faktorisera" -#: ../src/qalc.cc:988 ../src/qalc.cc:3170 ../src/qalc.cc:3863 +#: ../src/qalc.cc:989 ../src/qalc.cc:3171 ../src/qalc.cc:3864 msgid "ignore locale" msgstr "" -#: ../src/qalc.cc:1000 ../src/qalc.cc:3173 ../src/qalc.cc:3201 -#: ../src/qalc.cc:3866 +#: ../src/qalc.cc:1001 ../src/qalc.cc:3174 ../src/qalc.cc:3202 +#: ../src/qalc.cc:3867 msgid "save mode" msgstr "spara läge" -#: ../src/qalc.cc:1009 ../src/qalc.cc:3172 ../src/qalc.cc:3200 -#: ../src/qalc.cc:3865 +#: ../src/qalc.cc:1010 ../src/qalc.cc:3173 ../src/qalc.cc:3201 +#: ../src/qalc.cc:3866 msgid "save definitions" msgstr "spara definitioner" -#: ../src/qalc.cc:1018 ../src/qalc.cc:3080 ../src/qalc.cc:3764 +#: ../src/qalc.cc:1019 ../src/qalc.cc:3081 ../src/qalc.cc:3765 msgid "scientific notation" msgstr "grundpotensform" -#: ../src/qalc.cc:1022 ../src/qalc.cc:3083 ../src/qalc.cc:3769 +#: ../src/qalc.cc:1023 ../src/qalc.cc:3084 ../src/qalc.cc:3770 msgid "auto" msgstr "auto" -#: ../src/qalc.cc:1023 ../src/qalc.cc:3084 ../src/qalc.cc:3773 +#: ../src/qalc.cc:1024 ../src/qalc.cc:3085 ../src/qalc.cc:3774 msgid "pure" msgstr "ren" -#: ../src/qalc.cc:1024 ../src/qalc.cc:3085 ../src/qalc.cc:3775 +#: ../src/qalc.cc:1025 ../src/qalc.cc:3086 ../src/qalc.cc:3776 msgid "scientific" msgstr "vetenskaplig" -#: ../src/qalc.cc:1025 ../src/qalc.cc:3086 ../src/qalc.cc:3771 +#: ../src/qalc.cc:1026 ../src/qalc.cc:3087 ../src/qalc.cc:3772 msgid "engineering" msgstr "teknisk" -#: ../src/qalc.cc:1034 ../src/qalc.cc:2953 ../src/qalc.cc:3671 +#: ../src/qalc.cc:1035 ../src/qalc.cc:2954 ../src/qalc.cc:3672 msgid "precision" msgstr "precision" -#: ../src/qalc.cc:1043 ../src/qalc.cc:3047 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1044 ../src/qalc.cc:3048 ../src/qalc.cc:3746 msgid "interval display" msgstr "intervallvisning" -#: ../src/qalc.cc:1046 ../src/qalc.cc:3052 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1047 ../src/qalc.cc:3053 ../src/qalc.cc:3746 msgid "significant" msgstr "signifikant" -#: ../src/qalc.cc:1047 ../src/qalc.cc:3053 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1048 ../src/qalc.cc:3054 ../src/qalc.cc:3746 msgid "interval" msgstr "intervall" -#: ../src/qalc.cc:1048 ../src/qalc.cc:3054 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1049 ../src/qalc.cc:3055 ../src/qalc.cc:3746 msgid "plusminus" msgstr "plusminus" -#: ../src/qalc.cc:1049 ../src/qalc.cc:3055 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1050 ../src/qalc.cc:3056 ../src/qalc.cc:3746 msgid "midpoint" msgstr "mittpunkt" -#: ../src/qalc.cc:1050 ../src/qalc.cc:3057 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1051 ../src/qalc.cc:3058 ../src/qalc.cc:3746 msgid "upper" msgstr "övre" -#: ../src/qalc.cc:1051 ../src/qalc.cc:3056 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1052 ../src/qalc.cc:3057 ../src/qalc.cc:3746 msgid "lower" msgstr "undre" -#: ../src/qalc.cc:1076 ../src/qalc.cc:2965 ../src/qalc.cc:3685 +#: ../src/qalc.cc:1077 ../src/qalc.cc:2966 ../src/qalc.cc:3686 msgid "variable units" msgstr "variabelenheter" -#: ../src/qalc.cc:1083 ../src/qalc.cc:3064 ../src/qalc.cc:3748 +#: ../src/qalc.cc:1084 ../src/qalc.cc:3065 ../src/qalc.cc:3749 msgid "max decimals" msgstr "max decimaler" -#: ../src/qalc.cc:1095 ../src/qalc.cc:3071 ../src/qalc.cc:3755 +#: ../src/qalc.cc:1096 ../src/qalc.cc:3072 ../src/qalc.cc:3756 msgid "min decimals" msgstr "min decimaler" -#: ../src/qalc.cc:1108 ../src/qalc.cc:3037 ../src/qalc.cc:3742 +#: ../src/qalc.cc:1109 ../src/qalc.cc:3038 ../src/qalc.cc:3743 msgid "fractions" msgstr "bråktal" -#: ../src/qalc.cc:1113 +#: ../src/qalc.cc:1114 msgid "combined" msgstr "kombinerad" -#: ../src/qalc.cc:1114 ../src/qalc.cc:3041 ../src/qalc.cc:3742 +#: ../src/qalc.cc:1115 ../src/qalc.cc:3042 ../src/qalc.cc:3743 msgid "long" msgstr "lång" -#: ../src/qalc.cc:1127 ../src/qalc.cc:3017 ../src/qalc.cc:3727 +#: ../src/qalc.cc:1128 ../src/qalc.cc:3018 ../src/qalc.cc:3728 msgid "complex form" msgstr "komplex form" -#: ../src/qalc.cc:1129 ../src/qalc.cc:2667 ../src/qalc.cc:3019 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4856 ../libqalculate/Calculator.cc:3015 +#: ../src/qalc.cc:1130 ../src/qalc.cc:2668 ../src/qalc.cc:3020 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4857 +#: ../libqalculate/Calculator-calculate.cc:801 msgid "rectangular" msgstr "rektangulär" -#: ../src/qalc.cc:1129 ../src/qalc.cc:2667 ../src/qalc.cc:4856 -#: ../libqalculate/Calculator.cc:3015 +#: ../src/qalc.cc:1130 ../src/qalc.cc:2668 ../src/qalc.cc:4857 +#: ../libqalculate/Calculator-calculate.cc:801 msgid "cartesian" msgstr "kertisik" -#: ../src/qalc.cc:1130 ../src/qalc.cc:2679 ../src/qalc.cc:3020 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4867 ../libqalculate/Calculator.cc:3018 +#: ../src/qalc.cc:1131 ../src/qalc.cc:2680 ../src/qalc.cc:3021 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4868 +#: ../libqalculate/Calculator-calculate.cc:804 msgid "exponential" msgstr "exponentiell" -#: ../src/qalc.cc:1131 ../src/qalc.cc:2691 ../src/qalc.cc:3021 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4878 ../libqalculate/Calculator.cc:3021 +#: ../src/qalc.cc:1132 ../src/qalc.cc:2692 ../src/qalc.cc:3022 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4879 +#: ../libqalculate/Calculator-calculate.cc:807 msgid "polar" msgstr "polär" -#: ../src/qalc.cc:1132 ../src/qalc.cc:2703 ../src/qalc.cc:3022 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4889 ../libqalculate/Calculator.cc:3024 -#: ../libqalculate/Function.cc:2211 +#: ../src/qalc.cc:1133 ../src/qalc.cc:2704 ../src/qalc.cc:3023 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4890 +#: ../libqalculate/Calculator-calculate.cc:810 ../libqalculate/Function.cc:2245 msgid "angle" msgstr "vinkel" -#: ../src/qalc.cc:1132 ../src/qalc.cc:2703 ../src/qalc.cc:4889 -#: ../libqalculate/Calculator.cc:3024 +#: ../src/qalc.cc:1133 ../src/qalc.cc:2704 ../src/qalc.cc:4890 +#: ../libqalculate/Calculator-calculate.cc:810 msgid "phasor" msgstr "fasvektor" -#: ../src/qalc.cc:1145 ../src/qalc.cc:3130 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1146 ../src/qalc.cc:3131 ../src/qalc.cc:3827 msgid "read precision" msgstr "läs precision" -#: ../src/qalc.cc:1148 ../src/qalc.cc:3133 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1149 ../src/qalc.cc:3134 ../src/qalc.cc:3827 msgid "always" msgstr "alltid" -#: ../src/qalc.cc:1149 ../src/qalc.cc:3134 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1150 ../src/qalc.cc:3135 ../src/qalc.cc:3827 msgid "when decimals" msgstr "när decimaler" -#: ../src/qalc.cc:1180 +#: ../src/qalc.cc:1181 msgid "Unrecognized option." msgstr "Okänd inställning." -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Calendar" msgstr "Kalender" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Day" msgstr "Dag" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Month" msgstr "Månad" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Year" msgstr "År" -#: ../src/qalc.cc:1315 ../libqalculate/Calculator.cc:3124 +#: ../src/qalc.cc:1316 ../libqalculate/Calculator-calculate.cc:934 msgid "failed" msgstr "misslyckades" -#: ../src/qalc.cc:1316 ../libqalculate/Calculator.cc:3125 +#: ../src/qalc.cc:1317 ../libqalculate/Calculator-calculate.cc:935 msgid "Gregorian:" msgstr "Gregoriansk:" -#: ../src/qalc.cc:1317 ../libqalculate/Calculator.cc:3126 +#: ../src/qalc.cc:1318 ../libqalculate/Calculator-calculate.cc:936 msgid "Hebrew:" msgstr "Hebreisk:" -#: ../src/qalc.cc:1318 ../libqalculate/Calculator.cc:3127 +#: ../src/qalc.cc:1319 ../libqalculate/Calculator-calculate.cc:937 msgid "Islamic:" msgstr "Muslimsk:" -#: ../src/qalc.cc:1319 ../libqalculate/Calculator.cc:3128 +#: ../src/qalc.cc:1320 ../libqalculate/Calculator-calculate.cc:938 msgid "Persian:" msgstr "Persisk:" -#: ../src/qalc.cc:1320 ../libqalculate/Calculator.cc:3129 +#: ../src/qalc.cc:1321 ../libqalculate/Calculator-calculate.cc:939 msgid "Indian national:" msgstr "Indisk (nationell):" -#: ../src/qalc.cc:1321 ../libqalculate/Calculator.cc:3130 +#: ../src/qalc.cc:1322 ../libqalculate/Calculator-calculate.cc:940 msgid "Chinese:" msgstr "Kinesisk:" -#: ../src/qalc.cc:1326 ../libqalculate/Calculator.cc:3134 +#: ../src/qalc.cc:1327 ../libqalculate/Calculator-calculate.cc:944 msgid "Julian:" msgstr "Juliansk:" -#: ../src/qalc.cc:1327 ../libqalculate/Calculator.cc:3135 +#: ../src/qalc.cc:1328 ../libqalculate/Calculator-calculate.cc:945 msgid "Revised julian:" msgstr "Reviderad juliansk:" -#: ../src/qalc.cc:1328 ../libqalculate/Calculator.cc:3136 +#: ../src/qalc.cc:1329 ../libqalculate/Calculator-calculate.cc:946 msgid "Coptic:" msgstr "Koptisk:" -#: ../src/qalc.cc:1329 ../libqalculate/Calculator.cc:3137 +#: ../src/qalc.cc:1330 ../libqalculate/Calculator-calculate.cc:947 msgid "Ethiopian:" msgstr "Etiopisk:" -#: ../src/qalc.cc:1396 ../libqalculate/BuiltinFunctions.cc:6237 -#: ../libqalculate/BuiltinFunctions.cc:6267 +#: ../src/qalc.cc:1397 ../libqalculate/BuiltinFunctions-matrixvector.cc:567 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:597 msgid "No matching item found." msgstr "Inga matchande poster funna." -#: ../src/qalc.cc:1427 ../src/qalc.cc:1428 ../src/qalc.cc:1558 -#: ../src/qalc.cc:1559 ../src/qalc.cc:1626 ../src/qalc.cc:1627 +#: ../src/qalc.cc:1428 ../src/qalc.cc:1429 ../src/qalc.cc:1559 +#: ../src/qalc.cc:1560 ../src/qalc.cc:1627 ../src/qalc.cc:1628 msgid "" "For more information about a specific function, variable or unit, please use " "the info command (in interactive mode)." @@ -939,64 +946,64 @@ "För mer information om en specifik funktion, variabel eller enhet, vänligen " "använd info-kommandot (i interaktivt läge)." -#: ../src/qalc.cc:1441 +#: ../src/qalc.cc:1442 msgid "Variables:" msgstr "Variabler:" -#: ../src/qalc.cc:1443 +#: ../src/qalc.cc:1444 msgid "Name" msgstr "Namn" -#: ../src/qalc.cc:1444 ../src/qalc.cc:3552 ../src/qalc.cc:3559 +#: ../src/qalc.cc:1445 ../src/qalc.cc:3553 ../src/qalc.cc:3560 msgid "Value" msgstr "Värde" -#: ../src/qalc.cc:1532 +#: ../src/qalc.cc:1533 msgid "Functions:" msgstr "Funktioner:" -#: ../src/qalc.cc:1546 +#: ../src/qalc.cc:1547 msgid "Units:" msgstr "Enheter:" -#: ../src/qalc.cc:1553 +#: ../src/qalc.cc:1554 msgid "No local variables, functions or units have been defined." msgstr "Inga lokala variabler, funktioner eller enheter har definierats." -#: ../src/qalc.cc:1689 +#: ../src/qalc.cc:1690 msgid "usage: qalc [options] [expression]" msgstr "användning: qalc [alternativ] [uttryck]" -#: ../src/qalc.cc:1691 +#: ../src/qalc.cc:1692 msgid "where options are:" msgstr "där alternativen är:" -#: ../src/qalc.cc:1692 ../src/qalc.cc:1724 ../src/qalc.cc:3186 +#: ../src/qalc.cc:1693 ../src/qalc.cc:1725 ../src/qalc.cc:3187 msgid "BASE" msgstr "BAS" -#: ../src/qalc.cc:1693 +#: ../src/qalc.cc:1694 msgid "set the number base for results and, optionally, expressions" msgstr "ange talbas för resultat och uttryck (valfritt)" -#: ../src/qalc.cc:1698 +#: ../src/qalc.cc:1699 msgid "FILE" msgstr "FIL" -#: ../src/qalc.cc:1699 +#: ../src/qalc.cc:1700 msgid "execute commands from a file first" msgstr "utför kommandon från en fil först" -#: ../src/qalc.cc:1701 +#: ../src/qalc.cc:1702 msgid "start in interactive mode" msgstr "starta i interaktivt läge" -#: ../src/qalc.cc:1702 ../src/qalc.cc:1704 ../src/qalc.cc:1706 -#: ../src/qalc.cc:1708 +#: ../src/qalc.cc:1703 ../src/qalc.cc:1705 ../src/qalc.cc:1707 +#: ../src/qalc.cc:1709 msgid "SEARCH TERM" msgstr "SÖKTERM" -#: ../src/qalc.cc:1703 +#: ../src/qalc.cc:1704 msgid "" "displays a list of all user-defined or matching variables, functions and " "units" @@ -1004,52 +1011,52 @@ "visar en lista över alla användardefinierade eller matchande variabler, " "funktioner och enheter" -#: ../src/qalc.cc:1705 +#: ../src/qalc.cc:1706 msgid "displays a list of all or matching functions" msgstr "visar en lista över alla eller matchande funktioner" -#: ../src/qalc.cc:1707 +#: ../src/qalc.cc:1708 msgid "displays a list of all or matching units" msgstr "visar en lista över alla eller matchande enheter" -#: ../src/qalc.cc:1709 +#: ../src/qalc.cc:1710 msgid "displays a list of all or matching variables" msgstr "visar en lista över alla eller matchande variabler" -#: ../src/qalc.cc:1710 +#: ../src/qalc.cc:1711 msgid "MILLISECONDS" msgstr "MILLISEKUNDER" -#: ../src/qalc.cc:1711 +#: ../src/qalc.cc:1712 msgid "" "terminate calculation and display of result after specified amount of time" msgstr "avbryt beräkning eller visning av resultat efter en specificerad tid" -#: ../src/qalc.cc:1713 +#: ../src/qalc.cc:1714 msgid "do not load any functions, units, or variables from file" msgstr "läs inte in några funktioner, enheter, eller variabler från datafiler" -#: ../src/qalc.cc:1715 +#: ../src/qalc.cc:1716 msgid "do not load any global currencies from file" msgstr "läs inte in några systemvida valutor" -#: ../src/qalc.cc:1717 +#: ../src/qalc.cc:1718 msgid "do not load any global data sets from file" msgstr "läs inte in några systemvida dataset" -#: ../src/qalc.cc:1719 +#: ../src/qalc.cc:1720 msgid "do not load any global functions from file" msgstr "läs inte in några systemvida funktioner" -#: ../src/qalc.cc:1721 +#: ../src/qalc.cc:1722 msgid "do not load any global units from file" msgstr "läs inte in några systemvida enheter" -#: ../src/qalc.cc:1723 +#: ../src/qalc.cc:1724 msgid "do not load any global variables from file" msgstr "läs inte in några systemvida variabler" -#: ../src/qalc.cc:1725 +#: ../src/qalc.cc:1726 msgid "" "start in programming mode (same as -b \"BASE BASE\" -s \"xor^\", with base " "conversion)" @@ -1057,33 +1064,33 @@ "starta i programmeringsläge (samma som -b \"BAS BAS\" -s \"xor^\", med " "basomvandling" -#: ../src/qalc.cc:1726 ../src/qalc.cc:3202 +#: ../src/qalc.cc:1727 ../src/qalc.cc:3203 msgid "OPTION" msgstr "INSTÄLLNING" -#: ../src/qalc.cc:1726 ../src/qalc.cc:3202 +#: ../src/qalc.cc:1727 ../src/qalc.cc:3203 msgid "VALUE" msgstr "VÄRDE" -#: ../src/qalc.cc:1727 +#: ../src/qalc.cc:1728 msgid "as set command in interactive program session (e.g. -set \"base 16\")" msgstr "" "fungerar som set (sätt) kommandot i en interaktiv programsession (t.ex. -set " "\"bas 16\")" -#: ../src/qalc.cc:1729 +#: ../src/qalc.cc:1730 msgid "reduce output to just the result of the input expression" msgstr "begränsa utdata till enbart resultatet av angett uttryck" -#: ../src/qalc.cc:1731 +#: ../src/qalc.cc:1732 msgid "switch unicode support on/off" msgstr "aktivera/avaktivera unicode-stöd" -#: ../src/qalc.cc:1733 +#: ../src/qalc.cc:1734 msgid "show application version and exit" msgstr "visa programversion och avsluta" -#: ../src/qalc.cc:1735 +#: ../src/qalc.cc:1736 msgid "" "The program will start in interactive mode if no expression and no file is " "specified (or interactive mode is explicitly selected)." @@ -1091,67 +1098,67 @@ "Programmet startar i interaktivt läge om inget uttryck och ingen fil har " "angetts (eller om interaktivt läge explicit har valts)." -#: ../src/qalc.cc:1835 +#: ../src/qalc.cc:1836 msgid "No option and value specified for set command." msgstr "Ingen inställning och värde angett för set (sätt) kommandot." -#: ../src/qalc.cc:1843 +#: ../src/qalc.cc:1844 msgid "No file specified." msgstr "Ingen fil specificerad." -#: ../src/qalc.cc:1910 +#: ../src/qalc.cc:1911 msgid "Failed to load global definitions!" msgstr "Kunde inte inhämta systemvida definitioner!" -#: ../src/qalc.cc:1956 +#: ../src/qalc.cc:1957 #, c-format msgid "Could not open \"%s\".\n" msgstr "Kunde inte öppna \"%s\".\n" -#: ../src/qalc.cc:1996 ../src/qalc.cc:2048 ../src/qalc.cc:4087 +#: ../src/qalc.cc:1997 ../src/qalc.cc:2049 ../src/qalc.cc:4088 #, c-format msgid "Illegal character, '%c', in expression." msgstr "Otillåtet tecken, '%c', i uttryck." #. The qalc command "set" as in "set precision 10". The original text string for commands is kept in addition to the translation. -#: ../src/qalc.cc:2115 ../src/qalc.cc:3202 ../src/qalc.cc:3616 +#: ../src/qalc.cc:2116 ../src/qalc.cc:3203 ../src/qalc.cc:3617 msgid "set" msgstr "ange" #. qalc command -#: ../src/qalc.cc:2119 ../src/qalc.cc:3199 ../src/qalc.cc:3895 +#: ../src/qalc.cc:2120 ../src/qalc.cc:3200 ../src/qalc.cc:3896 msgid "save" msgstr "spara" -#: ../src/qalc.cc:2119 ../src/qalc.cc:3199 ../src/qalc.cc:3895 +#: ../src/qalc.cc:2120 ../src/qalc.cc:3200 ../src/qalc.cc:3896 msgid "store" msgstr "lagra" #. qalc command -#: ../src/qalc.cc:2122 ../src/qalc.cc:2887 ../src/qalc.cc:3197 -#: ../src/qalc.cc:3921 +#: ../src/qalc.cc:2123 ../src/qalc.cc:2888 ../src/qalc.cc:3198 +#: ../src/qalc.cc:3922 msgid "mode" msgstr "läge" -#: ../src/qalc.cc:2124 +#: ../src/qalc.cc:2125 msgid "mode saved" msgstr "läge sparades" -#: ../src/qalc.cc:2126 +#: ../src/qalc.cc:2127 msgid "definitions" msgstr "definitioner" -#: ../src/qalc.cc:2128 +#: ../src/qalc.cc:2129 msgid "definitions saved" msgstr "definitioner sparades" -#: ../src/qalc.cc:2175 ../src/qalc.cc:2177 ../src/qalc.cc:2235 -#: ../src/qalc.cc:2237 ../src/qalc.cc:2292 ../src/qalc.cc:2294 +#: ../src/qalc.cc:2176 ../src/qalc.cc:2178 ../src/qalc.cc:2236 +#: ../src/qalc.cc:2238 ../src/qalc.cc:2293 ../src/qalc.cc:2295 #, c-format msgid "Illegal name. Save as %s instead (default: no)?" msgstr "Otillåtet namn. Vill du spara som %s i stället (förvalt: nej)?" -#: ../src/qalc.cc:2184 ../src/qalc.cc:2244 +#: ../src/qalc.cc:2185 ../src/qalc.cc:2245 msgid "" "An unit or variable with the same name already exists.\n" "Do you want to overwrite it (default: no)?" @@ -1160,18 +1167,18 @@ "Vill du ersätta den (förvalt: nej)?" #. qalc command -#: ../src/qalc.cc:2207 ../src/qalc.cc:3205 ../src/qalc.cc:3902 -#: ../libqalculate/Function.cc:2172 +#: ../src/qalc.cc:2208 ../src/qalc.cc:3206 ../src/qalc.cc:3903 +#: ../libqalculate/Function.cc:2206 msgid "variable" msgstr "variabel" #. qalc command -#: ../src/qalc.cc:2264 ../src/qalc.cc:3195 ../src/qalc.cc:3908 -#: ../libqalculate/Function.cc:2144 +#: ../src/qalc.cc:2265 ../src/qalc.cc:3196 ../src/qalc.cc:3909 +#: ../libqalculate/Function.cc:2178 msgid "function" msgstr "funktion" -#: ../src/qalc.cc:2301 +#: ../src/qalc.cc:2302 msgid "" "An function with the same name already exists.\n" "Do you want to overwrite it (default: no)?" @@ -1180,275 +1187,284 @@ "Vill du ersätta den (förvalt: nej)?" #. qalc command -#: ../src/qalc.cc:2321 ../src/qalc.cc:3187 ../src/qalc.cc:3915 +#: ../src/qalc.cc:2322 ../src/qalc.cc:3188 ../src/qalc.cc:3916 msgid "delete" msgstr "frigör" -#: ../src/qalc.cc:2332 +#: ../src/qalc.cc:2333 msgid "No user-defined variable or function with the specified name exist." msgstr "" "Ingen användardefinierad variabel eller funktion med det angivna namnet " "existerar." #. qalc command -#: ../src/qalc.cc:2336 ../src/qalc.cc:3185 ../src/qalc.cc:3868 +#: ../src/qalc.cc:2337 ../src/qalc.cc:3186 ../src/qalc.cc:3869 msgid "assume" msgstr "antag" -#: ../src/qalc.cc:2346 +#: ../src/qalc.cc:2347 msgid "syntax" msgstr "syntax" #. qalc command -#: ../src/qalc.cc:2353 ../src/qalc.cc:2388 ../src/qalc.cc:3209 -#: ../src/qalc.cc:3960 +#: ../src/qalc.cc:2354 ../src/qalc.cc:2389 ../src/qalc.cc:3210 +#: ../src/qalc.cc:3961 msgid "stack" msgstr "stack" #. qalc command -#: ../src/qalc.cc:2373 ../src/qalc.cc:3190 ../src/qalc.cc:3940 +#: ../src/qalc.cc:2374 ../src/qalc.cc:3191 ../src/qalc.cc:3941 msgid "exrates" msgstr "växelkurser" -#: ../src/qalc.cc:2390 ../src/qalc.cc:2408 ../src/qalc.cc:2417 -#: ../src/qalc.cc:2450 ../src/qalc.cc:2479 ../src/qalc.cc:2488 -#: ../src/qalc.cc:2505 ../src/qalc.cc:2512 ../src/qalc.cc:2530 -#: ../src/qalc.cc:2537 +#: ../src/qalc.cc:2391 ../src/qalc.cc:2409 ../src/qalc.cc:2418 +#: ../src/qalc.cc:2451 ../src/qalc.cc:2480 ../src/qalc.cc:2489 +#: ../src/qalc.cc:2506 ../src/qalc.cc:2513 ../src/qalc.cc:2531 +#: ../src/qalc.cc:2538 msgid "The RPN stack is empty." msgstr "RPN-stacken är tom." #. qalc command -#: ../src/qalc.cc:2406 ../src/qalc.cc:2415 ../src/qalc.cc:3215 -#: ../src/qalc.cc:3964 +#: ../src/qalc.cc:2407 ../src/qalc.cc:2416 ../src/qalc.cc:3216 +#: ../src/qalc.cc:3965 msgid "swap" msgstr "swap" -#: ../src/qalc.cc:2410 ../src/qalc.cc:2419 ../src/qalc.cc:2452 -#: ../src/qalc.cc:2481 ../src/qalc.cc:2490 +#: ../src/qalc.cc:2411 ../src/qalc.cc:2420 ../src/qalc.cc:2453 +#: ../src/qalc.cc:2482 ../src/qalc.cc:2491 msgid "The RPN stack only contains one value." msgstr "RPN-stacken innehåller endast ett värde." -#: ../src/qalc.cc:2438 ../src/qalc.cc:2471 ../src/qalc.cc:2519 -#: ../src/qalc.cc:2543 +#: ../src/qalc.cc:2439 ../src/qalc.cc:2472 ../src/qalc.cc:2520 +#: ../src/qalc.cc:2544 msgid "The specified RPN stack index does not exist." msgstr "Angivet index på RPN-stacken finns inte." #. qalc command -#: ../src/qalc.cc:2448 ../src/qalc.cc:3212 ../src/qalc.cc:3986 +#: ../src/qalc.cc:2449 ../src/qalc.cc:3213 ../src/qalc.cc:3987 msgid "move" msgstr "flytta" #. qalc command -#: ../src/qalc.cc:2477 ../src/qalc.cc:2486 ../src/qalc.cc:3214 -#: ../src/qalc.cc:3982 +#: ../src/qalc.cc:2478 ../src/qalc.cc:2487 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3983 msgid "rotate" msgstr "rotera" -#: ../src/qalc.cc:2494 +#: ../src/qalc.cc:2495 msgid "up" msgstr "upp" -#: ../src/qalc.cc:2496 +#: ../src/qalc.cc:2497 msgid "down" msgstr "ner" #. qalc command -#: ../src/qalc.cc:2503 ../src/qalc.cc:2510 ../src/qalc.cc:3211 -#: ../src/qalc.cc:3974 +#: ../src/qalc.cc:2504 ../src/qalc.cc:2511 ../src/qalc.cc:3212 +#: ../src/qalc.cc:3975 msgid "copy" msgstr "kopiera" #. qalc command -#: ../src/qalc.cc:2525 ../src/qalc.cc:3210 ../src/qalc.cc:3950 +#: ../src/qalc.cc:2526 ../src/qalc.cc:3211 ../src/qalc.cc:3951 msgid "clear stack" msgstr "töm stacken" #. qalc command -#: ../src/qalc.cc:2528 ../src/qalc.cc:2535 ../src/qalc.cc:3213 -#: ../src/qalc.cc:3954 +#: ../src/qalc.cc:2529 ../src/qalc.cc:2536 ../src/qalc.cc:3214 +#: ../src/qalc.cc:3955 msgid "pop" msgstr "pop" #. qalc command -#: ../src/qalc.cc:2569 ../src/qalc.cc:3204 ../src/qalc.cc:4006 +#: ../src/qalc.cc:2570 ../src/qalc.cc:3205 ../src/qalc.cc:4007 msgid "convert" msgstr "omvandla" #. "to"-operator -#: ../src/qalc.cc:2569 ../src/qalc.cc:3204 ../src/qalc.cc:4006 -#: ../src/qalc.cc:4049 ../libqalculate/Calculator.cc:518 -#: ../libqalculate/Calculator.cc:744 ../libqalculate/Calculator.cc:1540 -#: ../libqalculate/Calculator.cc:1541 ../libqalculate/Calculator.cc:3233 -#: ../libqalculate/Calculator.cc:3235 ../libqalculate/Calculator.cc:3248 -#: ../libqalculate/Calculator.cc:3250 ../libqalculate/Calculator.cc:3264 -#: ../libqalculate/Calculator.cc:3266 +#: ../src/qalc.cc:2570 ../src/qalc.cc:3205 ../src/qalc.cc:4007 +#: ../src/qalc.cc:4050 ../libqalculate/Calculator-calculate.cc:1065 +#: ../libqalculate/Calculator-calculate.cc:1067 +#: ../libqalculate/Calculator-calculate.cc:1080 +#: ../libqalculate/Calculator-calculate.cc:1082 +#: ../libqalculate/Calculator-calculate.cc:1096 +#: ../libqalculate/Calculator-calculate.cc:1098 +#: ../libqalculate/Calculator.cc:296 ../libqalculate/Calculator.cc:524 +#: ../libqalculate/Calculator.cc:1322 ../libqalculate/Calculator.cc:1323 msgid "to" msgstr "till" -#: ../src/qalc.cc:2654 ../src/qalc.cc:4822 ../libqalculate/Calculator.cc:3006 +#: ../src/qalc.cc:2655 ../src/qalc.cc:4823 +#: ../libqalculate/Calculator-calculate.cc:792 msgid "Time zone parsing failed." msgstr "Tolkning av tidszon misslyckades." -#: ../src/qalc.cc:2727 ../src/qalc.cc:4850 ../libqalculate/Calculator.cc:3041 +#: ../src/qalc.cc:2728 ../src/qalc.cc:4851 +#: ../libqalculate/Calculator-calculate.cc:827 msgid "bases" msgstr "baser" -#: ../src/qalc.cc:2774 ../src/qalc.cc:4853 ../libqalculate/Calculator.cc:3044 +#: ../src/qalc.cc:2775 ../src/qalc.cc:4854 +#: ../libqalculate/Calculator-calculate.cc:830 msgid "calendars" msgstr "kalendrar" -#: ../src/qalc.cc:2784 ../src/qalc.cc:4841 ../libqalculate/Calculator.cc:3031 +#: ../src/qalc.cc:2785 ../src/qalc.cc:4842 +#: ../libqalculate/Calculator-calculate.cc:817 msgid "fraction" msgstr "bråktal" -#: ../src/qalc.cc:2793 ../src/qalc.cc:4844 ../libqalculate/Calculator.cc:3034 +#: ../src/qalc.cc:2794 ../src/qalc.cc:4845 +#: ../libqalculate/Calculator-calculate.cc:820 msgid "factors" msgstr "faktorer" #. qalc command -#: ../src/qalc.cc:2795 ../src/qalc.cc:2881 ../src/qalc.cc:3198 -#: ../src/qalc.cc:3608 ../src/qalc.cc:4847 ../libqalculate/Calculator.cc:3038 +#: ../src/qalc.cc:2796 ../src/qalc.cc:2882 ../src/qalc.cc:3199 +#: ../src/qalc.cc:3609 ../src/qalc.cc:4848 +#: ../libqalculate/Calculator-calculate.cc:824 msgid "partial fraction" msgstr "partialbråktal" #. qalc command -#: ../src/qalc.cc:2878 ../src/qalc.cc:3193 ../src/qalc.cc:3604 +#: ../src/qalc.cc:2879 ../src/qalc.cc:3194 ../src/qalc.cc:3605 msgid "factor" msgstr "faktor" -#: ../src/qalc.cc:2892 ../src/qalc.cc:3633 +#: ../src/qalc.cc:2893 ../src/qalc.cc:3634 msgid "Algebraic Mode" msgstr "Algebraiskt läge" -#: ../src/qalc.cc:2927 ../src/qalc.cc:3665 +#: ../src/qalc.cc:2928 ../src/qalc.cc:3666 msgid "Calculation" msgstr "Beräkning" -#: ../src/qalc.cc:2950 +#: ../src/qalc.cc:2951 msgid "simplified" msgstr "förenklad" -#: ../src/qalc.cc:2955 ../src/qalc.cc:3675 +#: ../src/qalc.cc:2956 ../src/qalc.cc:3676 msgid "Enabled Objects" msgstr "Aktiverade objekt" -#: ../src/qalc.cc:2967 ../src/qalc.cc:3687 +#: ../src/qalc.cc:2968 ../src/qalc.cc:3688 msgid "Generic Display Options" msgstr "Generella visningsalternativ" -#: ../src/qalc.cc:2992 ../src/qalc.cc:3700 +#: ../src/qalc.cc:2993 ../src/qalc.cc:3701 msgid "Numerical Display" msgstr "Numerisk visning" -#: ../src/qalc.cc:3093 ../src/qalc.cc:3783 +#: ../src/qalc.cc:3094 ../src/qalc.cc:3784 msgid "Parsing" msgstr "Tolkning" -#: ../src/qalc.cc:3139 ../src/qalc.cc:3829 +#: ../src/qalc.cc:3140 ../src/qalc.cc:3830 msgid "Units" msgstr "Enheter" -#: ../src/qalc.cc:3168 ../src/qalc.cc:3861 +#: ../src/qalc.cc:3169 ../src/qalc.cc:3862 msgid "Other" msgstr "Övrigt" #. qalc command -#: ../src/qalc.cc:3176 ../src/qalc.cc:3600 +#: ../src/qalc.cc:3177 ../src/qalc.cc:3601 msgid "help" msgstr "hjälp" -#: ../src/qalc.cc:3179 +#: ../src/qalc.cc:3180 msgid "Enter a mathematical expression or a command and press enter." msgstr "Skriv in ett matematiskt uttryck eller ett kommando och tryck enter." -#: ../src/qalc.cc:3180 +#: ../src/qalc.cc:3181 msgid "Complete functions, units and variables with the tabulator key." msgstr "Avsluta funktions-, enhets- och variabelnamn med tabulatortangenten." -#: ../src/qalc.cc:3182 +#: ../src/qalc.cc:3183 msgid "Available commands are:" msgstr "Tillgängliga kommandon:" -#: ../src/qalc.cc:3185 +#: ../src/qalc.cc:3186 msgid "ASSUMPTIONS" msgstr "ANTAGANDEN" -#: ../src/qalc.cc:3187 ../src/qalc.cc:3194 ../src/qalc.cc:3195 -#: ../src/qalc.cc:3199 ../src/qalc.cc:3205 +#: ../src/qalc.cc:3188 ../src/qalc.cc:3195 ../src/qalc.cc:3196 +#: ../src/qalc.cc:3200 ../src/qalc.cc:3206 msgid "NAME" msgstr "NAMN" -#: ../src/qalc.cc:3194 ../src/qalc.cc:3226 ../src/qalc.cc:3925 +#: ../src/qalc.cc:3195 ../src/qalc.cc:3227 ../src/qalc.cc:3926 msgid "find" msgstr "hitta" #. qalc command -#: ../src/qalc.cc:3194 ../src/qalc.cc:3224 ../src/qalc.cc:3226 -#: ../src/qalc.cc:3925 +#: ../src/qalc.cc:3195 ../src/qalc.cc:3225 ../src/qalc.cc:3227 +#: ../src/qalc.cc:3926 msgid "list" msgstr "lista" -#: ../src/qalc.cc:3195 ../src/qalc.cc:3205 +#: ../src/qalc.cc:3196 ../src/qalc.cc:3206 msgid "EXPRESSION" msgstr "UTTRYCK" #. qalc command -#: ../src/qalc.cc:3196 ../src/qalc.cc:3252 ../src/qalc.cc:3934 -#: ../libqalculate/Calculator.cc:11336 ../libqalculate/DataSet.cc:364 -#: ../libqalculate/DataSet.cc:391 ../libqalculate/DataSet.cc:1038 +#: ../src/qalc.cc:3197 ../src/qalc.cc:3253 ../src/qalc.cc:3935 +#: ../libqalculate/Calculator-definitions.cc:2887 +#: ../libqalculate/DataSet.cc:365 ../libqalculate/DataSet.cc:392 +#: ../libqalculate/DataSet.cc:1039 msgid "info" msgstr "info" -#: ../src/qalc.cc:3199 +#: ../src/qalc.cc:3200 msgid "CATEGORY" msgstr "KATEGORI" -#: ../src/qalc.cc:3199 +#: ../src/qalc.cc:3200 msgid "TITLE" msgstr "TITEL" -#: ../src/qalc.cc:3204 +#: ../src/qalc.cc:3205 msgid "UNIT or \"TO\" COMMAND" msgstr "ENHET eller \"TILL\"-KOMMANDO" #. qalc command -#: ../src/qalc.cc:3206 ../src/qalc.cc:4053 ../src/qalc.cc:4074 +#: ../src/qalc.cc:3207 ../src/qalc.cc:4054 ../src/qalc.cc:4075 msgid "quit" msgstr "avsluta" -#: ../src/qalc.cc:3206 ../src/qalc.cc:4053 ../src/qalc.cc:4074 +#: ../src/qalc.cc:3207 ../src/qalc.cc:4054 ../src/qalc.cc:4075 msgid "exit" msgstr "exit" -#: ../src/qalc.cc:3207 +#: ../src/qalc.cc:3208 msgid "Commands for RPN mode:" msgstr "Kommandon för RPN-läget:" -#: ../src/qalc.cc:3208 +#: ../src/qalc.cc:3209 msgid "STATE" msgstr "LÄGE" -#: ../src/qalc.cc:3211 ../src/qalc.cc:3213 +#: ../src/qalc.cc:3212 ../src/qalc.cc:3214 msgid "INDEX" msgstr "INDEX" -#: ../src/qalc.cc:3212 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3213 ../src/qalc.cc:3216 msgid "INDEX 1" msgstr "INDEX 1" -#: ../src/qalc.cc:3212 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3213 ../src/qalc.cc:3216 msgid "INDEX 2" msgstr "INDEX 2" -#: ../src/qalc.cc:3214 +#: ../src/qalc.cc:3215 msgid "DIRECTION" msgstr "RIKTNING" -#: ../src/qalc.cc:3217 +#: ../src/qalc.cc:3218 msgid "Type help COMMAND for more information (example: help save)." msgstr "Skriv in hjälp KOMMANDO för mer information (exemel: hjälp save)." -#: ../src/qalc.cc:3218 +#: ../src/qalc.cc:3219 msgid "" "Type info NAME for information about a function, variable or unit (example: " "info sin)." @@ -1456,14 +1472,14 @@ "Skriv info NAMN för information om en funktion, variabel eller enhet " "(exempel: info sin)." -#: ../src/qalc.cc:3219 +#: ../src/qalc.cc:3220 msgid "" "When a line begins with '/', the following text is always interpreted as a " "command." msgstr "" "När en rad inleds med '/', tolkas alltid efterföljande text som ett kommando." -#: ../src/qalc.cc:3221 +#: ../src/qalc.cc:3222 msgid "" "For more information about mathematical expression, different options, and a " "complete list of functions, variables and units, see the relevant sections " @@ -1475,79 +1491,79 @@ "avsnitt i instruktionsboken för det grafiska användargränssnittet " "(tillgänglig på https://qalculate.github.io/manual/index.html)." -#: ../src/qalc.cc:3239 ../src/qalc.cc:3244 +#: ../src/qalc.cc:3240 ../src/qalc.cc:3245 msgid "currencies" msgstr "valutor" -#: ../src/qalc.cc:3261 +#: ../src/qalc.cc:3262 msgid "No function, variable or unit with specified name exist." msgstr "Ingen funktion, variabel eller enhet med det angivna namnet existerar." -#: ../src/qalc.cc:3271 +#: ../src/qalc.cc:3272 msgid "Function" msgstr "Funktion" -#: ../src/qalc.cc:3408 +#: ../src/qalc.cc:3409 msgid "Expression:" msgstr "Uttryck:" -#: ../src/qalc.cc:3417 ../src/qalc.cc:3420 ../src/qalc.cc:3587 +#: ../src/qalc.cc:3418 ../src/qalc.cc:3421 ../src/qalc.cc:3588 msgid "Unit" msgstr "Enhet" -#: ../src/qalc.cc:3423 ../src/qalc.cc:3497 +#: ../src/qalc.cc:3424 ../src/qalc.cc:3498 msgid "Names" msgstr "Namn" -#: ../src/qalc.cc:3441 +#: ../src/qalc.cc:3442 msgid "Base Unit" msgstr "Grundenhet" -#: ../src/qalc.cc:3448 +#: ../src/qalc.cc:3449 msgid "Relation" msgstr "Relation" -#: ../src/qalc.cc:3453 ../src/qalc.cc:3555 +#: ../src/qalc.cc:3454 ../src/qalc.cc:3556 msgid "Relative uncertainty" msgstr "Relativt fel" -#: ../src/qalc.cc:3454 ../src/qalc.cc:3556 +#: ../src/qalc.cc:3455 ../src/qalc.cc:3557 msgid "Uncertainty" msgstr "Fel" -#: ../src/qalc.cc:3464 +#: ../src/qalc.cc:3465 msgid "Inverse Relation" msgstr "Omvänd relation" -#: ../src/qalc.cc:3476 +#: ../src/qalc.cc:3477 msgid "Base Units" msgstr "Grundenheter" -#: ../src/qalc.cc:3491 ../src/qalc.cc:3494 +#: ../src/qalc.cc:3492 ../src/qalc.cc:3495 msgid "Variable" msgstr "Variabel" -#: ../src/qalc.cc:3606 +#: ../src/qalc.cc:3607 msgid "Factorizes the current result." msgstr "Faktoriserar nuvaranda resultat." -#: ../src/qalc.cc:3610 +#: ../src/qalc.cc:3611 msgid "Applies partial fraction decomposition to the current result." msgstr "Tillämpar partialbråksuppdelning på det nuvarande resultatet." -#: ../src/qalc.cc:3614 +#: ../src/qalc.cc:3615 msgid "Expands the current result." msgstr "Expanderar nuvaranda resultat." -#: ../src/qalc.cc:3628 +#: ../src/qalc.cc:3629 msgid "Sets the value of an option." msgstr "Anger värdet för en inställning." -#: ../src/qalc.cc:3629 +#: ../src/qalc.cc:3630 msgid "Example: set base 16." msgstr "Exempel: set bas 16." -#: ../src/qalc.cc:3631 +#: ../src/qalc.cc:3632 msgid "" "Available options and accepted values are (the current value is marked with " "'*'):" @@ -1555,23 +1571,23 @@ "Tillgängliga inställningar och accepterade värden (det nuvarande värdet är " "markerat med '*'):" -#: ../src/qalc.cc:3635 +#: ../src/qalc.cc:3636 msgid "Determines if the expression is factorized or not after calculation." msgstr "Avgör huruvida uttryck ska faktoriseras eller inte efter beräkning." -#: ../src/qalc.cc:3636 +#: ../src/qalc.cc:3637 msgid "Determines if unknown values will be assumed non-zero (x/x=1)." msgstr "Avgör om ökända värden ska antas vara icke-noll (x/x=1)." -#: ../src/qalc.cc:3637 +#: ../src/qalc.cc:3638 msgid "Display a message after a value has been assumed non-zero." msgstr "Visa ett meddelande efter att ett har antagits vara icke-noll." -#: ../src/qalc.cc:3640 +#: ../src/qalc.cc:3641 msgid "Default assumptions for unknown variables." msgstr "Förvalda antaganden för okända variabler." -#: ../src/qalc.cc:3668 +#: ../src/qalc.cc:3669 msgid "" "How approximate variables and calculations are handled. In exact mode " "approximate values will not be calculated." @@ -1579,7 +1595,7 @@ "Hur approximerade beräkningar och variabler hanteras. I exakt läge beräknas " "ej approximerade värden." -#: ../src/qalc.cc:3669 +#: ../src/qalc.cc:3670 msgid "" "If activated, interval arithmetic determines the final precision of " "calculations (avoids wrong results after loss of significance) with " @@ -1589,13 +1605,13 @@ "intervallaritmetik (Undviker felaktiga resultat efter signifikansförlust) " "med approximerade funktioner och/eller irrationella tal." -#: ../src/qalc.cc:3670 +#: ../src/qalc.cc:3671 msgid "" "Determines the method used for interval calculation / uncertainty " "propagation." msgstr "Anger metod som används för intervallberäkning/felfortplantning." -#: ../src/qalc.cc:3672 +#: ../src/qalc.cc:3673 msgid "" "Specifies the default number of significant digits displayed and determines " "the precision used for approximate calculations." @@ -1603,63 +1619,63 @@ "Anger det förvalda visade antalet signifikanta siffor och avgör vilken " "precision som används för approximerade beräkningar." -#: ../src/qalc.cc:3683 +#: ../src/qalc.cc:3684 msgid "Interprete undefined symbols in expressions as unknown variables." msgstr "Tolka odefinierade symboler i uttryck som okända variabler." -#: ../src/qalc.cc:3685 +#: ../src/qalc.cc:3686 msgid "" "If activated physical constants include units (e.g. c = 299 792 458 m∕s)." msgstr "" "Om aktiverat inkluderar fysiska konstanter enheter (t.ex. c = 299 792 458 " "m∕s)." -#: ../src/qalc.cc:3689 +#: ../src/qalc.cc:3690 msgid "Use abbreviated names for units and variables." msgstr "Använda förkortade namn på enheter och variabler." -#: ../src/qalc.cc:3692 +#: ../src/qalc.cc:3693 msgid "Always place negative values last." msgstr "Placera alltid negativa värden sist." -#: ../src/qalc.cc:3694 +#: ../src/qalc.cc:3695 msgid "Use negative exponents instead of division in result (x/y = xy^-1)." msgstr "" "Använd negativa exponenter istället för division i result (x/y = xy^-1)." -#: ../src/qalc.cc:3696 +#: ../src/qalc.cc:3697 msgid "Add extra space around operators." msgstr "Lägg till extra blanksteg kring operatorer." -#: ../src/qalc.cc:3698 +#: ../src/qalc.cc:3699 msgid "Display Unicode characters." msgstr "Visa Unicode-tecken." -#: ../src/qalc.cc:3702 ../src/qalc.cc:3804 +#: ../src/qalc.cc:3703 ../src/qalc.cc:3805 msgid "bin" msgstr "bin" -#: ../src/qalc.cc:3704 ../src/qalc.cc:3806 +#: ../src/qalc.cc:3705 ../src/qalc.cc:3807 msgid "oct" msgstr "okt" -#: ../src/qalc.cc:3706 ../src/qalc.cc:3808 +#: ../src/qalc.cc:3707 ../src/qalc.cc:3809 msgid "dec" msgstr "dec" -#: ../src/qalc.cc:3708 ../src/qalc.cc:3810 +#: ../src/qalc.cc:3709 ../src/qalc.cc:3811 msgid "hex" msgstr "hex" -#: ../src/qalc.cc:3710 +#: ../src/qalc.cc:3711 msgid "sexa" msgstr "sexa" -#: ../src/qalc.cc:3729 ../src/qalc.cc:3787 +#: ../src/qalc.cc:3730 ../src/qalc.cc:3788 msgid "Determines the default decimal separator." msgstr "Anger förvald decimalavgränsare." -#: ../src/qalc.cc:3742 +#: ../src/qalc.cc:3743 msgid "" "Determines how rational numbers are displayed (e.g. 5/4 = 1 + 1/4 = 1.25). " "'long' removes limits on the size of the numerator and denonimator." @@ -1667,31 +1683,31 @@ "Avgör hur rationella tal visas (t.ex. 5/4 = 1 + 1/4 = 1.25). 'lång' " "avlägsnar begränsningar för storleken på täljare och nämnare." -#: ../src/qalc.cc:3743 +#: ../src/qalc.cc:3744 msgid "" "Enables two's complement representation for display of negative hexadecimal " "numbers." msgstr "Aktiverar tvåkomplementsform för visning av negative hexadecimala tal." -#: ../src/qalc.cc:3744 ../src/qalc.cc:3803 +#: ../src/qalc.cc:3745 ../src/qalc.cc:3804 msgid "Use 'j' (instead of 'i') as default symbol for the imaginary unit." msgstr "" "Använd 'j' (istället för 'i') som förvald symbol för den imaginära enheten." -#: ../src/qalc.cc:3746 +#: ../src/qalc.cc:3747 msgid "Use lowercase e for E-notation (5e2 = 5 * 10^2)." msgstr "Använda litet e för grundpotensform (5e2 = 5 * 10^2)." -#: ../src/qalc.cc:3747 +#: ../src/qalc.cc:3748 msgid "Use lowercase letters for number bases > 10." msgstr "Använd små bokstäver för talbaser > 10." -#: ../src/qalc.cc:3762 +#: ../src/qalc.cc:3763 msgid "" "If activated, 1/6 is displayed as '0.1 666...', otherwise as '0.166667'." msgstr "Om aktiverat visas 1/6 som '0.1 666...', annars som '0.166667'." -#: ../src/qalc.cc:3763 +#: ../src/qalc.cc:3764 msgid "" "Determines whether halfway numbers are rounded upwards or towards the " "nearest even integer." @@ -1699,37 +1715,37 @@ "Avgör om mitt-i-mellan tal ska avrundas uppåt eller mot närmaste jämna " "heltal." -#: ../src/qalc.cc:3765 +#: ../src/qalc.cc:3766 msgid "Determines how scientific notation are used (e.g. 5 543 000 = 5.543E6)." msgstr "Avgör grundpotensform används (t.ex. 5 543 000 = 5,543E6)." -#: ../src/qalc.cc:3780 +#: ../src/qalc.cc:3781 msgid "If actived, zeroes are kept at the end of approximate numbers." msgstr "Om aktiverat behålls nollor i slutet av approximerade tal." -#: ../src/qalc.cc:3781 +#: ../src/qalc.cc:3782 msgid "" "Enables two's complement representation for display of negative binary " "numbers." msgstr "Aktiverar tvåkomplementsform för visning av negative binära tal." -#: ../src/qalc.cc:3785 +#: ../src/qalc.cc:3786 msgid "Use ^ as bitwise exclusive OR operator." msgstr "Använd ^ som operator för bitvist exklusivt OR." -#: ../src/qalc.cc:3798 +#: ../src/qalc.cc:3799 msgid "Allows use of ',' as thousands separator." msgstr "Tillåter användning av ',' som tusentalsavgränsare." -#: ../src/qalc.cc:3801 +#: ../src/qalc.cc:3802 msgid "Allows use of '.' as thousands separator." msgstr "Tillåter användning av '.' som tusentalsavgränsare." -#: ../src/qalc.cc:3825 +#: ../src/qalc.cc:3826 msgid "See 'help parsing mode'." msgstr "Se 'hjälp tolkningsläge'." -#: ../src/qalc.cc:3826 +#: ../src/qalc.cc:3827 msgid "" "If activated, numbers be interpreted as approximate with precision equal to " "the number of significant digits (3.20 = 3.20+/-0.005)." @@ -1737,11 +1753,11 @@ "Om aktiverat kommer tal att tolkas som approximerade med en precision som är " "lika med antalet signifikanta siffror (3,20 = 3,20+/-0,005)." -#: ../src/qalc.cc:3831 +#: ../src/qalc.cc:3832 msgid "Enables automatic use of hecto, deca, deci, and centi." msgstr "Aktiverar automatisk användning av hekto, deka, deci och centi." -#: ../src/qalc.cc:3833 +#: ../src/qalc.cc:3834 msgid "" "Controls automatic unit conversion of the result. 'optimalsi' always " "converts non-SI units, while 'optimal' only converts to more optimal unit " @@ -1751,14 +1767,14 @@ "icke-SI-enheter, medans 'optimal' enbart omvandlar till mer optimala " "enhetsuttryck, med färre enheter och exponenter." -#: ../src/qalc.cc:3847 +#: ../src/qalc.cc:3848 msgid "" "If activated, binary prefixes are used by default for information units." msgstr "" "Om aktiverat kommer binära prefix att användas som förval för " "informationsenheter." -#: ../src/qalc.cc:3848 +#: ../src/qalc.cc:3849 msgid "" "Enables automatic conversion to the local currency when optimal unit " "conversion is enabled." @@ -1766,47 +1782,47 @@ "Aktiverar omvandling till den lokala valuta när optimal enhetsomvandling är " "aktiverad." -#: ../src/qalc.cc:3849 +#: ../src/qalc.cc:3850 msgid "" "Enables automatic use of prefixes in the denominator of unit expressions." msgstr "Aktiverar automatisk använding av prefix i täljare i enhetsuttryck." -#: ../src/qalc.cc:3850 +#: ../src/qalc.cc:3851 msgid "" "If activated, units are separated from variables at the end of the result." msgstr "" "Om aktiverat kommer enheter att separeras från variabler på slutet av " "resultat." -#: ../src/qalc.cc:3851 +#: ../src/qalc.cc:3852 msgid "Enables automatic use of prefixes in the result." msgstr "Aktiverar automatisk användning av prefix i resultat." -#: ../src/qalc.cc:3856 +#: ../src/qalc.cc:3857 msgid "days" msgstr "dagar" -#: ../src/qalc.cc:3863 +#: ../src/qalc.cc:3864 msgid "Ignore system language and use English (requires restart)." msgstr "Bortse från systemspråket och använd englelska (kräver omstart)." -#: ../src/qalc.cc:3864 +#: ../src/qalc.cc:3865 msgid "Activates the Reverse Polish Notation stack." msgstr "Aktiverar stacken för omvänd polsk notation." -#: ../src/qalc.cc:3865 +#: ../src/qalc.cc:3866 msgid "Save functions, units, and variables on exit." msgstr "Sparar enheter, funktioner och variabler vid avslut." -#: ../src/qalc.cc:3866 +#: ../src/qalc.cc:3867 msgid "Save settings on exit." msgstr "Sparar inställningar vid avslut." -#: ../src/qalc.cc:3870 +#: ../src/qalc.cc:3871 msgid "Set default assumptions for unknown variables." msgstr "Ange färvalda antaganden för okända variabler." -#: ../src/qalc.cc:3897 +#: ../src/qalc.cc:3898 msgid "" "Saves the current result in a variable with the specified name. You may " "optionally also provide a category (default \"Temporary\") and a title." @@ -1814,7 +1830,7 @@ "Sparar nuvarande resultat i en variabel med angivet namn. Du kan välja att " "också ange en kategori (förvald är \"Temporära\") och en titel." -#: ../src/qalc.cc:3898 +#: ../src/qalc.cc:3899 msgid "" "If name equals \"mode\" or \"definitions\", the current mode and " "definitions, respectively, will be saved." @@ -1822,49 +1838,49 @@ "Om angivet namn är \"läge\" eller \"definitioner\", sparas nuvarande läge " "respektive definitioner." -#: ../src/qalc.cc:3900 +#: ../src/qalc.cc:3901 msgid "Example: store var1." msgstr "Exempel: store var1." -#: ../src/qalc.cc:3904 +#: ../src/qalc.cc:3905 msgid "Create a variables with the specified name and expression." msgstr "Skapa en variabel med det angivna namnet och uttrycket." -#: ../src/qalc.cc:3906 +#: ../src/qalc.cc:3907 msgid "Example: variable var1 pi / 2." msgstr "Exempel: variabel var1 pi / 2." -#: ../src/qalc.cc:3910 +#: ../src/qalc.cc:3911 msgid "Creates a function with the specified name and expression." msgstr "Skapar en function med det angivna namnet och uttrycket." -#: ../src/qalc.cc:3911 +#: ../src/qalc.cc:3912 msgid "Use '\\x', '\\y', '\\z', '\\a', etc. for arguments in the expression." msgstr "Använd '\\x', '\\y', '\\z', '\\a', etc. för argument i uttrycket" -#: ../src/qalc.cc:3913 +#: ../src/qalc.cc:3914 msgid "Example: function func1 5*\\x." msgstr "Exempel: funktion func1 5*\\x." -#: ../src/qalc.cc:3917 +#: ../src/qalc.cc:3918 msgid "Removes the user-defined variable or function with the specified name." msgstr "" "Tar bort den användardefinierade variabeln eller funktionen med det angivna " "namnet." -#: ../src/qalc.cc:3919 +#: ../src/qalc.cc:3920 msgid "Example: delete var1." msgstr "Exempel: frigör var1." -#: ../src/qalc.cc:3923 +#: ../src/qalc.cc:3924 msgid "Displays the current mode." msgstr "Visar nuvarande läge." -#: ../src/qalc.cc:3927 +#: ../src/qalc.cc:3928 msgid "Displays a list of variables, functions and units." msgstr "Visar en lista över variabler, funktioner och enheter." -#: ../src/qalc.cc:3928 +#: ../src/qalc.cc:3929 msgid "" "Enter with argument 'currencies', 'functions', 'variables' or 'units' to " "show a list of all currencies, functions, variables or units. Enter a search " @@ -1876,51 +1892,51 @@ "sökterm för att hitta matchande variabler, funktioner, och/eller enheter. Om " "kommandot körs utan några parametrar visas alla användardefinierade objekt." -#: ../src/qalc.cc:3930 +#: ../src/qalc.cc:3931 msgid "Example: list functions." msgstr "Exempel: lista funktioner." -#: ../src/qalc.cc:3931 +#: ../src/qalc.cc:3932 msgid "Example: find dinar." msgstr "Exempel: hitta dinar." -#: ../src/qalc.cc:3932 +#: ../src/qalc.cc:3933 msgid "Example: find variables planck." msgstr "Exempel: hitta variabler planck." -#: ../src/qalc.cc:3936 +#: ../src/qalc.cc:3937 msgid "Displays information about a function, variable or unit." msgstr "Visar information om en funktion, variabel eller enhet." -#: ../src/qalc.cc:3938 +#: ../src/qalc.cc:3939 msgid "Example: info sin." msgstr "Exempel: info sin." -#: ../src/qalc.cc:3942 +#: ../src/qalc.cc:3943 msgid "Downloads current exchange rates from the Internet." msgstr "Hämtar nuvarande växelkurser från internet." -#: ../src/qalc.cc:3946 +#: ../src/qalc.cc:3947 msgid "(De)activates the Reverse Polish Notation stack and syntax." msgstr "(Av)aktiverar stack och syntax för omvänd polsk notation." -#: ../src/qalc.cc:3948 +#: ../src/qalc.cc:3949 msgid "" "\"syntax\" activates only the RPN syntax and \"stack\" enables the RPN stack." msgstr "" "\"syntax\" aktiverar enbart RPN-syntaxen och \"stack\" aktiverar RPN-stacken." -#: ../src/qalc.cc:3952 +#: ../src/qalc.cc:3953 msgid "Clears the entire RPN stack." msgstr "Tömmer hela RPN-stacken." -#: ../src/qalc.cc:3956 +#: ../src/qalc.cc:3957 msgid "Removes the top of the RPN stack or the value at the specified index." msgstr "" "Avlägsnar det översta värdet på RPN-stacken eller värdet med angivet index." -#: ../src/qalc.cc:3958 ../src/qalc.cc:3970 ../src/qalc.cc:3980 -#: ../src/qalc.cc:3990 +#: ../src/qalc.cc:3959 ../src/qalc.cc:3971 ../src/qalc.cc:3981 +#: ../src/qalc.cc:3991 msgid "" "Index 1 is the top of stack and negative index values counts from the bottom " "of the stack." @@ -1928,15 +1944,15 @@ "Index 1 anger toppen på stacken och negativa indexvärden räknar från botten " "på stacken." -#: ../src/qalc.cc:3962 +#: ../src/qalc.cc:3963 msgid "Displays the RPN stack." msgstr "Visar RPN-stacken." -#: ../src/qalc.cc:3966 +#: ../src/qalc.cc:3967 msgid "Swaps position of values on the RPN stack." msgstr "Byter position på värden på RPN-stacken" -#: ../src/qalc.cc:3968 +#: ../src/qalc.cc:3969 msgid "" "If no index is specified, the values on the top of the stack (index 1 and " "index 2) will be swapped and if only one index is specified, the value at " @@ -1946,172 +1962,172 @@ "plats och om enbart ett index anges, så byter värdet med angivet index plats " "med värdet överst på stacken." -#: ../src/qalc.cc:3972 +#: ../src/qalc.cc:3973 msgid "Example: swap 2 4" msgstr "Exempel: swap 2 4" -#: ../src/qalc.cc:3976 +#: ../src/qalc.cc:3977 msgid "Duplicates a value on the RPN stack to the top of the stack." msgstr "Kopierar ett värde på RPN-stacken och placerar det överst på stacken." -#: ../src/qalc.cc:3978 +#: ../src/qalc.cc:3979 msgid "If no index is specified, the top of the stack is duplicated." msgstr "Om inget index anges kopierar värdet överst på stacken." -#: ../src/qalc.cc:3984 +#: ../src/qalc.cc:3985 msgid "Rotates the RPN stack up (default) or down." msgstr "Roterar RPN-stacken upp (förvalt) eller ner." -#: ../src/qalc.cc:3988 +#: ../src/qalc.cc:3989 msgid "Changes the position of a value on the RPN stack." msgstr "Byter position på ett värdet på RPN-stacken." -#: ../src/qalc.cc:3992 +#: ../src/qalc.cc:3993 msgid "Example: move 2 4" msgstr "Exempel: flytta 2 4" -#: ../src/qalc.cc:3996 +#: ../src/qalc.cc:3997 msgid "Sets the result number base (equivalent to set base)." msgstr "Anger talbas för resultat (liktydigt med ange bas)." -#: ../src/qalc.cc:4000 +#: ../src/qalc.cc:4001 msgid "Equivalent to set approximation exact." msgstr "Liktydigt med ange approximation exakt." -#: ../src/qalc.cc:4004 +#: ../src/qalc.cc:4005 msgid "Equivalent to set approximation try exact." msgstr "Liktydigt med ange approximation försök exakt." -#: ../src/qalc.cc:4009 +#: ../src/qalc.cc:4010 msgid "Converts units or changes number base in current result." msgstr "Omvandlar enheter eller ändrar talbas i nuvarande resultat." -#: ../src/qalc.cc:4011 +#: ../src/qalc.cc:4012 msgid "Possible values:" msgstr "Möjliga värden:" -#: ../src/qalc.cc:4013 +#: ../src/qalc.cc:4014 msgid "- a unit or unit expression (e.g. meter or km/h)" msgstr "- en enhet eller ett enhetsuttryck (t.ex. meter eller km/h)" -#: ../src/qalc.cc:4014 +#: ../src/qalc.cc:4015 msgid "prepend with ? to request the optimal prefix" msgstr "inled med ? för att eftefråga optimalt prefix" -#: ../src/qalc.cc:4015 +#: ../src/qalc.cc:4016 msgid "prepend with b? to request the optimal binary prefix" msgstr "inled med b? för att eftefråga optimalt binärt prefix" -#: ../src/qalc.cc:4016 +#: ../src/qalc.cc:4017 msgid "prepend with + or - to force/disable use of mixed units" msgstr "" "inled med + eller - för att tvinga/avaktivera användning a blandade enheter" -#: ../src/qalc.cc:4017 +#: ../src/qalc.cc:4018 msgid "- a variable or physical constant (e.g. c)" msgstr "- en variabel eller fysikalisk konstant (t.ex. c)" -#: ../src/qalc.cc:4018 +#: ../src/qalc.cc:4019 msgid "- base (convert to base units)" msgstr "- bas (omvandla till basenheter)" -#: ../src/qalc.cc:4019 +#: ../src/qalc.cc:4020 msgid "- optimal (convert to optimal unit)" msgstr "- optimal (omvandla till optimal enhet)" -#: ../src/qalc.cc:4020 +#: ../src/qalc.cc:4021 msgid "- mixed (convert to mixed units, e.g. hours + minutes)" msgstr "- blandade (omvandla till blandade enheter, t.ex. timmar + minuter)" -#: ../src/qalc.cc:4022 +#: ../src/qalc.cc:4023 msgid "- bin / binary (show as binary number)" msgstr "- bin / binär (visa som binärt tal)" -#: ../src/qalc.cc:4023 +#: ../src/qalc.cc:4024 msgid "- oct / octal (show as octal number)" msgstr "- oct / oktal (visa som oktalt tal)" -#: ../src/qalc.cc:4024 +#: ../src/qalc.cc:4025 msgid "- duo / duodecimal (show as duodecimal number)" msgstr "- duo / duodecimal (visa som duodecimalt tal)" -#: ../src/qalc.cc:4025 +#: ../src/qalc.cc:4026 msgid "- hex / hexadecimal (show as hexadecimal number)" msgstr "- hex / hexadecimal (visa som hexadecimalt tal)" -#: ../src/qalc.cc:4026 +#: ../src/qalc.cc:4027 msgid "- sex / sexagesimal (show as sexagesimal number)" msgstr "- sex / sexagesimal (visa som sexagecimalt tal)" -#: ../src/qalc.cc:4027 +#: ../src/qalc.cc:4028 msgid "- bijective (shown in bijective base-26)" msgstr "- bijektiv (visas i bijektiv talbas 26)" -#: ../src/qalc.cc:4028 +#: ../src/qalc.cc:4029 msgid "- roman (show as roman numerals)" msgstr "- romersk (visa som romerska siffror)" -#: ../src/qalc.cc:4029 +#: ../src/qalc.cc:4030 msgid "- time (show in time format)" msgstr "- tid (visas i tidsformat)" -#: ../src/qalc.cc:4030 +#: ../src/qalc.cc:4031 msgid "- unicode" msgstr "" -#: ../src/qalc.cc:4031 +#: ../src/qalc.cc:4032 msgid "- base # (show in specified number base)" msgstr "- bas # (visa med angiven talbas)" -#: ../src/qalc.cc:4032 +#: ../src/qalc.cc:4033 msgid "- bases (show as binary, octal, decimal and hexadecimal number)" msgstr "- baser (visa som binärt, otkalt, decimalt och hexadecimalt tal)" -#: ../src/qalc.cc:4034 +#: ../src/qalc.cc:4035 msgid "- rectangular / cartesian (show complex numbers in rectangular form)" msgstr "- rektangulär / kartesisk (visa komplexa tal i rektangulär form)" -#: ../src/qalc.cc:4035 +#: ../src/qalc.cc:4036 msgid "- exponential (show complex numbers in exponential form)" msgstr "- exponentiell (visa komplexa tal i exponentiell form)" -#: ../src/qalc.cc:4036 +#: ../src/qalc.cc:4037 msgid "- polar (show complex numbers in polar form)" msgstr "- polär (visa komplexa tal i polär form)" -#: ../src/qalc.cc:4037 +#: ../src/qalc.cc:4038 msgid "- cis (show complex numbers in cis form)" msgstr "- cis (visa komplexa tal i cis-form)" -#: ../src/qalc.cc:4038 +#: ../src/qalc.cc:4039 msgid "- angle / phasor (show complex numbers in angle/phasor notation)" msgstr "- vinkel / fasvektor (visa komplexa tal i vinkelnotation)" -#: ../src/qalc.cc:4040 +#: ../src/qalc.cc:4041 msgid "- fraction (show result as mixed fraction)" msgstr "- bråktal (visa resultatet i blandad form)" -#: ../src/qalc.cc:4041 +#: ../src/qalc.cc:4042 msgid "- factors (factorize result)" msgstr "- faktorer (faktoriserar resultatet)" -#: ../src/qalc.cc:4043 +#: ../src/qalc.cc:4044 msgid "- UTC (show date and time in UTC time zone)" msgstr "- UTC (visa datum och tid för UTC-tidszonen)" -#: ../src/qalc.cc:4044 +#: ../src/qalc.cc:4045 msgid "- UTC+/-hh[:mm] (show date and time in specified time zone)" msgstr "- UTC+/-hh[:mm] (visa datum och tid för specificerad tidszon)" -#: ../src/qalc.cc:4045 +#: ../src/qalc.cc:4046 msgid "- calendars" msgstr "- kalendrar" -#: ../src/qalc.cc:4047 +#: ../src/qalc.cc:4048 msgid "Example: to ?g" msgstr "Exempel: till ?g" -#: ../src/qalc.cc:4050 +#: ../src/qalc.cc:4051 msgid "" "This command can also be typed directly at the end of the mathematical " "expression (e.g. 5 ft + 2 in to meter)." @@ -2119,11 +2135,11 @@ "Det här kommandot kan även skrivas direkt i slutet av det matematiska " "uttrycket (t.ex. 5 ft + 2 in till meter)." -#: ../src/qalc.cc:4055 +#: ../src/qalc.cc:4056 msgid "Terminates this program." msgstr "Avslutar det här programmet." -#: ../src/qalc.cc:4060 +#: ../src/qalc.cc:4061 msgid "" "Implicit multiplication does not differ from explicit multiplication " "(\"12/2(1+2) = 12/2*3 = 18\", \"5x/5y = 5*x/5*y = xy\")." @@ -2131,7 +2147,7 @@ "Implicit multiplikation särskiljer sig inte från explicit multiplikation " "(\"12/2(1+2) = 12/2*3 = 18\", \"5x/5y = 5*x/5*y = xy\")." -#: ../src/qalc.cc:4063 +#: ../src/qalc.cc:4064 msgid "" "Implicit multiplication is parsed before explicit multiplication " "(\"12/2(1+2) = 12/(2*3) = 2\", \"5x/5y = (5*x)/(5*y) = x/y\")." @@ -2139,7 +2155,7 @@ "Implicit multiplikation tolkas före explicit multiplikation (\"12/2(1+2) = " "12/(2*3) = 2\", \"5x/5y = (5*x)/(5*y) = x/y\")." -#: ../src/qalc.cc:4066 +#: ../src/qalc.cc:4067 msgid "" "The default adaptive mode works as the \"implicit first\" mode, unless " "spaces are found (\"1/5x = 1/(5*x)\", but \"1/5 x = (1/5)*x\"). In the " @@ -2151,7 +2167,7 @@ "adaptivt läge tolkas enhetsuttryck separat (\"5 m/5 m/s = (5*m)/(5*(m/s)) = " "1 s\")." -#: ../src/qalc.cc:4068 +#: ../src/qalc.cc:4069 msgid "" "Function arguments without parentheses are an exception, where implicit " "multiplication in front of variables and units is parsed first regardless of " @@ -2161,58 +2177,58 @@ "multiplikation frmför variabler och enheter tolkas först oavsett läge " "(\"sqrt 2x = sqrt(2x)\")." -#: ../src/qalc.cc:4082 +#: ../src/qalc.cc:4083 msgid "Unknown command." msgstr "Okänt kommando." -#: ../src/qalc.cc:4131 +#: ../src/qalc.cc:4132 msgid "error" msgstr "fel" -#: ../src/qalc.cc:4133 +#: ../src/qalc.cc:4134 msgid "warning" msgstr "varning" -#: ../src/qalc.cc:4156 ../src/qalc.cc:4441 ../src/qalc.cc:5320 +#: ../src/qalc.cc:4157 ../src/qalc.cc:4442 ../src/qalc.cc:5347 msgid "approx." msgstr "ca" -#: ../src/qalc.cc:4240 ../src/qalc.cc:4278 ../src/qalc.cc:4598 -#: ../src/qalc.cc:5173 ../libqalculate/Calculator.cc:11754 -#: ../libqalculate/MathStructure.cc:780 +#: ../src/qalc.cc:4241 ../src/qalc.cc:4279 ../src/qalc.cc:4599 +#: ../src/qalc.cc:5178 ../libqalculate/Calculator-calculate.cc:1615 +#: ../libqalculate/MathStructure.cc:448 #, c-format msgid "aborted" msgstr "avbruten" -#: ../src/qalc.cc:4290 +#: ../src/qalc.cc:4291 msgid "RPN Register Moved" msgstr "RPN-register flyttades" -#: ../src/qalc.cc:4346 +#: ../src/qalc.cc:4347 msgid "Processing (press Enter to abort)" msgstr "Behandlar (tryck Enter för att avbryta)" -#: ../src/qalc.cc:4615 +#: ../src/qalc.cc:4616 msgid "Factorizing (press Enter to abort)" msgstr "Faktoriserar (tryck Enter för att avbryta)" -#: ../src/qalc.cc:4619 +#: ../src/qalc.cc:4620 msgid "Expanding partial fractions…" msgstr "Expandarer partialbråk…" -#: ../src/qalc.cc:4623 +#: ../src/qalc.cc:4624 msgid "Expanding (press Enter to abort)" msgstr "Expanderar (tryck Enter för att avbryta)" -#: ../src/qalc.cc:4627 ../src/qalc.cc:5187 +#: ../src/qalc.cc:4628 ../src/qalc.cc:5192 msgid "Calculating (press Enter to abort)" msgstr "Beräknar (tryck Enter för att avbryta)" -#: ../src/qalc.cc:5273 +#: ../src/qalc.cc:5300 msgid "RPN Operation" msgstr "RPN-operation" -#: ../src/qalc.cc:5805 +#: ../src/qalc.cc:5832 #, c-format msgid "" "Couldn't write preferences to\n" @@ -2221,11 +2237,13 @@ "Kunde inte spara inställningar till\n" "%s" -#: ../src/qalc.cc:5913 +#: ../src/qalc.cc:5940 msgid "Couldn't write definitions" msgstr "Kunde inte spara definitioner" -#: ../src/test.cc:13 ../src/test.cc:28 ../libqalculate/Calculator.cc:2229 +#. thread cancellation is not safe +#: ../src/test.cc:13 ../src/test.cc:28 +#: ../libqalculate/Calculator-calculate.cc:172 msgid "" "The calculation has been forcibly terminated. Please restart the application " "and report this as a bug." @@ -2233,383 +2251,383 @@ "Beräkningen har avslutats med tvång. Vänligen starta om programmet och " "rapportera detta som en bug." -#: ../libqalculate/BuiltinFunctions.cc:109 +#: ../libqalculate/BuiltinFunctions-algebra.cc:359 +msgid "" +"No equality or inequality to solve. The entered expression to solve is not " +"correct (ex. \"x + 5 = 3\" is correct)" +msgstr "" +"Ingen ekvation eller olikhet att lösa. Angett uttryck att lösa var inte " +"korrekt (t ex \"x + 5 = 3\" är korrekt)" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:406 #, c-format -msgid "Too many elements (%s) for the dimensions (%sx%s) of the matrix." -msgstr "För många element (%s) för en %sx%s matris." +msgid "The comparison is true for all %s (with current assumptions)." +msgstr "Jämförelsen är sann för alla %s (med nuvarande antaganden)." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:410 +msgid "No possible solution was found (with current assumptions)." +msgstr "Ingen möjlig lösning funnen (med nuvarande antaganden)." -#: ../libqalculate/BuiltinFunctions.cc:172 -#: ../libqalculate/BuiltinFunctions.cc:234 +#: ../libqalculate/BuiltinFunctions-algebra.cc:414 #, c-format -msgid "Row %s does not exist in matrix." -msgstr "Rad %s finns inte i matrisen." +msgid "Was unable to completely isolate %s." +msgstr "Kunde inte isolera %s fullständigt." -#: ../libqalculate/BuiltinFunctions.cc:185 -#: ../libqalculate/BuiltinFunctions.cc:230 +#: ../libqalculate/BuiltinFunctions-algebra.cc:418 +#: ../libqalculate/BuiltinFunctions-algebra.cc:581 +#: ../libqalculate/BuiltinFunctions-algebra.cc:673 #, c-format -msgid "Column %s does not exist in matrix." -msgstr "Kolumn %s finns inte i matrisen." +msgid "The comparison is true for all %s if %s." +msgstr "Jämförelsen är sann för alla %s om %s." -#: ../libqalculate/BuiltinFunctions.cc:245 +#: ../libqalculate/BuiltinFunctions-algebra.cc:422 #, c-format -msgid "Argument 3, %s, is ignored for vectors." -msgstr "Parameter 3, %s, bortses från för vektorer." +msgid "Was unable to isolate %s." +msgstr "Kunde inte isolera %s." -#: ../libqalculate/BuiltinFunctions.cc:249 -#: ../libqalculate/BuiltinFunctions.cc:270 +#: ../libqalculate/BuiltinFunctions-algebra.cc:542 +#: ../libqalculate/BuiltinFunctions-algebra.cc:569 +#: ../libqalculate/BuiltinFunctions-algebra.cc:650 #, c-format -msgid "Element %s does not exist in vector." -msgstr "Element %s finns inte i vektorn." +msgid "" +"Was unable to isolate %s with the current assumptions. The assumed sign was " +"therefore temporarily set as unknown." +msgstr "" +"Kunde inte isolera %s med nuvarande antaganden. Antaget tecken sattes därför " +"temporärt till okänt." -#: ../libqalculate/BuiltinFunctions.cc:411 -#: ../libqalculate/BuiltinFunctions.cc:415 -#: ../libqalculate/BuiltinFunctions.cc:447 -#: ../libqalculate/BuiltinFunctions.cc:451 +#: ../libqalculate/BuiltinFunctions-algebra.cc:545 +#: ../libqalculate/BuiltinFunctions-algebra.cc:572 +#: ../libqalculate/BuiltinFunctions-algebra.cc:653 #, c-format -msgid "%s() requires that all matrices/vectors have the same dimensions." -msgstr "%s() kräver att alla matriser/vektorer har samma dimensioner." +msgid "" +"Was unable to isolate %s with the current assumptions. The assumed type and " +"sign was therefore temporarily set as unknown." +msgstr "" +"Kunde inte isolera %s med nuvarande antaganden. Antagen typ sattes därför " +"temporärt till okänd." -#: ../libqalculate/BuiltinFunctions.cc:4759 -#: ../libqalculate/BuiltinFunctions.cc:4802 +#: ../libqalculate/BuiltinFunctions-algebra.cc:577 +#: ../libqalculate/BuiltinFunctions-algebra.cc:660 #, c-format -msgid "Unsolvable comparison in %s()." -msgstr "Olöslig jämförelse i %s()." +msgid "The solution requires that %s." +msgstr "Lösningen kräver att %s." -#: ../libqalculate/BuiltinFunctions.cc:4972 -#: ../libqalculate/BuiltinFunctions.cc:5006 +#: ../libqalculate/BuiltinFunctions-algebra.cc:667 +#, c-format +msgid "Solution %s requires that %s." +msgstr "Lösning %s kräver att %s." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:738 +#, c-format +msgid "" +"Unable to isolate %s.\n" +"\n" +"You might need to place the equations and variables in an appropriate order " +"so that each equation at least contains the corresponding variable (if " +"automatic reordering failed)." +msgstr "" +"Kan inte isolera %s.\n" +"\n" +"Du behöver kanske placera ekvationerna och variablerna i lämplig ordning så " +"att varje ekvation åtminstone innehåller motsvarande variabel (om automatisk " +"omsortering misslyckades)." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:740 +#: ../libqalculate/BuiltinFunctions-algebra.cc:754 +#: ../libqalculate/BuiltinFunctions-algebra.cc:763 +#, c-format +msgid "Unable to isolate %s." +msgstr "Kan inte isolera %s." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:747 +#, c-format +msgid "Inequalities is not allowed in %s()." +msgstr "Olikheter är inte tillåtna i %s()." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:1089 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1094 +msgid "No differential equation found." +msgstr "Ingen differentialekvation funnen." + +#: ../libqalculate/BuiltinFunctions-algebra.cc:1098 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1127 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1133 +msgid "Unable to solve differential equation." +msgstr "Kunde inte lösa differentialekvation." + +#: ../libqalculate/BuiltinFunctions-datetime.cc:33 +#: ../libqalculate/BuiltinFunctions-datetime.cc:67 msgid "gregorian" msgstr "gregoriansk" -#: ../libqalculate/BuiltinFunctions.cc:4973 +#: ../libqalculate/BuiltinFunctions-datetime.cc:34 msgid "milankovic" msgstr "milankovic" -#: ../libqalculate/BuiltinFunctions.cc:4974 +#: ../libqalculate/BuiltinFunctions-datetime.cc:35 msgid "julian" msgstr "juliansk" -#: ../libqalculate/BuiltinFunctions.cc:4975 +#: ../libqalculate/BuiltinFunctions-datetime.cc:36 msgid "islamic" msgstr "muslimsk" -#: ../libqalculate/BuiltinFunctions.cc:4976 +#: ../libqalculate/BuiltinFunctions-datetime.cc:37 msgid "hebrew" msgstr "hebreisk" -#: ../libqalculate/BuiltinFunctions.cc:4977 +#: ../libqalculate/BuiltinFunctions-datetime.cc:38 msgid "egyptian" msgstr "egyptisk" -#: ../libqalculate/BuiltinFunctions.cc:4978 +#: ../libqalculate/BuiltinFunctions-datetime.cc:39 msgid "persian" msgstr "persisk" -#: ../libqalculate/BuiltinFunctions.cc:4979 +#: ../libqalculate/BuiltinFunctions-datetime.cc:40 msgid "coptic" msgstr "koptisk" -#: ../libqalculate/BuiltinFunctions.cc:4980 +#: ../libqalculate/BuiltinFunctions-datetime.cc:41 msgid "ethiopian" msgstr "etiopisk" -#: ../libqalculate/BuiltinFunctions.cc:4981 +#: ../libqalculate/BuiltinFunctions-datetime.cc:42 msgid "indian" msgstr "indisk" -#: ../libqalculate/BuiltinFunctions.cc:4982 +#: ../libqalculate/BuiltinFunctions-datetime.cc:43 msgid "chinese" msgstr "kinesisk" -#: ../libqalculate/BuiltinFunctions.cc:5408 -#: ../libqalculate/BuiltinFunctions.cc:5438 ../libqalculate/Number.cc:429 -#: ../libqalculate/Number.cc:900 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:57 #, c-format -msgid "Character '%s' was ignored in the number \"%s\" with base %s." -msgstr "Tecken '%s' ignorerades i numret \"%s\" med bas %s" +msgid "Too many elements (%s) for the dimensions (%sx%s) of the matrix." +msgstr "För många element (%s) för en %sx%s matris." -#: ../libqalculate/BuiltinFunctions.cc:5703 -#: ../libqalculate/BuiltinFunctions.cc:5708 -#: ../libqalculate/BuiltinFunctions.cc:5710 -#: ../libqalculate/BuiltinFunctions.cc:5726 ../libqalculate/Calculator.cc:3409 -#: ../libqalculate/Calculator.cc:3416 ../libqalculate/Calculator.cc:3418 -#: ../libqalculate/Calculator.cc:3482 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:120 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:182 #, c-format -msgid "Original value (%s) was not found." -msgstr "Ursprungligt värde (%s) hittades ej." - -#: ../libqalculate/BuiltinFunctions.cc:5862 -msgid "" -"The number of requested elements in generate vector function must be a " -"positive integer." -msgstr "" -"Antalet efterfrågade element i generera vektor-funktionen måste vara ett " -"positivt heltal." +msgid "Row %s does not exist in matrix." +msgstr "Rad %s finns inte i matrisen." -#: ../libqalculate/BuiltinFunctions.cc:6179 -#: ../libqalculate/BuiltinFunctions.cc:6183 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:133 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:178 #, c-format -msgid "Too few elements (%s) in vector (%s required)" -msgstr "För få element (%s) i vektor (%s krävs)" +msgid "Column %s does not exist in matrix." +msgstr "Kolumn %s finns inte i matrisen." -#: ../libqalculate/BuiltinFunctions.cc:6232 -#: ../libqalculate/BuiltinFunctions.cc:6249 -msgid "Comparison failed." -msgstr "Jämförelse misslyckades." +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:193 +#, c-format +msgid "Argument 3, %s, is ignored for vectors." +msgstr "Parameter 3, %s, bortses från för vektorer." -#: ../libqalculate/BuiltinFunctions.cc:6392 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:197 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:218 #, c-format -msgid "Object %s does not exist." -msgstr "Okjektet %s finns inte." +msgid "Element %s does not exist in vector." +msgstr "Element %s finns inte i vektorn." -#: ../libqalculate/BuiltinFunctions.cc:6410 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:359 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:363 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:395 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:399 #, c-format -msgid "Invalid variable name (%s)." -msgstr "Ogiltigt variabelnamn (%s)." +msgid "%s() requires that all matrices/vectors have the same dimensions." +msgstr "%s() kräver att alla matriser/vektorer har samma dimensioner." -#: ../libqalculate/BuiltinFunctions.cc:6427 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:539 msgid "" -"A global unit or variable was deactivated. It will be restored after the new " -"variable has been removed." +"The number of requested elements in generate vector function must be a " +"positive integer." msgstr "" -"En systemvid enhet eller variabel har avaktiverats. Den återaktiveras efter " -"att den nya variabeln har tagits bort." +"Antalet efterfrågade element i generera vektor-funktionen måste vara ett " +"positivt heltal." -#: ../libqalculate/BuiltinFunctions.cc:6442 -#, c-format -msgid "Register %s does not exist. Returning zero." -msgstr "RPN-registret %s finns inte. Returnerar noll." +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:562 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:579 +msgid "Comparison failed." +msgstr "Jämförelse misslyckades." -#: ../libqalculate/BuiltinFunctions.cc:7390 -#: ../libqalculate/MathStructure.cc:284 ../libqalculate/MathStructure.cc:306 -#: ../libqalculate/MathStructure.cc:337 +#: ../libqalculate/BuiltinFunctions-statistics.cc:178 +#: ../libqalculate/BuiltinFunctions-statistics.cc:221 #, c-format -msgid "To avoid division by zero, the following must be true: %s." -msgstr "För att undvika division med noll, krävs att följande är sant: %s." +msgid "Unsolvable comparison in %s()." +msgstr "Olöslig jämförelse i %s()." + +#: ../libqalculate/BuiltinFunctions-calculus.cc:314 +msgid "Unable to find limit." +msgstr "Kan inte hitta gränsvärdet." -#: ../libqalculate/BuiltinFunctions.cc:7598 -#: ../libqalculate/BuiltinFunctions.cc:7617 -#: ../libqalculate/BuiltinFunctions.cc:7650 -#: ../libqalculate/BuiltinFunctions.cc:7672 -#: ../libqalculate/BuiltinFunctions.cc:7721 -#: ../libqalculate/BuiltinFunctions.cc:7756 -#: ../libqalculate/BuiltinFunctions.cc:7871 -#: ../libqalculate/BuiltinFunctions.cc:7921 -#: ../libqalculate/BuiltinFunctions.cc:7955 -#: ../libqalculate/BuiltinFunctions.cc:7998 -#: ../libqalculate/BuiltinFunctions.cc:8030 +#: ../libqalculate/BuiltinFunctions-calculus.cc:409 +#: ../libqalculate/BuiltinFunctions-calculus.cc:441 +#: ../libqalculate/MathStructure-integrate.cc:7294 +#: ../libqalculate/MathStructure-integrate.cc:7314 +#: ../libqalculate/MathStructure-integrate.cc:7349 +#: ../libqalculate/MathStructure-integrate.cc:7373 +#: ../libqalculate/MathStructure-integrate.cc:7423 +#: ../libqalculate/MathStructure-integrate.cc:7462 +#: ../libqalculate/MathStructure-integrate.cc:7658 +#: ../libqalculate/MathStructure-integrate.cc:7712 +#: ../libqalculate/MathStructure-integrate.cc:7754 msgid "Unable to integrate the expression." msgstr "Kan inte integrera uttrycket." -#: ../libqalculate/BuiltinFunctions.cc:7878 -#: ../libqalculate/BuiltinFunctions.cc:7948 -msgid "Unable to integrate the expression exact." -msgstr "Kan inte integrera uttrycket exakt." - -#: ../libqalculate/BuiltinFunctions.cc:7915 -msgid "Definite integral was approximated." -msgstr "Definitiv integral approximerades." - -#: ../libqalculate/BuiltinFunctions.cc:8245 -msgid "" -"No equality or inequality to solve. The entered expression to solve is not " -"correct (ex. \"x + 5 = 3\" is correct)" -msgstr "" -"Ingen ekvation eller olikhet att lösa. Angett uttryck att lösa var inte " -"korrekt (t ex \"x + 5 = 3\" är korrekt)" - -#: ../libqalculate/BuiltinFunctions.cc:8292 -#, c-format -msgid "The comparison is true for all %s (with current assumptions)." -msgstr "Jämförelsen är sann för alla %s (med nuvarande antaganden)." - -#: ../libqalculate/BuiltinFunctions.cc:8296 -msgid "No possible solution was found (with current assumptions)." -msgstr "Ingen möjlig lösning funnen (med nuvarande antaganden)." - -#: ../libqalculate/BuiltinFunctions.cc:8300 -#, c-format -msgid "Was unable to completely isolate %s." -msgstr "Kunde inte isolera %s fullständigt." - -#: ../libqalculate/BuiltinFunctions.cc:8304 -#: ../libqalculate/BuiltinFunctions.cc:8467 -#: ../libqalculate/BuiltinFunctions.cc:8559 -#, c-format -msgid "The comparison is true for all %s if %s." -msgstr "Jämförelsen är sann för alla %s om %s." - -#: ../libqalculate/BuiltinFunctions.cc:8308 +#: ../libqalculate/BuiltinFunctions-number.cc:684 +#: ../libqalculate/BuiltinFunctions-number.cc:714 ../libqalculate/Number.cc:459 +#: ../libqalculate/Number.cc:970 #, c-format -msgid "Was unable to isolate %s." -msgstr "Kunde inte isolera %s." +msgid "Character '%s' was ignored in the number \"%s\" with base %s." +msgstr "Tecken '%s' ignorerades i numret \"%s\" med bas %s" -#: ../libqalculate/BuiltinFunctions.cc:8428 -#: ../libqalculate/BuiltinFunctions.cc:8455 -#: ../libqalculate/BuiltinFunctions.cc:8536 +#. if left value is a function without any arguments, do function replacement +#: ../libqalculate/BuiltinFunctions-util.cc:414 +#: ../libqalculate/BuiltinFunctions-util.cc:419 +#: ../libqalculate/BuiltinFunctions-util.cc:421 +#: ../libqalculate/BuiltinFunctions-util.cc:437 +#: ../libqalculate/Calculator-calculate.cc:1239 +#: ../libqalculate/Calculator-calculate.cc:1251 +#: ../libqalculate/Calculator-calculate.cc:1253 +#: ../libqalculate/Calculator-calculate.cc:1256 +#: ../libqalculate/Calculator-calculate.cc:1327 #, c-format -msgid "" -"Was unable to isolate %s with the current assumptions. The assumed sign was " -"therefore temporarily set as unknown." -msgstr "" -"Kunde inte isolera %s med nuvarande antaganden. Antaget tecken sattes därför " -"temporärt till okänt." +msgid "Original value (%s) was not found." +msgstr "Ursprungligt värde (%s) hittades ej." -#: ../libqalculate/BuiltinFunctions.cc:8431 -#: ../libqalculate/BuiltinFunctions.cc:8458 -#: ../libqalculate/BuiltinFunctions.cc:8539 +#: ../libqalculate/BuiltinFunctions-util.cc:627 +#: ../libqalculate/BuiltinFunctions-util.cc:631 #, c-format -msgid "" -"Was unable to isolate %s with the current assumptions. The assumed type and " -"sign was therefore temporarily set as unknown." -msgstr "" -"Kunde inte isolera %s med nuvarande antaganden. Antagen typ sattes därför " -"temporärt till okänd." +msgid "Too few elements (%s) in vector (%s required)" +msgstr "För få element (%s) i vektor (%s krävs)" -#: ../libqalculate/BuiltinFunctions.cc:8463 -#: ../libqalculate/BuiltinFunctions.cc:8546 +#: ../libqalculate/BuiltinFunctions-util.cc:677 #, c-format -msgid "The solution requires that %s." -msgstr "Lösningen kräver att %s." +msgid "Object %s does not exist." +msgstr "Okjektet %s finns inte." -#: ../libqalculate/BuiltinFunctions.cc:8553 +#: ../libqalculate/BuiltinFunctions-util.cc:695 #, c-format -msgid "Solution %s requires that %s." -msgstr "Lösning %s kräver att %s." +msgid "Invalid variable name (%s)." +msgstr "Ogiltigt variabelnamn (%s)." -#: ../libqalculate/BuiltinFunctions.cc:8624 -#, c-format +#: ../libqalculate/BuiltinFunctions-util.cc:712 msgid "" -"Unable to isolate %s.\n" -"\n" -"You might need to place the equations and variables in an appropriate order " -"so that each equation at least contains the corresponding variable (if " -"automatic reordering failed)." +"A global unit or variable was deactivated. It will be restored after the new " +"variable has been removed." msgstr "" -"Kan inte isolera %s.\n" -"\n" -"Du behöver kanske placera ekvationerna och variablerna i lämplig ordning så " -"att varje ekvation åtminstone innehåller motsvarande variabel (om automatisk " -"omsortering misslyckades)." - -#: ../libqalculate/BuiltinFunctions.cc:8626 -#: ../libqalculate/BuiltinFunctions.cc:8640 -#: ../libqalculate/BuiltinFunctions.cc:8649 -#, c-format -msgid "Unable to isolate %s." -msgstr "Kan inte isolera %s." +"En systemvid enhet eller variabel har avaktiverats. Den återaktiveras efter " +"att den nya variabeln har tagits bort." -#: ../libqalculate/BuiltinFunctions.cc:8633 +#: ../libqalculate/BuiltinFunctions-util.cc:727 #, c-format -msgid "Inequalities is not allowed in %s()." -msgstr "Olikheter är inte tillåtna i %s()." - -#: ../libqalculate/BuiltinFunctions.cc:8975 -#: ../libqalculate/BuiltinFunctions.cc:8980 -msgid "No differential equation found." -msgstr "Ingen differentialekvation funnen." - -#: ../libqalculate/BuiltinFunctions.cc:8984 -#: ../libqalculate/BuiltinFunctions.cc:9013 -#: ../libqalculate/BuiltinFunctions.cc:9019 -msgid "Unable to solve differential equation." -msgstr "Kunde inte lösa differentialekvation." - -#: ../libqalculate/BuiltinFunctions.cc:9045 -msgid "Unable to find limit." -msgstr "Kan inte hitta gränsvärdet." +msgid "Register %s does not exist. Returning zero." +msgstr "RPN-registret %s finns inte. Returnerar noll." -#: ../libqalculate/BuiltinFunctions.cc:9099 -#: ../libqalculate/BuiltinFunctions.cc:9113 +#: ../libqalculate/BuiltinFunctions-util.cc:794 +#: ../libqalculate/BuiltinFunctions-util.cc:808 msgid "Matrix" msgstr "Matris" -#: ../libqalculate/BuiltinFunctions.cc:9124 -#: ../libqalculate/BuiltinFunctions.cc:9174 +#: ../libqalculate/BuiltinFunctions-util.cc:819 +#: ../libqalculate/BuiltinFunctions-util.cc:869 msgid "Vector" msgstr "Vektor" -#: ../libqalculate/BuiltinFunctions.cc:9139 -#: ../libqalculate/BuiltinFunctions.cc:9185 ../libqalculate/Calculator.cc:12320 +#: ../libqalculate/BuiltinFunctions-util.cc:834 +#: ../libqalculate/BuiltinFunctions-util.cc:880 +#: ../libqalculate/Calculator-plot.cc:135 msgid "Unable to generate plot data with current min, max and step size." msgstr "Kunde inte generera diagramdata med angivet min, max och stegstorlek." -#: ../libqalculate/BuiltinFunctions.cc:9141 -#: ../libqalculate/BuiltinFunctions.cc:9187 +#: ../libqalculate/BuiltinFunctions-util.cc:836 +#: ../libqalculate/BuiltinFunctions-util.cc:882 msgid "Sampling rate must be a positive integer." msgstr "Frekvens måste vara ett positivt heltal." -#: ../libqalculate/BuiltinFunctions.cc:9150 -#: ../libqalculate/BuiltinFunctions.cc:9196 ../libqalculate/Calculator.cc:12290 +#: ../libqalculate/BuiltinFunctions-util.cc:845 +#: ../libqalculate/BuiltinFunctions-util.cc:891 +#: ../libqalculate/Calculator-plot.cc:105 msgid "Unable to generate plot data with current min, max and sampling rate." msgstr "Kunde inte generera diagramdata med angivet min, max och frekvens." -#: ../libqalculate/Calculator.cc:454 ../libqalculate/Calculator.cc:680 +#: ../libqalculate/Calculator-calculate.cc:303 +#: ../libqalculate/Calculator-calculate.cc:428 +msgid "Stack is empty. Filling remaining function arguments with zeroes." +msgstr "RPN-stacken är tom. Fyller återstående funktionsparametrar med nollor." + +#: ../libqalculate/Calculator-calculate.cc:1004 +msgid "calculating..." +msgstr "beräknar..." + +#. "where"-operator +#: ../libqalculate/Calculator-calculate.cc:1130 +#: ../libqalculate/Calculator-calculate.cc:1132 +#: ../libqalculate/Calculator-calculate.cc:1151 +#: ../libqalculate/Calculator-calculate.cc:1153 +#: ../libqalculate/Calculator.cc:1326 +msgid "where" +msgstr "där" + +#: ../libqalculate/Calculator-calculate.cc:1349 +#, c-format +msgid "Unhandled \"where\" expression: %s" +msgstr "Ohanterad \"där\"-uttryck: %s" + +#: ../libqalculate/Calculator-calculate.cc:1567 +#: ../libqalculate/Calculator-calculate.cc:1614 +msgid "timed out" +msgstr "tiden rann ut" + +#: ../libqalculate/Calculator.cc:232 ../libqalculate/Calculator.cc:460 msgid "per" msgstr "per" -#: ../libqalculate/Calculator.cc:456 ../libqalculate/Calculator.cc:682 +#: ../libqalculate/Calculator.cc:234 ../libqalculate/Calculator.cc:462 msgid "times" msgstr "gånger" -#: ../libqalculate/Calculator.cc:458 ../libqalculate/Calculator.cc:684 +#: ../libqalculate/Calculator.cc:236 ../libqalculate/Calculator.cc:464 msgid "plus" msgstr "plus" -#: ../libqalculate/Calculator.cc:460 ../libqalculate/Calculator.cc:686 +#: ../libqalculate/Calculator.cc:238 ../libqalculate/Calculator.cc:466 msgid "minus" msgstr "minus" -#: ../libqalculate/Calculator.cc:462 ../libqalculate/Calculator.cc:688 -#: ../libqalculate/MathStructure.cc:21575 ../libqalculate/Function.cc:1331 -#: ../libqalculate/Function.cc:1339 ../libqalculate/Function.cc:1768 -#: ../libqalculate/Function.cc:1930 ../libqalculate/Function.cc:1938 +#: ../libqalculate/Calculator.cc:240 ../libqalculate/Calculator.cc:468 +#: ../libqalculate/MathStructure-print.cc:3170 ../libqalculate/Function.cc:1361 +#: ../libqalculate/Function.cc:1369 ../libqalculate/Function.cc:1802 +#: ../libqalculate/Function.cc:1964 ../libqalculate/Function.cc:1972 msgid "and" msgstr "och" -#: ../libqalculate/Calculator.cc:831 +#: ../libqalculate/Calculator.cc:611 msgid "Gradians unit is missing. Creating one for this session." msgstr "Gradientenheten saknas. Skapar en för nuvarande session." -#: ../libqalculate/Calculator.cc:832 ../libqalculate/Calculator.cc:840 -#: ../libqalculate/Calculator.cc:848 +#: ../libqalculate/Calculator.cc:612 ../libqalculate/Calculator.cc:620 +#: ../libqalculate/Calculator.cc:628 msgid "Angle/Plane Angle" msgstr "Vinkel/Planvinkel" -#: ../libqalculate/Calculator.cc:839 +#: ../libqalculate/Calculator.cc:619 msgid "Radians unit is missing. Creating one for this session." msgstr "Radianenheten saknas. Skapar en för nuvarande session." -#: ../libqalculate/Calculator.cc:847 +#: ../libqalculate/Calculator.cc:627 msgid "Degrees unit is missing. Creating one for this session." msgstr "Gradenheten saknas. Skapar en för nuvarande session." -#. "where"-operator -#: ../libqalculate/Calculator.cc:1544 ../libqalculate/Calculator.cc:3298 -#: ../libqalculate/Calculator.cc:3300 ../libqalculate/Calculator.cc:3319 -#: ../libqalculate/Calculator.cc:3321 -msgid "where" -msgstr "där" - -#: ../libqalculate/Calculator.cc:2027 ../libqalculate/Calculator.cc:2028 -#: ../libqalculate/Calculator.cc:11818 ../libqalculate/Calculator.cc:11955 -#: ../libqalculate/Calculator.cc:12013 +#: ../libqalculate/Calculator.cc:1695 ../libqalculate/Calculator.cc:1696 +#: ../libqalculate/Calculator.cc:1700 +#: ../libqalculate/Calculator-definitions.cc:3285 +#: ../libqalculate/Calculator-definitions.cc:3455 +#: ../libqalculate/Calculator-definitions.cc:3513 msgid "Currency" msgstr "Valuta" -#: ../libqalculate/Calculator.cc:2563 ../libqalculate/Calculator.cc:2688 -msgid "Stack is empty. Filling remaining function arguments with zeroes." -msgstr "RPN-stacken är tom. Fyller återstående funktionsparametrar med nollor." - -#: ../libqalculate/Calculator.cc:3180 -msgid "calculating..." -msgstr "beräknar..." - -#: ../libqalculate/Calculator.cc:3502 -#, c-format -msgid "Unhandled \"where\" expression: %s" -msgstr "Ohanterad \"där\"-uttryck: %s" - -#: ../libqalculate/Calculator.cc:5259 +#: ../libqalculate/Calculator.cc:2635 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name of \"%s\", or " @@ -2618,7 +2636,7 @@ "\"%s\" tillåts inte längre i namn. Vänligen ändra namnet på \"%s\". Annars " "kommer variabeln att gå förlorad." -#: ../libqalculate/Calculator.cc:5277 +#: ../libqalculate/Calculator.cc:2653 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name \"%s\", or " @@ -2627,7 +2645,7 @@ "\"%s\" tillåts inte längre i namn. Vänligen ändra namnet på \"%s\". Annars " "kommer funktionen att gå förlorad." -#: ../libqalculate/Calculator.cc:5294 +#: ../libqalculate/Calculator.cc:2670 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name \"%s\", or " @@ -2636,32 +2654,84 @@ "\"%s\" tillåts inte längre i namn. Vänligen ändra namnet på \"%s\". Annars " "kommer enheten att gå förlorad." -#: ../libqalculate/Calculator.cc:6883 ../libqalculate/Calculator.cc:6927 -#: ../libqalculate/Calculator.cc:6930 ../libqalculate/Calculator.cc:8101 -#: ../libqalculate/Calculator.cc:8110 ../libqalculate/Calculator.cc:8165 -#: ../libqalculate/Calculator.cc:8227 ../libqalculate/Calculator.cc:8248 -#: ../libqalculate/Calculator.cc:8249 +#: ../libqalculate/Calculator.cc:2877 +#, c-format +msgid "Name \"%s\" is in use. Replacing with \"%s\"." +msgstr "Namnet \"%s\" är upptaget. Ändrar till \"%s\"." + +#: ../libqalculate/Calculator-definitions.cc:763 ../libqalculate/DataSet.cc:540 +#, c-format +msgid "File not identified as Qalculate! definitions file: %s." +msgstr "Filen identifierades inte som en Qalculate! definitionsfil: %s." + +#: ../libqalculate/Calculator-definitions.cc:2870 +#: ../libqalculate/DataSet.cc:363 +msgid "Object" +msgstr "Objekt" + +#: ../libqalculate/Calculator-definitions.cc:2879 +#: ../libqalculate/DataSet.cc:364 +msgid "Property" +msgstr "Egenskap" + +#: ../libqalculate/Calculator-definitions.cc:3178 +msgid "column" +msgstr "kolumn" + +#: ../libqalculate/Calculator-definitions.cc:3181 +msgid "Column " +msgstr "Kolumn" + +#: ../libqalculate/Calculator-definitions.cc:3632 +#: ../libqalculate/Calculator-definitions.cc:3633 +#: ../libqalculate/Calculator-definitions.cc:3637 +#: ../libqalculate/Calculator-definitions.cc:3640 +#: ../libqalculate/Calculator-definitions.cc:3672 +#: ../libqalculate/Calculator-definitions.cc:3673 +#: ../libqalculate/Calculator-definitions.cc:3676 +#: ../libqalculate/Calculator-definitions.cc:3695 +#: ../libqalculate/Calculator-definitions.cc:3696 +#: ../libqalculate/Calculator-definitions.cc:3699 +#: ../libqalculate/Calculator-definitions.cc:3719 +#: ../libqalculate/Calculator-definitions.cc:3720 +#: ../libqalculate/Calculator-definitions.cc:3723 +#, c-format +msgid "Failed to download exchange rates from %s: %s." +msgstr "Misslyckades med att ladda ner växelkurser från %s: %s." + +#. ignore operators +#: ../libqalculate/Calculator-parse.cc:1668 +#: ../libqalculate/Calculator-parse.cc:1721 +#: ../libqalculate/Calculator-parse.cc:1725 +#: ../libqalculate/Calculator-parse.cc:2926 +#: ../libqalculate/Calculator-parse.cc:2935 +#: ../libqalculate/Calculator-parse.cc:2990 +#: ../libqalculate/Calculator-parse.cc:3055 +#: ../libqalculate/Calculator-parse.cc:3077 +#: ../libqalculate/Calculator-parse.cc:3078 #, c-format msgid "Misplaced operator(s) \"%s\" ignored" msgstr "Malplacerad(e) \"%s\" ignorerades" -#: ../libqalculate/Calculator.cc:6924 ../libqalculate/Calculator.cc:8250 +#. ignore operators +#: ../libqalculate/Calculator-parse.cc:1717 +#: ../libqalculate/Calculator-parse.cc:3079 #, c-format msgid "Misplaced '%c' ignored" msgstr "Malplacerat '%c' ignorerades" -#: ../libqalculate/Calculator.cc:6962 ../libqalculate/Function.cc:1489 -#: ../libqalculate/Function.cc:1520 +#: ../libqalculate/Calculator-parse.cc:1759 ../libqalculate/Function.cc:1519 +#: ../libqalculate/Function.cc:1550 #, c-format msgid "Internal id %s does not exist." msgstr "Internt id %s finns inte." -#: ../libqalculate/Calculator.cc:6980 +#: ../libqalculate/Calculator-parse.cc:1779 #, c-format msgid "\"%s\" is not a valid variable/function/unit." msgstr "\"%s\" motsvarar inte någon giltig variabel/funktion/enhet." -#: ../libqalculate/Calculator.cc:6995 +#: ../libqalculate/Calculator-parse.cc:1794 #, c-format msgid "" "Trailing characters \"%s\" (not a valid variable/function/unit) in number " @@ -2670,87 +2740,52 @@ "Överblivna tecken i uttrycket \"%s\" (inte någon giltig variabel/funktion/" "enhet) ignorerades i talet \"%s\"." -#: ../libqalculate/Calculator.cc:7261 +#: ../libqalculate/Calculator-parse.cc:2072 msgid "RPN syntax error. Values left at the end of the RPN expression." msgstr "RPN syntaxfel. Värden kvar i slutet av RPN uttryck." -#: ../libqalculate/Calculator.cc:7264 ../libqalculate/Calculator.cc:7355 +#: ../libqalculate/Calculator-parse.cc:2075 +#: ../libqalculate/Calculator-parse.cc:2166 msgid "Unused stack values." msgstr "Oanvända stackvärden." -#: ../libqalculate/Calculator.cc:7397 ../libqalculate/Calculator.cc:7605 +#: ../libqalculate/Calculator-parse.cc:2208 +#: ../libqalculate/Calculator-parse.cc:2416 #, c-format msgid "RPN syntax error. Operator '%c' not supported." msgstr "RPN syntaxfel. Operator '%c' stöds ej." -#: ../libqalculate/Calculator.cc:7443 +#: ../libqalculate/Calculator-parse.cc:2254 msgid "RPN syntax error. Stack is empty." msgstr "RPN syntaxfel. Stacken är tom." -#: ../libqalculate/Calculator.cc:7464 +#: ../libqalculate/Calculator-parse.cc:2275 msgid "RPN syntax error. Operator ignored as there where only one stack value." msgstr "" "RPN syntaxfel. Operatorn ignorerades eftersom det enbart fanns ett " "stackvärde kvar." -#: ../libqalculate/Calculator.cc:8525 -#, c-format -msgid "Name \"%s\" is in use. Replacing with \"%s\"." -msgstr "Namnet \"%s\" är upptaget. Ändrar till \"%s\"." - -#: ../libqalculate/Calculator.cc:9212 ../libqalculate/DataSet.cc:539 -#, c-format -msgid "File not identified as Qalculate! definitions file: %s." -msgstr "Filen identifierades inte som en Qalculate! definitionsfil: %s." - -#: ../libqalculate/Calculator.cc:11319 ../libqalculate/DataSet.cc:362 -msgid "Object" -msgstr "Objekt" - -#: ../libqalculate/Calculator.cc:11328 ../libqalculate/DataSet.cc:363 -msgid "Property" -msgstr "Egenskap" - -#: ../libqalculate/Calculator.cc:11627 -msgid "column" -msgstr "kolumn" - -#: ../libqalculate/Calculator.cc:11630 -msgid "Column " -msgstr "Kolumn" - -#: ../libqalculate/Calculator.cc:11706 ../libqalculate/Calculator.cc:11753 -msgid "timed out" -msgstr "tiden rann ut" - -#: ../libqalculate/Calculator.cc:12125 ../libqalculate/Calculator.cc:12126 -#: ../libqalculate/Calculator.cc:12130 ../libqalculate/Calculator.cc:12133 -#: ../libqalculate/Calculator.cc:12165 ../libqalculate/Calculator.cc:12166 -#: ../libqalculate/Calculator.cc:12169 ../libqalculate/Calculator.cc:12188 -#: ../libqalculate/Calculator.cc:12189 ../libqalculate/Calculator.cc:12192 -#, c-format -msgid "Failed to download exchange rates from %s: %s." -msgstr "Misslyckades med att ladda ner växelkurser från %s: %s." - -#: ../libqalculate/Calculator.cc:12286 ../libqalculate/Calculator.cc:12316 -#: ../libqalculate/Calculator.cc:12346 ../libqalculate/Calculator.cc:12685 +#: ../libqalculate/Calculator-plot.cc:101 +#: ../libqalculate/Calculator-plot.cc:131 +#: ../libqalculate/Calculator-plot.cc:161 +#: ../libqalculate/Calculator-plot.cc:498 msgid "It took too long to generate the plot data." msgstr "Det tog för lång tid att generara data till diagrammet." -#: ../libqalculate/Calculator.cc:12380 +#: ../libqalculate/Calculator-plot.cc:193 msgid "No extension in file name. Saving as PNG image." msgstr "Inget tillägg i filnamnet. Sparar som PNG-bild." -#: ../libqalculate/Calculator.cc:12399 +#: ../libqalculate/Calculator-plot.cc:212 msgid "Unknown extension in file name. Saving as PNG image." msgstr "Okänt tillägg i filnamnet. Sparar som PNG-bild." -#: ../libqalculate/Calculator.cc:12616 +#: ../libqalculate/Calculator-plot.cc:429 #, c-format msgid "Could not create temporary file %s" msgstr "Kunde inte skapa temporär fil %s" -#: ../libqalculate/Calculator.cc:12732 +#: ../libqalculate/Calculator-plot.cc:545 msgid "" "Failed to invoke gnuplot. Make sure that you have gnuplot installed in your " "path." @@ -2758,63 +2793,72 @@ "Misslyckades med att aktivera gnuplot. Se till att du har gnuplot " "installerat i sökvägen för program." -#: ../libqalculate/DataSet.cc:388 +#: ../libqalculate/DataSet.cc:389 #, c-format msgid "Object %s not available in data set." msgstr "Okjektet %s finns inte i dataset." -#: ../libqalculate/DataSet.cc:398 +#: ../libqalculate/DataSet.cc:399 #, c-format msgid "Property %s not available in data set." msgstr "Egenskap %s är inte tillgänglig i dataset." -#: ../libqalculate/DataSet.cc:403 +#: ../libqalculate/DataSet.cc:404 #, c-format msgid "Property %s not defined for object %s." msgstr "Egenskap %s inte definierad för objekt %s." -#: ../libqalculate/DataSet.cc:516 ../libqalculate/DataSet.cc:524 +#: ../libqalculate/DataSet.cc:517 ../libqalculate/DataSet.cc:525 #, c-format msgid "Unable to load data objects in %s." msgstr "Kunde inhämte dataobjekt i %s." -#: ../libqalculate/DataSet.cc:1042 +#: ../libqalculate/DataSet.cc:1043 msgid "data property" msgstr "dataegenskap" -#: ../libqalculate/DataSet.cc:1044 +#: ../libqalculate/DataSet.cc:1045 msgid "name of a data property" msgstr "namn på dataegenskap" -#: ../libqalculate/DataSet.cc:1052 ../libqalculate/DataSet.cc:1068 +#: ../libqalculate/DataSet.cc:1053 ../libqalculate/DataSet.cc:1069 msgid "no properties available" msgstr "inga egenskaper tillgängliga" -#: ../libqalculate/DataSet.cc:1102 +#: ../libqalculate/DataSet.cc:1103 #, c-format msgid "" "Data set \"%s\" has no object key that supports the provided argument type." msgstr "" "Dataset \"%s\" har ingen objektnyckel som stödjer tillhandahållen argumenttyp" -#: ../libqalculate/DataSet.cc:1107 +#: ../libqalculate/DataSet.cc:1108 msgid "data object" msgstr "dataobjekt" -#: ../libqalculate/DataSet.cc:1110 +#: ../libqalculate/DataSet.cc:1111 msgid "an object from" msgstr "ett objekt från" -#: ../libqalculate/DataSet.cc:1137 +#: ../libqalculate/DataSet.cc:1138 msgid "use" msgstr "använd" -#: ../libqalculate/MathStructure.cc:265 +#: ../libqalculate/MathStructure-calculate.cc:76 #, c-format msgid "Required assumption: %s." msgstr "Nödvändigt antagande: %s." -#: ../libqalculate/MathStructure.cc:4031 ../libqalculate/MathStructure.cc:4052 +#: ../libqalculate/MathStructure-calculate.cc:95 +#: ../libqalculate/MathStructure-calculate.cc:117 +#: ../libqalculate/MathStructure-calculate.cc:148 +#: ../libqalculate/MathStructure-integrate.cc:7086 +#, c-format +msgid "To avoid division by zero, the following must be true: %s." +msgstr "För att undvika division med noll, krävs att följande är sant: %s." + +#: ../libqalculate/MathStructure-calculate.cc:1653 +#: ../libqalculate/MathStructure-calculate.cc:1675 #, c-format msgid "" "The second matrix must have as many rows (was %s) as the first has columns " @@ -2823,30 +2867,40 @@ "Den andra matrisen måste ha lika många rader (var %s) som den första har " "kolumner (var %s) för matrismultiplikation." -#: ../libqalculate/MathStructure.cc:8936 ../libqalculate/MathStructure.cc:8977 -#: ../libqalculate/MathStructure.cc:9010 ../libqalculate/MathStructure.cc:9077 -#: ../libqalculate/MathStructure.cc:9105 ../libqalculate/MathStructure.cc:9124 -#: ../libqalculate/MathStructure.cc:9143 ../libqalculate/MathStructure.cc:9162 -#: ../libqalculate/MathStructure.cc:9270 ../libqalculate/MathStructure.cc:16270 -#: ../libqalculate/MathStructure.cc:16661 +#: ../libqalculate/MathStructure-calculate.cc:6072 +#: ../libqalculate/MathStructure-calculate.cc:6113 +#: ../libqalculate/MathStructure-calculate.cc:6146 +#: ../libqalculate/MathStructure-calculate.cc:6213 +#: ../libqalculate/MathStructure-calculate.cc:6241 +#: ../libqalculate/MathStructure-calculate.cc:6260 +#: ../libqalculate/MathStructure-calculate.cc:6279 +#: ../libqalculate/MathStructure-calculate.cc:6298 +#: ../libqalculate/MathStructure-calculate.cc:6406 +#: ../libqalculate/MathStructure-factor.cc:413 +#: ../libqalculate/MathStructure-factor.cc:1304 msgid "This is a bug. Please report it." msgstr "Detta är en bug. Var vänlig rapportera felet." -#: ../libqalculate/MathStructure.cc:9353 ../libqalculate/Function.cc:527 +#: ../libqalculate/MathStructure-calculate.cc:6495 +#: ../libqalculate/Function.cc:557 msgid "No unknown variable/symbol was found." msgstr "Ingen okänd variabel/symbol hittades." -#: ../libqalculate/MathStructure.cc:11752 -#: ../libqalculate/MathStructure.cc:11757 -#, c-format -msgid "Limit for %s determined graphically." -msgstr "Gränsvärde för %s bestämt grafiskt." +#: ../libqalculate/MathStructure-convert.cc:262 +msgid "" +"Calculations involving conversion of units without proportional linear " +"relationship (e.g. with multiple temperature units), might give unexpected " +"results and is not recommended." +msgstr "" +"Beräkningar som involverar omvandling av enheter utan proportionella linjära " +"förhållanden (t.ex. med flera olika temperaturenheter), kan ge oförutsedda " +"svar och rekommenderas ej." -#: ../libqalculate/MathStructure.cc:12582 +#: ../libqalculate/MathStructure-eval.cc:754 msgid "Interval potentially calculated wide." msgstr "Intervall potentiellt beräknat brett." -#: ../libqalculate/MathStructure.cc:13500 +#: ../libqalculate/MathStructure-eval.cc:2024 msgid "" "Calculation of uncertainty propagation partially failed (using interval " "arithmetic instead when necessary)." @@ -2854,7 +2908,7 @@ "Beräkning av felfortplantning misslyckades delvis (intervallaritmetik " "används istället när nödvändigt)." -#: ../libqalculate/MathStructure.cc:13638 +#: ../libqalculate/MathStructure-eval.cc:2170 msgid "" "Calculation of uncertainty propagation failed (using interval arithmetic " "instead)." @@ -2862,7 +2916,7 @@ "Beräkning av felfortplantning misslyckades (intervallaritmetik används " "istället)." -#: ../libqalculate/MathStructure.cc:18517 +#: ../libqalculate/MathStructure-factor.cc:3160 msgid "" "Because of time constraints only a limited number of combinations of terms " "were tried during factorization. Repeat factorization to try other random " @@ -2872,55 +2926,80 @@ "kombinationer av termer under faktorisering. Uprepa faktoriseringen för att " "pröva andra slumpmässiga kombinationer." -#: ../libqalculate/MathStructure.cc:21769 -msgid "undefined" -msgstr "odefinierad" +#: ../libqalculate/MathStructure-integrate.cc:7668 +#: ../libqalculate/MathStructure-integrate.cc:7743 +msgid "Unable to integrate the expression exact." +msgstr "Kan inte integrera uttrycket exakt." + +#: ../libqalculate/MathStructure-integrate.cc:7707 +msgid "Definite integral was approximated." +msgstr "Definitiv integral approximerades." + +#: ../libqalculate/MathStructure-isolatex.cc:999 +#: ../libqalculate/MathStructure-isolatex.cc:1176 +#: ../libqalculate/MathStructure-isolatex.cc:1815 +#: ../libqalculate/MathStructure-isolatex.cc:2335 +#: ../libqalculate/MathStructure-isolatex.cc:2401 +#: ../libqalculate/MathStructure-isolatex.cc:2451 +#: ../libqalculate/MathStructure-isolatex.cc:2472 +#: ../libqalculate/MathStructure-isolatex.cc:2530 +#: ../libqalculate/MathStructure-isolatex.cc:2656 +#: ../libqalculate/MathStructure-isolatex.cc:2801 +#, c-format +msgid "Interval arithmetic was disabled during calculation of %s." +msgstr "Intervallarithmetik inaktiverades under beräkning av %s." + +#: ../libqalculate/MathStructure-isolatex.cc:2800 +#, c-format +msgid "Not all complex roots were calculated for %s." +msgstr "Alla komplexa rötter beräknades ej för %s." -#: ../libqalculate/MathStructure.cc:21810 +#: ../libqalculate/MathStructure-isolatex.cc:4394 +#, c-format +msgid "Only one or two of the roots where calculated for %s." +msgstr "Enbart en eller två av rötterna beräknades för %s." + +#: ../libqalculate/MathStructure-limit.cc:967 +#: ../libqalculate/MathStructure-limit.cc:972 +#, c-format +msgid "Limit for %s determined graphically." +msgstr "Gränsvärde för %s bestämt grafiskt." + +#: ../libqalculate/MathStructure-matrixvector.cc:62 #, c-format msgid "Unsolvable comparison at element %s when trying to rank vector." msgstr "Olöslig jämförelse vid element %s, vid rangordning av vektor." -#: ../libqalculate/MathStructure.cc:21860 +#: ../libqalculate/MathStructure-matrixvector.cc:112 #, c-format msgid "Unsolvable comparison at element %s when trying to sort vector." msgstr "Olöslig jämförelse vid element %s, vid sortering av vektor." -#: ../libqalculate/MathStructure.cc:22285 +#: ../libqalculate/MathStructure-matrixvector.cc:537 msgid "The determinant can only be calculated for square matrices." msgstr "Determinanten kan enbart beräknas för kvadratiska matriser." -#: ../libqalculate/MathStructure.cc:22348 +#: ../libqalculate/MathStructure-matrixvector.cc:600 msgid "The permanent can only be calculated for square matrices." msgstr "Permanenten kan enbart beräknas för kvadratiska matriser." -#: ../libqalculate/MathStructure.cc:22435 +#: ../libqalculate/MathStructure-matrixvector.cc:687 msgid "Inverse of singular matrix." msgstr "Invers av singulär matris." -#: ../libqalculate/MathStructure.cc:22789 -msgid "" -"Calculations involving conversion of units without proportional linear " -"relationship (e.g. with multiple temperature units), might give unexpected " -"results and is not recommended." -msgstr "" -"Beräkningar som involverar omvandling av enheter utan proportionella linjära " -"förhållanden (t.ex. med flera olika temperaturenheter), kan ge oförutsedda " -"svar och rekommenderas ej." - -#: ../libqalculate/MathStructure.cc:24092 -#: ../libqalculate/MathStructure.cc:24135 +#: ../libqalculate/MathStructure-matrixvector.cc:817 +#: ../libqalculate/MathStructure-matrixvector.cc:860 msgid "Too many data points" msgstr "För många datapunkter" -#: ../libqalculate/MathStructure.cc:24099 +#: ../libqalculate/MathStructure-matrixvector.cc:824 msgid "" "The selected min and max do not result in a positive, finite number of data " "points" msgstr "" "Valt min och max resulterar inte i ett positive, ändligt antal datapunkter" -#: ../libqalculate/MathStructure.cc:24132 +#: ../libqalculate/MathStructure-matrixvector.cc:857 msgid "" "The selected min, max and step size do not result in a positive, finite " "number of data points" @@ -2928,37 +3007,17 @@ "Valt min, max och stegstorlek resulterar inte i ett positive, ändligt antal " "datapunkter" -#: ../libqalculate/MathStructure.cc:32190 -#: ../libqalculate/MathStructure.cc:32368 -#: ../libqalculate/MathStructure.cc:33005 -#: ../libqalculate/MathStructure.cc:33525 -#: ../libqalculate/MathStructure.cc:33591 -#: ../libqalculate/MathStructure.cc:33641 -#: ../libqalculate/MathStructure.cc:33662 -#: ../libqalculate/MathStructure.cc:33720 -#: ../libqalculate/MathStructure.cc:33846 -#: ../libqalculate/MathStructure.cc:33990 -#, c-format -msgid "Interval arithmetic was disabled during calculation of %s." -msgstr "Intervallarithmetik inaktiverades under beräkning av %s." - -#: ../libqalculate/MathStructure.cc:33989 -#, c-format -msgid "Not all complex roots were calculated for %s." -msgstr "Alla komplexa rötter beräknades ej för %s." - -#: ../libqalculate/MathStructure.cc:35479 -#, c-format -msgid "Only one or two of the roots where calculated for %s." -msgstr "Enbart en eller två av rötterna beräknades för %s." +#: ../libqalculate/MathStructure-print.cc:3364 +msgid "undefined" +msgstr "odefinierad" -#: ../libqalculate/Function.cc:171 +#: ../libqalculate/Function.cc:185 #, c-format msgid "%s() requires that %s" msgstr "%s() kräver att %s" -#: ../libqalculate/Function.cc:326 ../libqalculate/Function.cc:385 -#: ../libqalculate/Function.cc:445 +#: ../libqalculate/Function.cc:351 ../libqalculate/Function.cc:413 +#: ../libqalculate/Function.cc:474 #, c-format msgid "" "Additional arguments for function %s() was ignored. Function can only use %s " @@ -2967,200 +3026,202 @@ "Övertaliga parametrar för funktionen %s() ignorerades. Funktionen kan inte " "använda fler än %s parametrar." -#: ../libqalculate/Function.cc:466 +#: ../libqalculate/Function.cc:495 #, c-format msgid "You need at least %s argument(s) (%s) in function %s()." msgstr "Det krävs minst %s parametrar (%s) i funktionen %s()." -#: ../libqalculate/Function.cc:468 +#: ../libqalculate/Function.cc:497 #, c-format msgid "You need at least %s argument(s) in function %s()." msgstr "Det krävs minst %s parametrar i funktionen %s()." -#: ../libqalculate/Function.cc:1321 +#: ../libqalculate/Function.cc:1351 msgid "a free value" msgstr "ett valfritt värde" -#: ../libqalculate/Function.cc:1326 +#: ../libqalculate/Function.cc:1356 msgid "that is nonzero" msgstr "som är icke-noll" -#: ../libqalculate/Function.cc:1334 +#: ../libqalculate/Function.cc:1364 msgid "that is rational (polynomial)" msgstr "som är rationellt (polynom)" -#: ../libqalculate/Function.cc:1342 +#: ../libqalculate/Function.cc:1372 msgid "that fulfills the condition:" msgstr "som uppfyller villkoret:" -#: ../libqalculate/Function.cc:1345 +#: ../libqalculate/Function.cc:1375 msgid "Argument" msgstr "Parameter" -#: ../libqalculate/Function.cc:1409 +#: ../libqalculate/Function.cc:1439 #, c-format msgid "Argument %s in %s() must be %s." msgstr "Parameter %s i %s() måste vara %s." -#: ../libqalculate/Function.cc:1411 +#: ../libqalculate/Function.cc:1441 #, c-format msgid "Argument %s, %s, in %s() must be %s." msgstr "Parameter %s, %s, i %s() måste vara %s." -#: ../libqalculate/Function.cc:1749 +#: ../libqalculate/Function.cc:1783 msgid "a rational number" msgstr "ett rationellt nummer" -#: ../libqalculate/Function.cc:1751 +#: ../libqalculate/Function.cc:1785 msgid "a number" msgstr "ett nummer" -#: ../libqalculate/Function.cc:1753 +#: ../libqalculate/Function.cc:1787 msgid "a real number" msgstr "ett reellt nummer" -#: ../libqalculate/Function.cc:1758 ../libqalculate/Function.cc:1911 -#: ../libqalculate/Function.cc:1916 +#: ../libqalculate/Function.cc:1792 ../libqalculate/Function.cc:1945 +#: ../libqalculate/Function.cc:1950 msgid ">=" msgstr ">=" -#: ../libqalculate/Function.cc:1760 +#: ../libqalculate/Function.cc:1794 msgid ">" msgstr ">" -#: ../libqalculate/Function.cc:1772 ../libqalculate/Function.cc:1933 -#: ../libqalculate/Function.cc:1940 +#: ../libqalculate/Function.cc:1806 ../libqalculate/Function.cc:1967 +#: ../libqalculate/Function.cc:1974 msgid "<=" msgstr "<=" -#: ../libqalculate/Function.cc:1774 +#: ../libqalculate/Function.cc:1808 msgid "<" msgstr "<" -#: ../libqalculate/Function.cc:1908 +#: ../libqalculate/Function.cc:1942 msgid "an integer" msgstr "ett heltal" -#: ../libqalculate/Function.cc:1965 +#: ../libqalculate/Function.cc:1999 msgid "symbol" msgstr "symbol" -#: ../libqalculate/Function.cc:1966 +#: ../libqalculate/Function.cc:2000 msgid "an unknown variable/symbol" msgstr "en okänd variabel/symbol" -#: ../libqalculate/Function.cc:1979 +#: ../libqalculate/Function.cc:2013 msgid "text" msgstr "text" -#: ../libqalculate/Function.cc:1980 +#: ../libqalculate/Function.cc:2014 msgid "a text string" msgstr "en textsträng" -#: ../libqalculate/Function.cc:2002 +#: ../libqalculate/Function.cc:2036 msgid "date" msgstr "datum" -#: ../libqalculate/Function.cc:2003 +#: ../libqalculate/Function.cc:2037 msgid "a date" msgstr "ett datum" -#: ../libqalculate/Function.cc:2052 +#: ../libqalculate/Function.cc:2086 msgid "a vector with " msgstr "en vektor med " -#: ../libqalculate/Function.cc:2064 +#: ../libqalculate/Function.cc:2098 msgid "a vector" msgstr "en vektor" -#: ../libqalculate/Function.cc:2113 +#: ../libqalculate/Function.cc:2147 msgid "a square matrix" msgstr "en kvadratisk matris" -#: ../libqalculate/Function.cc:2115 +#: ../libqalculate/Function.cc:2149 msgid "a matrix" msgstr "en matris" -#: ../libqalculate/Function.cc:2130 +#: ../libqalculate/Function.cc:2164 msgid "object" msgstr "objekt" -#: ../libqalculate/Function.cc:2131 +#: ../libqalculate/Function.cc:2165 msgid "a valid function, unit or variable name" msgstr "ett giltigt funktions, enhets eller variabelnamn" -#: ../libqalculate/Function.cc:2145 +#: ../libqalculate/Function.cc:2179 msgid "a valid function name" msgstr "ett giltigt funktionsnamn" -#: ../libqalculate/Function.cc:2158 +#: ../libqalculate/Function.cc:2192 msgid "unit" msgstr "enhet" -#: ../libqalculate/Function.cc:2159 +#: ../libqalculate/Function.cc:2193 msgid "a valid unit name" msgstr "ett giltigt enhetsnamn" -#: ../libqalculate/Function.cc:2173 +#: ../libqalculate/Function.cc:2207 msgid "a valid variable name" msgstr "ett giltigt variabelnamn" -#: ../libqalculate/Function.cc:2186 +#: ../libqalculate/Function.cc:2220 msgid "file" msgstr "fil" -#: ../libqalculate/Function.cc:2187 +#: ../libqalculate/Function.cc:2221 msgid "a valid file name" msgstr "ett giltigt filnamn" -#: ../libqalculate/Function.cc:2200 +#: ../libqalculate/Function.cc:2234 msgid "boolean" msgstr "boolskt värde" -#: ../libqalculate/Function.cc:2201 +#: ../libqalculate/Function.cc:2235 msgid "a boolean (0 or 1)" msgstr "ett boolskt värde (0 eller 1)" -#: ../libqalculate/Function.cc:2212 +#: ../libqalculate/Function.cc:2246 msgid "an angle or a number (using the default angle unit)" msgstr "en vinkel eller ett tal (som använder inställd vinkelenhet)" -#: ../libqalculate/Number.cc:254 ../libqalculate/Number.cc:8251 +#: ../libqalculate/Number.cc:263 ../libqalculate/Number.cc:10175 msgid "" "Cannot display numbers greater than 9999 or less than -9999 as roman " "numerals." msgstr "" "Kan inte visa tal större än 9999 eller mindre än -9999 som romerska siffror." -#: ../libqalculate/Number.cc:351 +#: ../libqalculate/Number.cc:363 #, c-format msgid "Character '%s' was ignored in the number \"%s\" in bijective base-26." msgstr "Tecken '%s' ignorerades i numret \"%s\" med bijektiv talbas 26." -#: ../libqalculate/Number.cc:433 ../libqalculate/Number.cc:474 -#: ../libqalculate/Number.cc:501 +#. digit value is higher than allowed by the base: show a warning, but use anyway +#. digit value is higher than allowed by base: show a warning, but use anyway +#: ../libqalculate/Number.cc:464 ../libqalculate/Number.cc:514 +#: ../libqalculate/Number.cc:544 #, c-format msgid "Digit '%s' is too high for number base." msgstr "Siffran '%s' är för hög för talbasen." -#: ../libqalculate/Number.cc:551 +#: ../libqalculate/Number.cc:601 msgid "" "Assuming the unusual practice of letting a last capital I mean 2 in a roman " "numeral." msgstr "Antar att ett sista stort I avses betyda 2." -#: ../libqalculate/Number.cc:635 ../libqalculate/Number.cc:662 -#: ../libqalculate/Number.cc:667 +#: ../libqalculate/Number.cc:685 ../libqalculate/Number.cc:712 +#: ../libqalculate/Number.cc:717 #, c-format msgid "Error in roman numerals: %s." msgstr "Fel i romerska siffor: \"%s\"." -#: ../libqalculate/Number.cc:672 +#: ../libqalculate/Number.cc:722 #, c-format msgid "Unknown roman numeral: %c." msgstr "Okänd romersk siffra: %c." -#: ../libqalculate/Number.cc:730 +#: ../libqalculate/Number.cc:780 #, c-format msgid "" "Errors in roman numerals: \"%s\". Interpreted as %s, which should be written " @@ -3168,76 +3229,78 @@ msgstr "" "Fel i romerska siffor: \"%s\". Tolkat som %s, vilket borde skrivits %s." -#: ../libqalculate/Number.cc:818 +#: ../libqalculate/Number.cc:881 msgid "Too large exponent." msgstr "För stor exponent." -#: ../libqalculate/Number.cc:850 +#. only allow decimals after last ":" +#: ../libqalculate/Number.cc:917 msgid "':' in decimal number ignored (decimal point detected)." msgstr "':' i decimalt tal ignorerades (decimalkomma upptäckt)." -#: ../libqalculate/Number.cc:1950 ../libqalculate/Number.cc:2072 +#. test calculated floating point value and show mpfr errors (show as errors if error_level > 1, show as warnings if error_level = 1, do not generate message if error_level is zero) +#: ../libqalculate/Number.cc:2035 ../libqalculate/Number.cc:2160 msgid "Floating point underflow" msgstr "Flyttalsbottning" -#: ../libqalculate/Number.cc:1951 ../libqalculate/Number.cc:2073 +#: ../libqalculate/Number.cc:2036 ../libqalculate/Number.cc:2161 msgid "Floating point overflow" msgstr "Flyttalsspill" -#: ../libqalculate/Number.cc:1952 ../libqalculate/Number.cc:2074 +#: ../libqalculate/Number.cc:2037 ../libqalculate/Number.cc:2162 msgid "Floating point division by zero exception" msgstr "Flyttalsundantag: division med noll" -#: ../libqalculate/Number.cc:1953 ../libqalculate/Number.cc:2077 +#: ../libqalculate/Number.cc:2038 ../libqalculate/Number.cc:2165 msgid "Floating point not a number exception" msgstr "Flyttalsundantag: inte ett tal" -#: ../libqalculate/Number.cc:1954 ../libqalculate/Number.cc:2075 +#: ../libqalculate/Number.cc:2039 ../libqalculate/Number.cc:2163 msgid "Floating point range exception" msgstr "Flyttalsomfångsundantag" -#: ../libqalculate/Number.cc:3528 +#: ../libqalculate/Number.cc:3637 msgid "Division by zero." msgstr "Division med noll." #. 0^0 -#: ../libqalculate/Number.cc:3534 +#: ../libqalculate/Number.cc:3643 msgid "0^0 might be considered undefined" msgstr "0^0 kan anses vara odefinierat" -#: ../libqalculate/Number.cc:3541 +#: ../libqalculate/Number.cc:3650 msgid "The result of 0^i is possibly undefined" msgstr "Resulatatet av 0^i är möjligen odefinierat" -#: ../libqalculate/Number.cc:3590 ../libqalculate/Number.cc:5389 -#: ../libqalculate/Number.cc:5500 ../libqalculate/Number.cc:5824 -#: ../libqalculate/Number.cc:5832 ../libqalculate/Number.cc:5865 -#: ../libqalculate/Number.cc:5962 ../libqalculate/Number.cc:6111 -#: ../libqalculate/Number.cc:6223 +#: ../libqalculate/Number.cc:3699 ../libqalculate/Number.cc:6103 +#: ../libqalculate/Number.cc:6214 ../libqalculate/Number.cc:6538 +#: ../libqalculate/Number.cc:6546 ../libqalculate/Number.cc:6579 +#: ../libqalculate/Number.cc:6676 ../libqalculate/Number.cc:6825 +#: ../libqalculate/Number.cc:6937 msgid "Interval calculated wide." msgstr "Intervall beräknat brett." -#: ../libqalculate/Number.cc:4942 -msgid "Cannot handle an argument (s) that large for Riemann Zeta." -msgstr "" -"Kan inte hantera ett så stort tal för parametern (s) till Riemann Zeta." - -#: ../libqalculate/Number.cc:5017 ../libqalculate/Number.cc:5119 -#: ../libqalculate/Number.cc:5150 ../libqalculate/Number.cc:5181 -#: ../libqalculate/Number.cc:6568 +#: ../libqalculate/Number.cc:5126 ../libqalculate/Number.cc:5352 +#: ../libqalculate/Number.cc:5439 ../libqalculate/Number.cc:5723 +#: ../libqalculate/Number.cc:5809 ../libqalculate/Number.cc:5895 +#: ../libqalculate/Number.cc:7142 ../libqalculate/Number.cc:7160 +#: ../libqalculate/Number.cc:7179 ../libqalculate/Number.cc:7515 +#: ../libqalculate/Number.cc:7562 ../libqalculate/Number.cc:7707 +#: ../libqalculate/Number.cc:8040 ../libqalculate/Number.cc:8196 +#: ../libqalculate/Number.cc:8628 ../libqalculate/Number.cc:9023 #, c-format msgid "%s() lacks proper support interval arithmetic." msgstr "%s() saknar adekvat stöd för intervallaritmetik." -#: ../libqalculate/Number.cc:7816 +#: ../libqalculate/Number.cc:9706 msgid "Unsupported base" msgstr "Talbasen stöds ej" -#: ../libqalculate/Number.cc:8248 +#: ../libqalculate/Number.cc:10172 msgid "Can only display rational numbers as roman numerals." msgstr "Kan enbert visa rationella tal som romerska siffror." -#: ../libqalculate/Number.cc:8693 ../libqalculate/Number.cc:8701 +#: ../libqalculate/Number.cc:10659 ../libqalculate/Number.cc:10667 msgid "infinity" msgstr "oändlighet" @@ -3625,11 +3688,11 @@ msgid "leap month" msgstr "skottmånad" -#: ../libqalculate/Unit.cc:1096 +#: ../libqalculate/Unit.cc:1100 msgid "Error(s) in unitexpression." msgstr "Fel i enhetsuttryck." -#: ../libqalculate/Variable.cc:501 +#: ../libqalculate/Variable.cc:502 #, c-format msgid "Recursive variable: %s = %s" msgstr "Rekursiv variabel: %s = %s" @@ -3658,6 +3721,10 @@ msgid "Off" msgstr "Av" +#~ msgid "Cannot handle an argument (s) that large for Riemann Zeta." +#~ msgstr "" +#~ "Kan inte hantera ett så stort tal för parametern (s) till Riemann Zeta." + #~ msgid "Definite integral was approximated with unknown precision." #~ msgstr "Definitiv integral approximerades med okänd precision." diff -Nru libqalculate-3.6.0/po/zh_CN.po libqalculate-3.7.0/po/zh_CN.po --- libqalculate-3.6.0/po/zh_CN.po 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/po/zh_CN.po 2020-01-21 22:54:40.000000000 +0000 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: zh_CN\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-25 10:28+0100\n" +"POT-Creation-Date: 2020-01-12 11:24+0100\n" "PO-Revision-Date: 2007-07-31 15:34+0800\n" "Last-Translator: Roy Qu \n" "Language-Team: Simplified Chinese\n" @@ -17,11 +17,11 @@ "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" -#: ../src/defs2doc.cc:301 ../src/qalc.cc:3298 ../libqalculate/Function.cc:207 +#: ../src/defs2doc.cc:301 ../src/qalc.cc:3299 ../libqalculate/Function.cc:222 msgid "argument" msgstr "argument" -#: ../src/defs2doc.cc:324 ../src/qalc.cc:3321 +#: ../src/defs2doc.cc:324 ../src/qalc.cc:3322 #, c-format msgid "" "Retrieves data from the %s data set for a given object and property. If " @@ -30,38 +30,38 @@ "从数据集%s中为给定的标量和属性读取数据。如果将\"info\"作为属性,则将会 列出对" "象的全部属性。" -#: ../src/defs2doc.cc:331 ../src/qalc.cc:3330 +#: ../src/defs2doc.cc:331 ../src/qalc.cc:3331 #, fuzzy msgid "Example:" msgstr "例如: store var1." -#: ../src/defs2doc.cc:339 ../src/qalc.cc:3339 +#: ../src/defs2doc.cc:339 ../src/qalc.cc:3340 msgid "Arguments" msgstr "自变量" #. optional argument, in description -#: ../src/defs2doc.cc:356 ../src/qalc.cc:3356 +#: ../src/defs2doc.cc:356 ../src/qalc.cc:3357 msgid "optional" msgstr "可选的" #. argument default, in description -#: ../src/defs2doc.cc:359 ../src/qalc.cc:3360 +#: ../src/defs2doc.cc:359 ../src/qalc.cc:3361 msgid "default: " msgstr "缺省:" -#: ../src/defs2doc.cc:372 ../src/qalc.cc:3371 +#: ../src/defs2doc.cc:372 ../src/qalc.cc:3372 msgid "Requirement" msgstr "要求" -#: ../src/defs2doc.cc:381 ../src/qalc.cc:3379 +#: ../src/defs2doc.cc:381 ../src/qalc.cc:3380 msgid "Properties" msgstr "属性" -#: ../src/defs2doc.cc:397 ../src/qalc.cc:3394 +#: ../src/defs2doc.cc:397 ../src/qalc.cc:3395 msgid "key" msgstr "key" -#: ../src/defs2doc.cc:431 ../src/qalc.cc:3509 +#: ../src/defs2doc.cc:431 ../src/qalc.cc:3510 msgid "a previous result" msgstr "之前的结果" @@ -70,91 +70,91 @@ msgid "current precision" msgstr "read precision" -#: ../src/defs2doc.cc:438 ../src/defs2doc.cc:539 ../src/qalc.cc:1456 +#: ../src/defs2doc.cc:438 ../src/defs2doc.cc:539 ../src/qalc.cc:1457 msgid "relative uncertainty" msgstr "" -#: ../src/defs2doc.cc:453 ../src/qalc.cc:1478 ../src/qalc.cc:3515 -#: ../libqalculate/Function.cc:2110 +#: ../src/defs2doc.cc:453 ../src/qalc.cc:1479 ../src/qalc.cc:3516 +#: ../libqalculate/Function.cc:2144 msgid "matrix" msgstr "matrix" -#: ../src/defs2doc.cc:455 ../src/qalc.cc:1480 ../src/qalc.cc:3517 -#: ../libqalculate/Function.cc:2049 +#: ../src/defs2doc.cc:455 ../src/qalc.cc:1481 ../src/qalc.cc:3518 +#: ../libqalculate/Function.cc:2083 msgid "vector" msgstr "vector" -#: ../src/defs2doc.cc:463 ../src/qalc.cc:249 ../src/qalc.cc:691 -#: ../src/qalc.cc:1497 ../src/qalc.cc:2907 ../src/qalc.cc:3527 -#: ../src/qalc.cc:3646 ../src/qalc.cc:3876 +#: ../src/defs2doc.cc:463 ../src/qalc.cc:250 ../src/qalc.cc:692 +#: ../src/qalc.cc:1498 ../src/qalc.cc:2908 ../src/qalc.cc:3528 +#: ../src/qalc.cc:3647 ../src/qalc.cc:3877 msgid "positive" msgstr "positive" -#: ../src/defs2doc.cc:464 ../src/qalc.cc:255 ../src/qalc.cc:692 -#: ../src/qalc.cc:1498 ../src/qalc.cc:2908 ../src/qalc.cc:3528 -#: ../src/qalc.cc:3650 ../src/qalc.cc:3880 +#: ../src/defs2doc.cc:464 ../src/qalc.cc:256 ../src/qalc.cc:693 +#: ../src/qalc.cc:1499 ../src/qalc.cc:2909 ../src/qalc.cc:3529 +#: ../src/qalc.cc:3651 ../src/qalc.cc:3881 msgid "non-positive" msgstr "non-positive" -#: ../src/defs2doc.cc:465 ../src/qalc.cc:253 ../src/qalc.cc:693 -#: ../src/qalc.cc:1499 ../src/qalc.cc:2909 ../src/qalc.cc:3529 -#: ../src/qalc.cc:3648 ../src/qalc.cc:3878 +#: ../src/defs2doc.cc:465 ../src/qalc.cc:254 ../src/qalc.cc:694 +#: ../src/qalc.cc:1500 ../src/qalc.cc:2910 ../src/qalc.cc:3530 +#: ../src/qalc.cc:3649 ../src/qalc.cc:3879 msgid "negative" msgstr "negative" -#: ../src/defs2doc.cc:466 ../src/qalc.cc:251 ../src/qalc.cc:694 -#: ../src/qalc.cc:1500 ../src/qalc.cc:2910 ../src/qalc.cc:3530 -#: ../src/qalc.cc:3652 ../src/qalc.cc:3882 +#: ../src/defs2doc.cc:466 ../src/qalc.cc:252 ../src/qalc.cc:695 +#: ../src/qalc.cc:1501 ../src/qalc.cc:2911 ../src/qalc.cc:3531 +#: ../src/qalc.cc:3653 ../src/qalc.cc:3883 msgid "non-negative" msgstr "non-negative" -#: ../src/defs2doc.cc:467 ../src/qalc.cc:247 ../src/qalc.cc:695 -#: ../src/qalc.cc:1501 ../src/qalc.cc:2911 ../src/qalc.cc:3531 -#: ../src/qalc.cc:3644 ../src/qalc.cc:3874 +#: ../src/defs2doc.cc:467 ../src/qalc.cc:248 ../src/qalc.cc:696 +#: ../src/qalc.cc:1502 ../src/qalc.cc:2912 ../src/qalc.cc:3532 +#: ../src/qalc.cc:3645 ../src/qalc.cc:3875 msgid "non-zero" msgstr "non-zero" -#: ../src/defs2doc.cc:472 ../src/qalc.cc:245 ../src/qalc.cc:700 -#: ../src/qalc.cc:1506 ../src/qalc.cc:2916 ../src/qalc.cc:3536 -#: ../src/qalc.cc:3660 ../src/qalc.cc:3890 ../libqalculate/Function.cc:1905 +#: ../src/defs2doc.cc:472 ../src/qalc.cc:246 ../src/qalc.cc:701 +#: ../src/qalc.cc:1507 ../src/qalc.cc:2917 ../src/qalc.cc:3537 +#: ../src/qalc.cc:3661 ../src/qalc.cc:3891 ../libqalculate/Function.cc:1939 msgid "integer" msgstr "integer" -#: ../src/defs2doc.cc:473 ../src/qalc.cc:243 ../src/qalc.cc:701 -#: ../src/qalc.cc:1507 ../src/qalc.cc:2917 ../src/qalc.cc:3537 -#: ../src/qalc.cc:3658 ../src/qalc.cc:3888 +#: ../src/defs2doc.cc:473 ../src/qalc.cc:244 ../src/qalc.cc:702 +#: ../src/qalc.cc:1508 ../src/qalc.cc:2918 ../src/qalc.cc:3538 +#: ../src/qalc.cc:3659 ../src/qalc.cc:3889 msgid "rational" msgstr "rational" -#: ../src/defs2doc.cc:474 ../src/qalc.cc:239 ../src/qalc.cc:702 -#: ../src/qalc.cc:1508 ../src/qalc.cc:2918 ../src/qalc.cc:3538 -#: ../src/qalc.cc:3656 ../src/qalc.cc:3886 +#: ../src/defs2doc.cc:474 ../src/qalc.cc:240 ../src/qalc.cc:703 +#: ../src/qalc.cc:1509 ../src/qalc.cc:2919 ../src/qalc.cc:3539 +#: ../src/qalc.cc:3657 ../src/qalc.cc:3887 msgid "real" msgstr "real" -#: ../src/defs2doc.cc:475 ../src/qalc.cc:703 ../src/qalc.cc:1509 -#: ../src/qalc.cc:2919 ../src/qalc.cc:3539 +#: ../src/defs2doc.cc:475 ../src/qalc.cc:704 ../src/qalc.cc:1510 +#: ../src/qalc.cc:2920 ../src/qalc.cc:3540 msgid "complex" msgstr "complex" -#: ../src/defs2doc.cc:476 ../src/qalc.cc:241 ../src/qalc.cc:704 -#: ../src/qalc.cc:1510 ../src/qalc.cc:2920 ../src/qalc.cc:3540 -#: ../src/qalc.cc:3654 ../src/qalc.cc:3884 ../libqalculate/Function.cc:1744 +#: ../src/defs2doc.cc:476 ../src/qalc.cc:242 ../src/qalc.cc:705 +#: ../src/qalc.cc:1511 ../src/qalc.cc:2921 ../src/qalc.cc:3541 +#: ../src/qalc.cc:3655 ../src/qalc.cc:3885 ../libqalculate/Function.cc:1778 msgid "number" msgstr "number" -#: ../src/defs2doc.cc:477 ../src/qalc.cc:705 ../src/qalc.cc:1511 -#: ../src/qalc.cc:2921 ../src/qalc.cc:3541 +#: ../src/defs2doc.cc:477 ../src/qalc.cc:706 ../src/qalc.cc:1512 +#: ../src/qalc.cc:2922 ../src/qalc.cc:3542 msgid "non-matrix" msgstr "non-matrix" -#: ../src/defs2doc.cc:480 ../src/qalc.cc:233 ../src/qalc.cc:708 -#: ../src/qalc.cc:1514 ../src/qalc.cc:2924 ../src/qalc.cc:3544 -#: ../src/qalc.cc:3642 ../src/qalc.cc:3872 +#: ../src/defs2doc.cc:480 ../src/qalc.cc:234 ../src/qalc.cc:709 +#: ../src/qalc.cc:1515 ../src/qalc.cc:2925 ../src/qalc.cc:3545 +#: ../src/qalc.cc:3643 ../src/qalc.cc:3873 msgid "unknown" msgstr "unknown" -#: ../src/defs2doc.cc:482 ../src/qalc.cc:1516 ../src/qalc.cc:3546 +#: ../src/defs2doc.cc:482 ../src/qalc.cc:1517 ../src/qalc.cc:3547 msgid "default assumptions" msgstr "缺省假设" @@ -164,47 +164,48 @@ msgstr "read precision" #. qalc command -#: ../src/defs2doc.cc:492 ../src/defs2doc.cc:546 ../src/qalc.cc:900 -#: ../src/qalc.cc:1472 ../src/qalc.cc:1489 ../src/qalc.cc:2559 -#: ../src/qalc.cc:2941 ../src/qalc.cc:3184 ../src/qalc.cc:3458 -#: ../src/qalc.cc:3468 ../src/qalc.cc:3572 ../src/qalc.cc:3668 -#: ../src/qalc.cc:4002 +#: ../src/defs2doc.cc:492 ../src/defs2doc.cc:546 ../src/qalc.cc:901 +#: ../src/qalc.cc:1473 ../src/qalc.cc:1490 ../src/qalc.cc:2560 +#: ../src/qalc.cc:2942 ../src/qalc.cc:3185 ../src/qalc.cc:3459 +#: ../src/qalc.cc:3469 ../src/qalc.cc:3573 ../src/qalc.cc:3669 +#: ../src/qalc.cc:4003 msgid "approximate" msgstr "approximate" -#: ../src/defs2doc.cc:583 ../src/qalc.cc:1892 +#: ../src/defs2doc.cc:583 ../src/qalc.cc:1893 msgid "ans" msgstr "ans" #: ../src/defs2doc.cc:584 ../src/defs2doc.cc:587 ../src/defs2doc.cc:588 -#: ../src/defs2doc.cc:589 ../src/defs2doc.cc:590 ../src/qalc.cc:1893 -#: ../src/qalc.cc:1896 ../src/qalc.cc:1897 ../src/qalc.cc:1898 -#: ../src/qalc.cc:1899 ../src/qalc.cc:2153 ../libqalculate/Calculator.cc:10674 -#: ../libqalculate/Calculator.cc:10690 +#: ../src/defs2doc.cc:589 ../src/defs2doc.cc:590 ../src/qalc.cc:1894 +#: ../src/qalc.cc:1897 ../src/qalc.cc:1898 ../src/qalc.cc:1899 +#: ../src/qalc.cc:1900 ../src/qalc.cc:2154 +#: ../libqalculate/Calculator-definitions.cc:2225 +#: ../libqalculate/Calculator-definitions.cc:2241 msgid "Temporary" msgstr "临时" -#: ../src/defs2doc.cc:584 ../src/qalc.cc:1893 +#: ../src/defs2doc.cc:584 ../src/qalc.cc:1894 msgid "Last Answer" msgstr "最后一个答案" -#: ../src/defs2doc.cc:585 ../src/qalc.cc:1894 +#: ../src/defs2doc.cc:585 ../src/qalc.cc:1895 msgid "answer" msgstr "answer" -#: ../src/defs2doc.cc:587 ../src/qalc.cc:1896 +#: ../src/defs2doc.cc:587 ../src/qalc.cc:1897 msgid "Answer 2" msgstr "答案2" -#: ../src/defs2doc.cc:588 ../src/qalc.cc:1897 +#: ../src/defs2doc.cc:588 ../src/qalc.cc:1898 msgid "Answer 3" msgstr "答案3" -#: ../src/defs2doc.cc:589 ../src/qalc.cc:1898 +#: ../src/defs2doc.cc:589 ../src/qalc.cc:1899 msgid "Answer 4" msgstr "答案4" -#: ../src/defs2doc.cc:590 ../src/qalc.cc:1899 +#: ../src/defs2doc.cc:590 ../src/qalc.cc:1900 msgid "Answer 5" msgstr "答案5" @@ -220,68 +221,68 @@ msgid "Uncategorized" msgstr "factorize" -#: ../src/qalc.cc:152 ../src/qalc.cc:219 ../src/qalc.cc:3621 +#: ../src/qalc.cc:153 ../src/qalc.cc:220 ../src/qalc.cc:3622 #: ../libqalculate/util.cc:175 msgid "yes" msgstr "yes" -#: ../src/qalc.cc:153 ../src/qalc.cc:221 ../src/qalc.cc:3621 +#: ../src/qalc.cc:154 ../src/qalc.cc:222 ../src/qalc.cc:3622 #: ../libqalculate/util.cc:176 msgid "no" msgstr "no" -#: ../src/qalc.cc:154 ../libqalculate/util.cc:183 +#: ../src/qalc.cc:155 ../libqalculate/util.cc:183 msgid "true" msgstr "true" -#: ../src/qalc.cc:155 ../libqalculate/util.cc:184 +#: ../src/qalc.cc:156 ../libqalculate/util.cc:184 msgid "false" msgstr "false" -#: ../src/qalc.cc:156 ../src/qalc.cc:777 ../src/qalc.cc:797 ../src/qalc.cc:1112 -#: ../src/qalc.cc:1149 ../src/qalc.cc:3028 ../src/qalc.cc:3041 -#: ../src/qalc.cc:3099 ../src/qalc.cc:3620 ../src/qalc.cc:3735 -#: ../src/qalc.cc:3742 ../src/qalc.cc:3793 ../libqalculate/util.cc:191 +#: ../src/qalc.cc:157 ../src/qalc.cc:778 ../src/qalc.cc:798 ../src/qalc.cc:1113 +#: ../src/qalc.cc:1150 ../src/qalc.cc:3029 ../src/qalc.cc:3042 +#: ../src/qalc.cc:3100 ../src/qalc.cc:3621 ../src/qalc.cc:3736 +#: ../src/qalc.cc:3743 ../src/qalc.cc:3794 ../libqalculate/util.cc:191 msgid "on" msgstr "on" -#: ../src/qalc.cc:157 ../src/qalc.cc:775 ../src/qalc.cc:796 ../src/qalc.cc:1021 -#: ../src/qalc.cc:1085 ../src/qalc.cc:1097 ../src/qalc.cc:1110 -#: ../src/qalc.cc:1147 ../src/qalc.cc:3027 ../src/qalc.cc:3032 -#: ../src/qalc.cc:3039 ../src/qalc.cc:3068 ../src/qalc.cc:3075 -#: ../src/qalc.cc:3082 ../src/qalc.cc:3098 ../src/qalc.cc:3132 -#: ../src/qalc.cc:3620 ../src/qalc.cc:3733 ../src/qalc.cc:3739 -#: ../src/qalc.cc:3742 ../src/qalc.cc:3750 ../src/qalc.cc:3757 -#: ../src/qalc.cc:3767 ../src/qalc.cc:3791 ../src/qalc.cc:3826 +#: ../src/qalc.cc:158 ../src/qalc.cc:776 ../src/qalc.cc:797 ../src/qalc.cc:1022 +#: ../src/qalc.cc:1086 ../src/qalc.cc:1098 ../src/qalc.cc:1111 +#: ../src/qalc.cc:1148 ../src/qalc.cc:3028 ../src/qalc.cc:3033 +#: ../src/qalc.cc:3040 ../src/qalc.cc:3069 ../src/qalc.cc:3076 +#: ../src/qalc.cc:3083 ../src/qalc.cc:3099 ../src/qalc.cc:3133 +#: ../src/qalc.cc:3621 ../src/qalc.cc:3734 ../src/qalc.cc:3740 +#: ../src/qalc.cc:3743 ../src/qalc.cc:3751 ../src/qalc.cc:3758 +#: ../src/qalc.cc:3768 ../src/qalc.cc:3792 ../src/qalc.cc:3827 #: ../libqalculate/util.cc:192 msgid "off" msgstr "off" -#: ../src/qalc.cc:226 +#: ../src/qalc.cc:227 msgid "Please answer yes or no" msgstr "请回答yes或者no" -#: ../src/qalc.cc:258 +#: ../src/qalc.cc:259 msgid "Unrecognized assumption." msgstr "未被承认的假设" -#: ../src/qalc.cc:425 ../src/qalc.cc:458 ../libqalculate/Calculator.cc:467 -#: ../libqalculate/Calculator.cc:693 ../libqalculate/DataSet.cc:1072 -#: ../libqalculate/DataSet.cc:1134 ../libqalculate/MathStructure.cc:21595 -#: ../libqalculate/Function.cc:2269 ../libqalculate/Function.cc:2285 +#: ../src/qalc.cc:426 ../src/qalc.cc:459 ../libqalculate/Calculator.cc:245 +#: ../libqalculate/Calculator.cc:473 ../libqalculate/DataSet.cc:1073 +#: ../libqalculate/DataSet.cc:1135 ../libqalculate/MathStructure-print.cc:3190 +#: ../libqalculate/Function.cc:2304 ../libqalculate/Function.cc:2320 msgid "or" msgstr "or" -#: ../src/qalc.cc:546 ../libqalculate/Calculator.cc:12220 +#: ../src/qalc.cc:547 ../libqalculate/Calculator-definitions.cc:3756 #, fuzzy, c-format msgid "It has been %s day(s) since the exchange rates last were updated." msgstr "距离最后一次汇率更新已超过一周了。" -#: ../src/qalc.cc:551 +#: ../src/qalc.cc:552 msgid "Do you wish to update the exchange rates now?" msgstr "" -#: ../src/qalc.cc:565 ../src/qalc.cc:566 +#: ../src/qalc.cc:566 ../src/qalc.cc:567 msgid "" "\n" "Press Enter to continue." @@ -289,900 +290,906 @@ "\n" "按回车键继续" -#: ../src/qalc.cc:581 ../src/qalc.cc:582 ../src/qalc.cc:583 ../src/qalc.cc:584 -#: ../src/qalc.cc:585 ../src/qalc.cc:586 ../src/qalc.cc:719 ../src/qalc.cc:814 -#: ../src/qalc.cc:817 ../src/qalc.cc:972 ../src/qalc.cc:991 ../src/qalc.cc:1003 -#: ../src/qalc.cc:1012 ../src/qalc.cc:2362 ../src/qalc.cc:2499 +#: ../src/qalc.cc:582 ../src/qalc.cc:583 ../src/qalc.cc:584 ../src/qalc.cc:585 +#: ../src/qalc.cc:586 ../src/qalc.cc:587 ../src/qalc.cc:720 ../src/qalc.cc:815 +#: ../src/qalc.cc:818 ../src/qalc.cc:973 ../src/qalc.cc:992 ../src/qalc.cc:1004 +#: ../src/qalc.cc:1013 ../src/qalc.cc:2363 ../src/qalc.cc:2500 msgid "Illegal value" msgstr "非法值" #. qalc command -#: ../src/qalc.cc:614 ../src/qalc.cc:934 ../src/qalc.cc:2340 -#: ../src/qalc.cc:2803 ../src/qalc.cc:2809 ../src/qalc.cc:2994 -#: ../src/qalc.cc:3150 ../src/qalc.cc:3186 ../src/qalc.cc:3702 -#: ../src/qalc.cc:3839 ../src/qalc.cc:3994 ../src/qalc.cc:4922 -#: ../src/qalc.cc:4933 ../libqalculate/Calculator.cc:3051 -#: ../libqalculate/Calculator.cc:3055 +#: ../src/qalc.cc:615 ../src/qalc.cc:935 ../src/qalc.cc:2341 +#: ../src/qalc.cc:2804 ../src/qalc.cc:2810 ../src/qalc.cc:2995 +#: ../src/qalc.cc:3151 ../src/qalc.cc:3187 ../src/qalc.cc:3703 +#: ../src/qalc.cc:3840 ../src/qalc.cc:3995 ../src/qalc.cc:4923 +#: ../src/qalc.cc:4934 ../libqalculate/Calculator-calculate.cc:837 +#: ../libqalculate/Calculator-calculate.cc:841 msgid "base" msgstr "base" -#: ../src/qalc.cc:614 ../src/qalc.cc:616 ../src/qalc.cc:3108 -#: ../src/qalc.cc:3804 +#: ../src/qalc.cc:615 ../src/qalc.cc:617 ../src/qalc.cc:3109 +#: ../src/qalc.cc:3805 msgid "input base" msgstr "input base" -#: ../src/qalc.cc:614 ../src/qalc.cc:617 +#: ../src/qalc.cc:615 ../src/qalc.cc:618 msgid "output base" msgstr "output base" -#: ../src/qalc.cc:618 ../src/qalc.cc:2606 ../src/qalc.cc:2996 -#: ../src/qalc.cc:3110 ../src/qalc.cc:3714 ../src/qalc.cc:3812 -#: ../src/qalc.cc:4756 ../libqalculate/Calculator.cc:2969 +#: ../src/qalc.cc:619 ../src/qalc.cc:2607 ../src/qalc.cc:2997 +#: ../src/qalc.cc:3111 ../src/qalc.cc:3715 ../src/qalc.cc:3813 +#: ../src/qalc.cc:4757 ../libqalculate/Calculator-calculate.cc:755 msgid "roman" msgstr "roman" -#: ../src/qalc.cc:619 ../src/qalc.cc:2611 ../src/qalc.cc:2997 -#: ../src/qalc.cc:3111 ../src/qalc.cc:4764 ../libqalculate/Calculator.cc:2972 +#: ../src/qalc.cc:620 ../src/qalc.cc:2612 ../src/qalc.cc:2998 +#: ../src/qalc.cc:3112 ../src/qalc.cc:4765 +#: ../libqalculate/Calculator-calculate.cc:758 #, fuzzy msgid "bijective" msgstr "对象" -#: ../src/qalc.cc:620 ../src/qalc.cc:2621 ../src/qalc.cc:2999 -#: ../src/qalc.cc:3712 ../src/qalc.cc:4780 ../libqalculate/Calculator.cc:2978 +#: ../src/qalc.cc:621 ../src/qalc.cc:2622 ../src/qalc.cc:3000 +#: ../src/qalc.cc:3713 ../src/qalc.cc:4781 +#: ../libqalculate/Calculator-calculate.cc:764 msgid "time" msgstr "time" -#: ../src/qalc.cc:621 ../src/qalc.cc:2581 ../src/qalc.cc:4716 -#: ../libqalculate/Calculator.cc:2954 +#: ../src/qalc.cc:622 ../src/qalc.cc:2582 ../src/qalc.cc:4717 +#: ../libqalculate/Calculator-calculate.cc:740 msgid "hexadecimal" msgstr "hexadecimal" -#: ../src/qalc.cc:628 ../src/qalc.cc:2601 ../src/qalc.cc:4748 -#: ../libqalculate/Calculator.cc:2966 +#: ../src/qalc.cc:629 ../src/qalc.cc:2602 ../src/qalc.cc:4749 +#: ../libqalculate/Calculator-calculate.cc:752 #, fuzzy msgid "duodecimal" msgstr "decimal" -#: ../src/qalc.cc:629 ../src/qalc.cc:2586 ../src/qalc.cc:4724 -#: ../libqalculate/Calculator.cc:2957 +#: ../src/qalc.cc:630 ../src/qalc.cc:2587 ../src/qalc.cc:4725 +#: ../libqalculate/Calculator-calculate.cc:743 msgid "binary" msgstr "binary" -#: ../src/qalc.cc:630 ../src/qalc.cc:2596 ../src/qalc.cc:4740 -#: ../libqalculate/Calculator.cc:2963 +#: ../src/qalc.cc:631 ../src/qalc.cc:2597 ../src/qalc.cc:4741 +#: ../libqalculate/Calculator-calculate.cc:749 msgid "octal" msgstr "octal" -#: ../src/qalc.cc:631 ../src/qalc.cc:2591 ../src/qalc.cc:4732 -#: ../libqalculate/Calculator.cc:2960 +#: ../src/qalc.cc:632 ../src/qalc.cc:2592 ../src/qalc.cc:4733 +#: ../libqalculate/Calculator-calculate.cc:746 msgid "decimal" msgstr "decimal" -#: ../src/qalc.cc:632 ../src/qalc.cc:2616 ../src/qalc.cc:2998 -#: ../src/qalc.cc:4772 ../libqalculate/Calculator.cc:2975 +#: ../src/qalc.cc:633 ../src/qalc.cc:2617 ../src/qalc.cc:2999 +#: ../src/qalc.cc:4773 ../libqalculate/Calculator-calculate.cc:761 msgid "sexagesimal" msgstr "sexagesimal" -#: ../src/qalc.cc:643 ../src/qalc.cc:757 ../src/qalc.cc:3010 -#: ../src/qalc.cc:3726 +#: ../src/qalc.cc:644 ../src/qalc.cc:758 ../src/qalc.cc:3011 +#: ../src/qalc.cc:3727 msgid "base display" msgstr "base display" -#: ../src/qalc.cc:673 +#: ../src/qalc.cc:674 msgid "Illegal base." msgstr "Illegal base." -#: ../src/qalc.cc:681 ../src/qalc.cc:709 ../src/qalc.cc:2925 -#: ../src/qalc.cc:3639 +#: ../src/qalc.cc:682 ../src/qalc.cc:710 ../src/qalc.cc:2926 +#: ../src/qalc.cc:3640 msgid "assumptions" msgstr "assumptions" -#: ../src/qalc.cc:712 ../src/qalc.cc:3141 ../src/qalc.cc:3831 +#: ../src/qalc.cc:713 ../src/qalc.cc:3142 ../src/qalc.cc:3832 msgid "all prefixes" msgstr "all prefixes" -#: ../src/qalc.cc:713 ../src/qalc.cc:2959 ../src/qalc.cc:3679 +#: ../src/qalc.cc:714 ../src/qalc.cc:2960 ../src/qalc.cc:3680 msgid "complex numbers" msgstr "complex numbers" -#: ../src/qalc.cc:714 ../src/qalc.cc:2977 ../src/qalc.cc:3691 +#: ../src/qalc.cc:715 ../src/qalc.cc:2978 ../src/qalc.cc:3692 msgid "excessive parentheses" msgstr "excessive parentheses" -#: ../src/qalc.cc:715 ../src/qalc.cc:2960 ../src/qalc.cc:3240 -#: ../src/qalc.cc:3245 ../src/qalc.cc:3680 +#: ../src/qalc.cc:716 ../src/qalc.cc:2961 ../src/qalc.cc:3241 +#: ../src/qalc.cc:3246 ../src/qalc.cc:3681 msgid "functions" msgstr "functions" -#: ../src/qalc.cc:716 ../src/qalc.cc:2961 ../src/qalc.cc:3681 +#: ../src/qalc.cc:717 ../src/qalc.cc:2962 ../src/qalc.cc:3682 msgid "infinite numbers" msgstr "infinite numbers" -#: ../src/qalc.cc:717 ../src/qalc.cc:2986 ../src/qalc.cc:3694 +#: ../src/qalc.cc:718 ../src/qalc.cc:2987 ../src/qalc.cc:3695 msgid "show negative exponents" msgstr "show negative exponents" -#: ../src/qalc.cc:718 ../src/qalc.cc:2978 ../src/qalc.cc:3692 +#: ../src/qalc.cc:719 ../src/qalc.cc:2979 ../src/qalc.cc:3693 #, fuzzy msgid "minus last" msgstr "minus" -#: ../src/qalc.cc:720 ../src/qalc.cc:2903 ../src/qalc.cc:3636 +#: ../src/qalc.cc:721 ../src/qalc.cc:2904 ../src/qalc.cc:3637 msgid "assume nonzero denominators" msgstr "assume nonzero denominators" -#: ../src/qalc.cc:721 ../src/qalc.cc:2904 ../src/qalc.cc:3637 +#: ../src/qalc.cc:722 ../src/qalc.cc:2905 ../src/qalc.cc:3638 msgid "warn nonzero denominators" msgstr "warn nonzero denominators" -#: ../src/qalc.cc:722 ../src/qalc.cc:3158 ../src/qalc.cc:3851 +#: ../src/qalc.cc:723 ../src/qalc.cc:3159 ../src/qalc.cc:3852 msgid "prefixes" msgstr "prefixes" -#: ../src/qalc.cc:723 ../src/qalc.cc:3154 ../src/qalc.cc:3847 +#: ../src/qalc.cc:724 ../src/qalc.cc:3155 ../src/qalc.cc:3848 #, fuzzy msgid "binary prefixes" msgstr "denominator prefixes" -#: ../src/qalc.cc:730 ../src/qalc.cc:3156 ../src/qalc.cc:3849 +#: ../src/qalc.cc:731 ../src/qalc.cc:3157 ../src/qalc.cc:3850 msgid "denominator prefixes" msgstr "denominator prefixes" -#: ../src/qalc.cc:731 ../src/qalc.cc:3157 ../src/qalc.cc:3850 +#: ../src/qalc.cc:732 ../src/qalc.cc:3158 ../src/qalc.cc:3851 msgid "place units separately" msgstr "place units separately" -#: ../src/qalc.cc:732 ../src/qalc.cc:2958 ../src/qalc.cc:3678 +#: ../src/qalc.cc:733 ../src/qalc.cc:2959 ../src/qalc.cc:3679 msgid "calculate variables" msgstr "calculate variables" -#: ../src/qalc.cc:733 ../src/qalc.cc:2957 ../src/qalc.cc:3677 +#: ../src/qalc.cc:734 ../src/qalc.cc:2958 ../src/qalc.cc:3678 msgid "calculate functions" msgstr "calculate functions" -#: ../src/qalc.cc:734 ../src/qalc.cc:3159 ../src/qalc.cc:3852 +#: ../src/qalc.cc:735 ../src/qalc.cc:3160 ../src/qalc.cc:3853 msgid "sync units" msgstr "sync units" -#: ../src/qalc.cc:735 ../src/qalc.cc:3079 ../src/qalc.cc:3763 +#: ../src/qalc.cc:736 ../src/qalc.cc:3080 ../src/qalc.cc:3764 msgid "round to even" msgstr "round to even" -#: ../src/qalc.cc:736 ../src/qalc.cc:3137 ../src/qalc.cc:3827 +#: ../src/qalc.cc:737 ../src/qalc.cc:3138 ../src/qalc.cc:3828 msgid "rpn syntax" msgstr "rpn syntax" #. qalc command -#: ../src/qalc.cc:737 ../src/qalc.cc:2343 ../src/qalc.cc:3171 -#: ../src/qalc.cc:3208 ../src/qalc.cc:3864 ../src/qalc.cc:3944 +#: ../src/qalc.cc:738 ../src/qalc.cc:2344 ../src/qalc.cc:3172 +#: ../src/qalc.cc:3209 ../src/qalc.cc:3865 ../src/qalc.cc:3945 msgid "rpn" msgstr "rpn" -#: ../src/qalc.cc:738 ../src/qalc.cc:2987 ../src/qalc.cc:3695 +#: ../src/qalc.cc:739 ../src/qalc.cc:2988 ../src/qalc.cc:3696 msgid "short multiplication" msgstr "short multiplication" -#: ../src/qalc.cc:739 ../src/qalc.cc:3062 ../src/qalc.cc:3746 +#: ../src/qalc.cc:740 ../src/qalc.cc:3063 ../src/qalc.cc:3747 msgid "lowercase e" msgstr "lowercase e" -#: ../src/qalc.cc:740 ../src/qalc.cc:3063 ../src/qalc.cc:3747 +#: ../src/qalc.cc:741 ../src/qalc.cc:3064 ../src/qalc.cc:3748 msgid "lowercase numbers" msgstr "lowercase numbers" -#: ../src/qalc.cc:741 ../src/qalc.cc:3046 ../src/qalc.cc:3107 -#: ../src/qalc.cc:3744 ../src/qalc.cc:3803 +#: ../src/qalc.cc:742 ../src/qalc.cc:3047 ../src/qalc.cc:3108 +#: ../src/qalc.cc:3745 ../src/qalc.cc:3804 msgid "imaginary j" msgstr "" -#: ../src/qalc.cc:759 ../src/qalc.cc:776 ../src/qalc.cc:830 ../src/qalc.cc:930 -#: ../src/qalc.cc:956 ../src/qalc.cc:2898 ../src/qalc.cc:2934 -#: ../src/qalc.cc:2947 ../src/qalc.cc:3012 ../src/qalc.cc:3146 -#: ../src/qalc.cc:3667 ../src/qalc.cc:3726 ../src/qalc.cc:3835 +#: ../src/qalc.cc:760 ../src/qalc.cc:777 ../src/qalc.cc:831 ../src/qalc.cc:931 +#: ../src/qalc.cc:957 ../src/qalc.cc:2899 ../src/qalc.cc:2935 +#: ../src/qalc.cc:2948 ../src/qalc.cc:3013 ../src/qalc.cc:3147 +#: ../src/qalc.cc:3668 ../src/qalc.cc:3727 ../src/qalc.cc:3836 msgid "none" msgstr "none" -#: ../src/qalc.cc:760 ../src/qalc.cc:3013 ../src/qalc.cc:3726 +#: ../src/qalc.cc:761 ../src/qalc.cc:3014 ../src/qalc.cc:3727 msgid "normal" msgstr "normal" -#: ../src/qalc.cc:761 ../src/qalc.cc:3014 ../src/qalc.cc:3726 +#: ../src/qalc.cc:762 ../src/qalc.cc:3015 ../src/qalc.cc:3727 msgid "alternative" msgstr "alternative" -#: ../src/qalc.cc:766 ../src/qalc.cc:783 ../src/qalc.cc:803 ../src/qalc.cc:835 -#: ../src/qalc.cc:852 ../src/qalc.cc:877 ../src/qalc.cc:891 ../src/qalc.cc:905 -#: ../src/qalc.cc:922 ../src/qalc.cc:947 ../src/qalc.cc:963 ../src/qalc.cc:1032 -#: ../src/qalc.cc:1038 ../src/qalc.cc:1062 ../src/qalc.cc:1119 -#: ../src/qalc.cc:1138 ../src/qalc.cc:1154 +#: ../src/qalc.cc:767 ../src/qalc.cc:784 ../src/qalc.cc:804 ../src/qalc.cc:836 +#: ../src/qalc.cc:853 ../src/qalc.cc:878 ../src/qalc.cc:892 ../src/qalc.cc:906 +#: ../src/qalc.cc:923 ../src/qalc.cc:948 ../src/qalc.cc:964 ../src/qalc.cc:1033 +#: ../src/qalc.cc:1039 ../src/qalc.cc:1063 ../src/qalc.cc:1120 +#: ../src/qalc.cc:1139 ../src/qalc.cc:1155 msgid "Illegal value." msgstr "非法数值。" -#: ../src/qalc.cc:771 ../src/qalc.cc:3091 ../src/qalc.cc:3781 +#: ../src/qalc.cc:772 ../src/qalc.cc:3092 ../src/qalc.cc:3782 msgid "two's complement" msgstr "" -#: ../src/qalc.cc:772 ../src/qalc.cc:3045 ../src/qalc.cc:3743 +#: ../src/qalc.cc:773 ../src/qalc.cc:3046 ../src/qalc.cc:3744 #, fuzzy msgid "hexadecimal two's" msgstr "hexadecimal" -#: ../src/qalc.cc:773 ../src/qalc.cc:3030 ../src/qalc.cc:3739 +#: ../src/qalc.cc:774 ../src/qalc.cc:3031 ../src/qalc.cc:3740 msgid "digit grouping" msgstr "" -#: ../src/qalc.cc:777 ../src/qalc.cc:3033 ../src/qalc.cc:3739 +#: ../src/qalc.cc:778 ../src/qalc.cc:3034 ../src/qalc.cc:3740 msgid "standard" msgstr "" -#: ../src/qalc.cc:778 ../src/qalc.cc:798 ../src/qalc.cc:3026 -#: ../src/qalc.cc:3034 ../src/qalc.cc:3097 ../src/qalc.cc:3731 -#: ../src/qalc.cc:3739 ../src/qalc.cc:3789 +#: ../src/qalc.cc:779 ../src/qalc.cc:799 ../src/qalc.cc:3027 +#: ../src/qalc.cc:3035 ../src/qalc.cc:3098 ../src/qalc.cc:3732 +#: ../src/qalc.cc:3740 ../src/qalc.cc:3790 msgid "locale" msgstr "" -#: ../src/qalc.cc:788 ../src/qalc.cc:2989 ../src/qalc.cc:3697 +#: ../src/qalc.cc:789 ../src/qalc.cc:2990 ../src/qalc.cc:3698 msgid "spell out logical" msgstr "spell out logical" -#: ../src/qalc.cc:789 ../src/qalc.cc:3105 ../src/qalc.cc:3801 +#: ../src/qalc.cc:790 ../src/qalc.cc:3106 ../src/qalc.cc:3802 msgid "ignore dot" msgstr "" -#: ../src/qalc.cc:790 ../src/qalc.cc:3102 ../src/qalc.cc:3798 +#: ../src/qalc.cc:791 ../src/qalc.cc:3103 ../src/qalc.cc:3799 msgid "ignore comma" msgstr "" -#: ../src/qalc.cc:794 ../src/qalc.cc:3025 ../src/qalc.cc:3096 -#: ../src/qalc.cc:3728 ../src/qalc.cc:3786 +#: ../src/qalc.cc:795 ../src/qalc.cc:3026 ../src/qalc.cc:3097 +#: ../src/qalc.cc:3729 ../src/qalc.cc:3787 #, fuzzy msgid "decimal comma" msgstr "decimal" -#: ../src/qalc.cc:813 ../src/qalc.cc:3122 ../src/qalc.cc:3824 +#: ../src/qalc.cc:814 ../src/qalc.cc:3123 ../src/qalc.cc:3825 msgid "limit implicit multiplication" msgstr "limit implicit multiplication" -#: ../src/qalc.cc:815 ../src/qalc.cc:2988 ../src/qalc.cc:3696 +#: ../src/qalc.cc:816 ../src/qalc.cc:2989 ../src/qalc.cc:3697 msgid "spacious" msgstr "spacious" -#: ../src/qalc.cc:816 ../src/qalc.cc:2990 ../src/qalc.cc:3698 +#: ../src/qalc.cc:817 ../src/qalc.cc:2991 ../src/qalc.cc:3699 msgid "unicode" msgstr "unicode" -#: ../src/qalc.cc:819 ../src/qalc.cc:2962 ../src/qalc.cc:3242 -#: ../src/qalc.cc:3247 ../src/qalc.cc:3682 +#: ../src/qalc.cc:820 ../src/qalc.cc:2963 ../src/qalc.cc:3243 +#: ../src/qalc.cc:3248 ../src/qalc.cc:3683 msgid "units" msgstr "units" -#: ../src/qalc.cc:820 ../src/qalc.cc:2963 ../src/qalc.cc:3683 +#: ../src/qalc.cc:821 ../src/qalc.cc:2964 ../src/qalc.cc:3684 msgid "unknowns" msgstr "unknowns" -#: ../src/qalc.cc:821 ../src/qalc.cc:2964 ../src/qalc.cc:3241 -#: ../src/qalc.cc:3246 ../src/qalc.cc:3684 +#: ../src/qalc.cc:822 ../src/qalc.cc:2965 ../src/qalc.cc:3242 +#: ../src/qalc.cc:3247 ../src/qalc.cc:3685 msgid "variables" msgstr "variables" -#: ../src/qalc.cc:822 ../src/qalc.cc:2969 ../src/qalc.cc:3689 +#: ../src/qalc.cc:823 ../src/qalc.cc:2970 ../src/qalc.cc:3690 msgid "abbreviations" msgstr "abbreviations" -#: ../src/qalc.cc:823 ../src/qalc.cc:3090 ../src/qalc.cc:3780 +#: ../src/qalc.cc:824 ../src/qalc.cc:3091 ../src/qalc.cc:3781 msgid "show ending zeroes" msgstr "show ending zeroes" -#: ../src/qalc.cc:824 ../src/qalc.cc:3078 ../src/qalc.cc:3762 +#: ../src/qalc.cc:825 ../src/qalc.cc:3079 ../src/qalc.cc:3763 #, fuzzy msgid "repeating decimals" msgstr "min decimals" -#: ../src/qalc.cc:825 ../src/qalc.cc:2929 ../src/qalc.cc:3667 +#: ../src/qalc.cc:826 ../src/qalc.cc:2930 ../src/qalc.cc:3668 msgid "angle unit" msgstr "angle unit" -#: ../src/qalc.cc:827 ../src/qalc.cc:2931 ../src/qalc.cc:2932 +#: ../src/qalc.cc:828 ../src/qalc.cc:2932 ../src/qalc.cc:2933 msgid "rad" msgstr "rad" -#: ../src/qalc.cc:827 ../src/qalc.cc:3667 +#: ../src/qalc.cc:828 ../src/qalc.cc:3668 msgid "radians" msgstr "radians" -#: ../src/qalc.cc:828 +#: ../src/qalc.cc:829 msgid "deg" msgstr "deg" -#: ../src/qalc.cc:828 ../src/qalc.cc:3667 +#: ../src/qalc.cc:829 ../src/qalc.cc:3668 msgid "degrees" msgstr "degrees" -#: ../src/qalc.cc:829 ../src/qalc.cc:2933 +#: ../src/qalc.cc:830 ../src/qalc.cc:2934 msgid "gra" msgstr "gra" -#: ../src/qalc.cc:829 ../src/qalc.cc:3667 +#: ../src/qalc.cc:830 ../src/qalc.cc:3668 msgid "gradians" msgstr "gradians" -#: ../src/qalc.cc:842 ../src/qalc.cc:3095 ../src/qalc.cc:3785 +#: ../src/qalc.cc:843 ../src/qalc.cc:3096 ../src/qalc.cc:3786 msgid "caret as xor" msgstr "" -#: ../src/qalc.cc:843 ../src/qalc.cc:3123 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4057 +#: ../src/qalc.cc:844 ../src/qalc.cc:3124 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4058 #, fuzzy msgid "parsing mode" msgstr "exp mode" -#: ../src/qalc.cc:845 ../src/qalc.cc:1045 ../src/qalc.cc:3049 -#: ../src/qalc.cc:3125 ../src/qalc.cc:3745 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4065 +#: ../src/qalc.cc:846 ../src/qalc.cc:1046 ../src/qalc.cc:3050 +#: ../src/qalc.cc:3126 ../src/qalc.cc:3746 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4066 #, fuzzy msgid "adaptive" msgstr "alternative" -#: ../src/qalc.cc:846 ../src/qalc.cc:3126 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4062 +#: ../src/qalc.cc:847 ../src/qalc.cc:3127 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4063 msgid "implicit first" msgstr "" -#: ../src/qalc.cc:847 ../src/qalc.cc:3127 ../src/qalc.cc:3825 -#: ../src/qalc.cc:4059 +#: ../src/qalc.cc:848 ../src/qalc.cc:3128 ../src/qalc.cc:3826 +#: ../src/qalc.cc:4060 #, fuzzy msgid "conventional" msgstr "可选的" -#: ../src/qalc.cc:857 ../src/qalc.cc:1696 ../src/qalc.cc:3160 -#: ../src/qalc.cc:3853 +#: ../src/qalc.cc:858 ../src/qalc.cc:1697 ../src/qalc.cc:3161 +#: ../src/qalc.cc:3854 msgid "update exchange rates" msgstr "" -#: ../src/qalc.cc:858 ../src/qalc.cc:3163 ../src/qalc.cc:3855 +#: ../src/qalc.cc:859 ../src/qalc.cc:3164 ../src/qalc.cc:3856 msgid "never" msgstr "" -#: ../src/qalc.cc:860 ../src/qalc.cc:3162 ../src/qalc.cc:3854 +#: ../src/qalc.cc:861 ../src/qalc.cc:3163 ../src/qalc.cc:3855 #, fuzzy msgid "ask" msgstr "ans" -#: ../src/qalc.cc:868 ../src/qalc.cc:2979 ../src/qalc.cc:3693 +#: ../src/qalc.cc:869 ../src/qalc.cc:2980 ../src/qalc.cc:3694 msgid "multiplication sign" msgstr "multiplication sign" -#: ../src/qalc.cc:882 ../src/qalc.cc:2970 ../src/qalc.cc:3690 +#: ../src/qalc.cc:883 ../src/qalc.cc:2971 ../src/qalc.cc:3691 msgid "division sign" msgstr "division sign" -#: ../src/qalc.cc:896 ../src/qalc.cc:2937 ../src/qalc.cc:3668 +#: ../src/qalc.cc:897 ../src/qalc.cc:2938 ../src/qalc.cc:3669 #, fuzzy msgid "approximation" msgstr "近似" #. qalc command -#: ../src/qalc.cc:898 ../src/qalc.cc:969 ../src/qalc.cc:1111 -#: ../src/qalc.cc:2549 ../src/qalc.cc:2939 ../src/qalc.cc:3040 -#: ../src/qalc.cc:3188 ../src/qalc.cc:3668 ../src/qalc.cc:3742 -#: ../src/qalc.cc:3998 +#: ../src/qalc.cc:899 ../src/qalc.cc:970 ../src/qalc.cc:1112 +#: ../src/qalc.cc:2550 ../src/qalc.cc:2940 ../src/qalc.cc:3041 +#: ../src/qalc.cc:3189 ../src/qalc.cc:3669 ../src/qalc.cc:3743 +#: ../src/qalc.cc:3999 msgid "exact" msgstr "exact" -#: ../src/qalc.cc:899 ../src/qalc.cc:2940 ../src/qalc.cc:3668 +#: ../src/qalc.cc:900 ../src/qalc.cc:2941 ../src/qalc.cc:3669 msgid "try exact" msgstr "try exact" -#: ../src/qalc.cc:914 ../src/qalc.cc:2945 ../src/qalc.cc:3670 +#: ../src/qalc.cc:915 ../src/qalc.cc:2946 ../src/qalc.cc:3671 #, fuzzy msgid "interval calculation" msgstr "正在计算" -#: ../src/qalc.cc:914 +#: ../src/qalc.cc:915 msgid "uncertainty propagation" msgstr "" -#: ../src/qalc.cc:916 ../src/qalc.cc:2948 ../src/qalc.cc:3670 +#: ../src/qalc.cc:917 ../src/qalc.cc:2949 ../src/qalc.cc:3671 msgid "variance formula" msgstr "" -#: ../src/qalc.cc:916 +#: ../src/qalc.cc:917 #, fuzzy msgid "variance" msgstr "variable" -#: ../src/qalc.cc:917 ../src/qalc.cc:1069 ../src/qalc.cc:2944 -#: ../src/qalc.cc:2949 ../src/qalc.cc:3669 ../src/qalc.cc:3670 +#: ../src/qalc.cc:918 ../src/qalc.cc:1070 ../src/qalc.cc:2945 +#: ../src/qalc.cc:2950 ../src/qalc.cc:3670 ../src/qalc.cc:3671 msgid "interval arithmetic" msgstr "" -#: ../src/qalc.cc:927 ../src/qalc.cc:3142 ../src/qalc.cc:3832 +#: ../src/qalc.cc:928 ../src/qalc.cc:3143 ../src/qalc.cc:3833 msgid "autoconversion" msgstr "autoconversion" -#: ../src/qalc.cc:931 ../src/qalc.cc:2797 +#: ../src/qalc.cc:932 ../src/qalc.cc:2798 msgid "best" msgstr "best" -#: ../src/qalc.cc:932 ../src/qalc.cc:3151 ../src/qalc.cc:3841 +#: ../src/qalc.cc:933 ../src/qalc.cc:3152 ../src/qalc.cc:3842 #, fuzzy msgid "optimalsi" msgstr "可选的" -#: ../src/qalc.cc:933 ../src/qalc.cc:2797 ../src/qalc.cc:3149 -#: ../src/qalc.cc:3837 ../src/qalc.cc:4911 ../libqalculate/Calculator.cc:3047 +#: ../src/qalc.cc:934 ../src/qalc.cc:2798 ../src/qalc.cc:3150 +#: ../src/qalc.cc:3838 ../src/qalc.cc:4912 +#: ../libqalculate/Calculator-calculate.cc:833 #, fuzzy msgid "optimal" msgstr "可选的" -#: ../src/qalc.cc:935 ../src/qalc.cc:1113 ../src/qalc.cc:3042 -#: ../src/qalc.cc:3145 ../src/qalc.cc:3742 ../src/qalc.cc:3843 -#: ../src/qalc.cc:4966 ../libqalculate/Calculator.cc:3076 +#: ../src/qalc.cc:936 ../src/qalc.cc:1114 ../src/qalc.cc:3043 +#: ../src/qalc.cc:3146 ../src/qalc.cc:3743 ../src/qalc.cc:3844 +#: ../src/qalc.cc:4967 ../libqalculate/Calculator-calculate.cc:862 msgid "mixed" msgstr "" -#: ../src/qalc.cc:953 ../src/qalc.cc:3155 ../src/qalc.cc:3848 +#: ../src/qalc.cc:954 ../src/qalc.cc:3156 ../src/qalc.cc:3849 #, fuzzy msgid "currency conversion" msgstr "autoconversion" -#: ../src/qalc.cc:954 ../src/qalc.cc:2896 ../src/qalc.cc:3635 +#: ../src/qalc.cc:955 ../src/qalc.cc:2897 ../src/qalc.cc:3636 msgid "algebra mode" msgstr "algebra mode" #. qalc command -#: ../src/qalc.cc:957 ../src/qalc.cc:2884 ../src/qalc.cc:3612 +#: ../src/qalc.cc:958 ../src/qalc.cc:2885 ../src/qalc.cc:3613 msgid "simplify" msgstr "simplify" -#: ../src/qalc.cc:957 ../src/qalc.cc:2884 ../src/qalc.cc:2900 -#: ../src/qalc.cc:3203 ../src/qalc.cc:3612 ../src/qalc.cc:3635 -#: ../src/qalc.cc:5015 ../libqalculate/Calculator.cc:3101 +#: ../src/qalc.cc:958 ../src/qalc.cc:2885 ../src/qalc.cc:2901 +#: ../src/qalc.cc:3204 ../src/qalc.cc:3613 ../src/qalc.cc:3636 +#: ../src/qalc.cc:5016 ../libqalculate/Calculator-calculate.cc:891 msgid "expand" msgstr "" -#: ../src/qalc.cc:958 ../src/qalc.cc:2899 ../src/qalc.cc:3635 -#: ../src/qalc.cc:5012 ../libqalculate/Calculator.cc:3097 +#: ../src/qalc.cc:959 ../src/qalc.cc:2900 ../src/qalc.cc:3636 +#: ../src/qalc.cc:5013 ../libqalculate/Calculator-calculate.cc:887 msgid "factorize" msgstr "factorize" -#: ../src/qalc.cc:988 ../src/qalc.cc:3170 ../src/qalc.cc:3863 +#: ../src/qalc.cc:989 ../src/qalc.cc:3171 ../src/qalc.cc:3864 msgid "ignore locale" msgstr "" -#: ../src/qalc.cc:1000 ../src/qalc.cc:3173 ../src/qalc.cc:3201 -#: ../src/qalc.cc:3866 +#: ../src/qalc.cc:1001 ../src/qalc.cc:3174 ../src/qalc.cc:3202 +#: ../src/qalc.cc:3867 msgid "save mode" msgstr "save mode" -#: ../src/qalc.cc:1009 ../src/qalc.cc:3172 ../src/qalc.cc:3200 -#: ../src/qalc.cc:3865 +#: ../src/qalc.cc:1010 ../src/qalc.cc:3173 ../src/qalc.cc:3201 +#: ../src/qalc.cc:3866 msgid "save definitions" msgstr "save definitions" -#: ../src/qalc.cc:1018 ../src/qalc.cc:3080 ../src/qalc.cc:3764 +#: ../src/qalc.cc:1019 ../src/qalc.cc:3081 ../src/qalc.cc:3765 #, fuzzy msgid "scientific notation" msgstr "scientific" -#: ../src/qalc.cc:1022 ../src/qalc.cc:3083 ../src/qalc.cc:3769 +#: ../src/qalc.cc:1023 ../src/qalc.cc:3084 ../src/qalc.cc:3770 msgid "auto" msgstr "auto" -#: ../src/qalc.cc:1023 ../src/qalc.cc:3084 ../src/qalc.cc:3773 +#: ../src/qalc.cc:1024 ../src/qalc.cc:3085 ../src/qalc.cc:3774 msgid "pure" msgstr "pure" -#: ../src/qalc.cc:1024 ../src/qalc.cc:3085 ../src/qalc.cc:3775 +#: ../src/qalc.cc:1025 ../src/qalc.cc:3086 ../src/qalc.cc:3776 msgid "scientific" msgstr "scientific" -#: ../src/qalc.cc:1025 ../src/qalc.cc:3086 ../src/qalc.cc:3771 +#: ../src/qalc.cc:1026 ../src/qalc.cc:3087 ../src/qalc.cc:3772 msgid "engineering" msgstr "engineering" -#: ../src/qalc.cc:1034 ../src/qalc.cc:2953 ../src/qalc.cc:3671 +#: ../src/qalc.cc:1035 ../src/qalc.cc:2954 ../src/qalc.cc:3672 msgid "precision" msgstr "precision" -#: ../src/qalc.cc:1043 ../src/qalc.cc:3047 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1044 ../src/qalc.cc:3048 ../src/qalc.cc:3746 #, fuzzy msgid "interval display" msgstr "base display" -#: ../src/qalc.cc:1046 ../src/qalc.cc:3052 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1047 ../src/qalc.cc:3053 ../src/qalc.cc:3746 #, fuzzy msgid "significant" msgstr "scientific" -#: ../src/qalc.cc:1047 ../src/qalc.cc:3053 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1048 ../src/qalc.cc:3054 ../src/qalc.cc:3746 #, fuzzy msgid "interval" msgstr "integer" -#: ../src/qalc.cc:1048 ../src/qalc.cc:3054 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1049 ../src/qalc.cc:3055 ../src/qalc.cc:3746 #, fuzzy msgid "plusminus" msgstr "minus" -#: ../src/qalc.cc:1049 ../src/qalc.cc:3055 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1050 ../src/qalc.cc:3056 ../src/qalc.cc:3746 msgid "midpoint" msgstr "" -#: ../src/qalc.cc:1050 ../src/qalc.cc:3057 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1051 ../src/qalc.cc:3058 ../src/qalc.cc:3746 msgid "upper" msgstr "" -#: ../src/qalc.cc:1051 ../src/qalc.cc:3056 ../src/qalc.cc:3745 +#: ../src/qalc.cc:1052 ../src/qalc.cc:3057 ../src/qalc.cc:3746 #, fuzzy msgid "lower" msgstr "lowercase e" -#: ../src/qalc.cc:1076 ../src/qalc.cc:2965 ../src/qalc.cc:3685 +#: ../src/qalc.cc:1077 ../src/qalc.cc:2966 ../src/qalc.cc:3686 #, fuzzy msgid "variable units" msgstr "variables" -#: ../src/qalc.cc:1083 ../src/qalc.cc:3064 ../src/qalc.cc:3748 +#: ../src/qalc.cc:1084 ../src/qalc.cc:3065 ../src/qalc.cc:3749 msgid "max decimals" msgstr "max decimals" -#: ../src/qalc.cc:1095 ../src/qalc.cc:3071 ../src/qalc.cc:3755 +#: ../src/qalc.cc:1096 ../src/qalc.cc:3072 ../src/qalc.cc:3756 msgid "min decimals" msgstr "min decimals" -#: ../src/qalc.cc:1108 ../src/qalc.cc:3037 ../src/qalc.cc:3742 +#: ../src/qalc.cc:1109 ../src/qalc.cc:3038 ../src/qalc.cc:3743 msgid "fractions" msgstr "fractions" -#: ../src/qalc.cc:1113 +#: ../src/qalc.cc:1114 msgid "combined" msgstr "combined" -#: ../src/qalc.cc:1114 ../src/qalc.cc:3041 ../src/qalc.cc:3742 +#: ../src/qalc.cc:1115 ../src/qalc.cc:3042 ../src/qalc.cc:3743 msgid "long" msgstr "" -#: ../src/qalc.cc:1127 ../src/qalc.cc:3017 ../src/qalc.cc:3727 +#: ../src/qalc.cc:1128 ../src/qalc.cc:3018 ../src/qalc.cc:3728 #, fuzzy msgid "complex form" msgstr "complex" -#: ../src/qalc.cc:1129 ../src/qalc.cc:2667 ../src/qalc.cc:3019 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4856 ../libqalculate/Calculator.cc:3015 +#: ../src/qalc.cc:1130 ../src/qalc.cc:2668 ../src/qalc.cc:3020 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4857 +#: ../libqalculate/Calculator-calculate.cc:801 msgid "rectangular" msgstr "" -#: ../src/qalc.cc:1129 ../src/qalc.cc:2667 ../src/qalc.cc:4856 -#: ../libqalculate/Calculator.cc:3015 +#: ../src/qalc.cc:1130 ../src/qalc.cc:2668 ../src/qalc.cc:4857 +#: ../libqalculate/Calculator-calculate.cc:801 msgid "cartesian" msgstr "" -#: ../src/qalc.cc:1130 ../src/qalc.cc:2679 ../src/qalc.cc:3020 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4867 ../libqalculate/Calculator.cc:3018 +#: ../src/qalc.cc:1131 ../src/qalc.cc:2680 ../src/qalc.cc:3021 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4868 +#: ../libqalculate/Calculator-calculate.cc:804 #, fuzzy msgid "exponential" msgstr "可选的" -#: ../src/qalc.cc:1131 ../src/qalc.cc:2691 ../src/qalc.cc:3021 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4878 ../libqalculate/Calculator.cc:3021 +#: ../src/qalc.cc:1132 ../src/qalc.cc:2692 ../src/qalc.cc:3022 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4879 +#: ../libqalculate/Calculator-calculate.cc:807 msgid "polar" msgstr "" -#: ../src/qalc.cc:1132 ../src/qalc.cc:2703 ../src/qalc.cc:3022 -#: ../src/qalc.cc:3727 ../src/qalc.cc:4889 ../libqalculate/Calculator.cc:3024 -#: ../libqalculate/Function.cc:2211 +#: ../src/qalc.cc:1133 ../src/qalc.cc:2704 ../src/qalc.cc:3023 +#: ../src/qalc.cc:3728 ../src/qalc.cc:4890 +#: ../libqalculate/Calculator-calculate.cc:810 ../libqalculate/Function.cc:2245 msgid "angle" msgstr "angle" -#: ../src/qalc.cc:1132 ../src/qalc.cc:2703 ../src/qalc.cc:4889 -#: ../libqalculate/Calculator.cc:3024 +#: ../src/qalc.cc:1133 ../src/qalc.cc:2704 ../src/qalc.cc:4890 +#: ../libqalculate/Calculator-calculate.cc:810 msgid "phasor" msgstr "" -#: ../src/qalc.cc:1145 ../src/qalc.cc:3130 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1146 ../src/qalc.cc:3131 ../src/qalc.cc:3827 msgid "read precision" msgstr "read precision" -#: ../src/qalc.cc:1148 ../src/qalc.cc:3133 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1149 ../src/qalc.cc:3134 ../src/qalc.cc:3827 msgid "always" msgstr "always" -#: ../src/qalc.cc:1149 ../src/qalc.cc:3134 ../src/qalc.cc:3826 +#: ../src/qalc.cc:1150 ../src/qalc.cc:3135 ../src/qalc.cc:3827 msgid "when decimals" msgstr "" -#: ../src/qalc.cc:1180 +#: ../src/qalc.cc:1181 msgid "Unrecognized option." msgstr "无法识别的选项。" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Calendar" msgstr "" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Day" msgstr "" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Month" msgstr "" -#: ../src/qalc.cc:1314 +#: ../src/qalc.cc:1315 msgid "Year" msgstr "" -#: ../src/qalc.cc:1315 ../libqalculate/Calculator.cc:3124 +#: ../src/qalc.cc:1316 ../libqalculate/Calculator-calculate.cc:934 msgid "failed" msgstr "" -#: ../src/qalc.cc:1316 ../libqalculate/Calculator.cc:3125 +#: ../src/qalc.cc:1317 ../libqalculate/Calculator-calculate.cc:935 msgid "Gregorian:" msgstr "" -#: ../src/qalc.cc:1317 ../libqalculate/Calculator.cc:3126 +#: ../src/qalc.cc:1318 ../libqalculate/Calculator-calculate.cc:936 msgid "Hebrew:" msgstr "" -#: ../src/qalc.cc:1318 ../libqalculate/Calculator.cc:3127 +#: ../src/qalc.cc:1319 ../libqalculate/Calculator-calculate.cc:937 msgid "Islamic:" msgstr "" -#: ../src/qalc.cc:1319 ../libqalculate/Calculator.cc:3128 +#: ../src/qalc.cc:1320 ../libqalculate/Calculator-calculate.cc:938 msgid "Persian:" msgstr "" -#: ../src/qalc.cc:1320 ../libqalculate/Calculator.cc:3129 +#: ../src/qalc.cc:1321 ../libqalculate/Calculator-calculate.cc:939 msgid "Indian national:" msgstr "" -#: ../src/qalc.cc:1321 ../libqalculate/Calculator.cc:3130 +#: ../src/qalc.cc:1322 ../libqalculate/Calculator-calculate.cc:940 msgid "Chinese:" msgstr "" -#: ../src/qalc.cc:1326 ../libqalculate/Calculator.cc:3134 +#: ../src/qalc.cc:1327 ../libqalculate/Calculator-calculate.cc:944 msgid "Julian:" msgstr "" -#: ../src/qalc.cc:1327 ../libqalculate/Calculator.cc:3135 +#: ../src/qalc.cc:1328 ../libqalculate/Calculator-calculate.cc:945 msgid "Revised julian:" msgstr "" -#: ../src/qalc.cc:1328 ../libqalculate/Calculator.cc:3136 +#: ../src/qalc.cc:1329 ../libqalculate/Calculator-calculate.cc:946 #, fuzzy msgid "Coptic:" msgstr "可选的" -#: ../src/qalc.cc:1329 ../libqalculate/Calculator.cc:3137 +#: ../src/qalc.cc:1330 ../libqalculate/Calculator-calculate.cc:947 msgid "Ethiopian:" msgstr "" -#: ../src/qalc.cc:1396 ../libqalculate/BuiltinFunctions.cc:6237 -#: ../libqalculate/BuiltinFunctions.cc:6267 +#: ../src/qalc.cc:1397 ../libqalculate/BuiltinFunctions-matrixvector.cc:567 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:597 msgid "No matching item found." msgstr "未能找到匹配项。" -#: ../src/qalc.cc:1427 ../src/qalc.cc:1428 ../src/qalc.cc:1558 -#: ../src/qalc.cc:1559 ../src/qalc.cc:1626 ../src/qalc.cc:1627 +#: ../src/qalc.cc:1428 ../src/qalc.cc:1429 ../src/qalc.cc:1559 +#: ../src/qalc.cc:1560 ../src/qalc.cc:1627 ../src/qalc.cc:1628 #, fuzzy msgid "" "For more information about a specific function, variable or unit, please use " "the info command (in interactive mode)." msgstr "输入info 名称 以获取关于函数,变量或单位的信息。(例:info sin)" -#: ../src/qalc.cc:1441 +#: ../src/qalc.cc:1442 #, fuzzy msgid "Variables:" msgstr "变量" -#: ../src/qalc.cc:1443 +#: ../src/qalc.cc:1444 #, fuzzy msgid "Name" msgstr "名称" -#: ../src/qalc.cc:1444 ../src/qalc.cc:3552 ../src/qalc.cc:3559 +#: ../src/qalc.cc:1445 ../src/qalc.cc:3553 ../src/qalc.cc:3560 msgid "Value" msgstr "值" -#: ../src/qalc.cc:1532 +#: ../src/qalc.cc:1533 #, fuzzy msgid "Functions:" msgstr "函数" -#: ../src/qalc.cc:1546 +#: ../src/qalc.cc:1547 #, fuzzy msgid "Units:" msgstr "单位" -#: ../src/qalc.cc:1553 +#: ../src/qalc.cc:1554 msgid "No local variables, functions or units have been defined." msgstr "" -#: ../src/qalc.cc:1689 +#: ../src/qalc.cc:1690 msgid "usage: qalc [options] [expression]" msgstr "用法:qalc [选项] [表达式]" -#: ../src/qalc.cc:1691 +#: ../src/qalc.cc:1692 msgid "where options are:" msgstr "可用选项有:" -#: ../src/qalc.cc:1692 ../src/qalc.cc:1724 ../src/qalc.cc:3186 +#: ../src/qalc.cc:1693 ../src/qalc.cc:1725 ../src/qalc.cc:3187 msgid "BASE" msgstr "BASE" -#: ../src/qalc.cc:1693 +#: ../src/qalc.cc:1694 msgid "set the number base for results and, optionally, expressions" msgstr "" -#: ../src/qalc.cc:1698 +#: ../src/qalc.cc:1699 msgid "FILE" msgstr "文件" -#: ../src/qalc.cc:1699 +#: ../src/qalc.cc:1700 msgid "execute commands from a file first" msgstr "首先执行指定文件中的命令" -#: ../src/qalc.cc:1701 +#: ../src/qalc.cc:1702 msgid "start in interactive mode" msgstr "" -#: ../src/qalc.cc:1702 ../src/qalc.cc:1704 ../src/qalc.cc:1706 -#: ../src/qalc.cc:1708 +#: ../src/qalc.cc:1703 ../src/qalc.cc:1705 ../src/qalc.cc:1707 +#: ../src/qalc.cc:1709 msgid "SEARCH TERM" msgstr "" -#: ../src/qalc.cc:1703 +#: ../src/qalc.cc:1704 #, fuzzy msgid "" "displays a list of all user-defined or matching variables, functions and " "units" msgstr "\"%s\"不是合法的变量/函数/单位。" -#: ../src/qalc.cc:1705 +#: ../src/qalc.cc:1706 #, fuzzy msgid "displays a list of all or matching functions" msgstr "例如: info sin." -#: ../src/qalc.cc:1707 +#: ../src/qalc.cc:1708 #, fuzzy msgid "displays a list of all or matching units" msgstr "例如: info sin." -#: ../src/qalc.cc:1709 +#: ../src/qalc.cc:1710 #, fuzzy msgid "displays a list of all or matching variables" msgstr "\"%s\"不是合法的变量/函数/单位。" -#: ../src/qalc.cc:1710 +#: ../src/qalc.cc:1711 msgid "MILLISECONDS" msgstr "" -#: ../src/qalc.cc:1711 +#: ../src/qalc.cc:1712 msgid "" "terminate calculation and display of result after specified amount of time" msgstr "" -#: ../src/qalc.cc:1713 +#: ../src/qalc.cc:1714 msgid "do not load any functions, units, or variables from file" msgstr "不载入文件中的函数、单位和变量定义" -#: ../src/qalc.cc:1715 +#: ../src/qalc.cc:1716 msgid "do not load any global currencies from file" msgstr "不载入文件中的全局货币定义" -#: ../src/qalc.cc:1717 +#: ../src/qalc.cc:1718 msgid "do not load any global data sets from file" msgstr "不载入文件中的全局数据集" -#: ../src/qalc.cc:1719 +#: ../src/qalc.cc:1720 msgid "do not load any global functions from file" msgstr "不载入文件中的全局函数定义" -#: ../src/qalc.cc:1721 +#: ../src/qalc.cc:1722 msgid "do not load any global units from file" msgstr "不载入文件中的全局单位定义" -#: ../src/qalc.cc:1723 +#: ../src/qalc.cc:1724 msgid "do not load any global variables from file" msgstr "不载入文件中的全局变量定义" -#: ../src/qalc.cc:1725 +#: ../src/qalc.cc:1726 msgid "" "start in programming mode (same as -b \"BASE BASE\" -s \"xor^\", with base " "conversion)" msgstr "" -#: ../src/qalc.cc:1726 ../src/qalc.cc:3202 +#: ../src/qalc.cc:1727 ../src/qalc.cc:3203 msgid "OPTION" msgstr "选项" -#: ../src/qalc.cc:1726 ../src/qalc.cc:3202 +#: ../src/qalc.cc:1727 ../src/qalc.cc:3203 msgid "VALUE" msgstr "值" -#: ../src/qalc.cc:1727 +#: ../src/qalc.cc:1728 msgid "as set command in interactive program session (e.g. -set \"base 16\")" msgstr "与在交互编程环境下使用set命令的作用一致 (例如, -set \"base 16\")" -#: ../src/qalc.cc:1729 +#: ../src/qalc.cc:1730 msgid "reduce output to just the result of the input expression" msgstr "限制输出,仅输出输入表达式的结果" -#: ../src/qalc.cc:1731 +#: ../src/qalc.cc:1732 msgid "switch unicode support on/off" msgstr "打开/关闭unicode支持" -#: ../src/qalc.cc:1733 +#: ../src/qalc.cc:1734 msgid "show application version and exit" msgstr "" -#: ../src/qalc.cc:1735 +#: ../src/qalc.cc:1736 msgid "" "The program will start in interactive mode if no expression and no file is " "specified (or interactive mode is explicitly selected)." msgstr "如果未指定表达式,程序将以交互模式启动。" -#: ../src/qalc.cc:1835 +#: ../src/qalc.cc:1836 msgid "No option and value specified for set command." msgstr "在set命令中未指定选项或数值。" -#: ../src/qalc.cc:1843 +#: ../src/qalc.cc:1844 msgid "No file specified." msgstr "未指定文件。" -#: ../src/qalc.cc:1910 +#: ../src/qalc.cc:1911 msgid "Failed to load global definitions!" msgstr "载入全局定义失败!" -#: ../src/qalc.cc:1956 +#: ../src/qalc.cc:1957 #, c-format msgid "Could not open \"%s\".\n" msgstr "无法打开\"%s\".\n" -#: ../src/qalc.cc:1996 ../src/qalc.cc:2048 ../src/qalc.cc:4087 +#: ../src/qalc.cc:1997 ../src/qalc.cc:2049 ../src/qalc.cc:4088 #, c-format msgid "Illegal character, '%c', in expression." msgstr "在表达式中有非法字符\"%c\"。" #. The qalc command "set" as in "set precision 10". The original text string for commands is kept in addition to the translation. -#: ../src/qalc.cc:2115 ../src/qalc.cc:3202 ../src/qalc.cc:3616 +#: ../src/qalc.cc:2116 ../src/qalc.cc:3203 ../src/qalc.cc:3617 msgid "set" msgstr "set" #. qalc command -#: ../src/qalc.cc:2119 ../src/qalc.cc:3199 ../src/qalc.cc:3895 +#: ../src/qalc.cc:2120 ../src/qalc.cc:3200 ../src/qalc.cc:3896 msgid "save" msgstr "save" -#: ../src/qalc.cc:2119 ../src/qalc.cc:3199 ../src/qalc.cc:3895 +#: ../src/qalc.cc:2120 ../src/qalc.cc:3200 ../src/qalc.cc:3896 msgid "store" msgstr "store" #. qalc command -#: ../src/qalc.cc:2122 ../src/qalc.cc:2887 ../src/qalc.cc:3197 -#: ../src/qalc.cc:3921 +#: ../src/qalc.cc:2123 ../src/qalc.cc:2888 ../src/qalc.cc:3198 +#: ../src/qalc.cc:3922 msgid "mode" msgstr "mode" -#: ../src/qalc.cc:2124 +#: ../src/qalc.cc:2125 msgid "mode saved" msgstr "模式已保存" -#: ../src/qalc.cc:2126 +#: ../src/qalc.cc:2127 msgid "definitions" msgstr "definitions" -#: ../src/qalc.cc:2128 +#: ../src/qalc.cc:2129 msgid "definitions saved" msgstr "定义已保存" -#: ../src/qalc.cc:2175 ../src/qalc.cc:2177 ../src/qalc.cc:2235 -#: ../src/qalc.cc:2237 ../src/qalc.cc:2292 ../src/qalc.cc:2294 +#: ../src/qalc.cc:2176 ../src/qalc.cc:2178 ../src/qalc.cc:2236 +#: ../src/qalc.cc:2238 ../src/qalc.cc:2293 ../src/qalc.cc:2295 #, c-format msgid "Illegal name. Save as %s instead (default: no)?" msgstr "非法文件名。是否另存为%s?" -#: ../src/qalc.cc:2184 ../src/qalc.cc:2244 +#: ../src/qalc.cc:2185 ../src/qalc.cc:2245 msgid "" "An unit or variable with the same name already exists.\n" "Do you want to overwrite it (default: no)?" @@ -1191,18 +1198,18 @@ "您要覆盖它吗?" #. qalc command -#: ../src/qalc.cc:2207 ../src/qalc.cc:3205 ../src/qalc.cc:3902 -#: ../libqalculate/Function.cc:2172 +#: ../src/qalc.cc:2208 ../src/qalc.cc:3206 ../src/qalc.cc:3903 +#: ../libqalculate/Function.cc:2206 msgid "variable" msgstr "variable" #. qalc command -#: ../src/qalc.cc:2264 ../src/qalc.cc:3195 ../src/qalc.cc:3908 -#: ../libqalculate/Function.cc:2144 +#: ../src/qalc.cc:2265 ../src/qalc.cc:3196 ../src/qalc.cc:3909 +#: ../libqalculate/Function.cc:2178 msgid "function" msgstr "function" -#: ../src/qalc.cc:2301 +#: ../src/qalc.cc:2302 #, fuzzy msgid "" "An function with the same name already exists.\n" @@ -1212,300 +1219,309 @@ "您要覆盖它吗?" #. qalc command -#: ../src/qalc.cc:2321 ../src/qalc.cc:3187 ../src/qalc.cc:3915 +#: ../src/qalc.cc:2322 ../src/qalc.cc:3188 ../src/qalc.cc:3916 msgid "delete" msgstr "" -#: ../src/qalc.cc:2332 +#: ../src/qalc.cc:2333 #, fuzzy msgid "No user-defined variable or function with the specified name exist." msgstr "找不到指定名称的函数、变量或单位。" #. qalc command -#: ../src/qalc.cc:2336 ../src/qalc.cc:3185 ../src/qalc.cc:3868 +#: ../src/qalc.cc:2337 ../src/qalc.cc:3186 ../src/qalc.cc:3869 msgid "assume" msgstr "assume" -#: ../src/qalc.cc:2346 +#: ../src/qalc.cc:2347 #, fuzzy msgid "syntax" msgstr "rpn syntax" #. qalc command -#: ../src/qalc.cc:2353 ../src/qalc.cc:2388 ../src/qalc.cc:3209 -#: ../src/qalc.cc:3960 +#: ../src/qalc.cc:2354 ../src/qalc.cc:2389 ../src/qalc.cc:3210 +#: ../src/qalc.cc:3961 msgid "stack" msgstr "stack" #. qalc command -#: ../src/qalc.cc:2373 ../src/qalc.cc:3190 ../src/qalc.cc:3940 +#: ../src/qalc.cc:2374 ../src/qalc.cc:3191 ../src/qalc.cc:3941 msgid "exrates" msgstr "exrates" -#: ../src/qalc.cc:2390 ../src/qalc.cc:2408 ../src/qalc.cc:2417 -#: ../src/qalc.cc:2450 ../src/qalc.cc:2479 ../src/qalc.cc:2488 -#: ../src/qalc.cc:2505 ../src/qalc.cc:2512 ../src/qalc.cc:2530 -#: ../src/qalc.cc:2537 +#: ../src/qalc.cc:2391 ../src/qalc.cc:2409 ../src/qalc.cc:2418 +#: ../src/qalc.cc:2451 ../src/qalc.cc:2480 ../src/qalc.cc:2489 +#: ../src/qalc.cc:2506 ../src/qalc.cc:2513 ../src/qalc.cc:2531 +#: ../src/qalc.cc:2538 msgid "The RPN stack is empty." msgstr "逆波兰范式栈为空。" #. qalc command -#: ../src/qalc.cc:2406 ../src/qalc.cc:2415 ../src/qalc.cc:3215 -#: ../src/qalc.cc:3964 +#: ../src/qalc.cc:2407 ../src/qalc.cc:2416 ../src/qalc.cc:3216 +#: ../src/qalc.cc:3965 msgid "swap" msgstr "" -#: ../src/qalc.cc:2410 ../src/qalc.cc:2419 ../src/qalc.cc:2452 -#: ../src/qalc.cc:2481 ../src/qalc.cc:2490 +#: ../src/qalc.cc:2411 ../src/qalc.cc:2420 ../src/qalc.cc:2453 +#: ../src/qalc.cc:2482 ../src/qalc.cc:2491 #, fuzzy msgid "The RPN stack only contains one value." msgstr "逆波兰范式栈为空。" -#: ../src/qalc.cc:2438 ../src/qalc.cc:2471 ../src/qalc.cc:2519 -#: ../src/qalc.cc:2543 +#: ../src/qalc.cc:2439 ../src/qalc.cc:2472 ../src/qalc.cc:2520 +#: ../src/qalc.cc:2544 msgid "The specified RPN stack index does not exist." msgstr "" #. qalc command -#: ../src/qalc.cc:2448 ../src/qalc.cc:3212 ../src/qalc.cc:3986 +#: ../src/qalc.cc:2449 ../src/qalc.cc:3213 ../src/qalc.cc:3987 msgid "move" msgstr "" #. qalc command -#: ../src/qalc.cc:2477 ../src/qalc.cc:2486 ../src/qalc.cc:3214 -#: ../src/qalc.cc:3982 +#: ../src/qalc.cc:2478 ../src/qalc.cc:2487 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3983 msgid "rotate" msgstr "" -#: ../src/qalc.cc:2494 +#: ../src/qalc.cc:2495 msgid "up" msgstr "" -#: ../src/qalc.cc:2496 +#: ../src/qalc.cc:2497 msgid "down" msgstr "" #. qalc command -#: ../src/qalc.cc:2503 ../src/qalc.cc:2510 ../src/qalc.cc:3211 -#: ../src/qalc.cc:3974 +#: ../src/qalc.cc:2504 ../src/qalc.cc:2511 ../src/qalc.cc:3212 +#: ../src/qalc.cc:3975 msgid "copy" msgstr "" #. qalc command -#: ../src/qalc.cc:2525 ../src/qalc.cc:3210 ../src/qalc.cc:3950 +#: ../src/qalc.cc:2526 ../src/qalc.cc:3211 ../src/qalc.cc:3951 msgid "clear stack" msgstr "clear stack" #. qalc command -#: ../src/qalc.cc:2528 ../src/qalc.cc:2535 ../src/qalc.cc:3213 -#: ../src/qalc.cc:3954 +#: ../src/qalc.cc:2529 ../src/qalc.cc:2536 ../src/qalc.cc:3214 +#: ../src/qalc.cc:3955 msgid "pop" msgstr "" #. qalc command -#: ../src/qalc.cc:2569 ../src/qalc.cc:3204 ../src/qalc.cc:4006 +#: ../src/qalc.cc:2570 ../src/qalc.cc:3205 ../src/qalc.cc:4007 msgid "convert" msgstr "convert" #. "to"-operator -#: ../src/qalc.cc:2569 ../src/qalc.cc:3204 ../src/qalc.cc:4006 -#: ../src/qalc.cc:4049 ../libqalculate/Calculator.cc:518 -#: ../libqalculate/Calculator.cc:744 ../libqalculate/Calculator.cc:1540 -#: ../libqalculate/Calculator.cc:1541 ../libqalculate/Calculator.cc:3233 -#: ../libqalculate/Calculator.cc:3235 ../libqalculate/Calculator.cc:3248 -#: ../libqalculate/Calculator.cc:3250 ../libqalculate/Calculator.cc:3264 -#: ../libqalculate/Calculator.cc:3266 +#: ../src/qalc.cc:2570 ../src/qalc.cc:3205 ../src/qalc.cc:4007 +#: ../src/qalc.cc:4050 ../libqalculate/Calculator-calculate.cc:1065 +#: ../libqalculate/Calculator-calculate.cc:1067 +#: ../libqalculate/Calculator-calculate.cc:1080 +#: ../libqalculate/Calculator-calculate.cc:1082 +#: ../libqalculate/Calculator-calculate.cc:1096 +#: ../libqalculate/Calculator-calculate.cc:1098 +#: ../libqalculate/Calculator.cc:296 ../libqalculate/Calculator.cc:524 +#: ../libqalculate/Calculator.cc:1322 ../libqalculate/Calculator.cc:1323 msgid "to" msgstr "to" -#: ../src/qalc.cc:2654 ../src/qalc.cc:4822 ../libqalculate/Calculator.cc:3006 +#: ../src/qalc.cc:2655 ../src/qalc.cc:4823 +#: ../libqalculate/Calculator-calculate.cc:792 #, fuzzy msgid "Time zone parsing failed." msgstr "比较失败。" -#: ../src/qalc.cc:2727 ../src/qalc.cc:4850 ../libqalculate/Calculator.cc:3041 +#: ../src/qalc.cc:2728 ../src/qalc.cc:4851 +#: ../libqalculate/Calculator-calculate.cc:827 #, fuzzy msgid "bases" msgstr "base" -#: ../src/qalc.cc:2774 ../src/qalc.cc:4853 ../libqalculate/Calculator.cc:3044 +#: ../src/qalc.cc:2775 ../src/qalc.cc:4854 +#: ../libqalculate/Calculator-calculate.cc:830 msgid "calendars" msgstr "" -#: ../src/qalc.cc:2784 ../src/qalc.cc:4841 ../libqalculate/Calculator.cc:3031 +#: ../src/qalc.cc:2785 ../src/qalc.cc:4842 +#: ../libqalculate/Calculator-calculate.cc:817 #, fuzzy msgid "fraction" msgstr "fractions" -#: ../src/qalc.cc:2793 ../src/qalc.cc:4844 ../libqalculate/Calculator.cc:3034 +#: ../src/qalc.cc:2794 ../src/qalc.cc:4845 +#: ../libqalculate/Calculator-calculate.cc:820 #, fuzzy msgid "factors" msgstr "factor" #. qalc command -#: ../src/qalc.cc:2795 ../src/qalc.cc:2881 ../src/qalc.cc:3198 -#: ../src/qalc.cc:3608 ../src/qalc.cc:4847 ../libqalculate/Calculator.cc:3038 +#: ../src/qalc.cc:2796 ../src/qalc.cc:2882 ../src/qalc.cc:3199 +#: ../src/qalc.cc:3609 ../src/qalc.cc:4848 +#: ../libqalculate/Calculator-calculate.cc:824 #, fuzzy msgid "partial fraction" msgstr "fractions" #. qalc command -#: ../src/qalc.cc:2878 ../src/qalc.cc:3193 ../src/qalc.cc:3604 +#: ../src/qalc.cc:2879 ../src/qalc.cc:3194 ../src/qalc.cc:3605 msgid "factor" msgstr "factor" -#: ../src/qalc.cc:2892 ../src/qalc.cc:3633 +#: ../src/qalc.cc:2893 ../src/qalc.cc:3634 #, fuzzy msgid "Algebraic Mode" msgstr "algebra mode" -#: ../src/qalc.cc:2927 ../src/qalc.cc:3665 +#: ../src/qalc.cc:2928 ../src/qalc.cc:3666 #, fuzzy msgid "Calculation" msgstr "正在计算" -#: ../src/qalc.cc:2950 +#: ../src/qalc.cc:2951 #, fuzzy msgid "simplified" msgstr "simplify" -#: ../src/qalc.cc:2955 ../src/qalc.cc:3675 +#: ../src/qalc.cc:2956 ../src/qalc.cc:3676 msgid "Enabled Objects" msgstr "" -#: ../src/qalc.cc:2967 ../src/qalc.cc:3687 +#: ../src/qalc.cc:2968 ../src/qalc.cc:3688 msgid "Generic Display Options" msgstr "" -#: ../src/qalc.cc:2992 ../src/qalc.cc:3700 +#: ../src/qalc.cc:2993 ../src/qalc.cc:3701 #, fuzzy msgid "Numerical Display" msgstr "base display" -#: ../src/qalc.cc:3093 ../src/qalc.cc:3783 +#: ../src/qalc.cc:3094 ../src/qalc.cc:3784 #, fuzzy msgid "Parsing" msgstr "exp mode" -#: ../src/qalc.cc:3139 ../src/qalc.cc:3829 +#: ../src/qalc.cc:3140 ../src/qalc.cc:3830 #, fuzzy msgid "Units" msgstr "单位" -#: ../src/qalc.cc:3168 ../src/qalc.cc:3861 +#: ../src/qalc.cc:3169 ../src/qalc.cc:3862 msgid "Other" msgstr "" #. qalc command -#: ../src/qalc.cc:3176 ../src/qalc.cc:3600 +#: ../src/qalc.cc:3177 ../src/qalc.cc:3601 msgid "help" msgstr "help" -#: ../src/qalc.cc:3179 +#: ../src/qalc.cc:3180 #, fuzzy msgid "Enter a mathematical expression or a command and press enter." msgstr "请输入一个数学表达式或命令。" -#: ../src/qalc.cc:3180 +#: ../src/qalc.cc:3181 msgid "Complete functions, units and variables with the tabulator key." msgstr "使用tab键补全函数、命令和单位。" -#: ../src/qalc.cc:3182 +#: ../src/qalc.cc:3183 msgid "Available commands are:" msgstr "候选命令有:" -#: ../src/qalc.cc:3185 +#: ../src/qalc.cc:3186 msgid "ASSUMPTIONS" msgstr "假设" -#: ../src/qalc.cc:3187 ../src/qalc.cc:3194 ../src/qalc.cc:3195 -#: ../src/qalc.cc:3199 ../src/qalc.cc:3205 +#: ../src/qalc.cc:3188 ../src/qalc.cc:3195 ../src/qalc.cc:3196 +#: ../src/qalc.cc:3200 ../src/qalc.cc:3206 msgid "NAME" msgstr "名称" -#: ../src/qalc.cc:3194 ../src/qalc.cc:3226 ../src/qalc.cc:3925 +#: ../src/qalc.cc:3195 ../src/qalc.cc:3227 ../src/qalc.cc:3926 msgid "find" msgstr "" #. qalc command -#: ../src/qalc.cc:3194 ../src/qalc.cc:3224 ../src/qalc.cc:3226 -#: ../src/qalc.cc:3925 +#: ../src/qalc.cc:3195 ../src/qalc.cc:3225 ../src/qalc.cc:3227 +#: ../src/qalc.cc:3926 msgid "list" msgstr "" -#: ../src/qalc.cc:3195 ../src/qalc.cc:3205 +#: ../src/qalc.cc:3196 ../src/qalc.cc:3206 msgid "EXPRESSION" msgstr "" #. qalc command -#: ../src/qalc.cc:3196 ../src/qalc.cc:3252 ../src/qalc.cc:3934 -#: ../libqalculate/Calculator.cc:11336 ../libqalculate/DataSet.cc:364 -#: ../libqalculate/DataSet.cc:391 ../libqalculate/DataSet.cc:1038 +#: ../src/qalc.cc:3197 ../src/qalc.cc:3253 ../src/qalc.cc:3935 +#: ../libqalculate/Calculator-definitions.cc:2887 +#: ../libqalculate/DataSet.cc:365 ../libqalculate/DataSet.cc:392 +#: ../libqalculate/DataSet.cc:1039 msgid "info" msgstr "info" -#: ../src/qalc.cc:3199 +#: ../src/qalc.cc:3200 msgid "CATEGORY" msgstr "类别" -#: ../src/qalc.cc:3199 +#: ../src/qalc.cc:3200 msgid "TITLE" msgstr "标题" -#: ../src/qalc.cc:3204 +#: ../src/qalc.cc:3205 msgid "UNIT or \"TO\" COMMAND" msgstr "" #. qalc command -#: ../src/qalc.cc:3206 ../src/qalc.cc:4053 ../src/qalc.cc:4074 +#: ../src/qalc.cc:3207 ../src/qalc.cc:4054 ../src/qalc.cc:4075 msgid "quit" msgstr "quit" -#: ../src/qalc.cc:3206 ../src/qalc.cc:4053 ../src/qalc.cc:4074 +#: ../src/qalc.cc:3207 ../src/qalc.cc:4054 ../src/qalc.cc:4075 msgid "exit" msgstr "exit" -#: ../src/qalc.cc:3207 +#: ../src/qalc.cc:3208 msgid "Commands for RPN mode:" msgstr "" -#: ../src/qalc.cc:3208 +#: ../src/qalc.cc:3209 msgid "STATE" msgstr "" -#: ../src/qalc.cc:3211 ../src/qalc.cc:3213 +#: ../src/qalc.cc:3212 ../src/qalc.cc:3214 msgid "INDEX" msgstr "" -#: ../src/qalc.cc:3212 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3213 ../src/qalc.cc:3216 msgid "INDEX 1" msgstr "" -#: ../src/qalc.cc:3212 ../src/qalc.cc:3215 +#: ../src/qalc.cc:3213 ../src/qalc.cc:3216 msgid "INDEX 2" msgstr "" -#: ../src/qalc.cc:3214 +#: ../src/qalc.cc:3215 msgid "DIRECTION" msgstr "" -#: ../src/qalc.cc:3217 +#: ../src/qalc.cc:3218 msgid "Type help COMMAND for more information (example: help save)." msgstr "输入help 命令 以获取更多帮助(例如:help save)" -#: ../src/qalc.cc:3218 +#: ../src/qalc.cc:3219 msgid "" "Type info NAME for information about a function, variable or unit (example: " "info sin)." msgstr "输入info 名称 以获取关于函数,变量或单位的信息。(例:info sin)" -#: ../src/qalc.cc:3219 +#: ../src/qalc.cc:3220 msgid "" "When a line begins with '/', the following text is always interpreted as a " "command." msgstr "" -#: ../src/qalc.cc:3221 +#: ../src/qalc.cc:3222 msgid "" "For more information about mathematical expression, different options, and a " "complete list of functions, variables and units, see the relevant sections " @@ -1513,320 +1529,320 @@ "qalculate.github.io/manual/index.html)." msgstr "" -#: ../src/qalc.cc:3239 ../src/qalc.cc:3244 +#: ../src/qalc.cc:3240 ../src/qalc.cc:3245 #, fuzzy msgid "currencies" msgstr "货币" -#: ../src/qalc.cc:3261 +#: ../src/qalc.cc:3262 msgid "No function, variable or unit with specified name exist." msgstr "找不到指定名称的函数、变量或单位。" -#: ../src/qalc.cc:3271 +#: ../src/qalc.cc:3272 msgid "Function" msgstr "函数" -#: ../src/qalc.cc:3408 +#: ../src/qalc.cc:3409 #, fuzzy msgid "Expression:" msgstr "precision" -#: ../src/qalc.cc:3417 ../src/qalc.cc:3420 ../src/qalc.cc:3587 +#: ../src/qalc.cc:3418 ../src/qalc.cc:3421 ../src/qalc.cc:3588 msgid "Unit" msgstr "单位" -#: ../src/qalc.cc:3423 ../src/qalc.cc:3497 +#: ../src/qalc.cc:3424 ../src/qalc.cc:3498 msgid "Names" msgstr "名称" -#: ../src/qalc.cc:3441 +#: ../src/qalc.cc:3442 msgid "Base Unit" msgstr "基准单位" -#: ../src/qalc.cc:3448 +#: ../src/qalc.cc:3449 msgid "Relation" msgstr "关系" -#: ../src/qalc.cc:3453 ../src/qalc.cc:3555 +#: ../src/qalc.cc:3454 ../src/qalc.cc:3556 msgid "Relative uncertainty" msgstr "" -#: ../src/qalc.cc:3454 ../src/qalc.cc:3556 +#: ../src/qalc.cc:3455 ../src/qalc.cc:3557 msgid "Uncertainty" msgstr "" -#: ../src/qalc.cc:3464 +#: ../src/qalc.cc:3465 msgid "Inverse Relation" msgstr "反向关系" -#: ../src/qalc.cc:3476 +#: ../src/qalc.cc:3477 msgid "Base Units" msgstr "基准单位" -#: ../src/qalc.cc:3491 ../src/qalc.cc:3494 +#: ../src/qalc.cc:3492 ../src/qalc.cc:3495 msgid "Variable" msgstr "变量" -#: ../src/qalc.cc:3606 +#: ../src/qalc.cc:3607 msgid "Factorizes the current result." msgstr "因式分解当前结果。" -#: ../src/qalc.cc:3610 +#: ../src/qalc.cc:3611 msgid "Applies partial fraction decomposition to the current result." msgstr "" -#: ../src/qalc.cc:3614 +#: ../src/qalc.cc:3615 #, fuzzy msgid "Expands the current result." msgstr "因式分解当前结果。" -#: ../src/qalc.cc:3628 +#: ../src/qalc.cc:3629 msgid "Sets the value of an option." msgstr "设置选项的值。" -#: ../src/qalc.cc:3629 +#: ../src/qalc.cc:3630 msgid "Example: set base 16." msgstr "例: set base 16." -#: ../src/qalc.cc:3631 +#: ../src/qalc.cc:3632 #, fuzzy msgid "" "Available options and accepted values are (the current value is marked with " "'*'):" msgstr "可用的选项以及相应的值有:" -#: ../src/qalc.cc:3635 +#: ../src/qalc.cc:3636 msgid "Determines if the expression is factorized or not after calculation." msgstr "" -#: ../src/qalc.cc:3636 +#: ../src/qalc.cc:3637 msgid "Determines if unknown values will be assumed non-zero (x/x=1)." msgstr "" -#: ../src/qalc.cc:3637 +#: ../src/qalc.cc:3638 msgid "Display a message after a value has been assumed non-zero." msgstr "" -#: ../src/qalc.cc:3640 +#: ../src/qalc.cc:3641 #, fuzzy msgid "Default assumptions for unknown variables." msgstr "设置关于未知数的缺省假设。" -#: ../src/qalc.cc:3668 +#: ../src/qalc.cc:3669 msgid "" "How approximate variables and calculations are handled. In exact mode " "approximate values will not be calculated." msgstr "" -#: ../src/qalc.cc:3669 +#: ../src/qalc.cc:3670 msgid "" "If activated, interval arithmetic determines the final precision of " "calculations (avoids wrong results after loss of significance) with " "approximate functions and/or irrational numbers." msgstr "" -#: ../src/qalc.cc:3670 +#: ../src/qalc.cc:3671 msgid "" "Determines the method used for interval calculation / uncertainty " "propagation." msgstr "" -#: ../src/qalc.cc:3672 +#: ../src/qalc.cc:3673 msgid "" "Specifies the default number of significant digits displayed and determines " "the precision used for approximate calculations." msgstr "" -#: ../src/qalc.cc:3683 +#: ../src/qalc.cc:3684 #, fuzzy msgid "Interprete undefined symbols in expressions as unknown variables." msgstr "设置关于未知数的缺省假设。" -#: ../src/qalc.cc:3685 +#: ../src/qalc.cc:3686 msgid "" "If activated physical constants include units (e.g. c = 299 792 458 m∕s)." msgstr "" -#: ../src/qalc.cc:3689 +#: ../src/qalc.cc:3690 #, fuzzy msgid "Use abbreviated names for units and variables." msgstr "设置关于未知数的缺省假设。" -#: ../src/qalc.cc:3692 +#: ../src/qalc.cc:3693 msgid "Always place negative values last." msgstr "" -#: ../src/qalc.cc:3694 +#: ../src/qalc.cc:3695 msgid "Use negative exponents instead of division in result (x/y = xy^-1)." msgstr "" -#: ../src/qalc.cc:3696 +#: ../src/qalc.cc:3697 msgid "Add extra space around operators." msgstr "" -#: ../src/qalc.cc:3698 +#: ../src/qalc.cc:3699 msgid "Display Unicode characters." msgstr "" -#: ../src/qalc.cc:3702 ../src/qalc.cc:3804 +#: ../src/qalc.cc:3703 ../src/qalc.cc:3805 msgid "bin" msgstr "bin" -#: ../src/qalc.cc:3704 ../src/qalc.cc:3806 +#: ../src/qalc.cc:3705 ../src/qalc.cc:3807 msgid "oct" msgstr "oct" -#: ../src/qalc.cc:3706 ../src/qalc.cc:3808 +#: ../src/qalc.cc:3707 ../src/qalc.cc:3809 msgid "dec" msgstr "dec" -#: ../src/qalc.cc:3708 ../src/qalc.cc:3810 +#: ../src/qalc.cc:3709 ../src/qalc.cc:3811 msgid "hex" msgstr "hex" -#: ../src/qalc.cc:3710 +#: ../src/qalc.cc:3711 msgid "sexa" msgstr "" -#: ../src/qalc.cc:3729 ../src/qalc.cc:3787 +#: ../src/qalc.cc:3730 ../src/qalc.cc:3788 msgid "Determines the default decimal separator." msgstr "" -#: ../src/qalc.cc:3742 +#: ../src/qalc.cc:3743 msgid "" "Determines how rational numbers are displayed (e.g. 5/4 = 1 + 1/4 = 1.25). " "'long' removes limits on the size of the numerator and denonimator." msgstr "" -#: ../src/qalc.cc:3743 +#: ../src/qalc.cc:3744 msgid "" "Enables two's complement representation for display of negative hexadecimal " "numbers." msgstr "" -#: ../src/qalc.cc:3744 ../src/qalc.cc:3803 +#: ../src/qalc.cc:3745 ../src/qalc.cc:3804 msgid "Use 'j' (instead of 'i') as default symbol for the imaginary unit." msgstr "" -#: ../src/qalc.cc:3746 +#: ../src/qalc.cc:3747 msgid "Use lowercase e for E-notation (5e2 = 5 * 10^2)." msgstr "" -#: ../src/qalc.cc:3747 +#: ../src/qalc.cc:3748 msgid "Use lowercase letters for number bases > 10." msgstr "" -#: ../src/qalc.cc:3762 +#: ../src/qalc.cc:3763 msgid "" "If activated, 1/6 is displayed as '0.1 666...', otherwise as '0.166667'." msgstr "" -#: ../src/qalc.cc:3763 +#: ../src/qalc.cc:3764 msgid "" "Determines whether halfway numbers are rounded upwards or towards the " "nearest even integer." msgstr "" -#: ../src/qalc.cc:3765 +#: ../src/qalc.cc:3766 msgid "Determines how scientific notation are used (e.g. 5 543 000 = 5.543E6)." msgstr "" -#: ../src/qalc.cc:3780 +#: ../src/qalc.cc:3781 msgid "If actived, zeroes are kept at the end of approximate numbers." msgstr "" -#: ../src/qalc.cc:3781 +#: ../src/qalc.cc:3782 msgid "" "Enables two's complement representation for display of negative binary " "numbers." msgstr "" -#: ../src/qalc.cc:3785 +#: ../src/qalc.cc:3786 msgid "Use ^ as bitwise exclusive OR operator." msgstr "" -#: ../src/qalc.cc:3798 +#: ../src/qalc.cc:3799 msgid "Allows use of ',' as thousands separator." msgstr "" -#: ../src/qalc.cc:3801 +#: ../src/qalc.cc:3802 msgid "Allows use of '.' as thousands separator." msgstr "" -#: ../src/qalc.cc:3825 +#: ../src/qalc.cc:3826 #, fuzzy msgid "See 'help parsing mode'." msgstr "exp mode" -#: ../src/qalc.cc:3826 +#: ../src/qalc.cc:3827 msgid "" "If activated, numbers be interpreted as approximate with precision equal to " "the number of significant digits (3.20 = 3.20+/-0.005)." msgstr "" -#: ../src/qalc.cc:3831 +#: ../src/qalc.cc:3832 msgid "Enables automatic use of hecto, deca, deci, and centi." msgstr "" -#: ../src/qalc.cc:3833 +#: ../src/qalc.cc:3834 msgid "" "Controls automatic unit conversion of the result. 'optimalsi' always " "converts non-SI units, while 'optimal' only converts to more optimal unit " "expressions, with less units and exponents." msgstr "" -#: ../src/qalc.cc:3847 +#: ../src/qalc.cc:3848 msgid "" "If activated, binary prefixes are used by default for information units." msgstr "" -#: ../src/qalc.cc:3848 +#: ../src/qalc.cc:3849 msgid "" "Enables automatic conversion to the local currency when optimal unit " "conversion is enabled." msgstr "" -#: ../src/qalc.cc:3849 +#: ../src/qalc.cc:3850 msgid "" "Enables automatic use of prefixes in the denominator of unit expressions." msgstr "" -#: ../src/qalc.cc:3850 +#: ../src/qalc.cc:3851 msgid "" "If activated, units are separated from variables at the end of the result." msgstr "" -#: ../src/qalc.cc:3851 +#: ../src/qalc.cc:3852 msgid "Enables automatic use of prefixes in the result." msgstr "" -#: ../src/qalc.cc:3856 +#: ../src/qalc.cc:3857 msgid "days" msgstr "" -#: ../src/qalc.cc:3863 +#: ../src/qalc.cc:3864 msgid "Ignore system language and use English (requires restart)." msgstr "" -#: ../src/qalc.cc:3864 +#: ../src/qalc.cc:3865 #, fuzzy msgid "Activates the Reverse Polish Notation stack." msgstr "切换逆波兰范式模式。" -#: ../src/qalc.cc:3865 +#: ../src/qalc.cc:3866 #, fuzzy msgid "Save functions, units, and variables on exit." msgstr "一个合法的函数、单位或函数名" -#: ../src/qalc.cc:3866 +#: ../src/qalc.cc:3867 msgid "Save settings on exit." msgstr "" -#: ../src/qalc.cc:3870 +#: ../src/qalc.cc:3871 msgid "Set default assumptions for unknown variables." msgstr "设置关于未知数的缺省假设。" -#: ../src/qalc.cc:3897 +#: ../src/qalc.cc:3898 msgid "" "Saves the current result in a variable with the specified name. You may " "optionally also provide a category (default \"Temporary\") and a title." @@ -1834,60 +1850,60 @@ "将当前结果保存在指定的变量中。您可以同时为它指定一个类别(缺省为\"临时\")和标" "题。" -#: ../src/qalc.cc:3898 +#: ../src/qalc.cc:3899 msgid "" "If name equals \"mode\" or \"definitions\", the current mode and " "definitions, respectively, will be saved." msgstr "如果名称等于\"mode\"或\"definitions\",将保存当前模式或定义。" -#: ../src/qalc.cc:3900 +#: ../src/qalc.cc:3901 msgid "Example: store var1." msgstr "例如: store var1." -#: ../src/qalc.cc:3904 +#: ../src/qalc.cc:3905 #, fuzzy msgid "Create a variables with the specified name and expression." msgstr "找不到指定名称的函数、变量或单位。" -#: ../src/qalc.cc:3906 +#: ../src/qalc.cc:3907 #, fuzzy msgid "Example: variable var1 pi / 2." msgstr "例如: store var1." -#: ../src/qalc.cc:3910 +#: ../src/qalc.cc:3911 #, fuzzy msgid "Creates a function with the specified name and expression." msgstr "找不到指定名称的函数、变量或单位。" -#: ../src/qalc.cc:3911 +#: ../src/qalc.cc:3912 msgid "Use '\\x', '\\y', '\\z', '\\a', etc. for arguments in the expression." msgstr "" -#: ../src/qalc.cc:3913 +#: ../src/qalc.cc:3914 #, fuzzy msgid "Example: function func1 5*\\x." msgstr "例如: info sin." -#: ../src/qalc.cc:3917 +#: ../src/qalc.cc:3918 #, fuzzy msgid "Removes the user-defined variable or function with the specified name." msgstr "找不到指定名称的函数、变量或单位。" -#: ../src/qalc.cc:3919 +#: ../src/qalc.cc:3920 #, fuzzy msgid "Example: delete var1." msgstr "例如: store var1." -#: ../src/qalc.cc:3923 +#: ../src/qalc.cc:3924 msgid "Displays the current mode." msgstr "显示当前模式。" -#: ../src/qalc.cc:3927 +#: ../src/qalc.cc:3928 #, fuzzy msgid "Displays a list of variables, functions and units." msgstr "\"%s\"不是合法的变量/函数/单位。" -#: ../src/qalc.cc:3928 +#: ../src/qalc.cc:3929 msgid "" "Enter with argument 'currencies', 'functions', 'variables' or 'units' to " "show a list of all currencies, functions, variables or units. Enter a search " @@ -1895,274 +1911,274 @@ "called with no argument all user-definied objects are listed." msgstr "" -#: ../src/qalc.cc:3930 +#: ../src/qalc.cc:3931 #, fuzzy msgid "Example: list functions." msgstr "例如: info sin." -#: ../src/qalc.cc:3931 +#: ../src/qalc.cc:3932 #, fuzzy msgid "Example: find dinar." msgstr "例如: info sin." -#: ../src/qalc.cc:3932 +#: ../src/qalc.cc:3933 #, fuzzy msgid "Example: find variables planck." msgstr "例如: store var1." -#: ../src/qalc.cc:3936 +#: ../src/qalc.cc:3937 msgid "Displays information about a function, variable or unit." msgstr "显示关于函数,变量或单位的信息。" -#: ../src/qalc.cc:3938 +#: ../src/qalc.cc:3939 msgid "Example: info sin." msgstr "例如: info sin." -#: ../src/qalc.cc:3942 +#: ../src/qalc.cc:3943 msgid "Downloads current exchange rates from the Internet." msgstr "从因特网上下载最新汇率。" -#: ../src/qalc.cc:3946 +#: ../src/qalc.cc:3947 #, fuzzy msgid "(De)activates the Reverse Polish Notation stack and syntax." msgstr "切换逆波兰范式模式。" -#: ../src/qalc.cc:3948 +#: ../src/qalc.cc:3949 msgid "" "\"syntax\" activates only the RPN syntax and \"stack\" enables the RPN stack." msgstr "" -#: ../src/qalc.cc:3952 +#: ../src/qalc.cc:3953 #, fuzzy msgid "Clears the entire RPN stack." msgstr "清空逆波兰范式(RPN)栈" -#: ../src/qalc.cc:3956 +#: ../src/qalc.cc:3957 #, fuzzy msgid "Removes the top of the RPN stack or the value at the specified index." msgstr "找不到指定名称的函数、变量或单位。" -#: ../src/qalc.cc:3958 ../src/qalc.cc:3970 ../src/qalc.cc:3980 -#: ../src/qalc.cc:3990 +#: ../src/qalc.cc:3959 ../src/qalc.cc:3971 ../src/qalc.cc:3981 +#: ../src/qalc.cc:3991 msgid "" "Index 1 is the top of stack and negative index values counts from the bottom " "of the stack." msgstr "" -#: ../src/qalc.cc:3962 +#: ../src/qalc.cc:3963 msgid "Displays the RPN stack." msgstr "显示逆波兰范式(RPN)栈" -#: ../src/qalc.cc:3966 +#: ../src/qalc.cc:3967 msgid "Swaps position of values on the RPN stack." msgstr "" -#: ../src/qalc.cc:3968 +#: ../src/qalc.cc:3969 msgid "" "If no index is specified, the values on the top of the stack (index 1 and " "index 2) will be swapped and if only one index is specified, the value at " "this index will be swapped with the top value." msgstr "" -#: ../src/qalc.cc:3972 +#: ../src/qalc.cc:3973 #, fuzzy msgid "Example: swap 2 4" msgstr "例如: store var1." -#: ../src/qalc.cc:3976 +#: ../src/qalc.cc:3977 msgid "Duplicates a value on the RPN stack to the top of the stack." msgstr "" -#: ../src/qalc.cc:3978 +#: ../src/qalc.cc:3979 msgid "If no index is specified, the top of the stack is duplicated." msgstr "" -#: ../src/qalc.cc:3984 +#: ../src/qalc.cc:3985 msgid "Rotates the RPN stack up (default) or down." msgstr "" -#: ../src/qalc.cc:3988 +#: ../src/qalc.cc:3989 msgid "Changes the position of a value on the RPN stack." msgstr "" -#: ../src/qalc.cc:3992 +#: ../src/qalc.cc:3993 #, fuzzy msgid "Example: move 2 4" msgstr "例如: store var1." -#: ../src/qalc.cc:3996 +#: ../src/qalc.cc:3997 #, fuzzy msgid "Sets the result number base (equivalent to set base)." msgstr "设置结果base(相当于set base)" -#: ../src/qalc.cc:4000 +#: ../src/qalc.cc:4001 msgid "Equivalent to set approximation exact." msgstr "相当于set approximation exact" -#: ../src/qalc.cc:4004 +#: ../src/qalc.cc:4005 msgid "Equivalent to set approximation try exact." msgstr "相当于set approximation try exact." -#: ../src/qalc.cc:4009 +#: ../src/qalc.cc:4010 #, fuzzy msgid "Converts units or changes number base in current result." msgstr "为当前结果换算单位" -#: ../src/qalc.cc:4011 +#: ../src/qalc.cc:4012 #, fuzzy msgid "Possible values:" msgstr "可用的单位值有:" -#: ../src/qalc.cc:4013 +#: ../src/qalc.cc:4014 #, fuzzy msgid "- a unit or unit expression (e.g. meter or km/h)" msgstr "一个单位表达式 (例如 km/h)" -#: ../src/qalc.cc:4014 +#: ../src/qalc.cc:4015 msgid "prepend with ? to request the optimal prefix" msgstr "" -#: ../src/qalc.cc:4015 +#: ../src/qalc.cc:4016 msgid "prepend with b? to request the optimal binary prefix" msgstr "" -#: ../src/qalc.cc:4016 +#: ../src/qalc.cc:4017 msgid "prepend with + or - to force/disable use of mixed units" msgstr "" -#: ../src/qalc.cc:4017 +#: ../src/qalc.cc:4018 msgid "- a variable or physical constant (e.g. c)" msgstr "" -#: ../src/qalc.cc:4018 +#: ../src/qalc.cc:4019 #, fuzzy msgid "- base (convert to base units)" msgstr "base (转换为基准单位)" -#: ../src/qalc.cc:4019 +#: ../src/qalc.cc:4020 #, fuzzy msgid "- optimal (convert to optimal unit)" msgstr "base (转换为基准单位)" -#: ../src/qalc.cc:4020 +#: ../src/qalc.cc:4021 msgid "- mixed (convert to mixed units, e.g. hours + minutes)" msgstr "" -#: ../src/qalc.cc:4022 +#: ../src/qalc.cc:4023 msgid "- bin / binary (show as binary number)" msgstr "" -#: ../src/qalc.cc:4023 +#: ../src/qalc.cc:4024 msgid "- oct / octal (show as octal number)" msgstr "" -#: ../src/qalc.cc:4024 +#: ../src/qalc.cc:4025 msgid "- duo / duodecimal (show as duodecimal number)" msgstr "" -#: ../src/qalc.cc:4025 +#: ../src/qalc.cc:4026 msgid "- hex / hexadecimal (show as hexadecimal number)" msgstr "" -#: ../src/qalc.cc:4026 +#: ../src/qalc.cc:4027 msgid "- sex / sexagesimal (show as sexagesimal number)" msgstr "" -#: ../src/qalc.cc:4027 +#: ../src/qalc.cc:4028 msgid "- bijective (shown in bijective base-26)" msgstr "" -#: ../src/qalc.cc:4028 +#: ../src/qalc.cc:4029 #, fuzzy msgid "- roman (show as roman numerals)" msgstr "在罗马数字中有错:\"%s\"" -#: ../src/qalc.cc:4029 +#: ../src/qalc.cc:4030 msgid "- time (show in time format)" msgstr "" -#: ../src/qalc.cc:4030 +#: ../src/qalc.cc:4031 #, fuzzy msgid "- unicode" msgstr "unicode" -#: ../src/qalc.cc:4031 +#: ../src/qalc.cc:4032 msgid "- base # (show in specified number base)" msgstr "" -#: ../src/qalc.cc:4032 +#: ../src/qalc.cc:4033 msgid "- bases (show as binary, octal, decimal and hexadecimal number)" msgstr "" -#: ../src/qalc.cc:4034 +#: ../src/qalc.cc:4035 msgid "- rectangular / cartesian (show complex numbers in rectangular form)" msgstr "" -#: ../src/qalc.cc:4035 +#: ../src/qalc.cc:4036 msgid "- exponential (show complex numbers in exponential form)" msgstr "" -#: ../src/qalc.cc:4036 +#: ../src/qalc.cc:4037 msgid "- polar (show complex numbers in polar form)" msgstr "" -#: ../src/qalc.cc:4037 +#: ../src/qalc.cc:4038 msgid "- cis (show complex numbers in cis form)" msgstr "" -#: ../src/qalc.cc:4038 +#: ../src/qalc.cc:4039 msgid "- angle / phasor (show complex numbers in angle/phasor notation)" msgstr "" -#: ../src/qalc.cc:4040 +#: ../src/qalc.cc:4041 msgid "- fraction (show result as mixed fraction)" msgstr "" -#: ../src/qalc.cc:4041 +#: ../src/qalc.cc:4042 #, fuzzy msgid "- factors (factorize result)" msgstr "因式分解当前结果。" -#: ../src/qalc.cc:4043 +#: ../src/qalc.cc:4044 msgid "- UTC (show date and time in UTC time zone)" msgstr "" -#: ../src/qalc.cc:4044 +#: ../src/qalc.cc:4045 msgid "- UTC+/-hh[:mm] (show date and time in specified time zone)" msgstr "" -#: ../src/qalc.cc:4045 +#: ../src/qalc.cc:4046 msgid "- calendars" msgstr "" -#: ../src/qalc.cc:4047 +#: ../src/qalc.cc:4048 #, fuzzy msgid "Example: to ?g" msgstr "例如: store var1." -#: ../src/qalc.cc:4050 +#: ../src/qalc.cc:4051 msgid "" "This command can also be typed directly at the end of the mathematical " "expression (e.g. 5 ft + 2 in to meter)." msgstr "" -#: ../src/qalc.cc:4055 +#: ../src/qalc.cc:4056 msgid "Terminates this program." msgstr "结束此程序。" -#: ../src/qalc.cc:4060 +#: ../src/qalc.cc:4061 msgid "" "Implicit multiplication does not differ from explicit multiplication " "(\"12/2(1+2) = 12/2*3 = 18\", \"5x/5y = 5*x/5*y = xy\")." msgstr "" -#: ../src/qalc.cc:4063 +#: ../src/qalc.cc:4064 msgid "" "Implicit multiplication is parsed before explicit multiplication " "(\"12/2(1+2) = 12/(2*3) = 2\", \"5x/5y = (5*x)/(5*y) = x/y\")." msgstr "" -#: ../src/qalc.cc:4066 +#: ../src/qalc.cc:4067 msgid "" "The default adaptive mode works as the \"implicit first\" mode, unless " "spaces are found (\"1/5x = 1/(5*x)\", but \"1/5 x = (1/5)*x\"). In the " @@ -2170,67 +2186,67 @@ "(5*(m/s)) = 1 s\")." msgstr "" -#: ../src/qalc.cc:4068 +#: ../src/qalc.cc:4069 msgid "" "Function arguments without parentheses are an exception, where implicit " "multiplication in front of variables and units is parsed first regardless of " "mode (\"sqrt 2x = sqrt(2x)\")." msgstr "" -#: ../src/qalc.cc:4082 +#: ../src/qalc.cc:4083 #, fuzzy msgid "Unknown command." msgstr "不认识的罗马数字:\"%c\"" -#: ../src/qalc.cc:4131 +#: ../src/qalc.cc:4132 msgid "error" msgstr "错误" -#: ../src/qalc.cc:4133 +#: ../src/qalc.cc:4134 msgid "warning" msgstr "警告" -#: ../src/qalc.cc:4156 ../src/qalc.cc:4441 ../src/qalc.cc:5320 +#: ../src/qalc.cc:4157 ../src/qalc.cc:4442 ../src/qalc.cc:5347 msgid "approx." msgstr "约" -#: ../src/qalc.cc:4240 ../src/qalc.cc:4278 ../src/qalc.cc:4598 -#: ../src/qalc.cc:5173 ../libqalculate/Calculator.cc:11754 -#: ../libqalculate/MathStructure.cc:780 +#: ../src/qalc.cc:4241 ../src/qalc.cc:4279 ../src/qalc.cc:4599 +#: ../src/qalc.cc:5178 ../libqalculate/Calculator-calculate.cc:1615 +#: ../libqalculate/MathStructure.cc:448 #, c-format msgid "aborted" msgstr "已终止" -#: ../src/qalc.cc:4290 +#: ../src/qalc.cc:4291 msgid "RPN Register Moved" msgstr "逆波兰范式寄存器已被移动" -#: ../src/qalc.cc:4346 +#: ../src/qalc.cc:4347 msgid "Processing (press Enter to abort)" msgstr "正在处理(按回车键终止)" -#: ../src/qalc.cc:4615 +#: ../src/qalc.cc:4616 msgid "Factorizing (press Enter to abort)" msgstr "正在分解因式(按回车键终止)" -#: ../src/qalc.cc:4619 +#: ../src/qalc.cc:4620 msgid "Expanding partial fractions…" msgstr "" -#: ../src/qalc.cc:4623 +#: ../src/qalc.cc:4624 #, fuzzy msgid "Expanding (press Enter to abort)" msgstr "正在分解因式(按回车键终止)" -#: ../src/qalc.cc:4627 ../src/qalc.cc:5187 +#: ../src/qalc.cc:4628 ../src/qalc.cc:5192 msgid "Calculating (press Enter to abort)" msgstr "正在计算(按回车键终止)" -#: ../src/qalc.cc:5273 +#: ../src/qalc.cc:5300 msgid "RPN Operation" msgstr "(RPN)逆波兰范式操作" -#: ../src/qalc.cc:5805 +#: ../src/qalc.cc:5832 #, c-format msgid "" "Couldn't write preferences to\n" @@ -2239,989 +2255,1037 @@ "无法将偏好设置写入\n" "%s" -#: ../src/qalc.cc:5913 +#: ../src/qalc.cc:5940 msgid "Couldn't write definitions" msgstr "无法写定义" -#: ../src/test.cc:13 ../src/test.cc:28 ../libqalculate/Calculator.cc:2229 +#. thread cancellation is not safe +#: ../src/test.cc:13 ../src/test.cc:28 +#: ../libqalculate/Calculator-calculate.cc:172 msgid "" "The calculation has been forcibly terminated. Please restart the application " "and report this as a bug." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:109 +#: ../libqalculate/BuiltinFunctions-algebra.cc:359 +msgid "" +"No equality or inequality to solve. The entered expression to solve is not " +"correct (ex. \"x + 5 = 3\" is correct)" +msgstr "无法解等式或不等式。 输入的表达式不正确(例如:\"x + 5 = 3\"是正确的)" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:406 #, c-format -msgid "Too many elements (%s) for the dimensions (%sx%s) of the matrix." -msgstr "%s个元素对于%s X %s的矩阵而言太多。" +msgid "The comparison is true for all %s (with current assumptions)." +msgstr "此比较对所有%s为真。 (按照目前的假设)" -#: ../libqalculate/BuiltinFunctions.cc:172 -#: ../libqalculate/BuiltinFunctions.cc:234 +#: ../libqalculate/BuiltinFunctions-algebra.cc:410 +msgid "No possible solution was found (with current assumptions)." +msgstr "未找到可行解。 (按照目前的假设)" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:414 #, c-format -msgid "Row %s does not exist in matrix." -msgstr "在矩阵中不存在行%s。" +msgid "Was unable to completely isolate %s." +msgstr "无法完成分离%s/" -#: ../libqalculate/BuiltinFunctions.cc:185 -#: ../libqalculate/BuiltinFunctions.cc:230 +#: ../libqalculate/BuiltinFunctions-algebra.cc:418 +#: ../libqalculate/BuiltinFunctions-algebra.cc:581 +#: ../libqalculate/BuiltinFunctions-algebra.cc:673 #, c-format -msgid "Column %s does not exist in matrix." -msgstr "在矩阵中不存在列%s。" +msgid "The comparison is true for all %s if %s." +msgstr "此比较对所有%s为真,如果%s。" -#: ../libqalculate/BuiltinFunctions.cc:245 +#: ../libqalculate/BuiltinFunctions-algebra.cc:422 #, c-format -msgid "Argument 3, %s, is ignored for vectors." -msgstr "已为向量忽略了参数3, %s。" +msgid "Was unable to isolate %s." +msgstr "无法分离%s。" -#: ../libqalculate/BuiltinFunctions.cc:249 -#: ../libqalculate/BuiltinFunctions.cc:270 +#: ../libqalculate/BuiltinFunctions-algebra.cc:542 +#: ../libqalculate/BuiltinFunctions-algebra.cc:569 +#: ../libqalculate/BuiltinFunctions-algebra.cc:650 #, c-format -msgid "Element %s does not exist in vector." -msgstr "在向量中不存在元素%s。" +msgid "" +"Was unable to isolate %s with the current assumptions. The assumed sign was " +"therefore temporarily set as unknown." +msgstr "按照当前的假设条件无法分离%s。 因此,假设符号暂时已被设成了未知。" -#: ../libqalculate/BuiltinFunctions.cc:411 -#: ../libqalculate/BuiltinFunctions.cc:415 -#: ../libqalculate/BuiltinFunctions.cc:447 -#: ../libqalculate/BuiltinFunctions.cc:451 +#: ../libqalculate/BuiltinFunctions-algebra.cc:545 +#: ../libqalculate/BuiltinFunctions-algebra.cc:572 +#: ../libqalculate/BuiltinFunctions-algebra.cc:653 #, c-format -msgid "%s() requires that all matrices/vectors have the same dimensions." +msgid "" +"Was unable to isolate %s with the current assumptions. The assumed type and " +"sign was therefore temporarily set as unknown." +msgstr "" +"按照当前的假设条件无法分离%s。 因此,假设类型和符号暂时都已被设成了未知。" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:577 +#: ../libqalculate/BuiltinFunctions-algebra.cc:660 +#, c-format +msgid "The solution requires that %s." +msgstr "解需要%s。" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:667 +#, c-format +msgid "Solution %s requires that %s." +msgstr "解%s需要%s。" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:738 +#, fuzzy, c-format +msgid "" +"Unable to isolate %s.\n" +"\n" +"You might need to place the equations and variables in an appropriate order " +"so that each equation at least contains the corresponding variable (if " +"automatic reordering failed)." msgstr "" +"无法分离%s。\n" +"\n" +"您可能需要按照正确的顺序排列等式和变量,这样每个等式都至少包含一个对应变量。 " +"(如果自动排序失败的话)。" -#: ../libqalculate/BuiltinFunctions.cc:4759 -#: ../libqalculate/BuiltinFunctions.cc:4802 +#: ../libqalculate/BuiltinFunctions-algebra.cc:740 +#: ../libqalculate/BuiltinFunctions-algebra.cc:754 +#: ../libqalculate/BuiltinFunctions-algebra.cc:763 #, c-format -msgid "Unsolvable comparison in %s()." -msgstr "在%s()中无法进行比较。" +msgid "Unable to isolate %s." +msgstr "无法分离%s。" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:747 +#, c-format +msgid "Inequalities is not allowed in %s()." +msgstr "在%s中不允许不等式。" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:1089 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1094 +msgid "No differential equation found." +msgstr "" + +#: ../libqalculate/BuiltinFunctions-algebra.cc:1098 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1127 +#: ../libqalculate/BuiltinFunctions-algebra.cc:1133 +msgid "Unable to solve differential equation." +msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4972 -#: ../libqalculate/BuiltinFunctions.cc:5006 +#: ../libqalculate/BuiltinFunctions-datetime.cc:33 +#: ../libqalculate/BuiltinFunctions-datetime.cc:67 msgid "gregorian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4973 +#: ../libqalculate/BuiltinFunctions-datetime.cc:34 msgid "milankovic" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4974 +#: ../libqalculate/BuiltinFunctions-datetime.cc:35 msgid "julian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4975 +#: ../libqalculate/BuiltinFunctions-datetime.cc:36 msgid "islamic" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4976 +#: ../libqalculate/BuiltinFunctions-datetime.cc:37 msgid "hebrew" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4977 +#: ../libqalculate/BuiltinFunctions-datetime.cc:38 msgid "egyptian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4978 +#: ../libqalculate/BuiltinFunctions-datetime.cc:39 msgid "persian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4979 +#: ../libqalculate/BuiltinFunctions-datetime.cc:40 #, fuzzy msgid "coptic" msgstr "可选的" -#: ../libqalculate/BuiltinFunctions.cc:4980 +#: ../libqalculate/BuiltinFunctions-datetime.cc:41 msgid "ethiopian" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:4981 +#: ../libqalculate/BuiltinFunctions-datetime.cc:42 #, fuzzy msgid "indian" msgstr "radians" -#: ../libqalculate/BuiltinFunctions.cc:4982 +#: ../libqalculate/BuiltinFunctions-datetime.cc:43 msgid "chinese" msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:5408 -#: ../libqalculate/BuiltinFunctions.cc:5438 ../libqalculate/Number.cc:429 -#: ../libqalculate/Number.cc:900 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:57 #, c-format -msgid "Character '%s' was ignored in the number \"%s\" with base %s." -msgstr "字符\"%s\"被忽略,在数字\"%s\"中,其base为\"%s\"。" +msgid "Too many elements (%s) for the dimensions (%sx%s) of the matrix." +msgstr "%s个元素对于%s X %s的矩阵而言太多。" -#: ../libqalculate/BuiltinFunctions.cc:5703 -#: ../libqalculate/BuiltinFunctions.cc:5708 -#: ../libqalculate/BuiltinFunctions.cc:5710 -#: ../libqalculate/BuiltinFunctions.cc:5726 ../libqalculate/Calculator.cc:3409 -#: ../libqalculate/Calculator.cc:3416 ../libqalculate/Calculator.cc:3418 -#: ../libqalculate/Calculator.cc:3482 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:120 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:182 #, c-format -msgid "Original value (%s) was not found." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:5862 -msgid "" -"The number of requested elements in generate vector function must be a " -"positive integer." -msgstr "在常规向量函数中,需求的元素个数必须为正整数。" +msgid "Row %s does not exist in matrix." +msgstr "在矩阵中不存在行%s。" -#: ../libqalculate/BuiltinFunctions.cc:6179 -#: ../libqalculate/BuiltinFunctions.cc:6183 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:133 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:178 #, c-format -msgid "Too few elements (%s) in vector (%s required)" -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:6232 -#: ../libqalculate/BuiltinFunctions.cc:6249 -msgid "Comparison failed." -msgstr "比较失败。" +msgid "Column %s does not exist in matrix." +msgstr "在矩阵中不存在列%s。" -#: ../libqalculate/BuiltinFunctions.cc:6392 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:193 #, c-format -msgid "Object %s does not exist." -msgstr "对象%s不存在。" - -#: ../libqalculate/BuiltinFunctions.cc:6410 -#, fuzzy, c-format -msgid "Invalid variable name (%s)." -msgstr "一个合法的变量名" - -#: ../libqalculate/BuiltinFunctions.cc:6427 -msgid "" -"A global unit or variable was deactivated. It will be restored after the new " -"variable has been removed." -msgstr "" +msgid "Argument 3, %s, is ignored for vectors." +msgstr "已为向量忽略了参数3, %s。" -#: ../libqalculate/BuiltinFunctions.cc:6442 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:197 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:218 #, c-format -msgid "Register %s does not exist. Returning zero." -msgstr "寄存器%s不存在。返回零。" +msgid "Element %s does not exist in vector." +msgstr "在向量中不存在元素%s。" -#: ../libqalculate/BuiltinFunctions.cc:7390 -#: ../libqalculate/MathStructure.cc:284 ../libqalculate/MathStructure.cc:306 -#: ../libqalculate/MathStructure.cc:337 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:359 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:363 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:395 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:399 #, c-format -msgid "To avoid division by zero, the following must be true: %s." -msgstr "为了避免被零,必须满足:%s。" - -#: ../libqalculate/BuiltinFunctions.cc:7598 -#: ../libqalculate/BuiltinFunctions.cc:7617 -#: ../libqalculate/BuiltinFunctions.cc:7650 -#: ../libqalculate/BuiltinFunctions.cc:7672 -#: ../libqalculate/BuiltinFunctions.cc:7721 -#: ../libqalculate/BuiltinFunctions.cc:7756 -#: ../libqalculate/BuiltinFunctions.cc:7871 -#: ../libqalculate/BuiltinFunctions.cc:7921 -#: ../libqalculate/BuiltinFunctions.cc:7955 -#: ../libqalculate/BuiltinFunctions.cc:7998 -#: ../libqalculate/BuiltinFunctions.cc:8030 -#, fuzzy -msgid "Unable to integrate the expression." -msgstr "无法分离%s。" - -#: ../libqalculate/BuiltinFunctions.cc:7878 -#: ../libqalculate/BuiltinFunctions.cc:7948 -#, fuzzy -msgid "Unable to integrate the expression exact." -msgstr "无法分离%s。" - -#: ../libqalculate/BuiltinFunctions.cc:7915 -msgid "Definite integral was approximated." +msgid "%s() requires that all matrices/vectors have the same dimensions." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:8245 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:539 msgid "" -"No equality or inequality to solve. The entered expression to solve is not " -"correct (ex. \"x + 5 = 3\" is correct)" -msgstr "无法解等式或不等式。 输入的表达式不正确(例如:\"x + 5 = 3\"是正确的)" - -#: ../libqalculate/BuiltinFunctions.cc:8292 -#, c-format -msgid "The comparison is true for all %s (with current assumptions)." -msgstr "此比较对所有%s为真。 (按照目前的假设)" +"The number of requested elements in generate vector function must be a " +"positive integer." +msgstr "在常规向量函数中,需求的元素个数必须为正整数。" -#: ../libqalculate/BuiltinFunctions.cc:8296 -msgid "No possible solution was found (with current assumptions)." -msgstr "未找到可行解。 (按照目前的假设)" +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:562 +#: ../libqalculate/BuiltinFunctions-matrixvector.cc:579 +msgid "Comparison failed." +msgstr "比较失败。" -#: ../libqalculate/BuiltinFunctions.cc:8300 +#: ../libqalculate/BuiltinFunctions-statistics.cc:178 +#: ../libqalculate/BuiltinFunctions-statistics.cc:221 #, c-format -msgid "Was unable to completely isolate %s." -msgstr "无法完成分离%s/" +msgid "Unsolvable comparison in %s()." +msgstr "在%s()中无法进行比较。" -#: ../libqalculate/BuiltinFunctions.cc:8304 -#: ../libqalculate/BuiltinFunctions.cc:8467 -#: ../libqalculate/BuiltinFunctions.cc:8559 -#, c-format -msgid "The comparison is true for all %s if %s." -msgstr "此比较对所有%s为真,如果%s。" +#: ../libqalculate/BuiltinFunctions-calculus.cc:314 +#, fuzzy +msgid "Unable to find limit." +msgstr "无法分离%s。" -#: ../libqalculate/BuiltinFunctions.cc:8308 -#, c-format -msgid "Was unable to isolate %s." +#: ../libqalculate/BuiltinFunctions-calculus.cc:409 +#: ../libqalculate/BuiltinFunctions-calculus.cc:441 +#: ../libqalculate/MathStructure-integrate.cc:7294 +#: ../libqalculate/MathStructure-integrate.cc:7314 +#: ../libqalculate/MathStructure-integrate.cc:7349 +#: ../libqalculate/MathStructure-integrate.cc:7373 +#: ../libqalculate/MathStructure-integrate.cc:7423 +#: ../libqalculate/MathStructure-integrate.cc:7462 +#: ../libqalculate/MathStructure-integrate.cc:7658 +#: ../libqalculate/MathStructure-integrate.cc:7712 +#: ../libqalculate/MathStructure-integrate.cc:7754 +#, fuzzy +msgid "Unable to integrate the expression." msgstr "无法分离%s。" -#: ../libqalculate/BuiltinFunctions.cc:8428 -#: ../libqalculate/BuiltinFunctions.cc:8455 -#: ../libqalculate/BuiltinFunctions.cc:8536 +#: ../libqalculate/BuiltinFunctions-number.cc:684 +#: ../libqalculate/BuiltinFunctions-number.cc:714 ../libqalculate/Number.cc:459 +#: ../libqalculate/Number.cc:970 #, c-format -msgid "" -"Was unable to isolate %s with the current assumptions. The assumed sign was " -"therefore temporarily set as unknown." -msgstr "按照当前的假设条件无法分离%s。 因此,假设符号暂时已被设成了未知。" +msgid "Character '%s' was ignored in the number \"%s\" with base %s." +msgstr "字符\"%s\"被忽略,在数字\"%s\"中,其base为\"%s\"。" -#: ../libqalculate/BuiltinFunctions.cc:8431 -#: ../libqalculate/BuiltinFunctions.cc:8458 -#: ../libqalculate/BuiltinFunctions.cc:8539 +#. if left value is a function without any arguments, do function replacement +#: ../libqalculate/BuiltinFunctions-util.cc:414 +#: ../libqalculate/BuiltinFunctions-util.cc:419 +#: ../libqalculate/BuiltinFunctions-util.cc:421 +#: ../libqalculate/BuiltinFunctions-util.cc:437 +#: ../libqalculate/Calculator-calculate.cc:1239 +#: ../libqalculate/Calculator-calculate.cc:1251 +#: ../libqalculate/Calculator-calculate.cc:1253 +#: ../libqalculate/Calculator-calculate.cc:1256 +#: ../libqalculate/Calculator-calculate.cc:1327 #, c-format -msgid "" -"Was unable to isolate %s with the current assumptions. The assumed type and " -"sign was therefore temporarily set as unknown." +msgid "Original value (%s) was not found." msgstr "" -"按照当前的假设条件无法分离%s。 因此,假设类型和符号暂时都已被设成了未知。" -#: ../libqalculate/BuiltinFunctions.cc:8463 -#: ../libqalculate/BuiltinFunctions.cc:8546 +#: ../libqalculate/BuiltinFunctions-util.cc:627 +#: ../libqalculate/BuiltinFunctions-util.cc:631 #, c-format -msgid "The solution requires that %s." -msgstr "解需要%s。" +msgid "Too few elements (%s) in vector (%s required)" +msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:8553 +#: ../libqalculate/BuiltinFunctions-util.cc:677 #, c-format -msgid "Solution %s requires that %s." -msgstr "解%s需要%s。" +msgid "Object %s does not exist." +msgstr "对象%s不存在。" -#: ../libqalculate/BuiltinFunctions.cc:8624 +#: ../libqalculate/BuiltinFunctions-util.cc:695 #, fuzzy, c-format +msgid "Invalid variable name (%s)." +msgstr "一个合法的变量名" + +#: ../libqalculate/BuiltinFunctions-util.cc:712 msgid "" -"Unable to isolate %s.\n" -"\n" -"You might need to place the equations and variables in an appropriate order " -"so that each equation at least contains the corresponding variable (if " -"automatic reordering failed)." +"A global unit or variable was deactivated. It will be restored after the new " +"variable has been removed." msgstr "" -"无法分离%s。\n" -"\n" -"您可能需要按照正确的顺序排列等式和变量,这样每个等式都至少包含一个对应变量。 " -"(如果自动排序失败的话)。" - -#: ../libqalculate/BuiltinFunctions.cc:8626 -#: ../libqalculate/BuiltinFunctions.cc:8640 -#: ../libqalculate/BuiltinFunctions.cc:8649 -#, c-format -msgid "Unable to isolate %s." -msgstr "无法分离%s。" -#: ../libqalculate/BuiltinFunctions.cc:8633 +#: ../libqalculate/BuiltinFunctions-util.cc:727 #, c-format -msgid "Inequalities is not allowed in %s()." -msgstr "在%s中不允许不等式。" - -#: ../libqalculate/BuiltinFunctions.cc:8975 -#: ../libqalculate/BuiltinFunctions.cc:8980 -msgid "No differential equation found." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:8984 -#: ../libqalculate/BuiltinFunctions.cc:9013 -#: ../libqalculate/BuiltinFunctions.cc:9019 -msgid "Unable to solve differential equation." -msgstr "" - -#: ../libqalculate/BuiltinFunctions.cc:9045 -#, fuzzy -msgid "Unable to find limit." -msgstr "无法分离%s。" +msgid "Register %s does not exist. Returning zero." +msgstr "寄存器%s不存在。返回零。" -#: ../libqalculate/BuiltinFunctions.cc:9099 -#: ../libqalculate/BuiltinFunctions.cc:9113 +#: ../libqalculate/BuiltinFunctions-util.cc:794 +#: ../libqalculate/BuiltinFunctions-util.cc:808 #, fuzzy msgid "Matrix" msgstr "matrix" -#: ../libqalculate/BuiltinFunctions.cc:9124 -#: ../libqalculate/BuiltinFunctions.cc:9174 +#: ../libqalculate/BuiltinFunctions-util.cc:819 +#: ../libqalculate/BuiltinFunctions-util.cc:869 #, fuzzy msgid "Vector" msgstr "vector" -#: ../libqalculate/BuiltinFunctions.cc:9139 -#: ../libqalculate/BuiltinFunctions.cc:9185 ../libqalculate/Calculator.cc:12320 +#: ../libqalculate/BuiltinFunctions-util.cc:834 +#: ../libqalculate/BuiltinFunctions-util.cc:880 +#: ../libqalculate/Calculator-plot.cc:135 msgid "Unable to generate plot data with current min, max and step size." msgstr "按照当前的最大、最小和步长,无法生成绘图数据。" -#: ../libqalculate/BuiltinFunctions.cc:9141 -#: ../libqalculate/BuiltinFunctions.cc:9187 +#: ../libqalculate/BuiltinFunctions-util.cc:836 +#: ../libqalculate/BuiltinFunctions-util.cc:882 msgid "Sampling rate must be a positive integer." msgstr "" -#: ../libqalculate/BuiltinFunctions.cc:9150 -#: ../libqalculate/BuiltinFunctions.cc:9196 ../libqalculate/Calculator.cc:12290 +#: ../libqalculate/BuiltinFunctions-util.cc:845 +#: ../libqalculate/BuiltinFunctions-util.cc:891 +#: ../libqalculate/Calculator-plot.cc:105 msgid "Unable to generate plot data with current min, max and sampling rate." msgstr "按照当前的最大、最小和采样率,无法生成绘图数据。" -#: ../libqalculate/Calculator.cc:454 ../libqalculate/Calculator.cc:680 +#: ../libqalculate/Calculator-calculate.cc:303 +#: ../libqalculate/Calculator-calculate.cc:428 +msgid "Stack is empty. Filling remaining function arguments with zeroes." +msgstr "" + +#: ../libqalculate/Calculator-calculate.cc:1004 +msgid "calculating..." +msgstr "正在计算" + +#. "where"-operator +#: ../libqalculate/Calculator-calculate.cc:1130 +#: ../libqalculate/Calculator-calculate.cc:1132 +#: ../libqalculate/Calculator-calculate.cc:1151 +#: ../libqalculate/Calculator-calculate.cc:1153 +#: ../libqalculate/Calculator.cc:1326 +msgid "where" +msgstr "" + +#: ../libqalculate/Calculator-calculate.cc:1349 +#, c-format +msgid "Unhandled \"where\" expression: %s" +msgstr "" + +#: ../libqalculate/Calculator-calculate.cc:1567 +#: ../libqalculate/Calculator-calculate.cc:1614 +msgid "timed out" +msgstr "已超时" + +#: ../libqalculate/Calculator.cc:232 ../libqalculate/Calculator.cc:460 msgid "per" msgstr "per" -#: ../libqalculate/Calculator.cc:456 ../libqalculate/Calculator.cc:682 +#: ../libqalculate/Calculator.cc:234 ../libqalculate/Calculator.cc:462 msgid "times" msgstr "times" -#: ../libqalculate/Calculator.cc:458 ../libqalculate/Calculator.cc:684 +#: ../libqalculate/Calculator.cc:236 ../libqalculate/Calculator.cc:464 msgid "plus" msgstr "plus" -#: ../libqalculate/Calculator.cc:460 ../libqalculate/Calculator.cc:686 +#: ../libqalculate/Calculator.cc:238 ../libqalculate/Calculator.cc:466 msgid "minus" msgstr "minus" -#: ../libqalculate/Calculator.cc:462 ../libqalculate/Calculator.cc:688 -#: ../libqalculate/MathStructure.cc:21575 ../libqalculate/Function.cc:1331 -#: ../libqalculate/Function.cc:1339 ../libqalculate/Function.cc:1768 -#: ../libqalculate/Function.cc:1930 ../libqalculate/Function.cc:1938 +#: ../libqalculate/Calculator.cc:240 ../libqalculate/Calculator.cc:468 +#: ../libqalculate/MathStructure-print.cc:3170 ../libqalculate/Function.cc:1361 +#: ../libqalculate/Function.cc:1369 ../libqalculate/Function.cc:1802 +#: ../libqalculate/Function.cc:1964 ../libqalculate/Function.cc:1972 msgid "and" msgstr "and" -#: ../libqalculate/Calculator.cc:831 +#: ../libqalculate/Calculator.cc:611 msgid "Gradians unit is missing. Creating one for this session." msgstr "梯度单位丢失。自动为本会话创建了一个。" -#: ../libqalculate/Calculator.cc:832 ../libqalculate/Calculator.cc:840 -#: ../libqalculate/Calculator.cc:848 +#: ../libqalculate/Calculator.cc:612 ../libqalculate/Calculator.cc:620 +#: ../libqalculate/Calculator.cc:628 msgid "Angle/Plane Angle" msgstr "角/平面角" -#: ../libqalculate/Calculator.cc:839 +#: ../libqalculate/Calculator.cc:619 msgid "Radians unit is missing. Creating one for this session." msgstr "弧度单位丢失。自动为本会话创建了一个。" -#: ../libqalculate/Calculator.cc:847 +#: ../libqalculate/Calculator.cc:627 msgid "Degrees unit is missing. Creating one for this session." msgstr "角度单位丢失。自动为本会话创建了一个。" -#. "where"-operator -#: ../libqalculate/Calculator.cc:1544 ../libqalculate/Calculator.cc:3298 -#: ../libqalculate/Calculator.cc:3300 ../libqalculate/Calculator.cc:3319 -#: ../libqalculate/Calculator.cc:3321 -msgid "where" -msgstr "" - -#: ../libqalculate/Calculator.cc:2027 ../libqalculate/Calculator.cc:2028 -#: ../libqalculate/Calculator.cc:11818 ../libqalculate/Calculator.cc:11955 -#: ../libqalculate/Calculator.cc:12013 +#: ../libqalculate/Calculator.cc:1695 ../libqalculate/Calculator.cc:1696 +#: ../libqalculate/Calculator.cc:1700 +#: ../libqalculate/Calculator-definitions.cc:3285 +#: ../libqalculate/Calculator-definitions.cc:3455 +#: ../libqalculate/Calculator-definitions.cc:3513 msgid "Currency" msgstr "货币" -#: ../libqalculate/Calculator.cc:2563 ../libqalculate/Calculator.cc:2688 -msgid "Stack is empty. Filling remaining function arguments with zeroes." -msgstr "" - -#: ../libqalculate/Calculator.cc:3180 -msgid "calculating..." -msgstr "正在计算" - -#: ../libqalculate/Calculator.cc:3502 -#, c-format -msgid "Unhandled \"where\" expression: %s" -msgstr "" - -#: ../libqalculate/Calculator.cc:5259 +#: ../libqalculate/Calculator.cc:2635 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name of \"%s\", or " "the variable will be lost." msgstr "在名称中不再允许使用\"%s\"。请修改名称\"%s\",否则此变量将消失。" -#: ../libqalculate/Calculator.cc:5277 +#: ../libqalculate/Calculator.cc:2653 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name \"%s\", or " "the function will be lost." msgstr "在名称中不再允许使用\"%s\"。请修改名称\"%s\",否则此函数将消失。" -#: ../libqalculate/Calculator.cc:5294 +#: ../libqalculate/Calculator.cc:2670 #, c-format msgid "" "\"%s\" is not allowed in names anymore. Please change the name \"%s\", or " "the unit will be lost." msgstr "在名称中不再允许使用\"%s\"。请修改名称\"%s\",否则此单位将消失。" -#: ../libqalculate/Calculator.cc:6883 ../libqalculate/Calculator.cc:6927 -#: ../libqalculate/Calculator.cc:6930 ../libqalculate/Calculator.cc:8101 -#: ../libqalculate/Calculator.cc:8110 ../libqalculate/Calculator.cc:8165 -#: ../libqalculate/Calculator.cc:8227 ../libqalculate/Calculator.cc:8248 -#: ../libqalculate/Calculator.cc:8249 +#: ../libqalculate/Calculator.cc:2877 +#, c-format +msgid "Name \"%s\" is in use. Replacing with \"%s\"." +msgstr "名称\"%s\"已被使用。替换为\"%s\"。" + +#: ../libqalculate/Calculator-definitions.cc:763 ../libqalculate/DataSet.cc:540 +#, c-format +msgid "File not identified as Qalculate! definitions file: %s." +msgstr "指定的文件无法被Qalculate!识别! 定义文件:%s。" + +#: ../libqalculate/Calculator-definitions.cc:2870 +#: ../libqalculate/DataSet.cc:363 +msgid "Object" +msgstr "对象" + +#: ../libqalculate/Calculator-definitions.cc:2879 +#: ../libqalculate/DataSet.cc:364 +msgid "Property" +msgstr "属性" + +#: ../libqalculate/Calculator-definitions.cc:3178 +msgid "column" +msgstr "column" + +#: ../libqalculate/Calculator-definitions.cc:3181 +msgid "Column " +msgstr "列" + +#: ../libqalculate/Calculator-definitions.cc:3632 +#: ../libqalculate/Calculator-definitions.cc:3633 +#: ../libqalculate/Calculator-definitions.cc:3637 +#: ../libqalculate/Calculator-definitions.cc:3640 +#: ../libqalculate/Calculator-definitions.cc:3672 +#: ../libqalculate/Calculator-definitions.cc:3673 +#: ../libqalculate/Calculator-definitions.cc:3676 +#: ../libqalculate/Calculator-definitions.cc:3695 +#: ../libqalculate/Calculator-definitions.cc:3696 +#: ../libqalculate/Calculator-definitions.cc:3699 +#: ../libqalculate/Calculator-definitions.cc:3719 +#: ../libqalculate/Calculator-definitions.cc:3720 +#: ../libqalculate/Calculator-definitions.cc:3723 +#, c-format +msgid "Failed to download exchange rates from %s: %s." +msgstr "从%s下载汇率失败:%s。" + +#. ignore operators +#: ../libqalculate/Calculator-parse.cc:1668 +#: ../libqalculate/Calculator-parse.cc:1721 +#: ../libqalculate/Calculator-parse.cc:1725 +#: ../libqalculate/Calculator-parse.cc:2926 +#: ../libqalculate/Calculator-parse.cc:2935 +#: ../libqalculate/Calculator-parse.cc:2990 +#: ../libqalculate/Calculator-parse.cc:3055 +#: ../libqalculate/Calculator-parse.cc:3077 +#: ../libqalculate/Calculator-parse.cc:3078 #, c-format msgid "Misplaced operator(s) \"%s\" ignored" msgstr "已忽略放错地方的运算符\"%s\"。" -#: ../libqalculate/Calculator.cc:6924 ../libqalculate/Calculator.cc:8250 +#. ignore operators +#: ../libqalculate/Calculator-parse.cc:1717 +#: ../libqalculate/Calculator-parse.cc:3079 #, c-format msgid "Misplaced '%c' ignored" msgstr "已忽略放错地方的\"%c\"。" -#: ../libqalculate/Calculator.cc:6962 ../libqalculate/Function.cc:1489 -#: ../libqalculate/Function.cc:1520 +#: ../libqalculate/Calculator-parse.cc:1759 ../libqalculate/Function.cc:1519 +#: ../libqalculate/Function.cc:1550 #, c-format msgid "Internal id %s does not exist." msgstr "内部id %s不存在。" -#: ../libqalculate/Calculator.cc:6980 +#: ../libqalculate/Calculator-parse.cc:1779 #, c-format msgid "\"%s\" is not a valid variable/function/unit." msgstr "\"%s\"不是合法的变量/函数/单位。" -#: ../libqalculate/Calculator.cc:6995 +#: ../libqalculate/Calculator-parse.cc:1794 #, c-format msgid "" "Trailing characters \"%s\" (not a valid variable/function/unit) in number " "\"%s\" was ignored." msgstr "尾部字符\"%s\"(不是合法的变量/函数/单位) in 数字\"%s\"已被忽略。" -#: ../libqalculate/Calculator.cc:7261 +#: ../libqalculate/Calculator-parse.cc:2072 msgid "RPN syntax error. Values left at the end of the RPN expression." msgstr "RPN语法错误。在逆波兰表达式的最后剩下了数值。" -#: ../libqalculate/Calculator.cc:7264 ../libqalculate/Calculator.cc:7355 +#: ../libqalculate/Calculator-parse.cc:2075 +#: ../libqalculate/Calculator-parse.cc:2166 msgid "Unused stack values." msgstr "栈内还有值未被使用。" -#: ../libqalculate/Calculator.cc:7397 ../libqalculate/Calculator.cc:7605 +#: ../libqalculate/Calculator-parse.cc:2208 +#: ../libqalculate/Calculator-parse.cc:2416 #, fuzzy, c-format msgid "RPN syntax error. Operator '%c' not supported." msgstr "RPN语法错误。栈内是空的。" -#: ../libqalculate/Calculator.cc:7443 +#: ../libqalculate/Calculator-parse.cc:2254 msgid "RPN syntax error. Stack is empty." msgstr "RPN语法错误。栈内是空的。" -#: ../libqalculate/Calculator.cc:7464 +#: ../libqalculate/Calculator-parse.cc:2275 msgid "RPN syntax error. Operator ignored as there where only one stack value." msgstr "RPN语法错误。栈内只有一个值,因此运算符已被忽略。" -#: ../libqalculate/Calculator.cc:8525 -#, c-format -msgid "Name \"%s\" is in use. Replacing with \"%s\"." -msgstr "名称\"%s\"已被使用。替换为\"%s\"。" - -#: ../libqalculate/Calculator.cc:9212 ../libqalculate/DataSet.cc:539 -#, c-format -msgid "File not identified as Qalculate! definitions file: %s." -msgstr "指定的文件无法被Qalculate!识别! 定义文件:%s。" - -#: ../libqalculate/Calculator.cc:11319 ../libqalculate/DataSet.cc:362 -msgid "Object" -msgstr "对象" - -#: ../libqalculate/Calculator.cc:11328 ../libqalculate/DataSet.cc:363 -msgid "Property" -msgstr "属性" - -#: ../libqalculate/Calculator.cc:11627 -msgid "column" -msgstr "column" - -#: ../libqalculate/Calculator.cc:11630 -msgid "Column " -msgstr "列" - -#: ../libqalculate/Calculator.cc:11706 ../libqalculate/Calculator.cc:11753 -msgid "timed out" -msgstr "已超时" - -#: ../libqalculate/Calculator.cc:12125 ../libqalculate/Calculator.cc:12126 -#: ../libqalculate/Calculator.cc:12130 ../libqalculate/Calculator.cc:12133 -#: ../libqalculate/Calculator.cc:12165 ../libqalculate/Calculator.cc:12166 -#: ../libqalculate/Calculator.cc:12169 ../libqalculate/Calculator.cc:12188 -#: ../libqalculate/Calculator.cc:12189 ../libqalculate/Calculator.cc:12192 -#, c-format -msgid "Failed to download exchange rates from %s: %s." -msgstr "从%s下载汇率失败:%s。" - -#: ../libqalculate/Calculator.cc:12286 ../libqalculate/Calculator.cc:12316 -#: ../libqalculate/Calculator.cc:12346 ../libqalculate/Calculator.cc:12685 +#: ../libqalculate/Calculator-plot.cc:101 +#: ../libqalculate/Calculator-plot.cc:131 +#: ../libqalculate/Calculator-plot.cc:161 +#: ../libqalculate/Calculator-plot.cc:498 msgid "It took too long to generate the plot data." msgstr "" -#: ../libqalculate/Calculator.cc:12380 +#: ../libqalculate/Calculator-plot.cc:193 msgid "No extension in file name. Saving as PNG image." msgstr "未指定文件扩展名。保存为PNG图像。" -#: ../libqalculate/Calculator.cc:12399 +#: ../libqalculate/Calculator-plot.cc:212 msgid "Unknown extension in file name. Saving as PNG image." msgstr "未知的文件扩展名。保存为PNG图像。" -#: ../libqalculate/Calculator.cc:12616 +#: ../libqalculate/Calculator-plot.cc:429 #, c-format msgid "Could not create temporary file %s" msgstr "无法创建临时文件%s" -#: ../libqalculate/Calculator.cc:12732 +#: ../libqalculate/Calculator-plot.cc:545 msgid "" "Failed to invoke gnuplot. Make sure that you have gnuplot installed in your " "path." msgstr "调用gnuplot失败。请确认在您的路径中包含gnuplot。" -#: ../libqalculate/DataSet.cc:388 +#: ../libqalculate/DataSet.cc:389 #, c-format msgid "Object %s not available in data set." msgstr "数据集中没有对象%s。" -#: ../libqalculate/DataSet.cc:398 +#: ../libqalculate/DataSet.cc:399 #, c-format msgid "Property %s not available in data set." msgstr "数据集中没有属性%s。" -#: ../libqalculate/DataSet.cc:403 +#: ../libqalculate/DataSet.cc:404 #, c-format msgid "Property %s not defined for object %s." msgstr "属性%s在对象%s中没有定义。" -#: ../libqalculate/DataSet.cc:516 ../libqalculate/DataSet.cc:524 +#: ../libqalculate/DataSet.cc:517 ../libqalculate/DataSet.cc:525 #, c-format msgid "Unable to load data objects in %s." msgstr "无法从%s中载入数据。" -#: ../libqalculate/DataSet.cc:1042 +#: ../libqalculate/DataSet.cc:1043 msgid "data property" msgstr "data property" -#: ../libqalculate/DataSet.cc:1044 +#: ../libqalculate/DataSet.cc:1045 msgid "name of a data property" msgstr "数据属性的名称" -#: ../libqalculate/DataSet.cc:1052 ../libqalculate/DataSet.cc:1068 +#: ../libqalculate/DataSet.cc:1053 ../libqalculate/DataSet.cc:1069 msgid "no properties available" msgstr "没有可用的属性" -#: ../libqalculate/DataSet.cc:1102 +#: ../libqalculate/DataSet.cc:1103 #, c-format msgid "" "Data set \"%s\" has no object key that supports the provided argument type." msgstr "数据集\"%s\"中没有支持所提供的参数类型的对象关键字。" -#: ../libqalculate/DataSet.cc:1107 +#: ../libqalculate/DataSet.cc:1108 msgid "data object" msgstr "data object" -#: ../libqalculate/DataSet.cc:1110 +#: ../libqalculate/DataSet.cc:1111 msgid "an object from" msgstr "来自于...的对象" -#: ../libqalculate/DataSet.cc:1137 +#: ../libqalculate/DataSet.cc:1138 msgid "use" msgstr "use" -#: ../libqalculate/MathStructure.cc:265 +#: ../libqalculate/MathStructure-calculate.cc:76 #, fuzzy, c-format msgid "Required assumption: %s." msgstr "未被承认的假设" -#: ../libqalculate/MathStructure.cc:4031 ../libqalculate/MathStructure.cc:4052 +#: ../libqalculate/MathStructure-calculate.cc:95 +#: ../libqalculate/MathStructure-calculate.cc:117 +#: ../libqalculate/MathStructure-calculate.cc:148 +#: ../libqalculate/MathStructure-integrate.cc:7086 +#, c-format +msgid "To avoid division by zero, the following must be true: %s." +msgstr "为了避免被零,必须满足:%s。" + +#: ../libqalculate/MathStructure-calculate.cc:1653 +#: ../libqalculate/MathStructure-calculate.cc:1675 #, c-format msgid "" "The second matrix must have as many rows (was %s) as the first has columns " "(was %s) for matrix multiplication." msgstr "在矩阵乘法中,第二个向量的列数(%s)必须与第一个向量的行数(%s)相同。" -#: ../libqalculate/MathStructure.cc:8936 ../libqalculate/MathStructure.cc:8977 -#: ../libqalculate/MathStructure.cc:9010 ../libqalculate/MathStructure.cc:9077 -#: ../libqalculate/MathStructure.cc:9105 ../libqalculate/MathStructure.cc:9124 -#: ../libqalculate/MathStructure.cc:9143 ../libqalculate/MathStructure.cc:9162 -#: ../libqalculate/MathStructure.cc:9270 ../libqalculate/MathStructure.cc:16270 -#: ../libqalculate/MathStructure.cc:16661 +#: ../libqalculate/MathStructure-calculate.cc:6072 +#: ../libqalculate/MathStructure-calculate.cc:6113 +#: ../libqalculate/MathStructure-calculate.cc:6146 +#: ../libqalculate/MathStructure-calculate.cc:6213 +#: ../libqalculate/MathStructure-calculate.cc:6241 +#: ../libqalculate/MathStructure-calculate.cc:6260 +#: ../libqalculate/MathStructure-calculate.cc:6279 +#: ../libqalculate/MathStructure-calculate.cc:6298 +#: ../libqalculate/MathStructure-calculate.cc:6406 +#: ../libqalculate/MathStructure-factor.cc:413 +#: ../libqalculate/MathStructure-factor.cc:1304 msgid "This is a bug. Please report it." msgstr "这是个bug。请想我们报告它。" -#: ../libqalculate/MathStructure.cc:9353 ../libqalculate/Function.cc:527 +#: ../libqalculate/MathStructure-calculate.cc:6495 +#: ../libqalculate/Function.cc:557 #, fuzzy msgid "No unknown variable/symbol was found." msgstr "一个未知变量或符号" -#: ../libqalculate/MathStructure.cc:11752 -#: ../libqalculate/MathStructure.cc:11757 -#, c-format -msgid "Limit for %s determined graphically." +#: ../libqalculate/MathStructure-convert.cc:262 +msgid "" +"Calculations involving conversion of units without proportional linear " +"relationship (e.g. with multiple temperature units), might give unexpected " +"results and is not recommended." msgstr "" -#: ../libqalculate/MathStructure.cc:12582 +#: ../libqalculate/MathStructure-eval.cc:754 msgid "Interval potentially calculated wide." msgstr "" -#: ../libqalculate/MathStructure.cc:13500 +#: ../libqalculate/MathStructure-eval.cc:2024 msgid "" "Calculation of uncertainty propagation partially failed (using interval " "arithmetic instead when necessary)." msgstr "" -#: ../libqalculate/MathStructure.cc:13638 +#: ../libqalculate/MathStructure-eval.cc:2170 msgid "" "Calculation of uncertainty propagation failed (using interval arithmetic " "instead)." msgstr "" -#: ../libqalculate/MathStructure.cc:18517 +#: ../libqalculate/MathStructure-factor.cc:3160 msgid "" "Because of time constraints only a limited number of combinations of terms " "were tried during factorization. Repeat factorization to try other random " "combinations." msgstr "" -#: ../libqalculate/MathStructure.cc:21769 -msgid "undefined" -msgstr "undefined" +#: ../libqalculate/MathStructure-integrate.cc:7668 +#: ../libqalculate/MathStructure-integrate.cc:7743 +#, fuzzy +msgid "Unable to integrate the expression exact." +msgstr "无法分离%s。" + +#: ../libqalculate/MathStructure-integrate.cc:7707 +msgid "Definite integral was approximated." +msgstr "" + +#: ../libqalculate/MathStructure-isolatex.cc:999 +#: ../libqalculate/MathStructure-isolatex.cc:1176 +#: ../libqalculate/MathStructure-isolatex.cc:1815 +#: ../libqalculate/MathStructure-isolatex.cc:2335 +#: ../libqalculate/MathStructure-isolatex.cc:2401 +#: ../libqalculate/MathStructure-isolatex.cc:2451 +#: ../libqalculate/MathStructure-isolatex.cc:2472 +#: ../libqalculate/MathStructure-isolatex.cc:2530 +#: ../libqalculate/MathStructure-isolatex.cc:2656 +#: ../libqalculate/MathStructure-isolatex.cc:2801 +#, c-format +msgid "Interval arithmetic was disabled during calculation of %s." +msgstr "" + +#: ../libqalculate/MathStructure-isolatex.cc:2800 +#, c-format +msgid "Not all complex roots were calculated for %s." +msgstr "" + +#: ../libqalculate/MathStructure-isolatex.cc:4394 +#, c-format +msgid "Only one or two of the roots where calculated for %s." +msgstr "" -#: ../libqalculate/MathStructure.cc:21810 +#: ../libqalculate/MathStructure-limit.cc:967 +#: ../libqalculate/MathStructure-limit.cc:972 +#, c-format +msgid "Limit for %s determined graphically." +msgstr "" + +#: ../libqalculate/MathStructure-matrixvector.cc:62 #, c-format msgid "Unsolvable comparison at element %s when trying to rank vector." msgstr "" -#: ../libqalculate/MathStructure.cc:21860 +#: ../libqalculate/MathStructure-matrixvector.cc:112 #, c-format msgid "Unsolvable comparison at element %s when trying to sort vector." msgstr "试图为向量排序,但无法比较元素%s。" -#: ../libqalculate/MathStructure.cc:22285 +#: ../libqalculate/MathStructure-matrixvector.cc:537 msgid "The determinant can only be calculated for square matrices." msgstr "只能为方阵计算行列式" -#: ../libqalculate/MathStructure.cc:22348 +#: ../libqalculate/MathStructure-matrixvector.cc:600 msgid "The permanent can only be calculated for square matrices." msgstr "只能为方阵计算不变积和式" -#: ../libqalculate/MathStructure.cc:22435 +#: ../libqalculate/MathStructure-matrixvector.cc:687 msgid "Inverse of singular matrix." msgstr "奇异矩阵的逆。" -#: ../libqalculate/MathStructure.cc:22789 -msgid "" -"Calculations involving conversion of units without proportional linear " -"relationship (e.g. with multiple temperature units), might give unexpected " -"results and is not recommended." -msgstr "" - -#: ../libqalculate/MathStructure.cc:24092 -#: ../libqalculate/MathStructure.cc:24135 +#: ../libqalculate/MathStructure-matrixvector.cc:817 +#: ../libqalculate/MathStructure-matrixvector.cc:860 msgid "Too many data points" msgstr "" -#: ../libqalculate/MathStructure.cc:24099 +#: ../libqalculate/MathStructure-matrixvector.cc:824 msgid "" "The selected min and max do not result in a positive, finite number of data " "points" msgstr "" -#: ../libqalculate/MathStructure.cc:24132 +#: ../libqalculate/MathStructure-matrixvector.cc:857 msgid "" "The selected min, max and step size do not result in a positive, finite " "number of data points" msgstr "" -#: ../libqalculate/MathStructure.cc:32190 -#: ../libqalculate/MathStructure.cc:32368 -#: ../libqalculate/MathStructure.cc:33005 -#: ../libqalculate/MathStructure.cc:33525 -#: ../libqalculate/MathStructure.cc:33591 -#: ../libqalculate/MathStructure.cc:33641 -#: ../libqalculate/MathStructure.cc:33662 -#: ../libqalculate/MathStructure.cc:33720 -#: ../libqalculate/MathStructure.cc:33846 -#: ../libqalculate/MathStructure.cc:33990 -#, c-format -msgid "Interval arithmetic was disabled during calculation of %s." -msgstr "" - -#: ../libqalculate/MathStructure.cc:33989 -#, c-format -msgid "Not all complex roots were calculated for %s." -msgstr "" - -#: ../libqalculate/MathStructure.cc:35479 -#, c-format -msgid "Only one or two of the roots where calculated for %s." -msgstr "" +#: ../libqalculate/MathStructure-print.cc:3364 +msgid "undefined" +msgstr "undefined" -#: ../libqalculate/Function.cc:171 +#: ../libqalculate/Function.cc:185 #, c-format msgid "%s() requires that %s" msgstr "%s()需要%s。" -#: ../libqalculate/Function.cc:326 ../libqalculate/Function.cc:385 -#: ../libqalculate/Function.cc:445 +#: ../libqalculate/Function.cc:351 ../libqalculate/Function.cc:413 +#: ../libqalculate/Function.cc:474 #, c-format msgid "" "Additional arguments for function %s() was ignored. Function can only use %s " "argument(s)." msgstr "已忽略函数%s的多余参数。它只需要%s个参数。" -#: ../libqalculate/Function.cc:466 +#: ../libqalculate/Function.cc:495 #, c-format msgid "You need at least %s argument(s) (%s) in function %s()." msgstr "你需要至少%s个参数(%s)提供给函数%s()" -#: ../libqalculate/Function.cc:468 +#: ../libqalculate/Function.cc:497 #, c-format msgid "You need at least %s argument(s) in function %s()." msgstr "你需要至少%s个参数提供给函数%s()" -#: ../libqalculate/Function.cc:1321 +#: ../libqalculate/Function.cc:1351 msgid "a free value" msgstr "一个自由量" -#: ../libqalculate/Function.cc:1326 +#: ../libqalculate/Function.cc:1356 msgid "that is nonzero" msgstr "非零" -#: ../libqalculate/Function.cc:1334 +#: ../libqalculate/Function.cc:1364 msgid "that is rational (polynomial)" msgstr "合理的(多项式的)" -#: ../libqalculate/Function.cc:1342 +#: ../libqalculate/Function.cc:1372 msgid "that fulfills the condition:" msgstr "满足下列条件:" -#: ../libqalculate/Function.cc:1345 +#: ../libqalculate/Function.cc:1375 msgid "Argument" msgstr "自变量" -#: ../libqalculate/Function.cc:1409 +#: ../libqalculate/Function.cc:1439 #, c-format msgid "Argument %s in %s() must be %s." msgstr "参数%s, 在%s()中必须为%s。" -#: ../libqalculate/Function.cc:1411 +#: ../libqalculate/Function.cc:1441 #, c-format msgid "Argument %s, %s, in %s() must be %s." msgstr "参数%s,%s, 在%s()中必须为%s。" -#: ../libqalculate/Function.cc:1749 +#: ../libqalculate/Function.cc:1783 msgid "a rational number" msgstr "一个有理数" -#: ../libqalculate/Function.cc:1751 +#: ../libqalculate/Function.cc:1785 msgid "a number" msgstr "一个数" -#: ../libqalculate/Function.cc:1753 +#: ../libqalculate/Function.cc:1787 msgid "a real number" msgstr "一个实数" -#: ../libqalculate/Function.cc:1758 ../libqalculate/Function.cc:1911 -#: ../libqalculate/Function.cc:1916 +#: ../libqalculate/Function.cc:1792 ../libqalculate/Function.cc:1945 +#: ../libqalculate/Function.cc:1950 msgid ">=" msgstr ">=" -#: ../libqalculate/Function.cc:1760 +#: ../libqalculate/Function.cc:1794 msgid ">" msgstr ">" -#: ../libqalculate/Function.cc:1772 ../libqalculate/Function.cc:1933 -#: ../libqalculate/Function.cc:1940 +#: ../libqalculate/Function.cc:1806 ../libqalculate/Function.cc:1967 +#: ../libqalculate/Function.cc:1974 msgid "<=" msgstr "<=" -#: ../libqalculate/Function.cc:1774 +#: ../libqalculate/Function.cc:1808 msgid "<" msgstr "<" -#: ../libqalculate/Function.cc:1908 +#: ../libqalculate/Function.cc:1942 msgid "an integer" msgstr "一个整数" -#: ../libqalculate/Function.cc:1965 +#: ../libqalculate/Function.cc:1999 msgid "symbol" msgstr "symbol" -#: ../libqalculate/Function.cc:1966 +#: ../libqalculate/Function.cc:2000 msgid "an unknown variable/symbol" msgstr "一个未知变量或符号" -#: ../libqalculate/Function.cc:1979 +#: ../libqalculate/Function.cc:2013 msgid "text" msgstr "text" -#: ../libqalculate/Function.cc:1980 +#: ../libqalculate/Function.cc:2014 msgid "a text string" msgstr "一段文字" -#: ../libqalculate/Function.cc:2002 +#: ../libqalculate/Function.cc:2036 msgid "date" msgstr "date" -#: ../libqalculate/Function.cc:2003 +#: ../libqalculate/Function.cc:2037 msgid "a date" msgstr "一个日期" -#: ../libqalculate/Function.cc:2052 +#: ../libqalculate/Function.cc:2086 msgid "a vector with " msgstr "一个向量with" -#: ../libqalculate/Function.cc:2064 +#: ../libqalculate/Function.cc:2098 msgid "a vector" msgstr "一个向量" -#: ../libqalculate/Function.cc:2113 +#: ../libqalculate/Function.cc:2147 msgid "a square matrix" msgstr "一个方阵" -#: ../libqalculate/Function.cc:2115 +#: ../libqalculate/Function.cc:2149 msgid "a matrix" msgstr "一个矩阵" -#: ../libqalculate/Function.cc:2130 +#: ../libqalculate/Function.cc:2164 msgid "object" msgstr "object" -#: ../libqalculate/Function.cc:2131 +#: ../libqalculate/Function.cc:2165 msgid "a valid function, unit or variable name" msgstr "一个合法的函数、单位或函数名" -#: ../libqalculate/Function.cc:2145 +#: ../libqalculate/Function.cc:2179 msgid "a valid function name" msgstr "一个合法的函数名" -#: ../libqalculate/Function.cc:2158 +#: ../libqalculate/Function.cc:2192 msgid "unit" msgstr "unit" -#: ../libqalculate/Function.cc:2159 +#: ../libqalculate/Function.cc:2193 msgid "a valid unit name" msgstr "一个合法的单位名" -#: ../libqalculate/Function.cc:2173 +#: ../libqalculate/Function.cc:2207 msgid "a valid variable name" msgstr "一个合法的变量名" -#: ../libqalculate/Function.cc:2186 +#: ../libqalculate/Function.cc:2220 msgid "file" msgstr "file" -#: ../libqalculate/Function.cc:2187 +#: ../libqalculate/Function.cc:2221 msgid "a valid file name" msgstr "一个合法的文件名" -#: ../libqalculate/Function.cc:2200 +#: ../libqalculate/Function.cc:2234 msgid "boolean" msgstr "boolean" -#: ../libqalculate/Function.cc:2201 +#: ../libqalculate/Function.cc:2235 msgid "a boolean (0 or 1)" msgstr "一个逻辑量(0或者1)" -#: ../libqalculate/Function.cc:2212 +#: ../libqalculate/Function.cc:2246 msgid "an angle or a number (using the default angle unit)" msgstr "一个角度或者数字(使用缺省角度单位)" -#: ../libqalculate/Number.cc:254 ../libqalculate/Number.cc:8251 +#: ../libqalculate/Number.cc:263 ../libqalculate/Number.cc:10175 msgid "" "Cannot display numbers greater than 9999 or less than -9999 as roman " "numerals." msgstr "无法显示大于9999或小于-9999的罗马数字。" -#: ../libqalculate/Number.cc:351 +#: ../libqalculate/Number.cc:363 #, fuzzy, c-format msgid "Character '%s' was ignored in the number \"%s\" in bijective base-26." msgstr "字符\"%s\"被忽略,在数字\"%s\"中,其base为\"%s\"。" -#: ../libqalculate/Number.cc:433 ../libqalculate/Number.cc:474 -#: ../libqalculate/Number.cc:501 +#. digit value is higher than allowed by the base: show a warning, but use anyway +#. digit value is higher than allowed by base: show a warning, but use anyway +#: ../libqalculate/Number.cc:464 ../libqalculate/Number.cc:514 +#: ../libqalculate/Number.cc:544 #, c-format msgid "Digit '%s' is too high for number base." msgstr "" -#: ../libqalculate/Number.cc:551 +#: ../libqalculate/Number.cc:601 msgid "" "Assuming the unusual practice of letting a last capital I mean 2 in a roman " "numeral." msgstr "假设一种不常见的情况:在罗马数字中,最后一个大写的\"I\"表示2。" -#: ../libqalculate/Number.cc:635 ../libqalculate/Number.cc:662 -#: ../libqalculate/Number.cc:667 +#: ../libqalculate/Number.cc:685 ../libqalculate/Number.cc:712 +#: ../libqalculate/Number.cc:717 #, c-format msgid "Error in roman numerals: %s." msgstr "在罗马数字中有错:\"%s\"" -#: ../libqalculate/Number.cc:672 +#: ../libqalculate/Number.cc:722 #, c-format msgid "Unknown roman numeral: %c." msgstr "不认识的罗马数字:\"%c\"" -#: ../libqalculate/Number.cc:730 +#: ../libqalculate/Number.cc:780 #, c-format msgid "" "Errors in roman numerals: \"%s\". Interpreted as %s, which should be written " "as %s." msgstr "罗马数字中有错误:\"%s\"。已被翻译成\"%s\",它正确的写法是\"%s\"。" -#: ../libqalculate/Number.cc:818 +#: ../libqalculate/Number.cc:881 #, fuzzy msgid "Too large exponent." msgstr "show negative exponents" -#: ../libqalculate/Number.cc:850 +#. only allow decimals after last ":" +#: ../libqalculate/Number.cc:917 msgid "':' in decimal number ignored (decimal point detected)." msgstr "十进制数中的\":\"被忽略。(已发现小数点)" -#: ../libqalculate/Number.cc:1950 ../libqalculate/Number.cc:2072 +#. test calculated floating point value and show mpfr errors (show as errors if error_level > 1, show as warnings if error_level = 1, do not generate message if error_level is zero) +#: ../libqalculate/Number.cc:2035 ../libqalculate/Number.cc:2160 msgid "Floating point underflow" msgstr "" -#: ../libqalculate/Number.cc:1951 ../libqalculate/Number.cc:2073 +#: ../libqalculate/Number.cc:2036 ../libqalculate/Number.cc:2161 msgid "Floating point overflow" msgstr "" -#: ../libqalculate/Number.cc:1952 ../libqalculate/Number.cc:2074 +#: ../libqalculate/Number.cc:2037 ../libqalculate/Number.cc:2162 msgid "Floating point division by zero exception" msgstr "" -#: ../libqalculate/Number.cc:1953 ../libqalculate/Number.cc:2077 +#: ../libqalculate/Number.cc:2038 ../libqalculate/Number.cc:2165 msgid "Floating point not a number exception" msgstr "" -#: ../libqalculate/Number.cc:1954 ../libqalculate/Number.cc:2075 +#: ../libqalculate/Number.cc:2039 ../libqalculate/Number.cc:2163 msgid "Floating point range exception" msgstr "" -#: ../libqalculate/Number.cc:3528 +#: ../libqalculate/Number.cc:3637 msgid "Division by zero." msgstr "被零除。" #. 0^0 -#: ../libqalculate/Number.cc:3534 +#: ../libqalculate/Number.cc:3643 msgid "0^0 might be considered undefined" msgstr "0^0将被当成未定义量处理" -#: ../libqalculate/Number.cc:3541 +#: ../libqalculate/Number.cc:3650 msgid "The result of 0^i is possibly undefined" msgstr "" -#: ../libqalculate/Number.cc:3590 ../libqalculate/Number.cc:5389 -#: ../libqalculate/Number.cc:5500 ../libqalculate/Number.cc:5824 -#: ../libqalculate/Number.cc:5832 ../libqalculate/Number.cc:5865 -#: ../libqalculate/Number.cc:5962 ../libqalculate/Number.cc:6111 -#: ../libqalculate/Number.cc:6223 +#: ../libqalculate/Number.cc:3699 ../libqalculate/Number.cc:6103 +#: ../libqalculate/Number.cc:6214 ../libqalculate/Number.cc:6538 +#: ../libqalculate/Number.cc:6546 ../libqalculate/Number.cc:6579 +#: ../libqalculate/Number.cc:6676 ../libqalculate/Number.cc:6825 +#: ../libqalculate/Number.cc:6937 msgid "Interval calculated wide." msgstr "" -#: ../libqalculate/Number.cc:4942 -msgid "Cannot handle an argument (s) that large for Riemann Zeta." -msgstr "无法处理对于黎曼Zeta函数来说太大的参数" - -#: ../libqalculate/Number.cc:5017 ../libqalculate/Number.cc:5119 -#: ../libqalculate/Number.cc:5150 ../libqalculate/Number.cc:5181 -#: ../libqalculate/Number.cc:6568 +#: ../libqalculate/Number.cc:5126 ../libqalculate/Number.cc:5352 +#: ../libqalculate/Number.cc:5439 ../libqalculate/Number.cc:5723 +#: ../libqalculate/Number.cc:5809 ../libqalculate/Number.cc:5895 +#: ../libqalculate/Number.cc:7142 ../libqalculate/Number.cc:7160 +#: ../libqalculate/Number.cc:7179 ../libqalculate/Number.cc:7515 +#: ../libqalculate/Number.cc:7562 ../libqalculate/Number.cc:7707 +#: ../libqalculate/Number.cc:8040 ../libqalculate/Number.cc:8196 +#: ../libqalculate/Number.cc:8628 ../libqalculate/Number.cc:9023 #, c-format msgid "%s() lacks proper support interval arithmetic." msgstr "" -#: ../libqalculate/Number.cc:7816 +#: ../libqalculate/Number.cc:9706 #, fuzzy msgid "Unsupported base" msgstr "input base" -#: ../libqalculate/Number.cc:8248 +#: ../libqalculate/Number.cc:10172 #, fuzzy msgid "Can only display rational numbers as roman numerals." msgstr "无法显示大于9999或小于-9999的罗马数字。" -#: ../libqalculate/Number.cc:8693 ../libqalculate/Number.cc:8701 +#: ../libqalculate/Number.cc:10659 ../libqalculate/Number.cc:10667 msgid "infinity" msgstr "infinity" @@ -3611,11 +3675,11 @@ msgid "leap month" msgstr "" -#: ../libqalculate/Unit.cc:1096 +#: ../libqalculate/Unit.cc:1100 msgid "Error(s) in unitexpression." msgstr "单位表达式里有错。" -#: ../libqalculate/Variable.cc:501 +#: ../libqalculate/Variable.cc:502 #, c-format msgid "Recursive variable: %s = %s" msgstr "" @@ -3644,6 +3708,9 @@ msgid "Off" msgstr "Off" +#~ msgid "Cannot handle an argument (s) that large for Riemann Zeta." +#~ msgstr "无法处理对于黎曼Zeta函数来说太大的参数" + #, fuzzy #~ msgid "No was unknown variable/symbol found." #~ msgstr "一个未知变量或符号" diff -Nru libqalculate-3.6.0/po-defs/fr.po libqalculate-3.7.0/po-defs/fr.po --- libqalculate-3.6.0/po-defs/fr.po 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/po-defs/fr.po 2020-01-21 22:54:40.000000000 +0000 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: fr\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-25 10:27+0100\n" +"POT-Creation-Date: 2020-01-12 11:29+0100\n" "PO-Revision-Date: 2006-12-06 15:54-0500\n" "Last-Translator: Nicolas Laug \n" "Language-Team: Français \n" @@ -633,1473 +633,1487 @@ msgstr "" #: ../data/currencies.xml.in.h:147 +#, fuzzy +msgid "Belarusian Ruble" +msgstr "Rouble russe" + +#: ../data/currencies.xml.in.h:148 +msgid "ar:BYN" +msgstr "" + +#: ../data/currencies.xml.in.h:149 +#, fuzzy +msgid "Belarus" +msgstr "Rouble russe" + +#: ../data/currencies.xml.in.h:150 msgid "Belarusian Ruble p. (obsolete)" msgstr "" -#: ../data/currencies.xml.in.h:148 +#: ../data/currencies.xml.in.h:151 msgid "ar:BYR" msgstr "" -#: ../data/currencies.xml.in.h:149 +#: ../data/currencies.xml.in.h:152 #, fuzzy msgid "Belize Dollar" msgstr "Dollar de Singapour" -#: ../data/currencies.xml.in.h:150 +#: ../data/currencies.xml.in.h:153 msgid "ar:BZD" msgstr "" -#: ../data/currencies.xml.in.h:151 +#: ../data/currencies.xml.in.h:154 msgid "Belize" msgstr "" -#: ../data/currencies.xml.in.h:152 +#: ../data/currencies.xml.in.h:155 #, fuzzy msgid "West African CFA Franc" msgstr "Rand sudafricaine" -#: ../data/currencies.xml.in.h:153 +#: ../data/currencies.xml.in.h:156 msgid "ar:XOF,a:CFA" msgstr "" -#: ../data/currencies.xml.in.h:154 +#: ../data/currencies.xml.in.h:157 msgid "" "Benin, Burkina Faso, Guinea-Bissau, Ivory Coast, Mali, Niger, Senegal, Togo" msgstr "" -#: ../data/currencies.xml.in.h:155 +#: ../data/currencies.xml.in.h:158 #, fuzzy msgid "Bermudian Dollar" msgstr "Dollar canadien" -#: ../data/currencies.xml.in.h:156 +#: ../data/currencies.xml.in.h:159 msgid "ar:BMD" msgstr "" -#: ../data/currencies.xml.in.h:157 +#: ../data/currencies.xml.in.h:160 msgid "Bermuda" msgstr "" -#: ../data/currencies.xml.in.h:158 +#: ../data/currencies.xml.in.h:161 msgid "Bolivian Boliviano Bs" msgstr "" -#: ../data/currencies.xml.in.h:159 +#: ../data/currencies.xml.in.h:162 msgid "ar:BOB" msgstr "" -#: ../data/currencies.xml.in.h:160 +#: ../data/currencies.xml.in.h:163 msgid "Bolivia" msgstr "" -#: ../data/currencies.xml.in.h:161 +#: ../data/currencies.xml.in.h:164 msgid "Bosnia and Herzegovina Convertible Mark" msgstr "" -#: ../data/currencies.xml.in.h:162 +#: ../data/currencies.xml.in.h:165 msgid "ar:BAM" msgstr "" -#: ../data/currencies.xml.in.h:163 +#: ../data/currencies.xml.in.h:166 msgid "Bosnia and Herzegovina" msgstr "" -#: ../data/currencies.xml.in.h:164 +#: ../data/currencies.xml.in.h:167 msgid "Botswana Pula" msgstr "" -#: ../data/currencies.xml.in.h:165 +#: ../data/currencies.xml.in.h:168 msgid "ar:BWP" msgstr "" -#: ../data/currencies.xml.in.h:166 +#: ../data/currencies.xml.in.h:169 msgid "Botswana" msgstr "" -#: ../data/currencies.xml.in.h:167 +#: ../data/currencies.xml.in.h:170 #, fuzzy msgid "Brunei Dollar" msgstr "Dollar canadien" -#: ../data/currencies.xml.in.h:168 +#: ../data/currencies.xml.in.h:171 msgid "ar:BND" msgstr "" -#: ../data/currencies.xml.in.h:169 +#: ../data/currencies.xml.in.h:172 msgid "Brunei" msgstr "" -#: ../data/currencies.xml.in.h:170 +#: ../data/currencies.xml.in.h:173 #, fuzzy msgid "Burundian Franc" msgstr "Franc belge" -#: ../data/currencies.xml.in.h:171 +#: ../data/currencies.xml.in.h:174 msgid "ar:BIF" msgstr "" -#: ../data/currencies.xml.in.h:172 +#: ../data/currencies.xml.in.h:175 msgid "Burundi" msgstr "" -#: ../data/currencies.xml.in.h:173 +#: ../data/currencies.xml.in.h:176 msgid "Cambodian Riel" msgstr "" -#: ../data/currencies.xml.in.h:174 +#: ../data/currencies.xml.in.h:177 #, fuzzy msgid "ar:KHR,aiu:៛" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:175 +#: ../data/currencies.xml.in.h:178 msgid "Cambodia" msgstr "" -#: ../data/currencies.xml.in.h:176 +#: ../data/currencies.xml.in.h:179 msgid "Central African CFA Franc" msgstr "" -#: ../data/currencies.xml.in.h:177 +#: ../data/currencies.xml.in.h:180 msgid "ar:XAF,a:FCFA" msgstr "" -#: ../data/currencies.xml.in.h:178 +#: ../data/currencies.xml.in.h:181 msgid "" "Cameroon, Central African Republic, Chad, Republic of the Congo, Equatorial " "Guinea, Gabon" msgstr "" -#: ../data/currencies.xml.in.h:179 +#: ../data/currencies.xml.in.h:182 msgid "Cape Verdean Escudo" msgstr "" -#: ../data/currencies.xml.in.h:180 +#: ../data/currencies.xml.in.h:183 msgid "ar:CVE" msgstr "" -#: ../data/currencies.xml.in.h:181 +#: ../data/currencies.xml.in.h:184 msgid "Cape Verde" msgstr "" -#: ../data/currencies.xml.in.h:182 +#: ../data/currencies.xml.in.h:185 #, fuzzy msgid "Cayman Islands Dollar" msgstr "Dollar canadien" -#: ../data/currencies.xml.in.h:183 +#: ../data/currencies.xml.in.h:186 msgid "ar:KYD" msgstr "" -#: ../data/currencies.xml.in.h:184 +#: ../data/currencies.xml.in.h:187 msgid "Cayman Islands" msgstr "" -#: ../data/currencies.xml.in.h:185 +#: ../data/currencies.xml.in.h:188 #, fuzzy msgid "Chilean Peso" msgstr "Peso philippin" -#: ../data/currencies.xml.in.h:186 +#: ../data/currencies.xml.in.h:189 msgid "ar:CLP" msgstr "" -#: ../data/currencies.xml.in.h:187 +#: ../data/currencies.xml.in.h:190 msgid "Chile" msgstr "" -#: ../data/currencies.xml.in.h:188 +#: ../data/currencies.xml.in.h:191 #, fuzzy msgid "Colombian Peso" msgstr "Combinaisons" -#: ../data/currencies.xml.in.h:189 +#: ../data/currencies.xml.in.h:192 msgid "ar:COP" msgstr "" -#: ../data/currencies.xml.in.h:190 +#: ../data/currencies.xml.in.h:193 #, fuzzy msgid "Colombia" msgstr "Combinaisons" -#: ../data/currencies.xml.in.h:191 +#: ../data/currencies.xml.in.h:194 #, fuzzy msgid "Comorian Franc" msgstr "Franc belge" -#: ../data/currencies.xml.in.h:192 +#: ../data/currencies.xml.in.h:195 msgid "ar:KMF" msgstr "" -#: ../data/currencies.xml.in.h:193 +#: ../data/currencies.xml.in.h:196 msgid "Comoros" msgstr "" -#: ../data/currencies.xml.in.h:194 +#: ../data/currencies.xml.in.h:197 msgid "Democratic Republic of the Congo (Congolese Franc)" msgstr "" -#: ../data/currencies.xml.in.h:195 +#: ../data/currencies.xml.in.h:198 msgid "ar:CDF" msgstr "" -#: ../data/currencies.xml.in.h:196 +#: ../data/currencies.xml.in.h:199 msgid "Democratic Republic of the Congo" msgstr "" -#: ../data/currencies.xml.in.h:197 +#: ../data/currencies.xml.in.h:200 msgid "Costa Rican colón" msgstr "" -#: ../data/currencies.xml.in.h:198 +#: ../data/currencies.xml.in.h:201 msgid "ar:CRC" msgstr "" -#: ../data/currencies.xml.in.h:199 +#: ../data/currencies.xml.in.h:202 msgid "Costa Rica" msgstr "" -#: ../data/currencies.xml.in.h:200 +#: ../data/currencies.xml.in.h:203 msgid "Cuban Peso" msgstr "" -#: ../data/currencies.xml.in.h:201 +#: ../data/currencies.xml.in.h:204 msgid "ar:CUP" msgstr "" -#: ../data/currencies.xml.in.h:202 +#: ../data/currencies.xml.in.h:205 msgid "Cuba" msgstr "" -#: ../data/currencies.xml.in.h:203 +#: ../data/currencies.xml.in.h:206 #, fuzzy msgid "Djiboutian Franc" msgstr "Franc belge" -#: ../data/currencies.xml.in.h:204 +#: ../data/currencies.xml.in.h:207 msgid "ar:DJF" msgstr "" -#: ../data/currencies.xml.in.h:205 +#: ../data/currencies.xml.in.h:208 msgid "Djibouti" msgstr "" -#: ../data/currencies.xml.in.h:206 +#: ../data/currencies.xml.in.h:209 msgid "Dominican Peso" msgstr "" -#: ../data/currencies.xml.in.h:207 +#: ../data/currencies.xml.in.h:210 msgid "ar:DOP" msgstr "" -#: ../data/currencies.xml.in.h:208 +#: ../data/currencies.xml.in.h:211 msgid "Dominican Republic" msgstr "" -#: ../data/currencies.xml.in.h:209 +#: ../data/currencies.xml.in.h:212 #, fuzzy msgid "Egyptian Pound" msgstr "Livre chypriote" -#: ../data/currencies.xml.in.h:210 +#: ../data/currencies.xml.in.h:213 msgid "ar:EGP" msgstr "" -#: ../data/currencies.xml.in.h:211 +#: ../data/currencies.xml.in.h:214 msgid "Egypt" msgstr "" -#: ../data/currencies.xml.in.h:212 +#: ../data/currencies.xml.in.h:215 msgid "El Salvadoran Colon (obsolete)" msgstr "" -#: ../data/currencies.xml.in.h:213 +#: ../data/currencies.xml.in.h:216 msgid "ar:SVC" msgstr "" -#: ../data/currencies.xml.in.h:214 +#: ../data/currencies.xml.in.h:217 msgid "Eritrean Nafka" msgstr "" -#: ../data/currencies.xml.in.h:215 +#: ../data/currencies.xml.in.h:218 msgid "ar:ERN" msgstr "" -#: ../data/currencies.xml.in.h:216 +#: ../data/currencies.xml.in.h:219 msgid "Eritrea" msgstr "" -#: ../data/currencies.xml.in.h:217 +#: ../data/currencies.xml.in.h:220 msgid "Ethiopian Birr" msgstr "" -#: ../data/currencies.xml.in.h:218 +#: ../data/currencies.xml.in.h:221 msgid "ar:ETB" msgstr "" -#: ../data/currencies.xml.in.h:219 +#: ../data/currencies.xml.in.h:222 msgid "Ethiopia" msgstr "" -#: ../data/currencies.xml.in.h:220 +#: ../data/currencies.xml.in.h:223 msgid "Falkland Islands Pound" msgstr "" -#: ../data/currencies.xml.in.h:221 +#: ../data/currencies.xml.in.h:224 msgid "ar:FKP" msgstr "" -#: ../data/currencies.xml.in.h:222 +#: ../data/currencies.xml.in.h:225 msgid "Falkland Islands" msgstr "" -#: ../data/currencies.xml.in.h:223 +#: ../data/currencies.xml.in.h:226 #, fuzzy msgid "Fijian Dollar" msgstr "Dollar canadien" -#: ../data/currencies.xml.in.h:224 +#: ../data/currencies.xml.in.h:227 msgid "ar:FJD" msgstr "" -#: ../data/currencies.xml.in.h:225 +#: ../data/currencies.xml.in.h:228 msgid "Fiji" msgstr "" -#: ../data/currencies.xml.in.h:226 +#: ../data/currencies.xml.in.h:229 msgid "CFP franc" msgstr "" -#: ../data/currencies.xml.in.h:227 +#: ../data/currencies.xml.in.h:230 msgid "ar:XPF" msgstr "" -#: ../data/currencies.xml.in.h:228 +#: ../data/currencies.xml.in.h:231 msgid "French Polynesia, New Caledonia, Wallis and Futuna" msgstr "" -#: ../data/currencies.xml.in.h:229 +#: ../data/currencies.xml.in.h:232 #, fuzzy msgid "Gambian Dalasi" msgstr "Dollar canadien" -#: ../data/currencies.xml.in.h:230 +#: ../data/currencies.xml.in.h:233 msgid "ar:GMD" msgstr "" -#: ../data/currencies.xml.in.h:231 +#: ../data/currencies.xml.in.h:234 msgid "Gambia" msgstr "" -#: ../data/currencies.xml.in.h:232 +#: ../data/currencies.xml.in.h:235 msgid "Georgian Lari" msgstr "" -#: ../data/currencies.xml.in.h:233 +#: ../data/currencies.xml.in.h:236 #, fuzzy msgid "ar:GEL,au:₾" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:234 +#: ../data/currencies.xml.in.h:237 msgid "Georgia" msgstr "" -#: ../data/currencies.xml.in.h:235 +#: ../data/currencies.xml.in.h:238 msgid "Ghanaian Cedi" msgstr "" -#: ../data/currencies.xml.in.h:236 +#: ../data/currencies.xml.in.h:239 #, fuzzy msgid "ar:GHS,au:₵" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:237 +#: ../data/currencies.xml.in.h:240 msgid "Ghana" msgstr "" -#: ../data/currencies.xml.in.h:238 +#: ../data/currencies.xml.in.h:241 msgid "Gibraltar Pound" msgstr "" -#: ../data/currencies.xml.in.h:239 +#: ../data/currencies.xml.in.h:242 msgid "ar:GIP" msgstr "" -#: ../data/currencies.xml.in.h:240 +#: ../data/currencies.xml.in.h:243 msgid "Gibraltar" msgstr "" -#: ../data/currencies.xml.in.h:241 +#: ../data/currencies.xml.in.h:244 msgid "Guatemalan Quetzal" msgstr "" -#: ../data/currencies.xml.in.h:242 +#: ../data/currencies.xml.in.h:245 msgid "ar:GTQ" msgstr "" -#: ../data/currencies.xml.in.h:243 +#: ../data/currencies.xml.in.h:246 msgid "Guatemala" msgstr "" -#: ../data/currencies.xml.in.h:244 +#: ../data/currencies.xml.in.h:247 #, fuzzy msgid "Guernsey Pound" msgstr "Livre irlandaise" -#: ../data/currencies.xml.in.h:245 +#: ../data/currencies.xml.in.h:248 msgid "ar:GGP" msgstr "" -#: ../data/currencies.xml.in.h:246 +#: ../data/currencies.xml.in.h:249 msgid "Guernsey" msgstr "" -#: ../data/currencies.xml.in.h:247 +#: ../data/currencies.xml.in.h:250 #, fuzzy msgid "Guinean Franc" msgstr "Franc belge" -#: ../data/currencies.xml.in.h:248 +#: ../data/currencies.xml.in.h:251 msgid "ar:GNF" msgstr "" -#: ../data/currencies.xml.in.h:249 +#: ../data/currencies.xml.in.h:252 msgid "Guinea" msgstr "" -#: ../data/currencies.xml.in.h:250 +#: ../data/currencies.xml.in.h:253 #, fuzzy msgid "Guyanese Dollar" msgstr "Dollar australien" -#: ../data/currencies.xml.in.h:251 +#: ../data/currencies.xml.in.h:254 msgid "ar:GYD" msgstr "" -#: ../data/currencies.xml.in.h:252 +#: ../data/currencies.xml.in.h:255 msgid "Guyana" msgstr "" -#: ../data/currencies.xml.in.h:253 +#: ../data/currencies.xml.in.h:256 msgid "Haitian Gourde" msgstr "" -#: ../data/currencies.xml.in.h:254 +#: ../data/currencies.xml.in.h:257 msgid "ar:HTG" msgstr "" -#: ../data/currencies.xml.in.h:255 +#: ../data/currencies.xml.in.h:258 msgid "Haiti" msgstr "" -#: ../data/currencies.xml.in.h:256 +#: ../data/currencies.xml.in.h:259 msgid "Honduran Lempira" msgstr "" -#: ../data/currencies.xml.in.h:257 +#: ../data/currencies.xml.in.h:260 msgid "ar:HNL" msgstr "" -#: ../data/currencies.xml.in.h:258 +#: ../data/currencies.xml.in.h:261 msgid "Honduras" msgstr "" -#: ../data/currencies.xml.in.h:259 +#: ../data/currencies.xml.in.h:262 #, fuzzy msgid "Iranian Rial" msgstr "Lire italienne" -#: ../data/currencies.xml.in.h:260 +#: ../data/currencies.xml.in.h:263 #, fuzzy msgid "ar:IRR,aiu:﷼" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:261 +#: ../data/currencies.xml.in.h:264 msgid "Iran" msgstr "" -#: ../data/currencies.xml.in.h:262 +#: ../data/currencies.xml.in.h:265 msgid "Iraqi Dinar" msgstr "" -#: ../data/currencies.xml.in.h:263 +#: ../data/currencies.xml.in.h:266 msgid "ar:IQD" msgstr "" -#: ../data/currencies.xml.in.h:264 +#: ../data/currencies.xml.in.h:267 msgid "Iraq" msgstr "" -#: ../data/currencies.xml.in.h:265 +#: ../data/currencies.xml.in.h:268 #, fuzzy msgid "Jamaican Dollar" msgstr "Dollar canadien" -#: ../data/currencies.xml.in.h:266 +#: ../data/currencies.xml.in.h:269 msgid "ar:JMD" msgstr "" -#: ../data/currencies.xml.in.h:267 +#: ../data/currencies.xml.in.h:270 msgid "Jamaica" msgstr "" -#: ../data/currencies.xml.in.h:268 +#: ../data/currencies.xml.in.h:271 msgid "Jordanian Dinar" msgstr "" -#: ../data/currencies.xml.in.h:269 +#: ../data/currencies.xml.in.h:272 msgid "ar:JOD" msgstr "" -#: ../data/currencies.xml.in.h:270 +#: ../data/currencies.xml.in.h:273 msgid "Jordan" msgstr "" -#: ../data/currencies.xml.in.h:271 +#: ../data/currencies.xml.in.h:274 msgid "Kazakhstani Tenge" msgstr "" -#: ../data/currencies.xml.in.h:272 +#: ../data/currencies.xml.in.h:275 #, fuzzy msgid "ar:KZT,au:₸" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:273 +#: ../data/currencies.xml.in.h:276 msgid "Kazakhstan" msgstr "" -#: ../data/currencies.xml.in.h:274 +#: ../data/currencies.xml.in.h:277 #, fuzzy msgid "North Korean Won" msgstr "Won sud corréenne" -#: ../data/currencies.xml.in.h:275 +#: ../data/currencies.xml.in.h:278 msgid "ar:KPW" msgstr "" -#: ../data/currencies.xml.in.h:276 +#: ../data/currencies.xml.in.h:279 #, fuzzy msgid "North Korea" msgstr "Won sud corréenne" -#: ../data/currencies.xml.in.h:277 +#: ../data/currencies.xml.in.h:280 msgid "Kuwaiti Dinar" msgstr "" -#: ../data/currencies.xml.in.h:278 +#: ../data/currencies.xml.in.h:281 msgid "ar:KWD" msgstr "" -#: ../data/currencies.xml.in.h:279 +#: ../data/currencies.xml.in.h:282 msgid "Kuwait" msgstr "" -#: ../data/currencies.xml.in.h:280 +#: ../data/currencies.xml.in.h:283 msgid "Kyrgyzstani Som" msgstr "" -#: ../data/currencies.xml.in.h:281 +#: ../data/currencies.xml.in.h:284 #, fuzzy msgid "ar:KGS,au:с" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:282 +#: ../data/currencies.xml.in.h:285 msgid "Kyrgyzstan" msgstr "" -#: ../data/currencies.xml.in.h:283 +#: ../data/currencies.xml.in.h:286 msgid "Lao Kip" msgstr "" -#: ../data/currencies.xml.in.h:284 +#: ../data/currencies.xml.in.h:287 #, fuzzy msgid "ar:LAK,au:₭" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:285 +#: ../data/currencies.xml.in.h:288 msgid "Laos" msgstr "" -#: ../data/currencies.xml.in.h:286 +#: ../data/currencies.xml.in.h:289 msgid "Lebanese Pound" msgstr "" -#: ../data/currencies.xml.in.h:287 +#: ../data/currencies.xml.in.h:290 msgid "ar:LBP" msgstr "" -#: ../data/currencies.xml.in.h:288 +#: ../data/currencies.xml.in.h:291 msgid "Lebanon" msgstr "" -#: ../data/currencies.xml.in.h:289 +#: ../data/currencies.xml.in.h:292 msgid "Lesotho Loti" msgstr "" -#: ../data/currencies.xml.in.h:290 +#: ../data/currencies.xml.in.h:293 msgid "ar:LSL" msgstr "" -#: ../data/currencies.xml.in.h:291 +#: ../data/currencies.xml.in.h:294 msgid "Lesotho" msgstr "" -#: ../data/currencies.xml.in.h:292 +#: ../data/currencies.xml.in.h:295 #, fuzzy msgid "Liberian Dollar" msgstr "Dollar australien" -#: ../data/currencies.xml.in.h:293 +#: ../data/currencies.xml.in.h:296 msgid "ar:LRD" msgstr "" -#: ../data/currencies.xml.in.h:294 +#: ../data/currencies.xml.in.h:297 msgid "Liberia" msgstr "" -#: ../data/currencies.xml.in.h:295 +#: ../data/currencies.xml.in.h:298 msgid "Libyan Dinar" msgstr "" -#: ../data/currencies.xml.in.h:296 +#: ../data/currencies.xml.in.h:299 msgid "ar:LYD" msgstr "" -#: ../data/currencies.xml.in.h:297 +#: ../data/currencies.xml.in.h:300 msgid "Libya" msgstr "" -#: ../data/currencies.xml.in.h:298 +#: ../data/currencies.xml.in.h:301 msgid "Macanese Pataca" msgstr "" -#: ../data/currencies.xml.in.h:299 +#: ../data/currencies.xml.in.h:302 msgid "ar:MOP" msgstr "" -#: ../data/currencies.xml.in.h:300 +#: ../data/currencies.xml.in.h:303 msgid "Macau" msgstr "" -#: ../data/currencies.xml.in.h:301 +#: ../data/currencies.xml.in.h:304 msgid "Macedonian Denar" msgstr "" -#: ../data/currencies.xml.in.h:302 +#: ../data/currencies.xml.in.h:305 msgid "ar:MKD" msgstr "" -#: ../data/currencies.xml.in.h:303 +#: ../data/currencies.xml.in.h:306 msgid "Macedonia" msgstr "" -#: ../data/currencies.xml.in.h:304 +#: ../data/currencies.xml.in.h:307 msgid "Malagasy Ariary" msgstr "" -#: ../data/currencies.xml.in.h:305 +#: ../data/currencies.xml.in.h:308 msgid "ar:MGA" msgstr "" -#: ../data/currencies.xml.in.h:306 +#: ../data/currencies.xml.in.h:309 msgid "Madagascar" msgstr "" -#: ../data/currencies.xml.in.h:307 +#: ../data/currencies.xml.in.h:310 msgid "Malawian Kwacha" msgstr "" -#: ../data/currencies.xml.in.h:308 +#: ../data/currencies.xml.in.h:311 msgid "ar:MWK" msgstr "" -#: ../data/currencies.xml.in.h:309 +#: ../data/currencies.xml.in.h:312 msgid "Malawi" msgstr "" -#: ../data/currencies.xml.in.h:310 +#: ../data/currencies.xml.in.h:313 msgid "Maldivian Rufiyaa" msgstr "" -#: ../data/currencies.xml.in.h:311 +#: ../data/currencies.xml.in.h:314 msgid "ar:MVR" msgstr "" -#: ../data/currencies.xml.in.h:312 +#: ../data/currencies.xml.in.h:315 msgid "Maldives" msgstr "" -#: ../data/currencies.xml.in.h:313 +#: ../data/currencies.xml.in.h:316 msgid "Mauritanian Ouguiya (obsolete)" msgstr "" -#: ../data/currencies.xml.in.h:314 +#: ../data/currencies.xml.in.h:317 msgid "ar:MRO" msgstr "" -#: ../data/currencies.xml.in.h:315 +#: ../data/currencies.xml.in.h:318 msgid "Mauritian Rupee" msgstr "" -#: ../data/currencies.xml.in.h:316 +#: ../data/currencies.xml.in.h:319 msgid "ar:MUR" msgstr "" -#: ../data/currencies.xml.in.h:317 +#: ../data/currencies.xml.in.h:320 msgid "Mauritius" msgstr "" -#: ../data/currencies.xml.in.h:318 +#: ../data/currencies.xml.in.h:321 msgid "Moldovan Leu" msgstr "" -#: ../data/currencies.xml.in.h:319 +#: ../data/currencies.xml.in.h:322 msgid "ar:MDL" msgstr "" -#: ../data/currencies.xml.in.h:320 +#: ../data/currencies.xml.in.h:323 msgid "Moldova" msgstr "" -#: ../data/currencies.xml.in.h:321 +#: ../data/currencies.xml.in.h:324 msgid "Mongolian Tögrög" msgstr "" -#: ../data/currencies.xml.in.h:322 +#: ../data/currencies.xml.in.h:325 #, fuzzy msgid "ar:MNT,au:₮" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:323 +#: ../data/currencies.xml.in.h:326 msgid "Mongolia" msgstr "" -#: ../data/currencies.xml.in.h:324 +#: ../data/currencies.xml.in.h:327 msgid "Moroccan Dirham" msgstr "" -#: ../data/currencies.xml.in.h:325 +#: ../data/currencies.xml.in.h:328 msgid "ar:MAD" msgstr "" -#: ../data/currencies.xml.in.h:326 +#: ../data/currencies.xml.in.h:329 msgid "Morocco" msgstr "" -#: ../data/currencies.xml.in.h:327 +#: ../data/currencies.xml.in.h:330 msgid "Mozambican Metical" msgstr "" -#: ../data/currencies.xml.in.h:328 +#: ../data/currencies.xml.in.h:331 msgid "ar:MZN" msgstr "" -#: ../data/currencies.xml.in.h:329 +#: ../data/currencies.xml.in.h:332 msgid "Mozambique" msgstr "" -#: ../data/currencies.xml.in.h:330 +#: ../data/currencies.xml.in.h:333 msgid "Myanmar (Burmese Kyat)" msgstr "" -#: ../data/currencies.xml.in.h:331 +#: ../data/currencies.xml.in.h:334 msgid "ar:MMK" msgstr "" -#: ../data/currencies.xml.in.h:332 +#: ../data/currencies.xml.in.h:335 msgid "Myanmar" msgstr "" -#: ../data/currencies.xml.in.h:333 +#: ../data/currencies.xml.in.h:336 #, fuzzy msgid "Namibian Dollar" msgstr "Dollar canadien" -#: ../data/currencies.xml.in.h:334 +#: ../data/currencies.xml.in.h:337 #, fuzzy msgid "ar:NAD" msgstr "ar:NLG,florin" -#: ../data/currencies.xml.in.h:335 +#: ../data/currencies.xml.in.h:338 msgid "Namibia" msgstr "" -#: ../data/currencies.xml.in.h:336 +#: ../data/currencies.xml.in.h:339 msgid "Nepalese Rupee" msgstr "" -#: ../data/currencies.xml.in.h:337 +#: ../data/currencies.xml.in.h:340 #, fuzzy msgid "ar:NPR" msgstr "ar:NLG,florin" -#: ../data/currencies.xml.in.h:338 +#: ../data/currencies.xml.in.h:341 msgid "Nepal" msgstr "" -#: ../data/currencies.xml.in.h:339 +#: ../data/currencies.xml.in.h:342 msgid "Nicaraguan Córdoba" msgstr "" -#: ../data/currencies.xml.in.h:340 +#: ../data/currencies.xml.in.h:343 #, fuzzy msgid "ar:NIO" msgstr "ar:NLG,florin" -#: ../data/currencies.xml.in.h:341 +#: ../data/currencies.xml.in.h:344 msgid "Nicaragua" msgstr "" -#: ../data/currencies.xml.in.h:342 +#: ../data/currencies.xml.in.h:345 msgid "Nigerian Naira" msgstr "" -#: ../data/currencies.xml.in.h:343 +#: ../data/currencies.xml.in.h:346 #, fuzzy msgid "ar:NGN,au:₦" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:344 +#: ../data/currencies.xml.in.h:347 msgid "Nigeria" msgstr "" -#: ../data/currencies.xml.in.h:345 +#: ../data/currencies.xml.in.h:348 msgid "Omani Rial" msgstr "" -#: ../data/currencies.xml.in.h:346 +#: ../data/currencies.xml.in.h:349 msgid "ar:OMR" msgstr "" -#: ../data/currencies.xml.in.h:347 +#: ../data/currencies.xml.in.h:350 msgid "Oman" msgstr "" -#: ../data/currencies.xml.in.h:348 +#: ../data/currencies.xml.in.h:351 msgid "Pakistani Rupee" msgstr "" -#: ../data/currencies.xml.in.h:349 +#: ../data/currencies.xml.in.h:352 msgid "ar:PKR" msgstr "" -#: ../data/currencies.xml.in.h:350 +#: ../data/currencies.xml.in.h:353 #, fuzzy msgid "Pakistan" msgstr "Constantes de Planck" -#: ../data/currencies.xml.in.h:351 +#: ../data/currencies.xml.in.h:354 msgid "Panamaian Balboa" msgstr "" -#: ../data/currencies.xml.in.h:352 +#: ../data/currencies.xml.in.h:355 msgid "ar:PAB" msgstr "" -#: ../data/currencies.xml.in.h:353 +#: ../data/currencies.xml.in.h:356 msgid "Panama" msgstr "" -#: ../data/currencies.xml.in.h:354 +#: ../data/currencies.xml.in.h:357 msgid "Papua New Guinean Kina" msgstr "" -#: ../data/currencies.xml.in.h:355 +#: ../data/currencies.xml.in.h:358 msgid "ar:PGK" msgstr "" -#: ../data/currencies.xml.in.h:356 +#: ../data/currencies.xml.in.h:359 msgid "Papua New Guinea" msgstr "" -#: ../data/currencies.xml.in.h:357 +#: ../data/currencies.xml.in.h:360 msgid "Paraguayan Guaraní" msgstr "" -#: ../data/currencies.xml.in.h:358 +#: ../data/currencies.xml.in.h:361 #, fuzzy msgid "ar:PYG,au:₲" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:359 +#: ../data/currencies.xml.in.h:362 msgid "Paraguay" msgstr "" -#: ../data/currencies.xml.in.h:360 +#: ../data/currencies.xml.in.h:363 msgid "Peruvian Sol" msgstr "" -#: ../data/currencies.xml.in.h:361 +#: ../data/currencies.xml.in.h:364 msgid "ar:PEN" msgstr "" -#: ../data/currencies.xml.in.h:362 +#: ../data/currencies.xml.in.h:365 msgid "Peru" msgstr "" -#: ../data/currencies.xml.in.h:363 +#: ../data/currencies.xml.in.h:366 msgid "Qatari Riyal" msgstr "" -#: ../data/currencies.xml.in.h:364 +#: ../data/currencies.xml.in.h:367 msgid "ar:QAR" msgstr "" -#: ../data/currencies.xml.in.h:365 +#: ../data/currencies.xml.in.h:368 msgid "Qatar" msgstr "" -#: ../data/currencies.xml.in.h:366 +#: ../data/currencies.xml.in.h:369 #, fuzzy msgid "Rwandan Franc" msgstr "Franc belge" -#: ../data/currencies.xml.in.h:367 +#: ../data/currencies.xml.in.h:370 msgid "ar:RWF" msgstr "" -#: ../data/currencies.xml.in.h:368 +#: ../data/currencies.xml.in.h:371 msgid "Rwanda" msgstr "" -#: ../data/currencies.xml.in.h:369 +#: ../data/currencies.xml.in.h:372 msgid "São Tomé and Príncipe Dobra" msgstr "" -#: ../data/currencies.xml.in.h:370 +#: ../data/currencies.xml.in.h:373 msgid "ar:STD" msgstr "" -#: ../data/currencies.xml.in.h:371 +#: ../data/currencies.xml.in.h:374 msgid "Sao Tome and Principe" msgstr "" -#: ../data/currencies.xml.in.h:372 +#: ../data/currencies.xml.in.h:375 msgid "Saudi Riyal" msgstr "" -#: ../data/currencies.xml.in.h:373 +#: ../data/currencies.xml.in.h:376 msgid "ar:SAR" msgstr "" -#: ../data/currencies.xml.in.h:374 +#: ../data/currencies.xml.in.h:377 msgid "Saudi Arabia" msgstr "" -#: ../data/currencies.xml.in.h:375 +#: ../data/currencies.xml.in.h:378 msgid "Serbian Dinar" msgstr "" -#: ../data/currencies.xml.in.h:376 +#: ../data/currencies.xml.in.h:379 msgid "ar:RSD" msgstr "" -#: ../data/currencies.xml.in.h:377 +#: ../data/currencies.xml.in.h:380 msgid "Serbia" msgstr "" -#: ../data/currencies.xml.in.h:378 +#: ../data/currencies.xml.in.h:381 msgid "Seychellois Rupee" msgstr "" -#: ../data/currencies.xml.in.h:379 +#: ../data/currencies.xml.in.h:382 msgid "ar:SCR" msgstr "" -#: ../data/currencies.xml.in.h:380 +#: ../data/currencies.xml.in.h:383 msgid "Seychelles" msgstr "" -#: ../data/currencies.xml.in.h:381 +#: ../data/currencies.xml.in.h:384 msgid "Sierra Leonean Leone" msgstr "" -#: ../data/currencies.xml.in.h:382 +#: ../data/currencies.xml.in.h:385 msgid "ar:SLL" msgstr "" -#: ../data/currencies.xml.in.h:383 +#: ../data/currencies.xml.in.h:386 msgid "Sierra Leone" msgstr "" -#: ../data/currencies.xml.in.h:384 +#: ../data/currencies.xml.in.h:387 msgid "Solomon Islands Dollar" msgstr "" -#: ../data/currencies.xml.in.h:385 +#: ../data/currencies.xml.in.h:388 msgid "ar:SBD" msgstr "" -#: ../data/currencies.xml.in.h:386 +#: ../data/currencies.xml.in.h:389 msgid "Solomon Islands" msgstr "" -#: ../data/currencies.xml.in.h:387 +#: ../data/currencies.xml.in.h:390 #, fuzzy msgid "Somali Shilling" msgstr "Shilling autrichien" -#: ../data/currencies.xml.in.h:388 +#: ../data/currencies.xml.in.h:391 msgid "ar:SOS" msgstr "" -#: ../data/currencies.xml.in.h:389 +#: ../data/currencies.xml.in.h:392 msgid "Somalia" msgstr "" -#: ../data/currencies.xml.in.h:390 +#: ../data/currencies.xml.in.h:393 msgid "Sri Lankan Rupee" msgstr "" -#: ../data/currencies.xml.in.h:391 +#: ../data/currencies.xml.in.h:394 #, fuzzy msgid "ar:LKR,au:௹" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:392 +#: ../data/currencies.xml.in.h:395 msgid "Sri Lanka" msgstr "" -#: ../data/currencies.xml.in.h:393 +#: ../data/currencies.xml.in.h:396 msgid "Sudanese Pound" msgstr "" -#: ../data/currencies.xml.in.h:394 +#: ../data/currencies.xml.in.h:397 msgid "ar:SDG" msgstr "" -#: ../data/currencies.xml.in.h:395 +#: ../data/currencies.xml.in.h:398 msgid "Sudan" msgstr "" -#: ../data/currencies.xml.in.h:396 +#: ../data/currencies.xml.in.h:399 #, fuzzy msgid "Surinamese Dollar" msgstr "Dollar de Singapour" -#: ../data/currencies.xml.in.h:397 +#: ../data/currencies.xml.in.h:400 msgid "ar:SRD" msgstr "" -#: ../data/currencies.xml.in.h:398 +#: ../data/currencies.xml.in.h:401 #, fuzzy msgid "Suriname" msgstr "r:nom" -#: ../data/currencies.xml.in.h:399 +#: ../data/currencies.xml.in.h:402 msgid "Swazi Lilangeni" msgstr "" -#: ../data/currencies.xml.in.h:400 +#: ../data/currencies.xml.in.h:403 msgid "ar:SZL" msgstr "" -#: ../data/currencies.xml.in.h:401 +#: ../data/currencies.xml.in.h:404 msgid "Swaziland" msgstr "" -#: ../data/currencies.xml.in.h:402 +#: ../data/currencies.xml.in.h:405 #, fuzzy msgid "Syrian Pound" msgstr "Livre chypriote" -#: ../data/currencies.xml.in.h:403 +#: ../data/currencies.xml.in.h:406 msgid "ar:SYP" msgstr "" -#: ../data/currencies.xml.in.h:404 +#: ../data/currencies.xml.in.h:407 msgid "Syria" msgstr "" -#: ../data/currencies.xml.in.h:405 +#: ../data/currencies.xml.in.h:408 #, fuzzy msgid "New Taiwan Dollar" msgstr "Dollars néo-zélandais" -#: ../data/currencies.xml.in.h:406 +#: ../data/currencies.xml.in.h:409 msgid "ar:TWD" msgstr "" -#: ../data/currencies.xml.in.h:407 +#: ../data/currencies.xml.in.h:410 msgid "Taiwan" msgstr "" -#: ../data/currencies.xml.in.h:408 +#: ../data/currencies.xml.in.h:411 msgid "Tajikistani Somoni" msgstr "" -#: ../data/currencies.xml.in.h:409 +#: ../data/currencies.xml.in.h:412 msgid "ar:TJS" msgstr "" -#: ../data/currencies.xml.in.h:410 +#: ../data/currencies.xml.in.h:413 msgid "Tajikistan" msgstr "" -#: ../data/currencies.xml.in.h:411 +#: ../data/currencies.xml.in.h:414 #, fuzzy msgid "Tanzanian Shilling" msgstr "Shilling autrichien" -#: ../data/currencies.xml.in.h:412 +#: ../data/currencies.xml.in.h:415 msgid "ar:TZS" msgstr "" -#: ../data/currencies.xml.in.h:413 +#: ../data/currencies.xml.in.h:416 msgid "Tanzania" msgstr "" -#: ../data/currencies.xml.in.h:414 +#: ../data/currencies.xml.in.h:417 msgid "Tongan Paʻanga" msgstr "" -#: ../data/currencies.xml.in.h:415 +#: ../data/currencies.xml.in.h:418 msgid "ar:TOP" msgstr "" -#: ../data/currencies.xml.in.h:416 +#: ../data/currencies.xml.in.h:419 msgid "Tonga" msgstr "" -#: ../data/currencies.xml.in.h:417 +#: ../data/currencies.xml.in.h:420 msgid "Trinidad and Tobago dollar" msgstr "" -#: ../data/currencies.xml.in.h:418 +#: ../data/currencies.xml.in.h:421 msgid "ar:TTD" msgstr "" -#: ../data/currencies.xml.in.h:419 +#: ../data/currencies.xml.in.h:422 msgid "Trinidad and Tobago" msgstr "" -#: ../data/currencies.xml.in.h:420 +#: ../data/currencies.xml.in.h:423 msgid "Tunisian Dinar" msgstr "" -#: ../data/currencies.xml.in.h:421 +#: ../data/currencies.xml.in.h:424 msgid "ar:TND" msgstr "" -#: ../data/currencies.xml.in.h:422 +#: ../data/currencies.xml.in.h:425 msgid "Tunisia" msgstr "" -#: ../data/currencies.xml.in.h:423 +#: ../data/currencies.xml.in.h:426 msgid "Turkmenistan Manat" msgstr "" -#: ../data/currencies.xml.in.h:424 +#: ../data/currencies.xml.in.h:427 msgid "ar:TMT" msgstr "" -#: ../data/currencies.xml.in.h:425 +#: ../data/currencies.xml.in.h:428 msgid "Turkmenistan" msgstr "" -#: ../data/currencies.xml.in.h:426 +#: ../data/currencies.xml.in.h:429 #, fuzzy msgid "Ugandan Shilling" msgstr "Shilling autrichien" -#: ../data/currencies.xml.in.h:427 +#: ../data/currencies.xml.in.h:430 msgid "ar:UGX" msgstr "" -#: ../data/currencies.xml.in.h:428 +#: ../data/currencies.xml.in.h:431 msgid "Uganda" msgstr "" -#: ../data/currencies.xml.in.h:429 +#: ../data/currencies.xml.in.h:432 msgid "Ukrainian Hryvnia" msgstr "" -#: ../data/currencies.xml.in.h:430 +#: ../data/currencies.xml.in.h:433 #, fuzzy msgid "ar:UAH,au:₴" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:431 +#: ../data/currencies.xml.in.h:434 msgid "Ukraine" msgstr "" -#: ../data/currencies.xml.in.h:432 +#: ../data/currencies.xml.in.h:435 msgid "United Arab Emirates Dirham" msgstr "" -#: ../data/currencies.xml.in.h:433 +#: ../data/currencies.xml.in.h:436 msgid "ar:AED" msgstr "" -#: ../data/currencies.xml.in.h:434 +#: ../data/currencies.xml.in.h:437 msgid "United Arab Emirates" msgstr "" -#: ../data/currencies.xml.in.h:435 +#: ../data/currencies.xml.in.h:438 msgid "Uruguayan Peso" msgstr "" -#: ../data/currencies.xml.in.h:436 +#: ../data/currencies.xml.in.h:439 msgid "ar:UYU" msgstr "" -#: ../data/currencies.xml.in.h:437 +#: ../data/currencies.xml.in.h:440 msgid "Uruguay" msgstr "" -#: ../data/currencies.xml.in.h:438 +#: ../data/currencies.xml.in.h:441 msgid "Uzbekistan Soʻm" msgstr "" -#: ../data/currencies.xml.in.h:439 +#: ../data/currencies.xml.in.h:442 msgid "ar:UZS" msgstr "" -#: ../data/currencies.xml.in.h:440 +#: ../data/currencies.xml.in.h:443 msgid "Uzbekistan" msgstr "" -#: ../data/currencies.xml.in.h:441 +#: ../data/currencies.xml.in.h:444 msgid "Vanuatu Vatu" msgstr "" -#: ../data/currencies.xml.in.h:442 +#: ../data/currencies.xml.in.h:445 msgid "ar:VUV" msgstr "" -#: ../data/currencies.xml.in.h:443 +#: ../data/currencies.xml.in.h:446 msgid "Vanuatu" msgstr "" -#: ../data/currencies.xml.in.h:444 +#: ../data/currencies.xml.in.h:447 #, fuzzy msgid "Venezuelan Bolívar (obsolete)" msgstr "Tolar slovène" -#: ../data/currencies.xml.in.h:445 +#: ../data/currencies.xml.in.h:448 msgid "ar:VEF" msgstr "" -#: ../data/currencies.xml.in.h:446 +#: ../data/currencies.xml.in.h:449 msgid "Vietnamese Dồng" msgstr "" -#: ../data/currencies.xml.in.h:447 +#: ../data/currencies.xml.in.h:450 #, fuzzy msgid "ar:VND,au:₫" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:448 +#: ../data/currencies.xml.in.h:451 msgid "Vietnam" msgstr "" -#: ../data/currencies.xml.in.h:449 +#: ../data/currencies.xml.in.h:452 msgid "Yemeni Rial" msgstr "" -#: ../data/currencies.xml.in.h:450 +#: ../data/currencies.xml.in.h:453 msgid "ar:YER" msgstr "" -#: ../data/currencies.xml.in.h:451 +#: ../data/currencies.xml.in.h:454 #, fuzzy msgid "Yemen" msgstr "Élément" -#: ../data/currencies.xml.in.h:452 +#: ../data/currencies.xml.in.h:455 msgid "Zambian Kwacha (obsolete)" msgstr "" -#: ../data/currencies.xml.in.h:453 +#: ../data/currencies.xml.in.h:456 msgid "ar:ZMK" msgstr "" -#: ../data/currencies.xml.in.h:454 +#: ../data/currencies.xml.in.h:457 msgid "Euro Cent" msgstr "Centime d'Euro" -#: ../data/currencies.xml.in.h:455 +#: ../data/currencies.xml.in.h:458 msgid "r:eurocent,p:eurocents" msgstr "" -#: ../data/currencies.xml.in.h:456 +#: ../data/currencies.xml.in.h:459 msgid "Cent (USD)" msgstr "" -#: ../data/currencies.xml.in.h:457 +#: ../data/currencies.xml.in.h:460 msgid "au:¢,r:cent,p:cents" msgstr "" -#: ../data/currencies.xml.in.h:458 +#: ../data/currencies.xml.in.h:461 #, fuzzy msgid "Belgian Franc (obsolete)" msgstr "Franc belge" -#: ../data/currencies.xml.in.h:459 +#: ../data/currencies.xml.in.h:462 msgid "ar:BEF" msgstr "" -#: ../data/currencies.xml.in.h:460 +#: ../data/currencies.xml.in.h:463 #, fuzzy msgid "Greek Drachma (obsolete)" msgstr "Drachme grecque" -#: ../data/currencies.xml.in.h:461 +#: ../data/currencies.xml.in.h:464 #, fuzzy msgid "ar:GRD,au:₯" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:462 +#: ../data/currencies.xml.in.h:465 #, fuzzy msgid "French Franc (obsolete)" msgstr "Franc français" -#: ../data/currencies.xml.in.h:463 +#: ../data/currencies.xml.in.h:466 #, fuzzy msgid "ar:FRF,au:₣" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:464 +#: ../data/currencies.xml.in.h:467 #, fuzzy msgid "Italian Lira (obsolete)" msgstr "Lire italienne" -#: ../data/currencies.xml.in.h:465 +#: ../data/currencies.xml.in.h:468 msgid "ar:ITL" msgstr "" -#: ../data/currencies.xml.in.h:466 +#: ../data/currencies.xml.in.h:469 #, fuzzy msgid "Dutch Guilder (obsolete)" msgstr "Florin néerlandais" -#: ../data/currencies.xml.in.h:467 +#: ../data/currencies.xml.in.h:470 #, fuzzy msgid "ar:NLG" msgstr "ar:NLG,florin" -#: ../data/currencies.xml.in.h:468 +#: ../data/currencies.xml.in.h:471 #, fuzzy msgid "Portuguese Escudo (obsolete)" msgstr "Escudo portugais" -#: ../data/currencies.xml.in.h:469 +#: ../data/currencies.xml.in.h:472 msgid "ar:PTE" msgstr "" -#: ../data/currencies.xml.in.h:470 +#: ../data/currencies.xml.in.h:473 msgid "Deutsche Mark (obsolete)" msgstr "" -#: ../data/currencies.xml.in.h:471 +#: ../data/currencies.xml.in.h:474 msgid "ar:DEM" msgstr "" -#: ../data/currencies.xml.in.h:472 +#: ../data/currencies.xml.in.h:475 #, fuzzy msgid "Spanish Peseta (obsolete)" msgstr "Peseta espagnole" -#: ../data/currencies.xml.in.h:473 +#: ../data/currencies.xml.in.h:476 #, fuzzy msgid "ar:ESP,au:₧" msgstr "ar:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:474 +#: ../data/currencies.xml.in.h:477 #, fuzzy msgid "Irish Pound (obsolete)" msgstr "Livre irlandaise" -#: ../data/currencies.xml.in.h:475 +#: ../data/currencies.xml.in.h:478 msgid "ar:IEP" msgstr "" -#: ../data/currencies.xml.in.h:476 +#: ../data/currencies.xml.in.h:479 #, fuzzy msgid "Luxembourg Franc (obsolete)" msgstr "Franc luxembourgeois" -#: ../data/currencies.xml.in.h:477 +#: ../data/currencies.xml.in.h:480 msgid "ar:LUF" msgstr "" -#: ../data/currencies.xml.in.h:478 +#: ../data/currencies.xml.in.h:481 #, fuzzy msgid "Austrian Schilling (obsolete)" msgstr "Shilling autrichien" -#: ../data/currencies.xml.in.h:479 +#: ../data/currencies.xml.in.h:482 msgid "ar:ATS" msgstr "" -#: ../data/currencies.xml.in.h:480 +#: ../data/currencies.xml.in.h:483 #, fuzzy msgid "Finnish Markka (obsolete)" msgstr "Markka finnois" -#: ../data/currencies.xml.in.h:481 +#: ../data/currencies.xml.in.h:484 msgid "ar:FIM" msgstr "" -#: ../data/currencies.xml.in.h:482 +#: ../data/currencies.xml.in.h:485 #, fuzzy msgid "Slovenian Tolar (obsolete)" msgstr "Tolar slovène" -#: ../data/currencies.xml.in.h:483 +#: ../data/currencies.xml.in.h:486 msgid "ar:SIT" msgstr "" -#: ../data/currencies.xml.in.h:484 +#: ../data/currencies.xml.in.h:487 #, fuzzy msgid "Cypriot Pound (obsolete)" msgstr "Livre chypriote" -#: ../data/currencies.xml.in.h:485 +#: ../data/currencies.xml.in.h:488 msgid "ar:CYP" msgstr "" -#: ../data/currencies.xml.in.h:486 +#: ../data/currencies.xml.in.h:489 #, fuzzy msgid "Estonian Kroon (obsolete)" msgstr "Kroon estonienne" -#: ../data/currencies.xml.in.h:487 +#: ../data/currencies.xml.in.h:490 msgid "ar:EEK" msgstr "" -#: ../data/currencies.xml.in.h:488 +#: ../data/currencies.xml.in.h:491 #, fuzzy msgid "Slovak Koruna (obsolete)" msgstr "Couronne slovaque" -#: ../data/currencies.xml.in.h:489 +#: ../data/currencies.xml.in.h:492 msgid "ar:SKK" msgstr "" -#: ../data/currencies.xml.in.h:490 +#: ../data/currencies.xml.in.h:493 #, fuzzy msgid "Maltese Lira (obsolete)" msgstr "Lire maltaise" -#: ../data/currencies.xml.in.h:491 +#: ../data/currencies.xml.in.h:494 msgid "ar:MTL" msgstr "" -#: ../data/currencies.xml.in.h:492 +#: ../data/currencies.xml.in.h:495 #, fuzzy msgid "Latvian Lats (obsolete)" msgstr "Lats letton" -#: ../data/currencies.xml.in.h:493 +#: ../data/currencies.xml.in.h:496 msgid "ar:LVL" msgstr "" -#: ../data/currencies.xml.in.h:494 +#: ../data/currencies.xml.in.h:497 #, fuzzy msgid "Lithuanian Litas (obsolete)" msgstr "Litas lituanien" -#: ../data/currencies.xml.in.h:495 +#: ../data/currencies.xml.in.h:498 msgid "ar:LTL" msgstr "" @@ -2139,7 +2153,7 @@ msgid "!datasets!r:number" msgstr "r:nombre" -#: ../data/datasets.xml.in.h:13 ../data/functions.xml.in.h:709 +#: ../data/datasets.xml.in.h:13 ../data/functions.xml.in.h:716 msgid "Name" msgstr "Nom" @@ -2168,7 +2182,7 @@ msgid "r:class" msgstr "r:classe" -#: ../data/datasets.xml.in.h:18 ../data/functions.xml.in.h:424 +#: ../data/datasets.xml.in.h:18 ../data/functions.xml.in.h:431 msgid "Weight" msgstr "Poids" @@ -3736,15 +3750,17 @@ msgstr "" #: ../data/functions.xml.in.h:216 -msgid "Fibonacci Number" -msgstr "Nombre de Fibonacci" +msgid "Bernoulli Number/Polynomial" +msgstr "" #: ../data/functions.xml.in.h:217 -msgid "r:fibonacci" +msgid "" +"Returns the nth Bernoulli number or polynomial (if the second argument is " +"non-zero)." msgstr "" #: ../data/functions.xml.in.h:218 -msgid "Returns the n-th term of the Fibonacci sequence." +msgid "r:bernoulli" msgstr "" #: ../data/functions.xml.in.h:219 @@ -3752,70 +3768,82 @@ msgstr "" #: ../data/functions.xml.in.h:220 +msgid "Fibonacci Number" +msgstr "Nombre de Fibonacci" + +#: ../data/functions.xml.in.h:221 +msgid "r:fibonacci" +msgstr "" + +#: ../data/functions.xml.in.h:222 +msgid "Returns the n-th term of the Fibonacci sequence." +msgstr "" + +#: ../data/functions.xml.in.h:223 msgid "Rounding" msgstr "Arrondi" -#: ../data/functions.xml.in.h:221 +#: ../data/functions.xml.in.h:224 msgid "Round" msgstr "Arrondi" -#: ../data/functions.xml.in.h:222 +#: ../data/functions.xml.in.h:225 msgid "r:round" msgstr "arrondi" -#: ../data/functions.xml.in.h:223 +#: ../data/functions.xml.in.h:226 msgid "Round Downwards" msgstr "Arrondi à la Valeur Inférieure" -#: ../data/functions.xml.in.h:224 +#: ../data/functions.xml.in.h:227 msgid "r:floor" msgstr "plancher" -#: ../data/functions.xml.in.h:225 +#: ../data/functions.xml.in.h:228 msgid "Round Upwards" msgstr "Arrondi à la Valeur Supérieure" -#: ../data/functions.xml.in.h:226 +#: ../data/functions.xml.in.h:229 msgid "r:ceil" msgstr "plafond" -#: ../data/functions.xml.in.h:227 +#: ../data/functions.xml.in.h:230 msgid "Round Towards Zero" msgstr "Arrondi vers Zéro" -#: ../data/functions.xml.in.h:228 +#: ../data/functions.xml.in.h:231 msgid "r:trunc" msgstr "" -#: ../data/functions.xml.in.h:229 +#: ../data/functions.xml.in.h:232 msgid "Integer Part" msgstr "Partie Entière" -#: ../data/functions.xml.in.h:230 +#: ../data/functions.xml.in.h:233 msgid "r:int" msgstr "" -#: ../data/functions.xml.in.h:231 +#: ../data/functions.xml.in.h:234 msgid "Fractional Part" msgstr "Partie Fractionnaire" -#: ../data/functions.xml.in.h:232 +#: ../data/functions.xml.in.h:235 msgid "r:frac" msgstr "" -#: ../data/functions.xml.in.h:233 +#: ../data/functions.xml.in.h:236 msgid "Number Bases" msgstr "Bases Numériques" -#: ../data/functions.xml.in.h:234 +#: ../data/functions.xml.in.h:237 msgid "Number Base" msgstr "Base Numérique" -#: ../data/functions.xml.in.h:235 +#: ../data/functions.xml.in.h:238 msgid "r:base" msgstr "" -#: ../data/functions.xml.in.h:236 +#: ../data/functions.xml.in.h:239 msgid "" "Returns a value from an expression using the specified number base (radix). " "For bases between -62 and 62 full mathematical expressions (including " @@ -3836,96 +3864,96 @@ "selected, the specified expression is always converted to a single number." msgstr "" -#: ../data/functions.xml.in.h:237 +#: ../data/functions.xml.in.h:240 msgid "Set of digits" msgstr "" -#: ../data/functions.xml.in.h:238 +#: ../data/functions.xml.in.h:241 msgid "Binary" msgstr "Binaire" -#: ../data/functions.xml.in.h:239 +#: ../data/functions.xml.in.h:242 msgid "r:bin" msgstr "" -#: ../data/functions.xml.in.h:240 +#: ../data/functions.xml.in.h:243 msgid "" "Returns a value from a binary expression. If two's complement is true, " "numbers beginning with '1' is interpreted as negative binary numbers using " "two's complement." msgstr "" -#: ../data/functions.xml.in.h:241 +#: ../data/functions.xml.in.h:244 msgid "Binary number" msgstr "Nombre binaire" -#: ../data/functions.xml.in.h:242 +#: ../data/functions.xml.in.h:245 msgid "Two's complement" msgstr "Complément à deux" -#: ../data/functions.xml.in.h:243 +#: ../data/functions.xml.in.h:246 msgid "Octal" msgstr "" -#: ../data/functions.xml.in.h:244 +#: ../data/functions.xml.in.h:247 msgid "r:oct" msgstr "" -#: ../data/functions.xml.in.h:245 +#: ../data/functions.xml.in.h:248 #, fuzzy msgid "Returns a value from an octal expression." msgstr "Retourne une valeur à partir d'un nombre hexadécimal" -#: ../data/functions.xml.in.h:246 +#: ../data/functions.xml.in.h:249 msgid "Octal number" msgstr "Nombre octal" -#: ../data/functions.xml.in.h:247 +#: ../data/functions.xml.in.h:250 msgid "Decimal" msgstr "Décimal" -#: ../data/functions.xml.in.h:248 +#: ../data/functions.xml.in.h:251 #, fuzzy msgid "r:dec" msgstr "degré" -#: ../data/functions.xml.in.h:249 +#: ../data/functions.xml.in.h:252 #, fuzzy msgid "Returns a value from a decimal expression." msgstr "Retourne une valeur à partir d'un nombre hexadécimal" -#: ../data/functions.xml.in.h:250 +#: ../data/functions.xml.in.h:253 msgid "Decimal number" msgstr "Nombre décimal" -#: ../data/functions.xml.in.h:251 +#: ../data/functions.xml.in.h:254 msgid "Hexadecimal" msgstr "Hexadécimal" -#: ../data/functions.xml.in.h:252 +#: ../data/functions.xml.in.h:255 msgid "r:hex" msgstr "" -#: ../data/functions.xml.in.h:253 +#: ../data/functions.xml.in.h:256 msgid "" "Returns a value from a hexadecimal expression. If two's complement is true, " "numbers beginning with 8 or higher is interpreted as negative hexadecimal " "numbers using two's complement." msgstr "" -#: ../data/functions.xml.in.h:254 +#: ../data/functions.xml.in.h:257 msgid "Hexadecimal number" msgstr "Nombre hexadécimal" -#: ../data/functions.xml.in.h:255 +#: ../data/functions.xml.in.h:258 msgid "Bijective base-26" msgstr "" -#: ../data/functions.xml.in.h:256 +#: ../data/functions.xml.in.h:259 msgid "r:bijective" msgstr "" -#: ../data/functions.xml.in.h:257 +#: ../data/functions.xml.in.h:260 #, fuzzy msgid "" "Returns a value from an expression in bijective base-26. Conversion in the " @@ -3933,680 +3961,696 @@ msgstr "" "Retourne un entier à partir d'un nombre dans une base spécifiée entre 2 et 36" -#: ../data/functions.xml.in.h:258 +#: ../data/functions.xml.in.h:261 msgid "Bijective base-26 number" msgstr "" -#: ../data/functions.xml.in.h:259 +#: ../data/functions.xml.in.h:262 msgid "Integers" msgstr "Entiers" -#: ../data/functions.xml.in.h:260 +#: ../data/functions.xml.in.h:263 msgid "Even" msgstr "Pair" -#: ../data/functions.xml.in.h:261 +#: ../data/functions.xml.in.h:264 msgid "r:even" msgstr "pair" -#: ../data/functions.xml.in.h:262 +#: ../data/functions.xml.in.h:265 msgid "Odd" msgstr "Impair" -#: ../data/functions.xml.in.h:263 +#: ../data/functions.xml.in.h:266 msgid "r:odd" msgstr "impair" -#: ../data/functions.xml.in.h:264 +#: ../data/functions.xml.in.h:267 msgid "Special Functions" msgstr "Fonction Remarquable" -#: ../data/functions.xml.in.h:265 +#: ../data/functions.xml.in.h:268 msgid "Gamma Function" msgstr "Fonction Gamma" -#: ../data/functions.xml.in.h:266 +#: ../data/functions.xml.in.h:269 msgid "r:gamma" msgstr "" -#: ../data/functions.xml.in.h:267 +#: ../data/functions.xml.in.h:270 msgid "Digamma Function" msgstr "Fonction Digamma" -#: ../data/functions.xml.in.h:268 +#: ../data/functions.xml.in.h:271 msgid "r:digamma,psi" msgstr "" -#: ../data/functions.xml.in.h:269 +#: ../data/functions.xml.in.h:272 msgid "Beta Function" msgstr "Fonction Bêta" -#: ../data/functions.xml.in.h:270 +#: ../data/functions.xml.in.h:273 msgid "r:beta" msgstr "" -#: ../data/functions.xml.in.h:271 +#: ../data/functions.xml.in.h:274 msgid "Error Function" msgstr "Fonction d'Erreur" -#: ../data/functions.xml.in.h:272 +#: ../data/functions.xml.in.h:275 msgid "r:erf" msgstr "" -#: ../data/functions.xml.in.h:273 +#: ../data/functions.xml.in.h:276 msgid "Complementary Error Function" msgstr "Fonction d'Erreur Complémentaire" -#: ../data/functions.xml.in.h:274 +#: ../data/functions.xml.in.h:277 msgid "r:erfc" msgstr "" -#: ../data/functions.xml.in.h:275 +#: ../data/functions.xml.in.h:278 +msgid "Imaginary Error Function" +msgstr "Fonction d'Erreur imaginaire" + +#: ../data/functions.xml.in.h:279 +msgid "r:erfi" +msgstr "" + +#: ../data/functions.xml.in.h:280 msgid "Polylogarithm" msgstr "Fonction Polylogarithme" -#: ../data/functions.xml.in.h:276 +#: ../data/functions.xml.in.h:281 msgid "rc:Li,polylog" msgstr "" -#: ../data/functions.xml.in.h:277 +#: ../data/functions.xml.in.h:282 msgid "Order" msgstr "Ordre" -#: ../data/functions.xml.in.h:278 +#: ../data/functions.xml.in.h:283 msgid "Argument" msgstr "" -#: ../data/functions.xml.in.h:279 +#: ../data/functions.xml.in.h:284 msgid "Airy Function" msgstr "Fonction d'Airy" -#: ../data/functions.xml.in.h:280 +#: ../data/functions.xml.in.h:285 msgid "r:airy" msgstr "" -#: ../data/functions.xml.in.h:281 +#: ../data/functions.xml.in.h:286 msgid "Bessel Function of the First Kind" msgstr "Fonction de Bessel de première espèce" -#: ../data/functions.xml.in.h:282 +#: ../data/functions.xml.in.h:287 msgid "r:besselj" msgstr "" -#: ../data/functions.xml.in.h:283 +#: ../data/functions.xml.in.h:288 msgid "Bessel Function of the Second Kind" msgstr "Fonction de Bessel de seconde espèce" -#: ../data/functions.xml.in.h:284 +#: ../data/functions.xml.in.h:289 msgid "r:bessely" msgstr "" -#: ../data/functions.xml.in.h:285 +#: ../data/functions.xml.in.h:290 msgid "Riemann Zeta" msgstr "Fonction Zêta de Riemann" -#: ../data/functions.xml.in.h:286 +#: ../data/functions.xml.in.h:291 +msgid "Calculates Hurwitz zeta function if the second argument is not 1." +msgstr "" + +#: ../data/functions.xml.in.h:292 msgid "r:zeta" msgstr "" -#: ../data/functions.xml.in.h:287 +#: ../data/functions.xml.in.h:293 msgid "Integral point" msgstr "Point intégral" -#: ../data/functions.xml.in.h:288 +#: ../data/functions.xml.in.h:294 +msgid "Hurwitz zeta argument" +msgstr "" + +#: ../data/functions.xml.in.h:295 msgid "Kronecker Delta" msgstr "Symbole de Kronecker" -#: ../data/functions.xml.in.h:289 +#: ../data/functions.xml.in.h:296 msgid "r:kronecker" msgstr "" -#: ../data/functions.xml.in.h:290 +#: ../data/functions.xml.in.h:297 msgid "Returns 0 if i != j and 1 if i = j." msgstr "" -#: ../data/functions.xml.in.h:291 +#: ../data/functions.xml.in.h:298 msgid "Value 1 (i)" msgstr "Valeur 1 (i)" -#: ../data/functions.xml.in.h:292 +#: ../data/functions.xml.in.h:299 msgid "Value 2 (j)" msgstr "Valeur 2 (j)" -#: ../data/functions.xml.in.h:293 +#: ../data/functions.xml.in.h:300 msgid "Logit Transformation" msgstr "Fonction Logit" -#: ../data/functions.xml.in.h:294 +#: ../data/functions.xml.in.h:301 msgid "r:logit" msgstr "" -#: ../data/functions.xml.in.h:295 +#: ../data/functions.xml.in.h:302 msgid "Sigmoid Function" msgstr "Fonction Sigmoïde" -#: ../data/functions.xml.in.h:296 +#: ../data/functions.xml.in.h:303 msgid "r:sigmoid" msgstr "" -#: ../data/functions.xml.in.h:297 +#: ../data/functions.xml.in.h:304 msgid "Step Functions" msgstr "" -#: ../data/functions.xml.in.h:298 +#: ../data/functions.xml.in.h:305 msgid "Heaviside Step Function" msgstr "Fonction de Heaviside" -#: ../data/functions.xml.in.h:299 +#: ../data/functions.xml.in.h:306 msgid "r:heaviside,au:θ" msgstr "" -#: ../data/functions.xml.in.h:300 +#: ../data/functions.xml.in.h:307 msgid "" "Discontinuous function also known as \"unit step function\". Returns 0 if x " "< 0, 1 if x > 0, and 1/2 if x = 0." msgstr "" -#: ../data/functions.xml.in.h:301 +#: ../data/functions.xml.in.h:308 msgid "Dirac Delta Function" msgstr "Fonction de Dirac" -#: ../data/functions.xml.in.h:302 +#: ../data/functions.xml.in.h:309 msgid "r:dirac,au:δ" msgstr "" -#: ../data/functions.xml.in.h:303 +#: ../data/functions.xml.in.h:310 msgid "Returns 0 if x is non-zero, and infinity if x is zero." msgstr "" -#: ../data/functions.xml.in.h:304 +#: ../data/functions.xml.in.h:311 msgid "Ramp Function" msgstr "Fonction Rampe" -#: ../data/functions.xml.in.h:305 +#: ../data/functions.xml.in.h:312 msgid "r:ramp" msgstr "" -#: ../data/functions.xml.in.h:306 +#: ../data/functions.xml.in.h:313 msgid "Rectangular Function" msgstr "Fonction Porte" -#: ../data/functions.xml.in.h:307 +#: ../data/functions.xml.in.h:314 msgid "r:rectangular" msgstr "" -#: ../data/functions.xml.in.h:308 +#: ../data/functions.xml.in.h:315 msgid "Triangular Function" msgstr "Fonction Triangulaire" -#: ../data/functions.xml.in.h:309 +#: ../data/functions.xml.in.h:316 msgid "r:triangular" msgstr "" -#: ../data/functions.xml.in.h:310 +#: ../data/functions.xml.in.h:317 msgid "Complex Numbers" msgstr "Nombres Complexes" -#: ../data/functions.xml.in.h:311 +#: ../data/functions.xml.in.h:318 msgid "Real Part" msgstr "Partie Réelle" -#: ../data/functions.xml.in.h:312 +#: ../data/functions.xml.in.h:319 #, fuzzy msgid "r:re,au:ℜ" msgstr "ar:ITL,au:₤,lire" -#: ../data/functions.xml.in.h:313 +#: ../data/functions.xml.in.h:320 msgid "Complex number" msgstr "Nombre complexe" -#: ../data/functions.xml.in.h:314 +#: ../data/functions.xml.in.h:321 msgid "Imaginary Part" msgstr "Partie Imaginaire" -#: ../data/functions.xml.in.h:315 +#: ../data/functions.xml.in.h:322 #, fuzzy msgid "r:im,au:ℑ" msgstr "pourmille,au:‰" -#: ../data/functions.xml.in.h:316 +#: ../data/functions.xml.in.h:323 msgid "Principal Argument" msgstr "Argument Principale" -#: ../data/functions.xml.in.h:317 +#: ../data/functions.xml.in.h:324 msgid "r:arg" msgstr "" -#: ../data/functions.xml.in.h:318 +#: ../data/functions.xml.in.h:325 msgid "Complex Conjugate" msgstr "Conjugué" -#: ../data/functions.xml.in.h:319 +#: ../data/functions.xml.in.h:326 msgid "r:conj" msgstr "" -#: ../data/functions.xml.in.h:320 +#: ../data/functions.xml.in.h:327 msgid "Exponents & Logarithms" msgstr "Exponentielles et Logarithmes" -#: ../data/functions.xml.in.h:321 +#: ../data/functions.xml.in.h:328 msgid "Square Root" msgstr "Racine Carrée" -#: ../data/functions.xml.in.h:322 +#: ../data/functions.xml.in.h:329 msgid "au:√,r:sqrt" msgstr "" -#: ../data/functions.xml.in.h:323 +#: ../data/functions.xml.in.h:330 msgid "" "Returns the principal square root (for positive values the positive root is " "returned)." msgstr "" -#: ../data/functions.xml.in.h:324 +#: ../data/functions.xml.in.h:331 msgid "Cube Root" msgstr "Racine Cubique" -#: ../data/functions.xml.in.h:325 +#: ../data/functions.xml.in.h:332 msgid "au:∛,r:cbrt" msgstr "" -#: ../data/functions.xml.in.h:326 +#: ../data/functions.xml.in.h:333 #, fuzzy msgid "Returns the third real root." msgstr "Retourne la plus grande valeur." -#: ../data/functions.xml.in.h:327 +#: ../data/functions.xml.in.h:334 msgid "Nth root" msgstr "Racine n-ième" -#: ../data/functions.xml.in.h:328 +#: ../data/functions.xml.in.h:335 msgid "r:root" msgstr "" -#: ../data/functions.xml.in.h:329 +#: ../data/functions.xml.in.h:336 msgid "" "Returns the real root. For negative values the degree must be odd. Complex " "values are not allowed." msgstr "" -#: ../data/functions.xml.in.h:330 ../data/units.xml.in.h:65 +#: ../data/functions.xml.in.h:337 ../data/units.xml.in.h:65 msgid "Degree" msgstr "Degré" -#: ../data/functions.xml.in.h:331 +#: ../data/functions.xml.in.h:338 msgid "Square" msgstr "Carré" -#: ../data/functions.xml.in.h:332 +#: ../data/functions.xml.in.h:339 msgid "r:sq" msgstr "" -#: ../data/functions.xml.in.h:333 +#: ../data/functions.xml.in.h:340 msgid "Exponential (e^x)" msgstr "Exponentielle (e^x)" -#: ../data/functions.xml.in.h:334 +#: ../data/functions.xml.in.h:341 msgid "r:exp" msgstr "" -#: ../data/functions.xml.in.h:335 +#: ../data/functions.xml.in.h:342 msgid "Natural Logarithm" msgstr "Logarithme Naturel (népérien)" -#: ../data/functions.xml.in.h:336 +#: ../data/functions.xml.in.h:343 msgid "r:ln" msgstr "" -#: ../data/functions.xml.in.h:337 +#: ../data/functions.xml.in.h:344 msgid "Base-N Logarithm" msgstr "Logarithme en base N" -#: ../data/functions.xml.in.h:338 +#: ../data/functions.xml.in.h:345 msgid "r:log" msgstr "" -#: ../data/functions.xml.in.h:339 +#: ../data/functions.xml.in.h:346 msgid "Lambert W Function (Omega Function, Product Log)" msgstr "Fonction W de Lambert (fonction Oméga)" -#: ../data/functions.xml.in.h:340 +#: ../data/functions.xml.in.h:347 msgid "r:lambertw,productlog" msgstr "" -#: ../data/functions.xml.in.h:341 +#: ../data/functions.xml.in.h:348 msgid "" "Returns the inverse function for mx*e^x as ln() does for e^x. Only the " "principal branch and real valued results are currently supported." msgstr "" -#: ../data/functions.xml.in.h:342 +#: ../data/functions.xml.in.h:349 msgid "Branch" msgstr "" -#: ../data/functions.xml.in.h:343 +#: ../data/functions.xml.in.h:350 msgid "Complex Exponential (Cis)" msgstr "Exponentielle Complexe" -#: ../data/functions.xml.in.h:344 +#: ../data/functions.xml.in.h:351 msgid "r:cis" msgstr "" -#: ../data/functions.xml.in.h:345 +#: ../data/functions.xml.in.h:352 msgid "Base-2 Logarithm" msgstr "Logarithme en base 2" -#: ../data/functions.xml.in.h:346 +#: ../data/functions.xml.in.h:353 msgid "rs:log2" msgstr "" -#: ../data/functions.xml.in.h:347 +#: ../data/functions.xml.in.h:354 msgid "Returns the base n logarithm." msgstr "Retourne le logarithme en base n." -#: ../data/functions.xml.in.h:348 +#: ../data/functions.xml.in.h:355 msgid "Base-10 Logarithm" msgstr "Logarithme en base 10" -#: ../data/functions.xml.in.h:349 +#: ../data/functions.xml.in.h:356 msgid "rs:log10" msgstr "" -#: ../data/functions.xml.in.h:350 +#: ../data/functions.xml.in.h:357 msgid "2 raised to the power X" msgstr "2 élevé à la puissance X" -#: ../data/functions.xml.in.h:351 +#: ../data/functions.xml.in.h:358 msgid "rs:exp2" msgstr "" -#: ../data/functions.xml.in.h:352 +#: ../data/functions.xml.in.h:359 msgid "10 raised to the power X" msgstr "10 élevé à la puissance X" -#: ../data/functions.xml.in.h:353 +#: ../data/functions.xml.in.h:360 msgid "rs:exp10" msgstr "" -#: ../data/functions.xml.in.h:354 +#: ../data/functions.xml.in.h:361 msgid "X raised to the power Y" msgstr "X élevé à la puissance Y" -#: ../data/functions.xml.in.h:355 +#: ../data/functions.xml.in.h:362 msgid "r:pow" msgstr "" -#: ../data/functions.xml.in.h:356 +#: ../data/functions.xml.in.h:363 msgid "Square root (x * pi)" msgstr "Racine carrée (x * pi)" -#: ../data/functions.xml.in.h:357 +#: ../data/functions.xml.in.h:364 msgid "r:sqrtpi" msgstr "" -#: ../data/functions.xml.in.h:358 +#: ../data/functions.xml.in.h:365 msgid "Returns the non-negative square root of x * pi" msgstr "Retourne la racine carrée de x * pi" -#: ../data/functions.xml.in.h:359 +#: ../data/functions.xml.in.h:366 msgid "Non-negative value" msgstr "Valeur strictement positive" -#: ../data/functions.xml.in.h:360 +#: ../data/functions.xml.in.h:367 msgid "Trigonometry" msgstr "Trigonométrie" -#: ../data/functions.xml.in.h:361 +#: ../data/functions.xml.in.h:368 msgid "Sine" msgstr "Sinus" -#: ../data/functions.xml.in.h:362 +#: ../data/functions.xml.in.h:369 msgid "r:sin" msgstr "" -#: ../data/functions.xml.in.h:363 +#: ../data/functions.xml.in.h:370 msgid "Angle" msgstr "" -#: ../data/functions.xml.in.h:364 +#: ../data/functions.xml.in.h:371 msgid "Cosine" msgstr "Cosinus" -#: ../data/functions.xml.in.h:365 +#: ../data/functions.xml.in.h:372 msgid "r:cos" msgstr "" -#: ../data/functions.xml.in.h:366 +#: ../data/functions.xml.in.h:373 msgid "Tangent" msgstr "Tangente" -#: ../data/functions.xml.in.h:367 +#: ../data/functions.xml.in.h:374 msgid "r:tan" msgstr "" -#: ../data/functions.xml.in.h:368 +#: ../data/functions.xml.in.h:375 msgid "Inverse Sine" msgstr "Arcsinus" -#: ../data/functions.xml.in.h:369 +#: ../data/functions.xml.in.h:376 msgid "r:asin" msgstr "arcsin" -#: ../data/functions.xml.in.h:370 +#: ../data/functions.xml.in.h:377 msgid "Inverse Cosine" msgstr "Arccosinus" -#: ../data/functions.xml.in.h:371 +#: ../data/functions.xml.in.h:378 msgid "r:acos" msgstr "arccos" -#: ../data/functions.xml.in.h:372 +#: ../data/functions.xml.in.h:379 msgid "Inverse Tangent" msgstr "Arctangente" -#: ../data/functions.xml.in.h:373 +#: ../data/functions.xml.in.h:380 msgid "r:atan" msgstr "arctan" -#: ../data/functions.xml.in.h:374 +#: ../data/functions.xml.in.h:381 msgid "Hyperbolic Sine" msgstr "Sinus Hyperbolique" -#: ../data/functions.xml.in.h:375 +#: ../data/functions.xml.in.h:382 msgid "r:sinh" msgstr "" -#: ../data/functions.xml.in.h:376 +#: ../data/functions.xml.in.h:383 msgid "Hyperbolic Cosine" msgstr "Cosinus Hyperbolique" -#: ../data/functions.xml.in.h:377 +#: ../data/functions.xml.in.h:384 msgid "r:cosh" msgstr "" -#: ../data/functions.xml.in.h:378 +#: ../data/functions.xml.in.h:385 msgid "Hyperbolic Tangent" msgstr "Tangente Hyperbolique" -#: ../data/functions.xml.in.h:379 +#: ../data/functions.xml.in.h:386 msgid "r:tanh" msgstr "" -#: ../data/functions.xml.in.h:380 +#: ../data/functions.xml.in.h:387 msgid "Inverse Hyperbolic Sine" msgstr "Argsinus Hyperbolique" -#: ../data/functions.xml.in.h:381 +#: ../data/functions.xml.in.h:388 msgid "r:asinh" msgstr "argsh" -#: ../data/functions.xml.in.h:382 +#: ../data/functions.xml.in.h:389 msgid "Inverse Hyperbolic Cosine" msgstr "Argcosinus Hyperbolique" -#: ../data/functions.xml.in.h:383 +#: ../data/functions.xml.in.h:390 msgid "r:acosh" msgstr "argcosh" -#: ../data/functions.xml.in.h:384 +#: ../data/functions.xml.in.h:391 msgid "Inverse Hyperbolic Tangent" msgstr "Argtangente Hyperbolique" -#: ../data/functions.xml.in.h:385 +#: ../data/functions.xml.in.h:392 msgid "r:atanh" msgstr "argth" -#: ../data/functions.xml.in.h:386 +#: ../data/functions.xml.in.h:393 msgid "Four-quadrant Inverse Tangent" msgstr "Fonction atan2" -#: ../data/functions.xml.in.h:387 +#: ../data/functions.xml.in.h:394 msgid "r:atan2" msgstr "" -#: ../data/functions.xml.in.h:388 +#: ../data/functions.xml.in.h:395 msgid "" "Computes the principal value of the argument function applied to the complex " "number x+iy." msgstr "" -#: ../data/functions.xml.in.h:389 +#: ../data/functions.xml.in.h:396 msgid "Y" msgstr "" -#: ../data/functions.xml.in.h:390 +#: ../data/functions.xml.in.h:397 msgid "X" msgstr "" -#: ../data/functions.xml.in.h:391 +#: ../data/functions.xml.in.h:398 msgid "Cardinal Sine (Sinc Function)" msgstr "Sinus Cardinal (fonction sinc)" -#: ../data/functions.xml.in.h:392 +#: ../data/functions.xml.in.h:399 msgid "r:sinc" msgstr "" -#: ../data/functions.xml.in.h:393 +#: ../data/functions.xml.in.h:400 msgid "Radians to Default Angle Unit" msgstr "Radians en Unité d'Angle par Défaut" -#: ../data/functions.xml.in.h:394 +#: ../data/functions.xml.in.h:401 msgid "r:radtodef" msgstr "" -#: ../data/functions.xml.in.h:395 +#: ../data/functions.xml.in.h:402 msgid "Radians" msgstr "" -#: ../data/functions.xml.in.h:396 +#: ../data/functions.xml.in.h:403 msgid "Secant" msgstr "" -#: ../data/functions.xml.in.h:397 +#: ../data/functions.xml.in.h:404 msgid "r:sec" msgstr "" -#: ../data/functions.xml.in.h:398 +#: ../data/functions.xml.in.h:405 msgid "Cosecant" msgstr "Cosécante" -#: ../data/functions.xml.in.h:399 +#: ../data/functions.xml.in.h:406 msgid "r:csc" msgstr "" -#: ../data/functions.xml.in.h:400 +#: ../data/functions.xml.in.h:407 msgid "Cotangent" msgstr "Cotangente" -#: ../data/functions.xml.in.h:401 +#: ../data/functions.xml.in.h:408 msgid "r:cot" msgstr "" -#: ../data/functions.xml.in.h:402 +#: ../data/functions.xml.in.h:409 msgid "Hyperbolic Secant" msgstr "Sécante Hyperbolique" -#: ../data/functions.xml.in.h:403 +#: ../data/functions.xml.in.h:410 msgid "r:sech" msgstr "" -#: ../data/functions.xml.in.h:404 +#: ../data/functions.xml.in.h:411 msgid "Hyperbolic Cosecant" msgstr "Cosécante Hyperbolique" -#: ../data/functions.xml.in.h:405 +#: ../data/functions.xml.in.h:412 msgid "r:csch" msgstr "" -#: ../data/functions.xml.in.h:406 +#: ../data/functions.xml.in.h:413 msgid "Hyperbolic Cotangent" msgstr "Cotangente Hyperbolique" -#: ../data/functions.xml.in.h:407 +#: ../data/functions.xml.in.h:414 msgid "r:coth" msgstr "" -#: ../data/functions.xml.in.h:408 +#: ../data/functions.xml.in.h:415 msgid "Inverse Secant" msgstr "Arcsécante" -#: ../data/functions.xml.in.h:409 +#: ../data/functions.xml.in.h:416 msgid "r:asec" msgstr "" -#: ../data/functions.xml.in.h:410 +#: ../data/functions.xml.in.h:417 msgid "Inverse Cosecant" msgstr "Arccosécante" -#: ../data/functions.xml.in.h:411 +#: ../data/functions.xml.in.h:418 msgid "r:acsc" msgstr "" -#: ../data/functions.xml.in.h:412 +#: ../data/functions.xml.in.h:419 msgid "Inverse Cotangent" msgstr "Arccotangente" -#: ../data/functions.xml.in.h:413 +#: ../data/functions.xml.in.h:420 msgid "r:acot" msgstr "" -#: ../data/functions.xml.in.h:414 +#: ../data/functions.xml.in.h:421 msgid "Inverse Hyperbolic Secant" msgstr "Argsécante Hyperbolique" -#: ../data/functions.xml.in.h:415 +#: ../data/functions.xml.in.h:422 msgid "r:asech" msgstr "" -#: ../data/functions.xml.in.h:416 +#: ../data/functions.xml.in.h:423 msgid "Inverse Hyperbolic Cosecant" msgstr "Argcosécante Hyperbolique" -#: ../data/functions.xml.in.h:417 +#: ../data/functions.xml.in.h:424 msgid "r:acsch" msgstr "" -#: ../data/functions.xml.in.h:418 +#: ../data/functions.xml.in.h:425 msgid "Inverse Hyperbolic Cotangent" msgstr "Argcotangente Hyperbolique" -#: ../data/functions.xml.in.h:419 +#: ../data/functions.xml.in.h:426 msgid "r:acoth" msgstr "" -#: ../data/functions.xml.in.h:420 +#: ../data/functions.xml.in.h:427 msgid "Miscellaneous" msgstr "Divers" -#: ../data/functions.xml.in.h:421 +#: ../data/functions.xml.in.h:428 msgid "Body Mass Index (BMI)" msgstr "Indice de masse corporelle (IMC)" -#: ../data/functions.xml.in.h:422 +#: ../data/functions.xml.in.h:429 msgid "-r:bmi" msgstr "imc" -#: ../data/functions.xml.in.h:423 +#: ../data/functions.xml.in.h:430 msgid "" "Calculates the Body Mass Index. The resulting BMI-value is sometimes " "interpreted as follows (although varies with age, sex, etc.): " @@ -4620,19 +4664,19 @@ "Obésité > 30 Notez que vous devez utiliser des unités pour la " "masse (p. ex. 59kg) et la taille (p. ex. 174cm)." -#: ../data/functions.xml.in.h:425 +#: ../data/functions.xml.in.h:432 msgid "Length" msgstr "Longueur" -#: ../data/functions.xml.in.h:426 +#: ../data/functions.xml.in.h:433 msgid "RAID Space" msgstr "Capacité RAID" -#: ../data/functions.xml.in.h:427 +#: ../data/functions.xml.in.h:434 msgid "r:raid" msgstr "" -#: ../data/functions.xml.in.h:428 +#: ../data/functions.xml.in.h:435 msgid "" "Calculates RAID array disk capacity usable for data storage. If the " "combination of number of disks and RAID level is invalid, zero is returned. " @@ -4641,48 +4685,48 @@ "1+0)." msgstr "" -#: ../data/functions.xml.in.h:429 +#: ../data/functions.xml.in.h:436 msgid "RAID level" msgstr "Niveaux de RAID" -#: ../data/functions.xml.in.h:430 +#: ../data/functions.xml.in.h:437 msgid "Capacity of each disk" msgstr "Capacité de chaque disque" -#: ../data/functions.xml.in.h:431 +#: ../data/functions.xml.in.h:438 msgid "Number of disks" msgstr "Nombre de disques" -#: ../data/functions.xml.in.h:432 +#: ../data/functions.xml.in.h:439 msgid "Stripes" msgstr "Bandes" -#: ../data/functions.xml.in.h:433 +#: ../data/functions.xml.in.h:440 msgid "Roman Number" msgstr "Nombre Romain" -#: ../data/functions.xml.in.h:434 +#: ../data/functions.xml.in.h:441 msgid "r:roman" msgstr "" -#: ../data/functions.xml.in.h:435 +#: ../data/functions.xml.in.h:442 msgid "Returns the value of a roman number." msgstr "" -#: ../data/functions.xml.in.h:436 +#: ../data/functions.xml.in.h:443 msgid "Roman number" msgstr "Nombre romain" -#: ../data/functions.xml.in.h:437 +#: ../data/functions.xml.in.h:444 #, fuzzy msgid "Depth of Field" msgstr "Longueur du côté" -#: ../data/functions.xml.in.h:438 +#: ../data/functions.xml.in.h:445 msgid "r:dof" msgstr "" -#: ../data/functions.xml.in.h:439 +#: ../data/functions.xml.in.h:446 msgid "" "Returns the estimated distance between the nearest and the farthest objects " "that are in acceptably sharp focus in a photo. Enter focal length (e.g. 50 " @@ -4694,198 +4738,198 @@ "on d/1500." msgstr "" -#: ../data/functions.xml.in.h:440 +#: ../data/functions.xml.in.h:447 #, fuzzy msgid "Focal Length" msgstr "Longueur" -#: ../data/functions.xml.in.h:441 +#: ../data/functions.xml.in.h:448 msgid "F-stop (aperture)" msgstr "" -#: ../data/functions.xml.in.h:442 +#: ../data/functions.xml.in.h:449 #, fuzzy msgid "Distance" msgstr "Matière" -#: ../data/functions.xml.in.h:443 +#: ../data/functions.xml.in.h:450 msgid "Circle of confusion or sensor size" msgstr "" -#: ../data/functions.xml.in.h:444 +#: ../data/functions.xml.in.h:451 msgid "American Wire Gauge Cross-Section Area" msgstr "" -#: ../data/functions.xml.in.h:445 +#: ../data/functions.xml.in.h:452 msgid "r:awg" msgstr "" -#: ../data/functions.xml.in.h:446 +#: ../data/functions.xml.in.h:453 msgid "" "For gauges larger than 0000 (4/0), please use negative values (00=-1, " "000=-2, 0000=-3, 00000=-4, etc). For conversion to AWG, use an equation (e." "g. awg(x) = 20 mm^2)." msgstr "" -#: ../data/functions.xml.in.h:447 +#: ../data/functions.xml.in.h:454 msgid "American Wire Gauge Diameter" msgstr "" -#: ../data/functions.xml.in.h:448 +#: ../data/functions.xml.in.h:455 msgid "r:awgd" msgstr "" -#: ../data/functions.xml.in.h:449 +#: ../data/functions.xml.in.h:456 msgid "" "For gauges larger than 0000 (4/0), please use negative values (00=-1, " "000=-2, 0000=-3, 00000=-4, etc). For conversion to AWG, use an equation (e." "g. awgd(x) = 5 mm)." msgstr "" -#: ../data/functions.xml.in.h:450 +#: ../data/functions.xml.in.h:457 msgid "Statistics" msgstr "Statistique" -#: ../data/functions.xml.in.h:451 +#: ../data/functions.xml.in.h:458 msgid "Descriptive Statistics" msgstr "Statistiques Descriptives" -#: ../data/functions.xml.in.h:452 +#: ../data/functions.xml.in.h:459 msgid "Sum (total)" msgstr "Somme (total)" -#: ../data/functions.xml.in.h:453 +#: ../data/functions.xml.in.h:460 msgid "r:total" msgstr "" -#: ../data/functions.xml.in.h:454 +#: ../data/functions.xml.in.h:461 msgid "Data" msgstr "Donnée" -#: ../data/functions.xml.in.h:455 +#: ../data/functions.xml.in.h:462 msgid "Percentile" msgstr "" -#: ../data/functions.xml.in.h:456 +#: ../data/functions.xml.in.h:463 msgid "r:percentile" msgstr "" -#: ../data/functions.xml.in.h:458 +#: ../data/functions.xml.in.h:465 #, no-c-format msgid "Percentile (%)" msgstr "" -#: ../data/functions.xml.in.h:459 +#: ../data/functions.xml.in.h:466 msgid "Quantile algorithm (as in R)" msgstr "Algorithme quantile (comme dans R)" -#: ../data/functions.xml.in.h:460 +#: ../data/functions.xml.in.h:467 msgid "r:min" msgstr "" -#: ../data/functions.xml.in.h:461 +#: ../data/functions.xml.in.h:468 msgid "Returns the lowest value." msgstr "Retourne la valeur la plus petite." -#: ../data/functions.xml.in.h:462 +#: ../data/functions.xml.in.h:469 msgid "r:max" msgstr "" -#: ../data/functions.xml.in.h:463 +#: ../data/functions.xml.in.h:470 msgid "Returns the highest value." msgstr "Retourne la plus grande valeur." -#: ../data/functions.xml.in.h:464 +#: ../data/functions.xml.in.h:471 msgid "Mode" msgstr "" -#: ../data/functions.xml.in.h:465 +#: ../data/functions.xml.in.h:472 msgid "r:mode" msgstr "" -#: ../data/functions.xml.in.h:466 +#: ../data/functions.xml.in.h:473 msgid "Returns the most frequently occurring value." msgstr "Retourne la valeur qui apparaît le plus souvent." -#: ../data/functions.xml.in.h:467 +#: ../data/functions.xml.in.h:474 msgid "Range" msgstr "" -#: ../data/functions.xml.in.h:468 +#: ../data/functions.xml.in.h:475 msgid "r:range" msgstr "" -#: ../data/functions.xml.in.h:469 +#: ../data/functions.xml.in.h:476 msgid "Calculates the difference between the min and max value." msgstr "Calcule la différence entre la valeur minimale et maximale." -#: ../data/functions.xml.in.h:470 +#: ../data/functions.xml.in.h:477 msgid "Median" msgstr "Médianne" -#: ../data/functions.xml.in.h:471 +#: ../data/functions.xml.in.h:478 msgid "r:median" msgstr "médiane" -#: ../data/functions.xml.in.h:472 +#: ../data/functions.xml.in.h:479 msgid "Quartile" msgstr "Quartile" -#: ../data/functions.xml.in.h:473 +#: ../data/functions.xml.in.h:480 msgid "r:quartile" msgstr "" -#: ../data/functions.xml.in.h:474 +#: ../data/functions.xml.in.h:481 #, fuzzy msgid "Quantile Algorithm (as in R)" msgstr "Algorithme quantile (comme dans R)" -#: ../data/functions.xml.in.h:475 +#: ../data/functions.xml.in.h:482 msgid "Decile" msgstr "Décile" -#: ../data/functions.xml.in.h:476 +#: ../data/functions.xml.in.h:483 msgid "r:decile" msgstr "" -#: ../data/functions.xml.in.h:477 +#: ../data/functions.xml.in.h:484 msgid "Interquartile Range" msgstr "Écart Interquartile" -#: ../data/functions.xml.in.h:478 +#: ../data/functions.xml.in.h:485 msgid "r:iqr" msgstr "" -#: ../data/functions.xml.in.h:479 +#: ../data/functions.xml.in.h:486 msgid "Calculates the difference between the first and third quartile." msgstr "Calcule la différence entre le premier et le troisième quartile." -#: ../data/functions.xml.in.h:480 +#: ../data/functions.xml.in.h:487 msgid "Number of Samples" msgstr "Nombre d'Échantillons" #. Number of samples -#: ../data/functions.xml.in.h:482 +#: ../data/functions.xml.in.h:489 msgid "r:number" msgstr "nombre" -#: ../data/functions.xml.in.h:483 +#: ../data/functions.xml.in.h:490 msgid "Returns the number of samples." msgstr "Retourne le nombre d'échantillons." -#: ../data/functions.xml.in.h:484 +#: ../data/functions.xml.in.h:491 msgid "Random Numbers" msgstr "Nombres aléatoires" -#: ../data/functions.xml.in.h:485 +#: ../data/functions.xml.in.h:492 msgid "Random Number" msgstr "Nombre aléatoire" -#: ../data/functions.xml.in.h:486 +#: ../data/functions.xml.in.h:493 msgid "r:rand" msgstr "" -#: ../data/functions.xml.in.h:487 +#: ../data/functions.xml.in.h:494 msgid "" "Generates a pseudo-random number. Returns a real number between 0 and 1, if " "ceil is zero (default), or an integer between 1 and (including) ceil." @@ -4894,334 +4938,334 @@ "le plafond est zéro (valeur par défaut), ou un entier entre 1 et le plafond " "(inclusivement)." -#: ../data/functions.xml.in.h:488 +#: ../data/functions.xml.in.h:495 msgid "Ceil" msgstr "Plafond" -#: ../data/functions.xml.in.h:489 +#: ../data/functions.xml.in.h:496 #, fuzzy msgid "Number of values" msgstr "Nombre d'Échantillons" -#: ../data/functions.xml.in.h:490 +#: ../data/functions.xml.in.h:497 msgid "Normally Distributed Random Number" msgstr "" -#: ../data/functions.xml.in.h:491 +#: ../data/functions.xml.in.h:498 msgid "r:randnorm" msgstr "" -#: ../data/functions.xml.in.h:492 +#: ../data/functions.xml.in.h:499 msgid "Mean" msgstr "Moyenne" -#: ../data/functions.xml.in.h:493 +#: ../data/functions.xml.in.h:500 #, fuzzy msgid "Standard deviation" msgstr "Déviation Moyenne" -#: ../data/functions.xml.in.h:494 +#: ../data/functions.xml.in.h:501 #, fuzzy msgid "Poisson Distributed Random Number" msgstr "Distribution logistique" -#: ../data/functions.xml.in.h:495 +#: ../data/functions.xml.in.h:502 msgid "r:randpoisson" msgstr "" -#: ../data/functions.xml.in.h:496 +#: ../data/functions.xml.in.h:503 msgid "Uniformly Distributed Random Number" msgstr "" -#: ../data/functions.xml.in.h:497 +#: ../data/functions.xml.in.h:504 msgid "r:randuniform" msgstr "" -#: ../data/functions.xml.in.h:498 +#: ../data/functions.xml.in.h:505 msgid "Random Number Between Limits" msgstr "Nombre Aléatoire entre les limites" -#: ../data/functions.xml.in.h:499 +#: ../data/functions.xml.in.h:506 msgid "r:randbetween" msgstr "" -#: ../data/functions.xml.in.h:500 +#: ../data/functions.xml.in.h:507 msgid "Returns an integer between (including) bottom and top." msgstr "Retourne un entier entre le bas et le haut (inclusivement)." -#: ../data/functions.xml.in.h:501 +#: ../data/functions.xml.in.h:508 msgid "Bottom" msgstr "Bas" -#: ../data/functions.xml.in.h:502 +#: ../data/functions.xml.in.h:509 msgid "Top" msgstr "Haut" -#: ../data/functions.xml.in.h:503 +#: ../data/functions.xml.in.h:510 #, fuzzy msgid "Exponential Random Number" msgstr "Nombre Aléatoire" -#: ../data/functions.xml.in.h:504 +#: ../data/functions.xml.in.h:511 msgid "r:randexp" msgstr "" -#: ../data/functions.xml.in.h:505 +#: ../data/functions.xml.in.h:512 #, fuzzy msgid "Rate parameter" msgstr "Mètre par Mètre" -#: ../data/functions.xml.in.h:506 +#: ../data/functions.xml.in.h:513 #, fuzzy msgid "Rayleigh Distributed Random Number" msgstr "Distribution logistique" -#: ../data/functions.xml.in.h:507 +#: ../data/functions.xml.in.h:514 msgid "r:randrayleigh" msgstr "" -#: ../data/functions.xml.in.h:508 +#: ../data/functions.xml.in.h:515 msgid "Sigma" msgstr "" -#: ../data/functions.xml.in.h:509 +#: ../data/functions.xml.in.h:516 msgid "Means" msgstr "Moyenne" -#: ../data/functions.xml.in.h:510 +#: ../data/functions.xml.in.h:517 msgid "r:mean,average,au:x̄" msgstr "moyenne,au:x̄" -#: ../data/functions.xml.in.h:511 +#: ../data/functions.xml.in.h:518 msgid "Harmonic Mean" msgstr "Moyenne Harmonique" -#: ../data/functions.xml.in.h:512 +#: ../data/functions.xml.in.h:519 msgid "r:harmmean" msgstr "" -#: ../data/functions.xml.in.h:513 +#: ../data/functions.xml.in.h:520 msgid "Geometric Mean" msgstr "Moyenne Géométrique" -#: ../data/functions.xml.in.h:514 +#: ../data/functions.xml.in.h:521 msgid "r:geomean" msgstr "" -#: ../data/functions.xml.in.h:515 +#: ../data/functions.xml.in.h:522 msgid "Trimmed Mean" msgstr "Moyenne Tronquée" -#: ../data/functions.xml.in.h:516 +#: ../data/functions.xml.in.h:523 msgid "r:trimmean" msgstr "" -#: ../data/functions.xml.in.h:517 +#: ../data/functions.xml.in.h:524 msgid "Trimmed percentage (at each end)" msgstr "" -#: ../data/functions.xml.in.h:518 +#: ../data/functions.xml.in.h:525 msgid "Winsorized Mean" msgstr "" -#: ../data/functions.xml.in.h:519 +#: ../data/functions.xml.in.h:526 msgid "r:winsormean" msgstr "" -#: ../data/functions.xml.in.h:520 +#: ../data/functions.xml.in.h:527 msgid "Winsorized percentage (at each end)" msgstr "" -#: ../data/functions.xml.in.h:521 +#: ../data/functions.xml.in.h:528 msgid "Weighted Mean" msgstr "Moyenne Pondérée" -#: ../data/functions.xml.in.h:522 +#: ../data/functions.xml.in.h:529 msgid "r:weighmean" msgstr "" -#: ../data/functions.xml.in.h:523 +#: ../data/functions.xml.in.h:530 msgid "Weights" msgstr "Poids" -#: ../data/functions.xml.in.h:524 +#: ../data/functions.xml.in.h:531 msgid "Quadratic Mean (RMS)" msgstr "Moyenne Quadratique (RMS)" -#: ../data/functions.xml.in.h:525 +#: ../data/functions.xml.in.h:532 msgid "r:rms" msgstr "" -#: ../data/functions.xml.in.h:526 +#: ../data/functions.xml.in.h:533 msgid "Moments" msgstr "" -#: ../data/functions.xml.in.h:527 +#: ../data/functions.xml.in.h:534 msgid "Standard Deviation (entire population)" msgstr "Écart Type (population entière)" -#: ../data/functions.xml.in.h:528 +#: ../data/functions.xml.in.h:535 msgid "r:stdevp" msgstr "" -#: ../data/functions.xml.in.h:529 +#: ../data/functions.xml.in.h:536 msgid "Standard Deviation (random sampling)" msgstr "Écart Type (échantillon aléatoire)" -#: ../data/functions.xml.in.h:530 +#: ../data/functions.xml.in.h:537 msgid "r:stdev" msgstr "" -#: ../data/functions.xml.in.h:531 +#: ../data/functions.xml.in.h:538 msgid "Variance (entire population)" msgstr "Variance (population entière)" -#: ../data/functions.xml.in.h:532 +#: ../data/functions.xml.in.h:539 msgid "r:varp" msgstr "" -#: ../data/functions.xml.in.h:533 +#: ../data/functions.xml.in.h:540 msgid "Variance (random sampling)" msgstr "Variance (échantillon aléatoire)" -#: ../data/functions.xml.in.h:534 +#: ../data/functions.xml.in.h:541 msgid "r:var" msgstr "" -#: ../data/functions.xml.in.h:535 +#: ../data/functions.xml.in.h:542 msgid "Standard Error" msgstr "Erreur Type" -#: ../data/functions.xml.in.h:536 +#: ../data/functions.xml.in.h:543 msgid "r:stderr" msgstr "" -#: ../data/functions.xml.in.h:537 +#: ../data/functions.xml.in.h:544 msgid "Mean Deviation" msgstr "Déviation Moyenne" -#: ../data/functions.xml.in.h:538 +#: ../data/functions.xml.in.h:545 msgid "r:meandev" msgstr "" -#: ../data/functions.xml.in.h:539 +#: ../data/functions.xml.in.h:546 msgid "Covariance" msgstr "" -#: ../data/functions.xml.in.h:540 +#: ../data/functions.xml.in.h:547 msgid "r:cov,r:covar" msgstr "" -#: ../data/functions.xml.in.h:541 +#: ../data/functions.xml.in.h:548 msgid "Data 1" msgstr "Donnée 1" -#: ../data/functions.xml.in.h:542 +#: ../data/functions.xml.in.h:549 msgid "Data 2" msgstr "Donnée 2" -#: ../data/functions.xml.in.h:543 +#: ../data/functions.xml.in.h:550 msgid "Pooled Variance" msgstr "" -#: ../data/functions.xml.in.h:544 +#: ../data/functions.xml.in.h:551 msgid "r:poolvar" msgstr "" -#: ../data/functions.xml.in.h:545 +#: ../data/functions.xml.in.h:552 msgid "Regression" msgstr "Régression" -#: ../data/functions.xml.in.h:546 +#: ../data/functions.xml.in.h:553 msgid "Statistical Correlation" msgstr "Corrélation Statistique" -#: ../data/functions.xml.in.h:547 +#: ../data/functions.xml.in.h:554 msgid "r:cor" msgstr "" -#: ../data/functions.xml.in.h:548 +#: ../data/functions.xml.in.h:555 msgid "Pearson's Correlation Coefficient" msgstr "Coefficient de Corrélation de Pearson" -#: ../data/functions.xml.in.h:549 +#: ../data/functions.xml.in.h:556 msgid "r:pearson,r:correl" msgstr "" -#: ../data/functions.xml.in.h:550 +#: ../data/functions.xml.in.h:557 msgid "Spearman's Rho" msgstr "" -#: ../data/functions.xml.in.h:551 +#: ../data/functions.xml.in.h:558 msgid "r:spearman" msgstr "" -#: ../data/functions.xml.in.h:552 +#: ../data/functions.xml.in.h:559 msgid "Statistical Tests" msgstr "Test Statistique" -#: ../data/functions.xml.in.h:553 +#: ../data/functions.xml.in.h:560 msgid "Unpaired T-Test" msgstr "" -#: ../data/functions.xml.in.h:554 +#: ../data/functions.xml.in.h:561 msgid "r:ttest" msgstr "" -#: ../data/functions.xml.in.h:555 +#: ../data/functions.xml.in.h:562 msgid "Paired T-Test" msgstr "Test du T" -#: ../data/functions.xml.in.h:556 +#: ../data/functions.xml.in.h:563 msgid "r:pttest" msgstr "" -#: ../data/functions.xml.in.h:557 +#: ../data/functions.xml.in.h:564 msgid "Distribution" msgstr "Loi" -#: ../data/functions.xml.in.h:558 +#: ../data/functions.xml.in.h:565 msgid "Binomial Distribution" msgstr "Loi binomiale" -#: ../data/functions.xml.in.h:559 +#: ../data/functions.xml.in.h:566 msgid "r:binomdist" msgstr "" -#: ../data/functions.xml.in.h:560 +#: ../data/functions.xml.in.h:567 msgid "" "Returns the probability mass or cumulative distribution function of the " "binomial distribution." msgstr "" -#: ../data/functions.xml.in.h:561 +#: ../data/functions.xml.in.h:568 #, fuzzy msgid "Number of successes" msgstr "Nombre de disques" -#: ../data/functions.xml.in.h:562 +#: ../data/functions.xml.in.h:569 #, fuzzy msgid "Number of trials" msgstr "Nombre d'Échantillons" -#: ../data/functions.xml.in.h:563 +#: ../data/functions.xml.in.h:570 #, fuzzy msgid "Probability" msgstr "Perméabilité" -#: ../data/functions.xml.in.h:564 +#: ../data/functions.xml.in.h:571 msgid "Cumulative" msgstr "" -#: ../data/functions.xml.in.h:565 +#: ../data/functions.xml.in.h:572 msgid "Exponential Distribution" msgstr "Loi exponentielle" -#: ../data/functions.xml.in.h:566 +#: ../data/functions.xml.in.h:573 msgid "r:expondist" msgstr "" -#: ../data/functions.xml.in.h:567 +#: ../data/functions.xml.in.h:574 #, fuzzy msgid "" "Returns the probability density or cumulative distribution function of the " @@ -5230,33 +5274,33 @@ "Retourne la densité de probabilité p(x) au x choisi pour une distribution de " "Pareto avec l'exposant et l'échelle. (utilise Gnumeric)" -#: ../data/functions.xml.in.h:568 +#: ../data/functions.xml.in.h:575 msgid "Logistic Distribution" msgstr "Loi logistique" -#: ../data/functions.xml.in.h:569 +#: ../data/functions.xml.in.h:576 msgid "r:logistic" msgstr "logistique" -#: ../data/functions.xml.in.h:570 +#: ../data/functions.xml.in.h:577 msgid "" "Returns the probability density p(x) at x for a logistic distribution with " "scale parameter. (from Gnumeric)" msgstr "" -#: ../data/functions.xml.in.h:571 +#: ../data/functions.xml.in.h:578 msgid "Scale" msgstr "Échelle" -#: ../data/functions.xml.in.h:572 +#: ../data/functions.xml.in.h:579 msgid "Normal Distribution" msgstr "Loi normale" -#: ../data/functions.xml.in.h:573 +#: ../data/functions.xml.in.h:580 msgid "r:normdist" msgstr "" -#: ../data/functions.xml.in.h:574 +#: ../data/functions.xml.in.h:581 #, fuzzy msgid "" "Returns the probability density or cumulative distribution function of a " @@ -5265,15 +5309,15 @@ "Retourne la densité de probabilité p(x) au x choisi pour une distribution de " "Pareto avec l'exposant et l'échelle. (utilise Gnumeric)" -#: ../data/functions.xml.in.h:575 +#: ../data/functions.xml.in.h:582 msgid "Pareto Distribution" msgstr "Loi de Pareto" -#: ../data/functions.xml.in.h:576 +#: ../data/functions.xml.in.h:583 msgid "r:pareto" msgstr "" -#: ../data/functions.xml.in.h:577 +#: ../data/functions.xml.in.h:584 msgid "" "Returns the probability density p(x) at x for a Pareto distribution with " "exponent and scale. (from Gnumeric)" @@ -5281,34 +5325,34 @@ "Retourne la densité de probabilité p(x) au x choisi pour une distribution de " "Pareto avec l'exposant et l'échelle. (utilise Gnumeric)" -#: ../data/functions.xml.in.h:578 +#: ../data/functions.xml.in.h:585 msgid "Poisson Distribution" msgstr "Loi de Poisson" -#: ../data/functions.xml.in.h:579 +#: ../data/functions.xml.in.h:586 msgid "r:poisson" msgstr "" -#: ../data/functions.xml.in.h:580 +#: ../data/functions.xml.in.h:587 msgid "" "Returns the probability mass or cumulative distribution of the Poisson " "distribution." msgstr "" -#: ../data/functions.xml.in.h:581 +#: ../data/functions.xml.in.h:588 #, fuzzy msgid "Number of events (x)" msgstr "Nombre d'eléments" -#: ../data/functions.xml.in.h:582 +#: ../data/functions.xml.in.h:589 msgid "Rayleigh Distribution" msgstr "Loi de Rayleigh" -#: ../data/functions.xml.in.h:583 +#: ../data/functions.xml.in.h:590 msgid "r:rayleigh" msgstr "" -#: ../data/functions.xml.in.h:584 +#: ../data/functions.xml.in.h:591 msgid "" "Returns the probability density p(x) at x for a Rayleigh distribution with " "scale parameter sigma. (from Gnumeric)" @@ -5316,33 +5360,33 @@ "Retourne la densité de probabilité p(x) au x choisi pour une distribution de " "Rayleigh avec le paramètre d'échelle sigma. (utilise Gnumeric)" -#: ../data/functions.xml.in.h:585 +#: ../data/functions.xml.in.h:592 msgid "Rayleigh Tail Distribution" msgstr "Loi de Queue de Rayleigh" -#: ../data/functions.xml.in.h:586 +#: ../data/functions.xml.in.h:593 msgid "r:rayleightail" msgstr "" -#: ../data/functions.xml.in.h:587 +#: ../data/functions.xml.in.h:594 msgid "" "Returns the probability density p(x) at x for a Rayleigh tail distribution " "with scale parameter sigma and a lower limit. (from Gnumeric)" msgstr "" -#: ../data/functions.xml.in.h:588 ../data/variables.xml.in.h:204 +#: ../data/functions.xml.in.h:595 ../data/variables.xml.in.h:204 msgid "Date & Time" msgstr "Date & Heure" -#: ../data/functions.xml.in.h:589 +#: ../data/functions.xml.in.h:596 msgid "Construct Date" msgstr "Construire date" -#: ../data/functions.xml.in.h:590 +#: ../data/functions.xml.in.h:597 msgid "r:date" msgstr "" -#: ../data/functions.xml.in.h:591 +#: ../data/functions.xml.in.h:598 msgid "" "Returns a date. Available calendars gregorian (1), hebrew (2), islamic (3), " "persian (4), indian (5), chinese (6), julian (7), milankovic (8), coptic " @@ -5351,51 +5395,51 @@ "(e.g. leap month 4 = 16)." msgstr "" -#: ../data/functions.xml.in.h:592 +#: ../data/functions.xml.in.h:599 msgid "Year" msgstr "Année" -#: ../data/functions.xml.in.h:593 ../data/units.xml.in.h:153 +#: ../data/functions.xml.in.h:600 ../data/units.xml.in.h:153 msgid "Month" msgstr "Mois" -#: ../data/functions.xml.in.h:594 ../data/units.xml.in.h:145 +#: ../data/functions.xml.in.h:601 ../data/units.xml.in.h:145 msgid "Day" msgstr "Jour" -#: ../data/functions.xml.in.h:595 +#: ../data/functions.xml.in.h:602 msgid "Calendar" msgstr "" -#: ../data/functions.xml.in.h:596 +#: ../data/functions.xml.in.h:603 msgid "Construct Date and Time" msgstr "Construire Date et Heure" -#: ../data/functions.xml.in.h:597 +#: ../data/functions.xml.in.h:604 msgid "r:datetime" msgstr "" -#: ../data/functions.xml.in.h:598 ../data/units.xml.in.h:143 +#: ../data/functions.xml.in.h:605 ../data/units.xml.in.h:143 msgid "Hour" msgstr "Heure" -#: ../data/functions.xml.in.h:599 ../data/units.xml.in.h:141 +#: ../data/functions.xml.in.h:606 ../data/units.xml.in.h:141 msgid "Minute" msgstr "" -#: ../data/functions.xml.in.h:600 ../data/units.xml.in.h:139 +#: ../data/functions.xml.in.h:607 ../data/units.xml.in.h:139 msgid "Second" msgstr "Seconde" -#: ../data/functions.xml.in.h:601 +#: ../data/functions.xml.in.h:608 msgid "Days between two dates" msgstr "Jours entre deux dates" -#: ../data/functions.xml.in.h:602 +#: ../data/functions.xml.in.h:609 msgid "r:days" msgstr "jours" -#: ../data/functions.xml.in.h:603 +#: ../data/functions.xml.in.h:610 msgid "" "Returns the number of days between two dates. Basis is the type of " "day counting you want to use: 0: US 30/360, 1: real days (default), 2: real " @@ -5406,31 +5450,31 @@ "1 : jours réels (par défaut), 2 : jours réels/360, 3 : jours réels/365 ou " "4 : Européenne 30/360." -#: ../data/functions.xml.in.h:604 +#: ../data/functions.xml.in.h:611 msgid "First date" msgstr "Première date" -#: ../data/functions.xml.in.h:605 +#: ../data/functions.xml.in.h:612 msgid "Second date" msgstr "Deuxième date" -#: ../data/functions.xml.in.h:606 +#: ../data/functions.xml.in.h:613 msgid "Day counting basis" msgstr "Base de comptage des jours" -#: ../data/functions.xml.in.h:607 +#: ../data/functions.xml.in.h:614 msgid "Financial function mode" msgstr "Mode de fonctions financières" -#: ../data/functions.xml.in.h:608 +#: ../data/functions.xml.in.h:615 msgid "Years between two dates" msgstr "Années entre deux dates" -#: ../data/functions.xml.in.h:609 +#: ../data/functions.xml.in.h:616 msgid "r:yearfrac" msgstr "" -#: ../data/functions.xml.in.h:610 +#: ../data/functions.xml.in.h:617 msgid "" "Returns the number of years (fractional) between two dates. Basis " "is the type of day counting you want to use: 0: US 30/360, 1: real days " @@ -5441,178 +5485,178 @@ "utiliser : 0 : US 30/360, 1 : jours réels (par défaut), 2 : jours réels/360, " "3 : jours réels/365 ou 4 : Européenne 30/360." -#: ../data/functions.xml.in.h:611 +#: ../data/functions.xml.in.h:618 msgid "Week of Year" msgstr "Semaine de l'Année" -#: ../data/functions.xml.in.h:612 +#: ../data/functions.xml.in.h:619 msgid "r:week" msgstr "" -#: ../data/functions.xml.in.h:613 +#: ../data/functions.xml.in.h:620 msgid "Date" msgstr "" -#: ../data/functions.xml.in.h:614 +#: ../data/functions.xml.in.h:621 msgid "Week begins on Sunday" msgstr "La semaine commence le dimanche" -#: ../data/functions.xml.in.h:615 +#: ../data/functions.xml.in.h:622 msgid "Day of Week" msgstr "Jour de la Semaine" -#: ../data/functions.xml.in.h:616 +#: ../data/functions.xml.in.h:623 msgid "r:weekday" msgstr "" -#: ../data/functions.xml.in.h:617 +#: ../data/functions.xml.in.h:624 msgid "r:month" msgstr "mois" -#: ../data/functions.xml.in.h:618 +#: ../data/functions.xml.in.h:625 msgid "Day of Month" msgstr "Jour du Mois" -#: ../data/functions.xml.in.h:619 +#: ../data/functions.xml.in.h:626 msgid "r:day" msgstr "jour" -#: ../data/functions.xml.in.h:620 +#: ../data/functions.xml.in.h:627 msgid "r:year" msgstr "" -#: ../data/functions.xml.in.h:621 +#: ../data/functions.xml.in.h:628 msgid "Day of Year" msgstr "Jour de l'année" -#: ../data/functions.xml.in.h:622 +#: ../data/functions.xml.in.h:629 msgid "r:yearday" msgstr "" -#: ../data/functions.xml.in.h:623 +#: ../data/functions.xml.in.h:630 msgid "Current Time" msgstr "Heure Actuelle" -#: ../data/functions.xml.in.h:624 +#: ../data/functions.xml.in.h:631 msgid "r:time" msgstr "" -#: ../data/functions.xml.in.h:625 +#: ../data/functions.xml.in.h:632 msgid "Time Value" msgstr "Valeur de Temps" -#: ../data/functions.xml.in.h:626 +#: ../data/functions.xml.in.h:633 msgid "r:timevalue" msgstr "" -#: ../data/functions.xml.in.h:627 +#: ../data/functions.xml.in.h:634 msgid "Returns the time part, in fractional hours, of a date and time value." msgstr "" -#: ../data/functions.xml.in.h:628 +#: ../data/functions.xml.in.h:635 msgid "Date to Unix Timestamp" msgstr "Date selon l'Horodatage Unix" -#: ../data/functions.xml.in.h:629 +#: ../data/functions.xml.in.h:636 msgid "r:timestamp" msgstr "" -#: ../data/functions.xml.in.h:630 +#: ../data/functions.xml.in.h:637 msgid "Unix Timestamp to Date" msgstr "" -#: ../data/functions.xml.in.h:631 +#: ../data/functions.xml.in.h:638 msgid "r:stamptodate,unix2date" msgstr "" -#: ../data/functions.xml.in.h:632 +#: ../data/functions.xml.in.h:639 msgid "" "Returns the local date and time represented by the specified Unix timestamp " "(seconds, excluding leap seconds, since 1970-01-01). Supports time units." msgstr "" -#: ../data/functions.xml.in.h:633 +#: ../data/functions.xml.in.h:640 msgid "Timestamp" msgstr "" -#: ../data/functions.xml.in.h:634 +#: ../data/functions.xml.in.h:641 msgid "Add Days" msgstr "Ajouter des Jours" -#: ../data/functions.xml.in.h:635 +#: ../data/functions.xml.in.h:642 msgid "r:addDays" msgstr "" -#: ../data/functions.xml.in.h:636 +#: ../data/functions.xml.in.h:643 msgid "Days" msgstr "Journées" -#: ../data/functions.xml.in.h:637 +#: ../data/functions.xml.in.h:644 msgid "Add Months" msgstr "Ajouter des Mois" -#: ../data/functions.xml.in.h:638 +#: ../data/functions.xml.in.h:645 msgid "r:addMonths" msgstr "" -#: ../data/functions.xml.in.h:639 +#: ../data/functions.xml.in.h:646 msgid "Months" msgstr "Mois" -#: ../data/functions.xml.in.h:640 +#: ../data/functions.xml.in.h:647 msgid "Add Years" msgstr "Ajouter des Années" -#: ../data/functions.xml.in.h:641 +#: ../data/functions.xml.in.h:648 msgid "r:addYears" msgstr "" -#: ../data/functions.xml.in.h:642 +#: ../data/functions.xml.in.h:649 msgid "Years" msgstr "Années" -#: ../data/functions.xml.in.h:643 +#: ../data/functions.xml.in.h:650 msgid "Add Time" msgstr "Ajouter du Temps" -#: ../data/functions.xml.in.h:644 +#: ../data/functions.xml.in.h:651 msgid "r:addTime" msgstr "" -#: ../data/functions.xml.in.h:645 +#: ../data/functions.xml.in.h:652 msgid "" "Adds a time value to a date. The value can be positive or negative, but must " "use a unit based on seconds (such as day and year). Fractions of days are " "truncated." msgstr "" -#: ../data/functions.xml.in.h:646 ../data/units.xml.in.h:138 +#: ../data/functions.xml.in.h:653 ../data/units.xml.in.h:138 msgid "Time" msgstr "Temps" -#: ../data/functions.xml.in.h:647 +#: ../data/functions.xml.in.h:654 msgid "Lunar Phase" msgstr "" -#: ../data/functions.xml.in.h:648 +#: ../data/functions.xml.in.h:655 msgid "r:lunarphase" msgstr "" -#: ../data/functions.xml.in.h:649 +#: ../data/functions.xml.in.h:656 msgid "" "Returns the lunar phase, as a number between 0 and 1, for the specified " "date. 0 represents new moon, 0.5 full moon, and 0.25 and 0.75 quarter moons." msgstr "" -#: ../data/functions.xml.in.h:650 +#: ../data/functions.xml.in.h:657 msgid "Find Lunar Phase" msgstr "" -#: ../data/functions.xml.in.h:651 +#: ../data/functions.xml.in.h:658 msgid "r:nextlunarphase" msgstr "" -#: ../data/functions.xml.in.h:652 +#: ../data/functions.xml.in.h:659 msgid "" "Returns the date when the specified lunar phase occurs. The function " "searches forward beginning at the specified date. The lunar phase are " @@ -5620,48 +5664,48 @@ "moon, and 0.25 and 0.75 quarter moons." msgstr "" -#: ../data/functions.xml.in.h:653 +#: ../data/functions.xml.in.h:660 #, fuzzy msgid "Start Date" msgstr "Construire une Matrice" -#: ../data/functions.xml.in.h:654 ../data/variables.xml.in.h:197 +#: ../data/functions.xml.in.h:661 ../data/variables.xml.in.h:197 msgid "Utilities" msgstr "Utilitaires" -#: ../data/functions.xml.in.h:655 +#: ../data/functions.xml.in.h:662 msgid "Plot Functions and Vectors" msgstr "" -#: ../data/functions.xml.in.h:656 +#: ../data/functions.xml.in.h:663 #, fuzzy msgid "r:plot" msgstr "r:planète" -#: ../data/functions.xml.in.h:657 +#: ../data/functions.xml.in.h:664 #, fuzzy msgid "Expression or vector" msgstr "Matrice ou vecteur" -#: ../data/functions.xml.in.h:658 +#: ../data/functions.xml.in.h:665 msgid "Minimum x value" msgstr "" -#: ../data/functions.xml.in.h:659 +#: ../data/functions.xml.in.h:666 #, fuzzy msgid "Maximum x value" msgstr "Variable matricielle" -#: ../data/functions.xml.in.h:660 +#: ../data/functions.xml.in.h:667 msgid "Number of samples / Step size" msgstr "Nombre d'Échantillons / Taille du pas" -#: ../data/functions.xml.in.h:661 +#: ../data/functions.xml.in.h:668 #, fuzzy msgid "X variable" msgstr "Variable de Ligne" -#: ../data/functions.xml.in.h:662 +#: ../data/functions.xml.in.h:669 msgid "" "Plots one or more expressions or vectors. Use a vector for the first " "argument to plot multiple series. Only the first argument is used for vector " @@ -5669,65 +5713,65 @@ "and y values." msgstr "" -#: ../data/functions.xml.in.h:663 +#: ../data/functions.xml.in.h:670 #, fuzzy msgid "Unicode Value" msgstr "Valeur de Temps" -#: ../data/functions.xml.in.h:664 +#: ../data/functions.xml.in.h:671 msgid "r:code" msgstr "" -#: ../data/functions.xml.in.h:665 +#: ../data/functions.xml.in.h:672 msgid "Character" msgstr "Caractère" -#: ../data/functions.xml.in.h:666 +#: ../data/functions.xml.in.h:673 #, fuzzy msgid "Unicode Character" msgstr "Caractère" -#: ../data/functions.xml.in.h:667 +#: ../data/functions.xml.in.h:674 msgid "r:char" msgstr "" -#: ../data/functions.xml.in.h:668 +#: ../data/functions.xml.in.h:675 msgid "Length of string" msgstr "Longueur de la chaîne" -#: ../data/functions.xml.in.h:669 +#: ../data/functions.xml.in.h:676 msgid "r:len" msgstr "" -#: ../data/functions.xml.in.h:670 +#: ../data/functions.xml.in.h:677 msgid "Text" msgstr "Texte" -#: ../data/functions.xml.in.h:671 +#: ../data/functions.xml.in.h:678 msgid "Concatenate Strings" msgstr "Concaténer les chaînes" -#: ../data/functions.xml.in.h:672 +#: ../data/functions.xml.in.h:679 msgid "r:concatenate" msgstr "" -#: ../data/functions.xml.in.h:673 +#: ../data/functions.xml.in.h:680 msgid "Text string 1" msgstr "Chaîne de texte 1" -#: ../data/functions.xml.in.h:674 +#: ../data/functions.xml.in.h:681 msgid "Text string 2" msgstr "Chaîne de texte 2" -#: ../data/functions.xml.in.h:675 +#: ../data/functions.xml.in.h:682 msgid "Replace" msgstr "Remplacer" -#: ../data/functions.xml.in.h:676 +#: ../data/functions.xml.in.h:683 msgid "r:replace" msgstr "" -#: ../data/functions.xml.in.h:677 +#: ../data/functions.xml.in.h:684 msgid "" "Replaces a certain value in an expression with a new value. The expression " "is calculated before the replacement if the fourth argument is true." @@ -5736,31 +5780,31 @@ "L'expression est calculée avant le remplacement si le quatrième argument est " "vrai." -#: ../data/functions.xml.in.h:678 +#: ../data/functions.xml.in.h:685 msgid "Expression" msgstr "" -#: ../data/functions.xml.in.h:679 +#: ../data/functions.xml.in.h:686 msgid "Original value" msgstr "Valeur originale" -#: ../data/functions.xml.in.h:680 +#: ../data/functions.xml.in.h:687 msgid "New value" msgstr "Nouvelle valeur" -#: ../data/functions.xml.in.h:681 +#: ../data/functions.xml.in.h:688 msgid "Precalculate expression" msgstr "Expression précalculée" -#: ../data/functions.xml.in.h:682 +#: ../data/functions.xml.in.h:689 msgid "Strip Units" msgstr "" -#: ../data/functions.xml.in.h:683 +#: ../data/functions.xml.in.h:690 msgid "r:nounit,strip_units" msgstr "" -#: ../data/functions.xml.in.h:684 +#: ../data/functions.xml.in.h:691 msgid "" "Removes all units from an expression. The expression is calculated before " "the removal." @@ -5768,400 +5812,400 @@ "Enlève toutes les unités de l'expression. L'expression est calculée avant la " "suppression." -#: ../data/functions.xml.in.h:685 +#: ../data/functions.xml.in.h:692 msgid "Process Vector Elements" msgstr "Calculer les Éléments de Vecteur" -#: ../data/functions.xml.in.h:686 +#: ../data/functions.xml.in.h:693 msgid "r:process" msgstr "" -#: ../data/functions.xml.in.h:687 +#: ../data/functions.xml.in.h:694 msgid "Element variable" msgstr "Variable Élément" -#: ../data/functions.xml.in.h:688 +#: ../data/functions.xml.in.h:695 msgid "Index variable" msgstr "Variable d'index" -#: ../data/functions.xml.in.h:689 +#: ../data/functions.xml.in.h:696 msgid "Vector variable" msgstr "Variable vecteur" -#: ../data/functions.xml.in.h:690 +#: ../data/functions.xml.in.h:697 msgid "Process Matrix Elements" msgstr "Calculer les Éléments de Matrice" -#: ../data/functions.xml.in.h:691 +#: ../data/functions.xml.in.h:698 msgid "r:processm" msgstr "" -#: ../data/functions.xml.in.h:692 +#: ../data/functions.xml.in.h:699 msgid "Row variable" msgstr "Variable de Ligne" -#: ../data/functions.xml.in.h:693 +#: ../data/functions.xml.in.h:700 msgid "Column variable" msgstr "Variable de colonne" -#: ../data/functions.xml.in.h:694 +#: ../data/functions.xml.in.h:701 msgid "Matrix variable" msgstr "Variable matricielle" -#: ../data/functions.xml.in.h:695 +#: ../data/functions.xml.in.h:702 msgid "Custom Sum of Elements" msgstr "Somme d'éléments personnalisée" -#: ../data/functions.xml.in.h:696 +#: ../data/functions.xml.in.h:703 msgid "r:csum" msgstr "" -#: ../data/functions.xml.in.h:697 +#: ../data/functions.xml.in.h:704 msgid "First element" msgstr "Premier élément" -#: ../data/functions.xml.in.h:698 +#: ../data/functions.xml.in.h:705 msgid "Last element" msgstr "Dernier élément" -#: ../data/functions.xml.in.h:699 +#: ../data/functions.xml.in.h:706 msgid "Initial value" msgstr "Valeur initiale" -#: ../data/functions.xml.in.h:700 +#: ../data/functions.xml.in.h:707 msgid "Value variable" msgstr "Variable valeur" -#: ../data/functions.xml.in.h:701 +#: ../data/functions.xml.in.h:708 msgid "Select Vector Elements" msgstr "Sélectionner les Éléments de Vecteur" -#: ../data/functions.xml.in.h:702 +#: ../data/functions.xml.in.h:709 msgid "r:select" msgstr "" -#: ../data/functions.xml.in.h:703 +#: ../data/functions.xml.in.h:710 msgid "Condition" msgstr "" -#: ../data/functions.xml.in.h:704 +#: ../data/functions.xml.in.h:711 msgid "Select first match" msgstr "Sélectionner la première occurrence" -#: ../data/functions.xml.in.h:705 +#: ../data/functions.xml.in.h:712 msgid "r:function" msgstr "fonction" -#: ../data/functions.xml.in.h:706 +#: ../data/functions.xml.in.h:713 msgid "Arguments" msgstr "Arguments" -#: ../data/functions.xml.in.h:707 +#: ../data/functions.xml.in.h:714 msgid "Title" msgstr "Titre" -#: ../data/functions.xml.in.h:708 +#: ../data/functions.xml.in.h:715 msgid "r:title" msgstr "" -#: ../data/functions.xml.in.h:710 +#: ../data/functions.xml.in.h:717 msgid "Display Error" msgstr "Afficher l'erreur" -#: ../data/functions.xml.in.h:711 +#: ../data/functions.xml.in.h:718 msgid "r:error" msgstr "erreur" -#: ../data/functions.xml.in.h:712 +#: ../data/functions.xml.in.h:719 msgid "Message" msgstr "" -#: ../data/functions.xml.in.h:713 +#: ../data/functions.xml.in.h:720 msgid "Display Warning" msgstr "Afficher l'avertissement" -#: ../data/functions.xml.in.h:714 +#: ../data/functions.xml.in.h:721 msgid "r:warning" msgstr "" -#: ../data/functions.xml.in.h:715 +#: ../data/functions.xml.in.h:722 msgid "Display Message" msgstr "Afficher le message" -#: ../data/functions.xml.in.h:716 +#: ../data/functions.xml.in.h:723 msgid "r:message" msgstr "" -#: ../data/functions.xml.in.h:717 +#: ../data/functions.xml.in.h:724 msgid "Save as Variable" msgstr "Enregistrer comme variable" -#: ../data/functions.xml.in.h:718 +#: ../data/functions.xml.in.h:725 msgid "r:save" msgstr "" -#: ../data/functions.xml.in.h:719 +#: ../data/functions.xml.in.h:726 msgid "Category" msgstr "Catégorie" -#: ../data/functions.xml.in.h:720 +#: ../data/functions.xml.in.h:727 msgid "RPN Stack Register" msgstr "Registre de Pile NPI" -#: ../data/functions.xml.in.h:721 +#: ../data/functions.xml.in.h:728 msgid "r:register" msgstr "" -#: ../data/functions.xml.in.h:722 +#: ../data/functions.xml.in.h:729 msgid "Returns the value of a RPN stack register." msgstr "Retourne la valeur d'un registre de pile NPI." -#: ../data/functions.xml.in.h:723 +#: ../data/functions.xml.in.h:730 msgid "Index" msgstr "" -#: ../data/functions.xml.in.h:724 +#: ../data/functions.xml.in.h:731 msgid "RPN Stack Vector" msgstr "Vecteur de Pile NPI" -#: ../data/functions.xml.in.h:725 +#: ../data/functions.xml.in.h:732 msgid "r:stack" msgstr "" -#: ../data/functions.xml.in.h:726 +#: ../data/functions.xml.in.h:733 msgid "Returns the RPN stack as a vector." msgstr "Retourne la pile NPI sous forme de vecteur." -#: ../data/functions.xml.in.h:727 +#: ../data/functions.xml.in.h:734 msgid "Is Number" msgstr "" -#: ../data/functions.xml.in.h:728 +#: ../data/functions.xml.in.h:735 msgid "r:isNumber" msgstr "" -#: ../data/functions.xml.in.h:729 +#: ../data/functions.xml.in.h:736 msgid "Is Real" msgstr "" -#: ../data/functions.xml.in.h:730 +#: ../data/functions.xml.in.h:737 msgid "r:isReal" msgstr "" -#: ../data/functions.xml.in.h:731 +#: ../data/functions.xml.in.h:738 msgid "Is Rational" msgstr "" -#: ../data/functions.xml.in.h:732 +#: ../data/functions.xml.in.h:739 msgid "r:isRational" msgstr "" -#: ../data/functions.xml.in.h:733 +#: ../data/functions.xml.in.h:740 msgid "Is Integer" msgstr "" -#: ../data/functions.xml.in.h:734 +#: ../data/functions.xml.in.h:741 msgid "r:isInteger" msgstr "" -#: ../data/functions.xml.in.h:735 +#: ../data/functions.xml.in.h:742 msgid "Represents Number" msgstr "" -#: ../data/functions.xml.in.h:736 +#: ../data/functions.xml.in.h:743 msgid "r:representsNumber" msgstr "" -#: ../data/functions.xml.in.h:737 +#: ../data/functions.xml.in.h:744 msgid "Represents Real" msgstr "" -#: ../data/functions.xml.in.h:738 +#: ../data/functions.xml.in.h:745 msgid "r:representsReal" msgstr "" -#: ../data/functions.xml.in.h:739 +#: ../data/functions.xml.in.h:746 msgid "Represents Rational" msgstr "" -#: ../data/functions.xml.in.h:740 +#: ../data/functions.xml.in.h:747 msgid "r:representsRational" msgstr "" -#: ../data/functions.xml.in.h:741 +#: ../data/functions.xml.in.h:748 msgid "Represents Integer" msgstr "" -#: ../data/functions.xml.in.h:742 +#: ../data/functions.xml.in.h:749 msgid "r:representsInteger" msgstr "" -#: ../data/functions.xml.in.h:743 +#: ../data/functions.xml.in.h:750 msgid "Interval" msgstr "Intervalle" -#: ../data/functions.xml.in.h:744 +#: ../data/functions.xml.in.h:751 msgid "r:interval" msgstr "" -#: ../data/functions.xml.in.h:745 +#: ../data/functions.xml.in.h:752 #, fuzzy msgid "Lower endpoint" msgstr "Limite inférieure" -#: ../data/functions.xml.in.h:746 +#: ../data/functions.xml.in.h:753 #, fuzzy msgid "Upper endpoint" msgstr "Limite Supérieure" -#: ../data/functions.xml.in.h:747 +#: ../data/functions.xml.in.h:754 msgid "Uncertainty" msgstr "Incertitudes" -#: ../data/functions.xml.in.h:748 +#: ../data/functions.xml.in.h:755 msgid "r:uncertainty" msgstr "" -#: ../data/functions.xml.in.h:749 +#: ../data/functions.xml.in.h:756 msgid "Uncertainty is relative" msgstr "" -#: ../data/functions.xml.in.h:750 +#: ../data/functions.xml.in.h:757 msgid "Logical" msgstr "Logique" -#: ../data/functions.xml.in.h:751 +#: ../data/functions.xml.in.h:758 msgid "For...Do" msgstr "For...Do (Pour...Faire)" -#: ../data/functions.xml.in.h:752 +#: ../data/functions.xml.in.h:759 msgid "r:for" msgstr "pour" -#: ../data/functions.xml.in.h:753 +#: ../data/functions.xml.in.h:760 msgid "Initial value of counter" msgstr "Valeur initiale du compteur" -#: ../data/functions.xml.in.h:754 +#: ../data/functions.xml.in.h:761 msgid "Counter variable" msgstr "Variable de compteur" -#: ../data/functions.xml.in.h:755 +#: ../data/functions.xml.in.h:762 msgid "For condition" msgstr "Condition de boucle for" -#: ../data/functions.xml.in.h:756 +#: ../data/functions.xml.in.h:763 msgid "Counter update function" msgstr "Fonction d'incrémentation du compteur" -#: ../data/functions.xml.in.h:757 +#: ../data/functions.xml.in.h:764 msgid "Do function" msgstr "Fonction 'faire'" -#: ../data/functions.xml.in.h:758 +#: ../data/functions.xml.in.h:765 msgid "If...Then...Else" msgstr "Si...Sinon..Alors" -#: ../data/functions.xml.in.h:759 +#: ../data/functions.xml.in.h:766 msgid "r:if" msgstr "si" -#: ../data/functions.xml.in.h:760 +#: ../data/functions.xml.in.h:767 #, fuzzy msgid "" "Tests a condition and returns a value depending on the result. Vectors can " "be used for argument 1 and 2, instead of nested functions." msgstr "Teste une condition et retourne une valeur en fonction du résultat." -#: ../data/functions.xml.in.h:761 +#: ../data/functions.xml.in.h:768 msgid "Expression if condition is met" msgstr "Expression si la condition est remplie" -#: ../data/functions.xml.in.h:762 +#: ../data/functions.xml.in.h:769 msgid "Expression if condition is NOT met" msgstr "Expression si la condition N'EST PAS remplie" -#: ../data/functions.xml.in.h:763 +#: ../data/functions.xml.in.h:770 msgid "Assume false if not true" msgstr "" -#: ../data/functions.xml.in.h:764 +#: ../data/functions.xml.in.h:771 msgid "Bitwise Exclusive OR" msgstr "OU exclusif bit à bit" -#: ../data/functions.xml.in.h:765 +#: ../data/functions.xml.in.h:772 msgid "r:xor" msgstr "" -#: ../data/functions.xml.in.h:766 +#: ../data/functions.xml.in.h:773 msgid "Value 1" msgstr "Valeur 1" -#: ../data/functions.xml.in.h:767 +#: ../data/functions.xml.in.h:774 msgid "Value 2" msgstr "Valeur 2" -#: ../data/functions.xml.in.h:768 +#: ../data/functions.xml.in.h:775 msgid "Logical Exclusive OR" msgstr "OU Exclusif Logique" -#: ../data/functions.xml.in.h:769 +#: ../data/functions.xml.in.h:776 msgid "r:lxor" msgstr "" -#: ../data/functions.xml.in.h:770 +#: ../data/functions.xml.in.h:777 msgid "Bitwise Shift" msgstr "Décalage de bits" -#: ../data/functions.xml.in.h:771 +#: ../data/functions.xml.in.h:778 msgid "" "Applies logical or arithmetic bitwise shift to an integer. The second " "argument specifies the number of steps that each binary bit is shifted to " "the left (use negative values for right shift)." msgstr "" -#: ../data/functions.xml.in.h:772 +#: ../data/functions.xml.in.h:779 msgid "r:shift" msgstr "" -#: ../data/functions.xml.in.h:773 +#: ../data/functions.xml.in.h:780 msgid "Steps" msgstr "" -#: ../data/functions.xml.in.h:774 +#: ../data/functions.xml.in.h:781 msgid "Arithmetic shift using two's complement" msgstr "" -#: ../data/functions.xml.in.h:775 +#: ../data/functions.xml.in.h:782 msgid "Bitwise Complement (Not)" msgstr "" -#: ../data/functions.xml.in.h:776 +#: ../data/functions.xml.in.h:783 msgid "" "Applies bitwise NOT to an integer of specified bit width and signedness (use " "1 for signed and 0 for unsigned). If bit width is zero, the smallest " "necessary number of bits (of 8, 16, 32, 64, 128, ...) will be used." msgstr "" -#: ../data/functions.xml.in.h:777 +#: ../data/functions.xml.in.h:784 msgid "r:bitcmp" msgstr "" -#: ../data/functions.xml.in.h:778 +#: ../data/functions.xml.in.h:785 #, fuzzy msgid "Bit Width" msgstr "Largeur" -#: ../data/functions.xml.in.h:779 +#: ../data/functions.xml.in.h:786 #, fuzzy msgid "Signed Integer" msgstr "Intégrale" -#: ../data/functions.xml.in.h:780 +#: ../data/functions.xml.in.h:787 msgid "Bit Rotation" msgstr "" -#: ../data/functions.xml.in.h:781 +#: ../data/functions.xml.in.h:788 msgid "" "Applies circular bitwise shift to an integer of specified bit width and " "signedness (use 1 for signed and 0 for unsigned). The second argument " @@ -6170,23 +6214,23 @@ "necessary number of bits (of 8, 16, 32, 64, 128, ...) will be used." msgstr "" -#: ../data/functions.xml.in.h:782 +#: ../data/functions.xml.in.h:789 msgid "r:bitrot" msgstr "" -#: ../data/functions.xml.in.h:783 +#: ../data/functions.xml.in.h:790 msgid "Algebra" msgstr "Algèbre" -#: ../data/functions.xml.in.h:784 +#: ../data/functions.xml.in.h:791 msgid "Summation" msgstr "Somme" -#: ../data/functions.xml.in.h:785 +#: ../data/functions.xml.in.h:792 msgid "au:Σ,r:sum" msgstr "" -#: ../data/functions.xml.in.h:786 +#: ../data/functions.xml.in.h:793 #, fuzzy msgid "" "Corresponds to the summation symbol. Adds terms for each x ranging from the " @@ -6195,27 +6239,27 @@ "Correspond au symbole de la somme. Ajoute les termes pour chaque x allant de " "la borne inférieure à la borne supérieure." -#: ../data/functions.xml.in.h:787 +#: ../data/functions.xml.in.h:794 msgid "Term expression" msgstr "" -#: ../data/functions.xml.in.h:788 +#: ../data/functions.xml.in.h:795 msgid "Lower limit (i)" msgstr "Limite inférieure (i)" -#: ../data/functions.xml.in.h:789 +#: ../data/functions.xml.in.h:796 msgid "Upper limit (n)" msgstr "Limite Supérieure (n)" -#: ../data/functions.xml.in.h:790 +#: ../data/functions.xml.in.h:797 msgid "Product of a sequence" msgstr "Produit" -#: ../data/functions.xml.in.h:791 +#: ../data/functions.xml.in.h:798 msgid "au:Π,r:product" msgstr "" -#: ../data/functions.xml.in.h:792 +#: ../data/functions.xml.in.h:799 msgid "" "Corresponds to the product symbol. Multiplies factors for each x ranging " "from the lower to the upper limit." @@ -6223,74 +6267,74 @@ "Correspond au symbole du produit. Multiplie les facteurs pour chaque x " "allant de la la limite inférieure à la limite supérieure." -#: ../data/functions.xml.in.h:793 +#: ../data/functions.xml.in.h:800 msgid "Factor expression" msgstr "Factoriser l'expression" -#: ../data/functions.xml.in.h:794 +#: ../data/functions.xml.in.h:801 msgid "Solve for multiple variables" msgstr "Résoudre pour des variables multiples" -#: ../data/functions.xml.in.h:795 +#: ../data/functions.xml.in.h:802 msgid "r:multisolve" msgstr "" -#: ../data/functions.xml.in.h:796 +#: ../data/functions.xml.in.h:803 msgid "Equation vector" msgstr "Vecteur d'équation" -#: ../data/functions.xml.in.h:797 +#: ../data/functions.xml.in.h:804 msgid "Variable vector" msgstr "Variable vecteur" -#: ../data/functions.xml.in.h:798 +#: ../data/functions.xml.in.h:805 msgid "Solve equation" msgstr "Résoudre l'équation" -#: ../data/functions.xml.in.h:799 +#: ../data/functions.xml.in.h:806 msgid "r:solve" msgstr "" -#: ../data/functions.xml.in.h:800 +#: ../data/functions.xml.in.h:807 msgid "Equation" msgstr "Équation" -#: ../data/functions.xml.in.h:801 +#: ../data/functions.xml.in.h:808 msgid "With respect to" msgstr "" -#: ../data/functions.xml.in.h:802 +#: ../data/functions.xml.in.h:809 msgid "Solve differential equation" msgstr "Résoudre l'Équation Différentielle" -#: ../data/functions.xml.in.h:803 +#: ../data/functions.xml.in.h:810 msgid "r:dsolve" msgstr "" -#: ../data/functions.xml.in.h:804 +#: ../data/functions.xml.in.h:811 msgid "Initial condition: function value (y)" msgstr "" -#: ../data/functions.xml.in.h:805 +#: ../data/functions.xml.in.h:812 msgid "Initial condition: argument value (x)" msgstr "" -#: ../data/functions.xml.in.h:806 +#: ../data/functions.xml.in.h:813 msgid "" "Solves a differential equation and returns the value of y(x). The derivative " "in the equation should be in the format diff(y, x). Only first-order " "differential equations are currently supported." msgstr "" -#: ../data/functions.xml.in.h:807 +#: ../data/functions.xml.in.h:814 msgid "Solve for two variables" msgstr "Résoudre pour deux variables" -#: ../data/functions.xml.in.h:808 +#: ../data/functions.xml.in.h:815 msgid "r:solve2" msgstr "" -#: ../data/functions.xml.in.h:809 +#: ../data/functions.xml.in.h:816 msgid "" "Solves two equations with two unknown variables. Returns the value of the " "first variable." @@ -6298,509 +6342,535 @@ "Résout deux équations à deux inconnues. Retourne la valeur de la première " "variable." -#: ../data/functions.xml.in.h:810 +#: ../data/functions.xml.in.h:817 msgid "Equation 1" msgstr "Équation 2" -#: ../data/functions.xml.in.h:811 +#: ../data/functions.xml.in.h:818 msgid "Equation 2" msgstr "Équation 2" -#: ../data/functions.xml.in.h:812 +#: ../data/functions.xml.in.h:819 msgid "Variable 1" msgstr "Variable 1" -#: ../data/functions.xml.in.h:813 +#: ../data/functions.xml.in.h:820 msgid "Variable 2" msgstr "Variable 2" -#: ../data/functions.xml.in.h:814 +#: ../data/functions.xml.in.h:821 msgid "Find Linear Function" msgstr "Trouver une fonction affine" -#: ../data/functions.xml.in.h:815 +#: ../data/functions.xml.in.h:822 msgid "r:linearfunction" msgstr "" -#: ../data/functions.xml.in.h:816 +#: ../data/functions.xml.in.h:823 msgid "" "Finds the linear function for the straight line between two distinct points." msgstr "" "Trouve la fonction affine pour la ligne droite passant entre deux points " "distincts." -#: ../data/functions.xml.in.h:817 +#: ../data/functions.xml.in.h:824 msgid "x1" msgstr "" -#: ../data/functions.xml.in.h:818 +#: ../data/functions.xml.in.h:825 msgid "y1" msgstr "" -#: ../data/functions.xml.in.h:819 +#: ../data/functions.xml.in.h:826 msgid "x2" msgstr "" -#: ../data/functions.xml.in.h:820 +#: ../data/functions.xml.in.h:827 msgid "y2" msgstr "" -#: ../data/functions.xml.in.h:821 +#: ../data/functions.xml.in.h:828 msgid "Calculus" msgstr "Calcul" -#: ../data/functions.xml.in.h:822 +#: ../data/functions.xml.in.h:829 msgid "Differentiate" msgstr "Dérivée" -#: ../data/functions.xml.in.h:823 +#: ../data/functions.xml.in.h:830 msgid "r:diff,derivative" msgstr "diff,dérivée" -#: ../data/functions.xml.in.h:824 +#: ../data/functions.xml.in.h:831 #, fuzzy msgid "Variable value" msgstr "Variable vecteur" -#: ../data/functions.xml.in.h:825 +#: ../data/functions.xml.in.h:832 msgid "Integrate" msgstr "Intégrale" -#: ../data/functions.xml.in.h:826 +#: ../data/functions.xml.in.h:833 msgid "r:integrate,integral,au:∫" msgstr "integrér,intégrale,au:∫" -#: ../data/functions.xml.in.h:827 +#: ../data/functions.xml.in.h:834 msgid "Variable of integration" msgstr "Variable d'intégration" -#: ../data/functions.xml.in.h:828 +#: ../data/functions.xml.in.h:835 #, fuzzy msgid "Force numerical integration" msgstr "Variable d'intégration" -#: ../data/functions.xml.in.h:829 +#: ../data/functions.xml.in.h:836 #, fuzzy msgid "Romberg Integration" msgstr "Variable d'intégration" -#: ../data/functions.xml.in.h:830 +#: ../data/functions.xml.in.h:837 #, fuzzy msgid "r:romberg" msgstr "nombre" -#: ../data/functions.xml.in.h:831 +#: ../data/functions.xml.in.h:838 #, fuzzy msgid "Min iterations" msgstr "Déviation Moyenne" -#: ../data/functions.xml.in.h:832 +#: ../data/functions.xml.in.h:839 #, fuzzy msgid "Max iterations" msgstr "Fraction massique" -#: ../data/functions.xml.in.h:833 +#: ../data/functions.xml.in.h:840 #, fuzzy msgid "Monte Carlo Integration" msgstr "Variable d'intégration" -#: ../data/functions.xml.in.h:834 +#: ../data/functions.xml.in.h:841 #, fuzzy msgid "r:montecarlo" msgstr "mois" -#: ../data/functions.xml.in.h:835 +#: ../data/functions.xml.in.h:842 #, fuzzy msgid "Number of samples" msgstr "Nombre d'Échantillons" -#: ../data/functions.xml.in.h:836 +#: ../data/functions.xml.in.h:843 msgid "Limit" msgstr "Limite" -#: ../data/functions.xml.in.h:837 +#: ../data/functions.xml.in.h:844 msgid "" "Returns the two-sided limit of the function if direction is zero, limit from " "left (below) if direction is -1, or limit from right (above) if direction is " "+1." msgstr "" -#: ../data/functions.xml.in.h:838 +#: ../data/functions.xml.in.h:845 #, fuzzy msgid "r:limit" msgstr "limites" -#: ../data/functions.xml.in.h:839 +#: ../data/functions.xml.in.h:846 msgid "Value to approach" msgstr "" -#: ../data/functions.xml.in.h:840 +#: ../data/functions.xml.in.h:847 #, fuzzy msgid "Direction" msgstr "Durée" -#: ../data/functions.xml.in.h:841 +#: ../data/functions.xml.in.h:848 msgid "Extreme Values" msgstr "Valeurs extrêmes" -#: ../data/functions.xml.in.h:842 +#: ../data/functions.xml.in.h:849 msgid "r:extremum" msgstr "" -#: ../data/functions.xml.in.h:843 +#: ../data/functions.xml.in.h:850 #, fuzzy msgid "Named Integrals" msgstr "Entiers" -#: ../data/functions.xml.in.h:844 +#: ../data/functions.xml.in.h:851 msgid "Logarithmic Integral" msgstr "" -#: ../data/functions.xml.in.h:845 +#: ../data/functions.xml.in.h:852 #, fuzzy msgid "rc:li,logint" msgstr "logistique" -#: ../data/functions.xml.in.h:846 +#: ../data/functions.xml.in.h:853 msgid "The integral of 1/ln(x)." msgstr "" -#: ../data/functions.xml.in.h:847 +#: ../data/functions.xml.in.h:854 #, fuzzy msgid "Exponential Integral" msgstr "Exponentielle (e^x)" -#: ../data/functions.xml.in.h:848 +#: ../data/functions.xml.in.h:855 msgid "rc:Ei,expint" msgstr "" -#: ../data/functions.xml.in.h:849 +#: ../data/functions.xml.in.h:856 msgid "The integral of e^x/x." msgstr "" -#: ../data/functions.xml.in.h:850 +#: ../data/functions.xml.in.h:857 #, fuzzy msgid "Sine Integral" msgstr "Intégrale" -#: ../data/functions.xml.in.h:851 +#: ../data/functions.xml.in.h:858 msgid "rc:Si,sinint" msgstr "" -#: ../data/functions.xml.in.h:852 +#: ../data/functions.xml.in.h:859 msgid "The integral of sin(x)/x." msgstr "" -#: ../data/functions.xml.in.h:853 +#: ../data/functions.xml.in.h:860 #, fuzzy msgid "Cosine Integral" msgstr "Intégrale" -#: ../data/functions.xml.in.h:854 +#: ../data/functions.xml.in.h:861 msgid "rc:Ci,cosint" msgstr "" -#: ../data/functions.xml.in.h:855 +#: ../data/functions.xml.in.h:862 msgid "The integral of cos(x)/x." msgstr "" -#: ../data/functions.xml.in.h:856 +#: ../data/functions.xml.in.h:863 #, fuzzy msgid "Hyperbolic Sine Integral" msgstr "Sinus Hyperbolique" -#: ../data/functions.xml.in.h:857 +#: ../data/functions.xml.in.h:864 msgid "rc:Shi,sinhint" msgstr "" -#: ../data/functions.xml.in.h:858 +#: ../data/functions.xml.in.h:865 msgid "The integral of sinh(x)/x." msgstr "" -#: ../data/functions.xml.in.h:859 +#: ../data/functions.xml.in.h:866 #, fuzzy msgid "Hyperbolic Cosine Integral" msgstr "Cosinus Hyperbolique" -#: ../data/functions.xml.in.h:860 +#: ../data/functions.xml.in.h:867 msgid "rc:Chi,coshint" msgstr "" -#: ../data/functions.xml.in.h:861 +#: ../data/functions.xml.in.h:868 msgid "The integral of cosh(x)/x." msgstr "" -#: ../data/functions.xml.in.h:862 +#: ../data/functions.xml.in.h:869 +#, fuzzy +msgid "Fresnel Integral S" +msgstr "Intégrale" + +#: ../data/functions.xml.in.h:870 +msgid "r:fresnels" +msgstr "" + +#: ../data/functions.xml.in.h:871 +msgid "The integral of sin(pi*x^2/2)." +msgstr "" + +#: ../data/functions.xml.in.h:872 +#, fuzzy +msgid "Fresnel Integral C" +msgstr "Intégrale" + +#: ../data/functions.xml.in.h:873 +msgid "r:fresnelc" +msgstr "" + +#: ../data/functions.xml.in.h:874 +msgid "The integral of cos(pi*x^2/2)." +msgstr "" + +#: ../data/functions.xml.in.h:875 #, fuzzy msgid "Upper Incomplete Gamma Function" msgstr "Fonction Gamma" -#: ../data/functions.xml.in.h:863 +#: ../data/functions.xml.in.h:876 msgid "r:igamma" msgstr "" -#: ../data/functions.xml.in.h:864 +#: ../data/functions.xml.in.h:877 #, fuzzy msgid "Lower Incomplete Gamma Function" msgstr "Fonction Gamma" -#: ../data/functions.xml.in.h:865 +#: ../data/functions.xml.in.h:878 msgid "r:gammainc" msgstr "" -#: ../data/functions.xml.in.h:866 +#: ../data/functions.xml.in.h:879 msgid "Geometry" msgstr "Géométrie" -#: ../data/functions.xml.in.h:867 +#: ../data/functions.xml.in.h:880 msgid "Triangle" msgstr "" -#: ../data/functions.xml.in.h:868 +#: ../data/functions.xml.in.h:881 msgid "Hypotenuse" msgstr "Hypoténuse" -#: ../data/functions.xml.in.h:869 +#: ../data/functions.xml.in.h:882 msgid "r:hypot" msgstr "" -#: ../data/functions.xml.in.h:870 +#: ../data/functions.xml.in.h:883 msgid "Side A" msgstr "Côté A" -#: ../data/functions.xml.in.h:871 +#: ../data/functions.xml.in.h:884 msgid "Side B" msgstr "Côté B" -#: ../data/functions.xml.in.h:872 +#: ../data/functions.xml.in.h:885 msgid "Triangle Area" msgstr "Aire de Triangle" -#: ../data/functions.xml.in.h:873 +#: ../data/functions.xml.in.h:886 msgid "r:triangle" msgstr "" -#: ../data/functions.xml.in.h:874 +#: ../data/functions.xml.in.h:887 msgid "Height" msgstr "Hauteur" -#: ../data/functions.xml.in.h:875 +#: ../data/functions.xml.in.h:888 msgid "Triangle Perimeter" msgstr "Périmètre de Triangle" -#: ../data/functions.xml.in.h:876 +#: ../data/functions.xml.in.h:889 msgid "r:triangle_perimeter" msgstr "" -#: ../data/functions.xml.in.h:877 +#: ../data/functions.xml.in.h:890 msgid "Side C" msgstr "Côté C" -#: ../data/functions.xml.in.h:878 +#: ../data/functions.xml.in.h:891 msgid "Circle" msgstr "Cercle" -#: ../data/functions.xml.in.h:879 +#: ../data/functions.xml.in.h:892 msgid "Circle Area" msgstr "Aire d'un cercle" -#: ../data/functions.xml.in.h:880 +#: ../data/functions.xml.in.h:893 msgid "r:circle" msgstr "cercle" -#: ../data/functions.xml.in.h:881 +#: ../data/functions.xml.in.h:894 msgid "Calculates the area of a circle using the radius" msgstr "Calcule l'aire d'un cercle d'après son rayon" -#: ../data/functions.xml.in.h:882 +#: ../data/functions.xml.in.h:895 msgid "Radius" msgstr "Rayon" -#: ../data/functions.xml.in.h:883 +#: ../data/functions.xml.in.h:896 msgid "Circle Circumference" msgstr "Circonférence d'un cercle" -#: ../data/functions.xml.in.h:884 +#: ../data/functions.xml.in.h:897 msgid "r:circumference" msgstr "circonférence" -#: ../data/functions.xml.in.h:885 +#: ../data/functions.xml.in.h:898 msgid "Cylinder" msgstr "Cylindre" -#: ../data/functions.xml.in.h:886 +#: ../data/functions.xml.in.h:899 msgid "Cylinder Volume" msgstr "Volume d'un cylindre" -#: ../data/functions.xml.in.h:887 +#: ../data/functions.xml.in.h:900 msgid "r:cylinder" msgstr "cylindre" -#: ../data/functions.xml.in.h:888 +#: ../data/functions.xml.in.h:901 msgid "Surface Area of Cylinder" msgstr "Aire de la Surface d'un Cylindre" -#: ../data/functions.xml.in.h:889 +#: ../data/functions.xml.in.h:902 msgid "r:cylinder_sa" msgstr "" -#: ../data/functions.xml.in.h:890 +#: ../data/functions.xml.in.h:903 msgid "Cone" msgstr "Cône" -#: ../data/functions.xml.in.h:891 +#: ../data/functions.xml.in.h:904 msgid "Cone Volume" msgstr "Volume d'un cône" -#: ../data/functions.xml.in.h:892 +#: ../data/functions.xml.in.h:905 msgid "r:cone" msgstr "cône" -#: ../data/functions.xml.in.h:893 +#: ../data/functions.xml.in.h:906 msgid "Surface Area of Cone" msgstr "Aire de la Surface d'un Cône" -#: ../data/functions.xml.in.h:894 +#: ../data/functions.xml.in.h:907 msgid "r:cone_sa" msgstr "" -#: ../data/functions.xml.in.h:895 +#: ../data/functions.xml.in.h:908 msgid "Sphere" msgstr "Sphère" -#: ../data/functions.xml.in.h:896 +#: ../data/functions.xml.in.h:909 msgid "Sphere Volume" msgstr "Volume de Sphère" -#: ../data/functions.xml.in.h:897 +#: ../data/functions.xml.in.h:910 msgid "r:sphere" msgstr "" -#: ../data/functions.xml.in.h:898 +#: ../data/functions.xml.in.h:911 msgid "Surface Area of Sphere" msgstr "Aire de la Surface d'une Sphère" -#: ../data/functions.xml.in.h:899 +#: ../data/functions.xml.in.h:912 msgid "r:sphere_sa" msgstr "" -#: ../data/functions.xml.in.h:900 +#: ../data/functions.xml.in.h:913 msgid "Square Area" msgstr "Aire d'un Carré" -#: ../data/functions.xml.in.h:901 +#: ../data/functions.xml.in.h:914 msgid "r:square" msgstr "" -#: ../data/functions.xml.in.h:902 +#: ../data/functions.xml.in.h:915 msgid "Length of side" msgstr "Longueur du côté" -#: ../data/functions.xml.in.h:903 +#: ../data/functions.xml.in.h:916 msgid "Square Perimeter" msgstr "Périmètre d'un Carré" -#: ../data/functions.xml.in.h:904 +#: ../data/functions.xml.in.h:917 msgid "r:square_perimeter" msgstr "" -#: ../data/functions.xml.in.h:905 +#: ../data/functions.xml.in.h:918 msgid "Cube" msgstr "" -#: ../data/functions.xml.in.h:906 +#: ../data/functions.xml.in.h:919 msgid "Cube Volume" msgstr "Volume d'un cube" -#: ../data/functions.xml.in.h:907 +#: ../data/functions.xml.in.h:920 msgid "r:cube" msgstr "" -#: ../data/functions.xml.in.h:908 +#: ../data/functions.xml.in.h:921 msgid "Surface Area of Cube" msgstr "Aire de la Surface d'un Cube" -#: ../data/functions.xml.in.h:909 +#: ../data/functions.xml.in.h:922 msgid "r:cube_sa" msgstr "" -#: ../data/functions.xml.in.h:910 +#: ../data/functions.xml.in.h:923 msgid "Rectangle" msgstr "" -#: ../data/functions.xml.in.h:911 +#: ../data/functions.xml.in.h:924 msgid "Rectangle Area" msgstr "Aire de Rectangle" -#: ../data/functions.xml.in.h:912 +#: ../data/functions.xml.in.h:925 msgid "r:rect" msgstr "" -#: ../data/functions.xml.in.h:913 +#: ../data/functions.xml.in.h:926 msgid "Width" msgstr "Largeur" -#: ../data/functions.xml.in.h:914 +#: ../data/functions.xml.in.h:927 msgid "Rectangle Perimeter" msgstr "Périmètre de Rectangle" -#: ../data/functions.xml.in.h:915 +#: ../data/functions.xml.in.h:928 msgid "r:rect_perimeter" msgstr "" -#: ../data/functions.xml.in.h:916 +#: ../data/functions.xml.in.h:929 msgid "Prism" msgstr "Prisme" -#: ../data/functions.xml.in.h:917 +#: ../data/functions.xml.in.h:930 msgid "Volume of Rectangular Prism" msgstr "Volume de Prisme Rectangulaire" -#: ../data/functions.xml.in.h:918 +#: ../data/functions.xml.in.h:931 msgid "r:rectprism" msgstr "" -#: ../data/functions.xml.in.h:919 +#: ../data/functions.xml.in.h:932 msgid "Calculates the volume of a prism with rectangular base." msgstr "Calcule le volume d'un prisme à base rectangulaire." -#: ../data/functions.xml.in.h:920 +#: ../data/functions.xml.in.h:933 msgid "Surface Area of Rectangular Prism" msgstr "Aire de la Surface d'un Prisme Rectangulaire" -#: ../data/functions.xml.in.h:921 +#: ../data/functions.xml.in.h:934 msgid "r:rectprism_sa" msgstr "" -#: ../data/functions.xml.in.h:922 +#: ../data/functions.xml.in.h:935 msgid "Calculates the surface area of a prism with rectangular base." msgstr "Calcule l'aire de la surface d'un prisme à base rectangulaire." -#: ../data/functions.xml.in.h:923 +#: ../data/functions.xml.in.h:936 msgid "Volume of Triangular Prism" msgstr "Volume de Prisme Rectangulaire" -#: ../data/functions.xml.in.h:924 +#: ../data/functions.xml.in.h:937 msgid "r:triangleprism" msgstr "" -#: ../data/functions.xml.in.h:925 +#: ../data/functions.xml.in.h:938 msgid "Calculates the volume of a prism with triangular base." msgstr "Calcule le volume d'un prisme à base triangulaire." -#: ../data/functions.xml.in.h:926 +#: ../data/functions.xml.in.h:939 msgid "Pyramid" msgstr "Pyramide" -#: ../data/functions.xml.in.h:927 +#: ../data/functions.xml.in.h:940 msgid "Pyramid Volume" msgstr "Volume de Pyramide" -#: ../data/functions.xml.in.h:928 +#: ../data/functions.xml.in.h:941 msgid "r:pyramid" msgstr "" -#: ../data/functions.xml.in.h:929 +#: ../data/functions.xml.in.h:942 msgid "" "Calculates the volume of a 3-dimensional shape standing on a rectangular " "base and terminating in a point at the top." @@ -6808,75 +6878,75 @@ "Calcule le volume d'une forme à trois dimensions basée sur un rectangle et " "se finissant en un point au sommet." -#: ../data/functions.xml.in.h:930 +#: ../data/functions.xml.in.h:943 msgid "Length of base" msgstr "Longueur de la taille" -#: ../data/functions.xml.in.h:931 +#: ../data/functions.xml.in.h:944 msgid "Width of base" msgstr "Largeur de la base" -#: ../data/functions.xml.in.h:932 +#: ../data/functions.xml.in.h:945 msgid "Volume of Regular Tetrahedron" msgstr "Volume de Tétraèdre Régulier" -#: ../data/functions.xml.in.h:933 +#: ../data/functions.xml.in.h:946 msgid "r:tetrahedron" msgstr "" -#: ../data/functions.xml.in.h:934 +#: ../data/functions.xml.in.h:947 msgid "Surface Area of Regular Tetrahedron" msgstr "Aire de la Surface d'un Tétraèdre Régulier" -#: ../data/functions.xml.in.h:935 +#: ../data/functions.xml.in.h:948 msgid "r:tetrahedron_sa" msgstr "" -#: ../data/functions.xml.in.h:936 +#: ../data/functions.xml.in.h:949 msgid "Height of Regular Tetrahedron" msgstr "Hauteur d'un Tétraèdre Régulier" -#: ../data/functions.xml.in.h:937 +#: ../data/functions.xml.in.h:950 msgid "r:tetrahedron_height" msgstr "" -#: ../data/functions.xml.in.h:938 +#: ../data/functions.xml.in.h:951 msgid "Volume of Square Pyramid" msgstr "Volume de Pyramide à Base Carrée" -#: ../data/functions.xml.in.h:939 +#: ../data/functions.xml.in.h:952 msgid "r:sqpyramid" msgstr "" -#: ../data/functions.xml.in.h:940 +#: ../data/functions.xml.in.h:953 msgid "Surface Area of Square Pyramid" msgstr "Aire de la Surface d'une Pyramide" -#: ../data/functions.xml.in.h:941 +#: ../data/functions.xml.in.h:954 msgid "r:sqpyramid_sa" msgstr "" -#: ../data/functions.xml.in.h:942 +#: ../data/functions.xml.in.h:955 msgid "Height of Square Pyramid" msgstr "Hauteur d'une Pyramide à Base Carrée" -#: ../data/functions.xml.in.h:943 +#: ../data/functions.xml.in.h:956 msgid "r:sqpyramid_height" msgstr "" -#: ../data/functions.xml.in.h:944 +#: ../data/functions.xml.in.h:957 msgid "Parallelogram" msgstr "Parallélogramme" -#: ../data/functions.xml.in.h:945 +#: ../data/functions.xml.in.h:958 msgid "Parallelogram Area" msgstr "Aire d'un Parallélogramme" -#: ../data/functions.xml.in.h:946 +#: ../data/functions.xml.in.h:959 msgid "r:parallelogram" msgstr "parallélogramme" -#: ../data/functions.xml.in.h:947 +#: ../data/functions.xml.in.h:960 #, fuzzy msgid "" "Calculates the area of a four-sided figure whose opposite sides are both " @@ -6885,15 +6955,15 @@ "Calcule l'aire d'un parallélogramme (quadrilatère dont les côtés opposés " "sont parallèles et de même longueur)." -#: ../data/functions.xml.in.h:948 +#: ../data/functions.xml.in.h:961 msgid "Parallelogram Perimeter" msgstr "Périmètre d'un Parallélogramme" -#: ../data/functions.xml.in.h:949 +#: ../data/functions.xml.in.h:962 msgid "r:parallelogram_perimeter" msgstr "périmètre_de_parallélogramme" -#: ../data/functions.xml.in.h:950 +#: ../data/functions.xml.in.h:963 #, fuzzy msgid "" "Calculates the perimeter of a four-sided figure whose opposite sides are " @@ -6902,41 +6972,41 @@ "Calcule le périmètre d'un parallélogramme (quadrilatère dont les côtés " "opposés sont parallèles et de même longueur)." -#: ../data/functions.xml.in.h:951 +#: ../data/functions.xml.in.h:964 msgid "Trapezoid" msgstr "" -#: ../data/functions.xml.in.h:952 +#: ../data/functions.xml.in.h:965 msgid "Trapezoid Area" msgstr "" -#: ../data/functions.xml.in.h:953 +#: ../data/functions.xml.in.h:966 msgid "r:trapezoid" msgstr "" -#: ../data/functions.xml.in.h:954 +#: ../data/functions.xml.in.h:967 #, fuzzy msgid "Calculates the area of a four-sided figure with two parallel sides." msgstr "" "Calcule l'aire d'un trapèze (quadrilatère dont deux côtés sont parallèles)." -#: ../data/functions.xml.in.h:955 +#: ../data/functions.xml.in.h:968 msgid "Economics" msgstr "Économie" -#: ../data/functions.xml.in.h:956 +#: ../data/functions.xml.in.h:969 msgid "Microeconomics" msgstr "Micro-économie" -#: ../data/functions.xml.in.h:957 +#: ../data/functions.xml.in.h:970 msgid "Elasticity" msgstr "Élasticité" -#: ../data/functions.xml.in.h:958 +#: ../data/functions.xml.in.h:971 msgid "r:elasticity" msgstr "élasticité" -#: ../data/functions.xml.in.h:959 +#: ../data/functions.xml.in.h:972 msgid "" "Calculates the demand elasticity. Also works for supply elasticity, income " "elasticity, cross-price elasticity, etc. Just replace demand with supply, or " @@ -6950,27 +7020,27 @@ "l'élasticité de la demande quand le prix est 3 pour la fonction \"Q = 100 - " "x^2\" où x est la variable de prix par défaut." -#: ../data/functions.xml.in.h:960 +#: ../data/functions.xml.in.h:973 msgid "Demand function" msgstr "Fonction de la demande" -#: ../data/functions.xml.in.h:961 +#: ../data/functions.xml.in.h:974 msgid "Price" msgstr "Prix" -#: ../data/functions.xml.in.h:962 +#: ../data/functions.xml.in.h:975 msgid "Price variable" msgstr "Variable de prix" -#: ../data/functions.xml.in.h:963 +#: ../data/functions.xml.in.h:976 msgid "Sum-of-Years Digits Depreciation" msgstr "" -#: ../data/functions.xml.in.h:964 +#: ../data/functions.xml.in.h:977 msgid "r:syd" msgstr "" -#: ../data/functions.xml.in.h:965 +#: ../data/functions.xml.in.h:978 msgid "" "Calculates the sum-of-years digits depreciation for an asset based on its " "cost, salvage value, anticipated life, and a particular period. This method " @@ -6986,31 +7056,31 @@ "valeur réelle moins la valeur résiduelle. La vie utile est le nombre de " "périodes (typiquement années) pendant lesquelles les actifs sont dépréciés." -#: ../data/functions.xml.in.h:966 +#: ../data/functions.xml.in.h:979 msgid "Cost" msgstr "Coût" -#: ../data/functions.xml.in.h:967 +#: ../data/functions.xml.in.h:980 msgid "Salvage value" msgstr "" -#: ../data/functions.xml.in.h:968 +#: ../data/functions.xml.in.h:981 msgid "Life" msgstr "Vie" -#: ../data/functions.xml.in.h:969 +#: ../data/functions.xml.in.h:982 msgid "Period" msgstr "Période" -#: ../data/functions.xml.in.h:970 +#: ../data/functions.xml.in.h:983 msgid "Straight Line Depreciation" msgstr "" -#: ../data/functions.xml.in.h:971 +#: ../data/functions.xml.in.h:984 msgid "r:sln" msgstr "" -#: ../data/functions.xml.in.h:972 +#: ../data/functions.xml.in.h:985 msgid "" "Determines the straight line depreciation of an asset for a single period." " Cost is the amount you paid for the asset. Salvage is the value of " @@ -7023,15 +7093,15 @@ "résiduelle est la valeur de l'actif à la fin de la période. La vie est le " "nombre de périodes pendant lesquelles l'actif est déprécié." -#: ../data/functions.xml.in.h:973 +#: ../data/functions.xml.in.h:986 msgid "Present Value" msgstr "Valeur Actuelle" -#: ../data/functions.xml.in.h:974 +#: ../data/functions.xml.in.h:987 msgid "r:pv" msgstr "" -#: ../data/functions.xml.in.h:975 +#: ../data/functions.xml.in.h:988 msgid "" "Returns the present value of an investment. If type = 1 then the " "payment is made at the beginning of the period, If type = 0 (or omitted) it " @@ -7041,35 +7111,35 @@ "le paiement est fait au début de la période, si type = 0 (ou omis) il est " "fait à la fin de chaque période." -#: ../data/functions.xml.in.h:976 +#: ../data/functions.xml.in.h:989 msgid "Interest rate" msgstr "Taux d'intérêt" -#: ../data/functions.xml.in.h:977 +#: ../data/functions.xml.in.h:990 msgid "Number of periods" msgstr "Nombre de périodes" -#: ../data/functions.xml.in.h:978 +#: ../data/functions.xml.in.h:991 msgid "Payment made each period" msgstr "Versement effectué à chaque période" -#: ../data/functions.xml.in.h:979 +#: ../data/functions.xml.in.h:992 msgid "Future value" msgstr "Valeur future" -#: ../data/functions.xml.in.h:980 +#: ../data/functions.xml.in.h:993 msgid "Type" msgstr "" -#: ../data/functions.xml.in.h:981 +#: ../data/functions.xml.in.h:994 msgid "Nominal Interest Rate" msgstr "Taux d'Intérêt Nominal" -#: ../data/functions.xml.in.h:982 +#: ../data/functions.xml.in.h:995 msgid "r:nominal" msgstr "" -#: ../data/functions.xml.in.h:983 +#: ../data/functions.xml.in.h:996 msgid "" "Calculates the nominal interest rate from a given effective interest rate " "compounded at given intervals." @@ -7077,115 +7147,115 @@ "Calcule le taux d'intérêt nominal pour un taux d'intérêt effectif donné " "composé à des intervalles donnés." -#: ../data/functions.xml.in.h:984 +#: ../data/functions.xml.in.h:997 msgid "Effective interest rate" msgstr "Taux d'intérêt effectif" -#: ../data/functions.xml.in.h:985 +#: ../data/functions.xml.in.h:998 msgid "Periods" msgstr "Périodes" -#: ../data/functions.xml.in.h:986 +#: ../data/functions.xml.in.h:999 msgid "Zero Coupon" msgstr "" -#: ../data/functions.xml.in.h:987 +#: ../data/functions.xml.in.h:1000 msgid "r:zero_coupon" msgstr "" -#: ../data/functions.xml.in.h:988 +#: ../data/functions.xml.in.h:1001 msgid "Calculates the value of a zero-coupon (pure discount) bond." msgstr "" -#: ../data/functions.xml.in.h:989 +#: ../data/functions.xml.in.h:1002 msgid "Face value" msgstr "Valeur nominale" -#: ../data/functions.xml.in.h:990 +#: ../data/functions.xml.in.h:1003 msgid "Treasury Bill Yield" msgstr "" -#: ../data/functions.xml.in.h:991 +#: ../data/functions.xml.in.h:1004 msgid "r:tbillyield" msgstr "" -#: ../data/functions.xml.in.h:992 +#: ../data/functions.xml.in.h:1005 msgid "Returns the yield for a treasury bill." msgstr "" -#: ../data/functions.xml.in.h:993 +#: ../data/functions.xml.in.h:1006 msgid "Settlement date" msgstr "" -#: ../data/functions.xml.in.h:994 +#: ../data/functions.xml.in.h:1007 msgid "Maturity date" msgstr "Échéance" -#: ../data/functions.xml.in.h:995 +#: ../data/functions.xml.in.h:1008 msgid "Price per $100 face value" msgstr "Prix pour 100 $ de valeur faciale" -#: ../data/functions.xml.in.h:996 +#: ../data/functions.xml.in.h:1009 msgid "Treasury Bill Price" msgstr "" -#: ../data/functions.xml.in.h:997 +#: ../data/functions.xml.in.h:1010 msgid "r:tbillprice" msgstr "" -#: ../data/functions.xml.in.h:998 +#: ../data/functions.xml.in.h:1011 msgid "Returns the price per $100 value for a treasury bill." msgstr "Retourne le prix pour 100 $ de valeur de bons du trésor." -#: ../data/functions.xml.in.h:999 +#: ../data/functions.xml.in.h:1012 msgid "Discount rate" msgstr "Taux d'actualisation" -#: ../data/functions.xml.in.h:1000 +#: ../data/functions.xml.in.h:1013 msgid "Treasury Bill Equivalent" msgstr "" -#: ../data/functions.xml.in.h:1001 +#: ../data/functions.xml.in.h:1014 msgid "r:tbilleq" msgstr "" -#: ../data/functions.xml.in.h:1002 +#: ../data/functions.xml.in.h:1015 msgid "Returns the bond equivalent for a treasury bill." msgstr "" -#: ../data/functions.xml.in.h:1003 +#: ../data/functions.xml.in.h:1016 msgid "Interest paid on a given period of an investment (ISPMT)" msgstr "Intérêt payé pour une période donnée d'un investissement" -#: ../data/functions.xml.in.h:1004 +#: ../data/functions.xml.in.h:1017 msgid "r:ispmt" msgstr "" -#: ../data/functions.xml.in.h:1005 +#: ../data/functions.xml.in.h:1018 msgid "Calculates the interest paid on a given period of an investment." msgstr "Calcule l'intérêt d'un investissement payé sur une période donnée." -#: ../data/functions.xml.in.h:1006 +#: ../data/functions.xml.in.h:1019 msgid "Periodic interest rate" msgstr "" -#: ../data/functions.xml.in.h:1007 +#: ../data/functions.xml.in.h:1020 msgid "Amortizement period" msgstr "Période d'amortissement" -#: ../data/functions.xml.in.h:1008 +#: ../data/functions.xml.in.h:1021 msgid "Present value" msgstr "Valeur actuelle" -#: ../data/functions.xml.in.h:1009 +#: ../data/functions.xml.in.h:1022 msgid "Payment for a loan" msgstr "Versement pour un emprunt" -#: ../data/functions.xml.in.h:1010 +#: ../data/functions.xml.in.h:1023 msgid "r:pmt" msgstr "" -#: ../data/functions.xml.in.h:1011 +#: ../data/functions.xml.in.h:1024 #, fuzzy msgid "" "Returns the amount of payment (negative) each period for a loan based on a " @@ -7203,19 +7273,19 @@ "paiement est réalisé en début de période, si type = 0 (ou omis) il est fait " "en fin de chaque période." -#: ../data/functions.xml.in.h:1012 +#: ../data/functions.xml.in.h:1025 msgid "Rate" msgstr "" -#: ../data/functions.xml.in.h:1013 +#: ../data/functions.xml.in.h:1026 msgid "Periods of an investment" msgstr "" -#: ../data/functions.xml.in.h:1014 +#: ../data/functions.xml.in.h:1027 msgid "r:nper" msgstr "" -#: ../data/functions.xml.in.h:1015 +#: ../data/functions.xml.in.h:1028 msgid "" "Calculates number of periods of an investment based on periodic constant " "payments and a constant interest rate. Type defines the due date. 1 " @@ -7227,15 +7297,15 @@ "définit l'échéance. 1 pour paiement en début de période et 0 (par défaut) " "pour paiement en fin de période." -#: ../data/functions.xml.in.h:1016 +#: ../data/functions.xml.in.h:1029 msgid "Periods for investment to attain desired value" msgstr "" -#: ../data/functions.xml.in.h:1017 +#: ../data/functions.xml.in.h:1030 msgid "r:g_duration" msgstr "" -#: ../data/functions.xml.in.h:1018 +#: ../data/functions.xml.in.h:1031 msgid "" "Returns the number of periods needed for an investment to attain a desired " "value." @@ -7243,15 +7313,15 @@ "Retourne le nombre de périodes nécessaires à un investissement pour " "atteindre un valeur désirée." -#: ../data/functions.xml.in.h:1019 +#: ../data/functions.xml.in.h:1032 msgid "Payment of an annuity going towards principal (PPMT)" msgstr "Versements d'une rente orientée vers le capital" -#: ../data/functions.xml.in.h:1020 +#: ../data/functions.xml.in.h:1033 msgid "r:ppmt" msgstr "" -#: ../data/functions.xml.in.h:1021 +#: ../data/functions.xml.in.h:1034 msgid "" "Calculates the amount of a payment of an annuity going towards principal." " Type defines the due date. 1 for payment at the beginning of a " @@ -7261,35 +7331,35 @@ " Le type définit la date de paiement. 1 pour des paiements en début de " "période et 0 (par défaut) pour des paiements en fin de période." -#: ../data/functions.xml.in.h:1022 +#: ../data/functions.xml.in.h:1035 msgid "Desired future value" msgstr "Valeur future souhaitée" -#: ../data/functions.xml.in.h:1023 +#: ../data/functions.xml.in.h:1036 msgid "Effective Interest Rate" msgstr "Taux d'intérêt effectif" -#: ../data/functions.xml.in.h:1024 +#: ../data/functions.xml.in.h:1037 msgid "r:effect" msgstr "effet" -#: ../data/functions.xml.in.h:1025 +#: ../data/functions.xml.in.h:1038 msgid "Calculates the effective interest for a given nominal rate." msgstr "Calcule l'intérêt effectif pour un taux nominal donné." -#: ../data/functions.xml.in.h:1026 +#: ../data/functions.xml.in.h:1039 msgid "Nominal interest rate" msgstr "Taux d'intérêt nominal" -#: ../data/functions.xml.in.h:1027 +#: ../data/functions.xml.in.h:1040 msgid "Future Value" msgstr "Valeur Future" -#: ../data/functions.xml.in.h:1028 +#: ../data/functions.xml.in.h:1041 msgid "r:fv" msgstr "" -#: ../data/functions.xml.in.h:1029 +#: ../data/functions.xml.in.h:1042 msgid "" "Computes the future value of an investment. This is based on periodic, " "constant payments and a constant interest rate. If type = 1 then " @@ -7301,15 +7371,15 @@ "le type = 1 alors le paiement est effectué au début de chaque période; si le " "type = 0 (ou omis), il a lieu à la fin de chaque période." -#: ../data/functions.xml.in.h:1030 +#: ../data/functions.xml.in.h:1043 msgid "Return on continuously compounded interest" msgstr "Retour sur intérêt continûment composé" -#: ../data/functions.xml.in.h:1031 +#: ../data/functions.xml.in.h:1044 msgid "r:continuous" msgstr "" -#: ../data/functions.xml.in.h:1032 +#: ../data/functions.xml.in.h:1045 msgid "" "Calculates the return on continuously compounded interest, given the " "principal, nominal rate and time in years." @@ -7317,37 +7387,37 @@ "Calcule le retour sur intérêt composé continument, étant donnés le taux " "nominal principal et la durée en années." -#: ../data/functions.xml.in.h:1033 +#: ../data/functions.xml.in.h:1046 msgid "Principal" msgstr "Capital" -#: ../data/functions.xml.in.h:1034 +#: ../data/functions.xml.in.h:1047 msgid "Compound" msgstr "Composé" -#: ../data/functions.xml.in.h:1035 +#: ../data/functions.xml.in.h:1048 msgid "r:compound" msgstr "" -#: ../data/functions.xml.in.h:1036 +#: ../data/functions.xml.in.h:1049 msgid "" "Returns the value of an investment, given the principal, nominal interest " "rate, compounding frequency and time." msgstr "" -#: ../data/functions.xml.in.h:1037 +#: ../data/functions.xml.in.h:1050 msgid "Periods per year" msgstr "" -#: ../data/functions.xml.in.h:1038 +#: ../data/functions.xml.in.h:1051 msgid "Payment of an annuity going towards interest (IPMT)" msgstr "Versements d'une rente orientée vers les intérêts" -#: ../data/functions.xml.in.h:1039 +#: ../data/functions.xml.in.h:1052 msgid "r:ipmt" msgstr "" -#: ../data/functions.xml.in.h:1040 +#: ../data/functions.xml.in.h:1053 msgid "" "Calculates the amount of a payment of an annuity going towards interest. " " Type defines the due date. 1 for payment at the beginning of a period " @@ -7357,15 +7427,15 @@ " Le type définit la date de paiement. 1 pour des paiements en début " "de période et 0 (par défaut) pour des paiements en fin de période." -#: ../data/functions.xml.in.h:1041 +#: ../data/functions.xml.in.h:1054 msgid "Interest rate for a fully invested security" msgstr "Taux d'intérêt d'une obligation entièrement investie" -#: ../data/functions.xml.in.h:1042 +#: ../data/functions.xml.in.h:1055 msgid "r:intrate" msgstr "" -#: ../data/functions.xml.in.h:1043 +#: ../data/functions.xml.in.h:1056 msgid "" "Returns the interest rate for a fully invested security. Basis is " "the type of day counting you want to use: 0: US 30/360 (default), 1: real " @@ -7376,46 +7446,46 @@ "30/360 (par défaut), 1 : jours réels, 2: jours réels/360, 3: jours réels/365 " "or 4: Européenne 30/360.La date de contrat doit être antérieure à l'échéance." -#: ../data/functions.xml.in.h:1044 +#: ../data/functions.xml.in.h:1057 msgid "Investment" msgstr "Investissement" -#: ../data/functions.xml.in.h:1045 +#: ../data/functions.xml.in.h:1058 msgid "Redemption" msgstr "Amortissement" -#: ../data/functions.xml.in.h:1046 +#: ../data/functions.xml.in.h:1059 msgid "Dollar Fraction" msgstr "Fraction en dollars" -#: ../data/functions.xml.in.h:1047 +#: ../data/functions.xml.in.h:1060 msgid "r:dollarfr" msgstr "" -#: ../data/functions.xml.in.h:1048 +#: ../data/functions.xml.in.h:1061 msgid "" "Converts a decimal dollar price into a dollar price expressed as a fraction." msgstr "" "Convertit un prix en dollars décimaux en un prix en dollars sous forme de " "fraction." -#: ../data/functions.xml.in.h:1049 +#: ../data/functions.xml.in.h:1062 msgid "Decimal dollar" msgstr "Dollar décimal" -#: ../data/functions.xml.in.h:1050 +#: ../data/functions.xml.in.h:1063 msgid "Denominator of fraction" msgstr "Dénominateur d'une fraction" -#: ../data/functions.xml.in.h:1051 +#: ../data/functions.xml.in.h:1064 msgid "Dollar Decimal" msgstr "Dollar décimal" -#: ../data/functions.xml.in.h:1052 +#: ../data/functions.xml.in.h:1065 msgid "r:dollarde" msgstr "" -#: ../data/functions.xml.in.h:1053 +#: ../data/functions.xml.in.h:1066 msgid "" "Converts a dollar price expressed as a fraction into a dollar price " "expressed as a decimal number." @@ -7423,19 +7493,19 @@ "Convertit en prix en dollars sous forme de fraction en un prix en dollars " "décimaux." -#: ../data/functions.xml.in.h:1054 +#: ../data/functions.xml.in.h:1067 msgid "Fractional dollar" msgstr "Dollar fractionnaire" -#: ../data/functions.xml.in.h:1055 +#: ../data/functions.xml.in.h:1068 msgid "Amount received at maturity for a security bond" msgstr "Montant reçu à maturité par un bon de sécurité" -#: ../data/functions.xml.in.h:1056 +#: ../data/functions.xml.in.h:1069 msgid "r:received" msgstr "" -#: ../data/functions.xml.in.h:1057 +#: ../data/functions.xml.in.h:1070 msgid "" "Returns the amount received at the maturity date for an invested security." " Basis is the type of day counting you want to use: 0: US 30/360 " @@ -7448,31 +7518,31 @@ "réels/365 or 4: Européenne 30/360.La date de contrat doit être antérieure à " "l'échéance." -#: ../data/functions.xml.in.h:1058 +#: ../data/functions.xml.in.h:1071 msgid "Discount rate for a security" msgstr "Taux d'actualisation d'une obligation" -#: ../data/functions.xml.in.h:1059 +#: ../data/functions.xml.in.h:1072 msgid "r:disc" msgstr "" -#: ../data/functions.xml.in.h:1060 +#: ../data/functions.xml.in.h:1073 msgid "" "Returns the discount rate for a security. Basis is the type of day " "counting you want to use: 0: US 30/360 (default), 1: real days, 2: real " "days/360, 3: real days/365 or 4: European 30/360." msgstr "" -#: ../data/functions.xml.in.h:1061 +#: ../data/functions.xml.in.h:1074 #, fuzzy msgid "Accrued interest of security paying at maturity" msgstr "Intérêt de sécurité cumulé payé à maturité" -#: ../data/functions.xml.in.h:1062 +#: ../data/functions.xml.in.h:1075 msgid "r:accrintm" msgstr "" -#: ../data/functions.xml.in.h:1063 +#: ../data/functions.xml.in.h:1076 msgid "" "Returns the accrued interest for a security which pays interest at maturity " "date. Basis is the type of day counting you want to use: 0: US " @@ -7484,28 +7554,28 @@ "utiliser : 0 : US 30/360 (par défaut), 1 : jours réels, 2: jours réels/360, " "3: jours réels/365 or 4: Européenne 30/360." -#: ../data/functions.xml.in.h:1064 +#: ../data/functions.xml.in.h:1077 msgid "Issue date" msgstr "Date de fin" -#: ../data/functions.xml.in.h:1065 +#: ../data/functions.xml.in.h:1078 msgid "Annual rate of security" msgstr "Taux de sécurité annuel" -#: ../data/functions.xml.in.h:1066 +#: ../data/functions.xml.in.h:1079 msgid "Par value" msgstr "Montant nominal" -#: ../data/functions.xml.in.h:1067 +#: ../data/functions.xml.in.h:1080 #, fuzzy msgid "Accrued interest of security with periodic interest payments" msgstr "Intérêt de sécurité cumulé avec paiements périodiques" -#: ../data/functions.xml.in.h:1068 +#: ../data/functions.xml.in.h:1081 msgid "r:accrint" msgstr "" -#: ../data/functions.xml.in.h:1069 +#: ../data/functions.xml.in.h:1082 msgid "" "Returns accrued interest for a security which pays periodic interest. " " Allowed frequencies are 1 - annual, 2 - semi-annual or 4 - quarterly. " @@ -7518,23 +7588,23 @@ "jours que vous souhaitez utiliser : 0 : US 30/360 (par défaut), 1 : jours " "réels, 2: jours réels/360, 3: jours réels/365 or 4: Européenne 30/360." -#: ../data/functions.xml.in.h:1070 +#: ../data/functions.xml.in.h:1083 msgid "First interest" msgstr "Premier intérêt" -#: ../data/functions.xml.in.h:1071 +#: ../data/functions.xml.in.h:1084 msgid "Frequency" msgstr "Fréquence" -#: ../data/functions.xml.in.h:1072 +#: ../data/functions.xml.in.h:1085 msgid "Number of coupons to be paid" msgstr "Nombre de coupons à payer" -#: ../data/functions.xml.in.h:1073 +#: ../data/functions.xml.in.h:1086 msgid "r:coupnum" msgstr "" -#: ../data/functions.xml.in.h:1074 +#: ../data/functions.xml.in.h:1087 msgid "" "Returns the number of coupons to be paid between the settlement and the " "maturity. Basis is the type of day counting you want to use: 0: US " @@ -7547,16 +7617,16 @@ "3: jours réels/365 or 4: Européenne 30/360.La date de contrat doit être " "antérieure à l'échéance." -#: ../data/functions.xml.in.h:1075 +#: ../data/functions.xml.in.h:1088 #, fuzzy msgid "Price per $100 face value of a discounted security" msgstr "Prix pour 100 $ de valeur faciale d'une obligation" -#: ../data/functions.xml.in.h:1076 +#: ../data/functions.xml.in.h:1089 msgid "r:pricedisc" msgstr "" -#: ../data/functions.xml.in.h:1077 +#: ../data/functions.xml.in.h:1090 #, fuzzy msgid "" "Calculates and returns the price per $100 face value of a discounted " @@ -7570,19 +7640,19 @@ "(par défaut), 1: jours réels, 2: jours réels/360, 3: jours réels/365 or 4: " "Européenne 30/360." -#: ../data/functions.xml.in.h:1078 +#: ../data/functions.xml.in.h:1091 msgid "Discount" msgstr "Escompte" -#: ../data/functions.xml.in.h:1079 +#: ../data/functions.xml.in.h:1092 msgid "Price per $100 face value of a security" msgstr "Prix pour 100 $ de valeur faciale d'une obligation" -#: ../data/functions.xml.in.h:1080 +#: ../data/functions.xml.in.h:1093 msgid "r:pricemat" msgstr "" -#: ../data/functions.xml.in.h:1081 +#: ../data/functions.xml.in.h:1094 msgid "" "Calculates and returns the price per $100 face value of a security. The " "security pays interest at maturity. Basis is the type of day " @@ -7595,31 +7665,31 @@ "défaut), 1: jours réels, 2: jours réels/360, 3: jours réels/365 or 4: " "Européenne 30/360." -#: ../data/functions.xml.in.h:1082 +#: ../data/functions.xml.in.h:1095 msgid "Annual yield" msgstr "Revenu annuel" -#: ../data/functions.xml.in.h:1083 +#: ../data/functions.xml.in.h:1096 msgid "Level-Coupon Bond" msgstr "" -#: ../data/functions.xml.in.h:1084 +#: ../data/functions.xml.in.h:1097 msgid "r:level_coupon" msgstr "" -#: ../data/functions.xml.in.h:1085 +#: ../data/functions.xml.in.h:1098 msgid "Calculates the value of a level-coupon bond." msgstr "" -#: ../data/functions.xml.in.h:1086 +#: ../data/functions.xml.in.h:1099 msgid "Coupon rate" msgstr "Taux du coupon" -#: ../data/functions.xml.in.h:1087 +#: ../data/functions.xml.in.h:1100 msgid "Coupons per year" msgstr "Coupons par an" -#: ../data/functions.xml.in.h:1088 +#: ../data/functions.xml.in.h:1101 msgid "Market interest rate" msgstr "Taux d'intérêt du marché" @@ -10928,10 +10998,6 @@ #~ msgstr "Le Nombre d'Or" #, fuzzy -#~ msgid "Belarusian Ruble" -#~ msgstr "Rouble russe" - -#, fuzzy #~ msgid "Mauritania" #~ msgstr "Échéance" diff -Nru libqalculate-3.6.0/po-defs/libqalculate.pot libqalculate-3.7.0/po-defs/libqalculate.pot --- libqalculate-3.6.0/po-defs/libqalculate.pot 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/po-defs/libqalculate.pot 2020-01-21 22:54:40.000000000 +0000 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-25 10:28+0100\n" +"POT-Creation-Date: 2020-01-12 11:29+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -609,1401 +609,1413 @@ msgstr "" #: ../data/currencies.xml.in.h:147 -msgid "Belarusian Ruble p. (obsolete)" +msgid "Belarusian Ruble" msgstr "" #: ../data/currencies.xml.in.h:148 -msgid "ar:BYR" +msgid "ar:BYN" msgstr "" #: ../data/currencies.xml.in.h:149 -msgid "Belize Dollar" +msgid "Belarus" msgstr "" #: ../data/currencies.xml.in.h:150 -msgid "ar:BZD" +msgid "Belarusian Ruble p. (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:151 -msgid "Belize" +msgid "ar:BYR" msgstr "" #: ../data/currencies.xml.in.h:152 -msgid "West African CFA Franc" +msgid "Belize Dollar" msgstr "" #: ../data/currencies.xml.in.h:153 -msgid "ar:XOF,a:CFA" +msgid "ar:BZD" msgstr "" #: ../data/currencies.xml.in.h:154 -msgid "" -"Benin, Burkina Faso, Guinea-Bissau, Ivory Coast, Mali, Niger, Senegal, Togo" +msgid "Belize" msgstr "" #: ../data/currencies.xml.in.h:155 -msgid "Bermudian Dollar" +msgid "West African CFA Franc" msgstr "" #: ../data/currencies.xml.in.h:156 -msgid "ar:BMD" +msgid "ar:XOF,a:CFA" msgstr "" #: ../data/currencies.xml.in.h:157 -msgid "Bermuda" +msgid "" +"Benin, Burkina Faso, Guinea-Bissau, Ivory Coast, Mali, Niger, Senegal, Togo" msgstr "" #: ../data/currencies.xml.in.h:158 -msgid "Bolivian Boliviano Bs" +msgid "Bermudian Dollar" msgstr "" #: ../data/currencies.xml.in.h:159 -msgid "ar:BOB" +msgid "ar:BMD" msgstr "" #: ../data/currencies.xml.in.h:160 -msgid "Bolivia" +msgid "Bermuda" msgstr "" #: ../data/currencies.xml.in.h:161 -msgid "Bosnia and Herzegovina Convertible Mark" +msgid "Bolivian Boliviano Bs" msgstr "" #: ../data/currencies.xml.in.h:162 -msgid "ar:BAM" +msgid "ar:BOB" msgstr "" #: ../data/currencies.xml.in.h:163 -msgid "Bosnia and Herzegovina" +msgid "Bolivia" msgstr "" #: ../data/currencies.xml.in.h:164 -msgid "Botswana Pula" +msgid "Bosnia and Herzegovina Convertible Mark" msgstr "" #: ../data/currencies.xml.in.h:165 -msgid "ar:BWP" +msgid "ar:BAM" msgstr "" #: ../data/currencies.xml.in.h:166 -msgid "Botswana" +msgid "Bosnia and Herzegovina" msgstr "" #: ../data/currencies.xml.in.h:167 -msgid "Brunei Dollar" +msgid "Botswana Pula" msgstr "" #: ../data/currencies.xml.in.h:168 -msgid "ar:BND" +msgid "ar:BWP" msgstr "" #: ../data/currencies.xml.in.h:169 -msgid "Brunei" +msgid "Botswana" msgstr "" #: ../data/currencies.xml.in.h:170 -msgid "Burundian Franc" +msgid "Brunei Dollar" msgstr "" #: ../data/currencies.xml.in.h:171 -msgid "ar:BIF" +msgid "ar:BND" msgstr "" #: ../data/currencies.xml.in.h:172 -msgid "Burundi" +msgid "Brunei" msgstr "" #: ../data/currencies.xml.in.h:173 -msgid "Cambodian Riel" +msgid "Burundian Franc" msgstr "" #: ../data/currencies.xml.in.h:174 -msgid "ar:KHR,aiu:៛" +msgid "ar:BIF" msgstr "" #: ../data/currencies.xml.in.h:175 -msgid "Cambodia" +msgid "Burundi" msgstr "" #: ../data/currencies.xml.in.h:176 -msgid "Central African CFA Franc" +msgid "Cambodian Riel" msgstr "" #: ../data/currencies.xml.in.h:177 -msgid "ar:XAF,a:FCFA" +msgid "ar:KHR,aiu:៛" msgstr "" #: ../data/currencies.xml.in.h:178 -msgid "" -"Cameroon, Central African Republic, Chad, Republic of the Congo, Equatorial " -"Guinea, Gabon" +msgid "Cambodia" msgstr "" #: ../data/currencies.xml.in.h:179 -msgid "Cape Verdean Escudo" +msgid "Central African CFA Franc" msgstr "" #: ../data/currencies.xml.in.h:180 -msgid "ar:CVE" +msgid "ar:XAF,a:FCFA" msgstr "" #: ../data/currencies.xml.in.h:181 -msgid "Cape Verde" +msgid "" +"Cameroon, Central African Republic, Chad, Republic of the Congo, Equatorial " +"Guinea, Gabon" msgstr "" #: ../data/currencies.xml.in.h:182 -msgid "Cayman Islands Dollar" +msgid "Cape Verdean Escudo" msgstr "" #: ../data/currencies.xml.in.h:183 -msgid "ar:KYD" +msgid "ar:CVE" msgstr "" #: ../data/currencies.xml.in.h:184 -msgid "Cayman Islands" +msgid "Cape Verde" msgstr "" #: ../data/currencies.xml.in.h:185 -msgid "Chilean Peso" +msgid "Cayman Islands Dollar" msgstr "" #: ../data/currencies.xml.in.h:186 -msgid "ar:CLP" +msgid "ar:KYD" msgstr "" #: ../data/currencies.xml.in.h:187 -msgid "Chile" +msgid "Cayman Islands" msgstr "" #: ../data/currencies.xml.in.h:188 -msgid "Colombian Peso" +msgid "Chilean Peso" msgstr "" #: ../data/currencies.xml.in.h:189 -msgid "ar:COP" +msgid "ar:CLP" msgstr "" #: ../data/currencies.xml.in.h:190 -msgid "Colombia" +msgid "Chile" msgstr "" #: ../data/currencies.xml.in.h:191 -msgid "Comorian Franc" +msgid "Colombian Peso" msgstr "" #: ../data/currencies.xml.in.h:192 -msgid "ar:KMF" +msgid "ar:COP" msgstr "" #: ../data/currencies.xml.in.h:193 -msgid "Comoros" +msgid "Colombia" msgstr "" #: ../data/currencies.xml.in.h:194 -msgid "Democratic Republic of the Congo (Congolese Franc)" +msgid "Comorian Franc" msgstr "" #: ../data/currencies.xml.in.h:195 -msgid "ar:CDF" +msgid "ar:KMF" msgstr "" #: ../data/currencies.xml.in.h:196 -msgid "Democratic Republic of the Congo" +msgid "Comoros" msgstr "" #: ../data/currencies.xml.in.h:197 -msgid "Costa Rican colón" +msgid "Democratic Republic of the Congo (Congolese Franc)" msgstr "" #: ../data/currencies.xml.in.h:198 -msgid "ar:CRC" +msgid "ar:CDF" msgstr "" #: ../data/currencies.xml.in.h:199 -msgid "Costa Rica" +msgid "Democratic Republic of the Congo" msgstr "" #: ../data/currencies.xml.in.h:200 -msgid "Cuban Peso" +msgid "Costa Rican colón" msgstr "" #: ../data/currencies.xml.in.h:201 -msgid "ar:CUP" +msgid "ar:CRC" msgstr "" #: ../data/currencies.xml.in.h:202 -msgid "Cuba" +msgid "Costa Rica" msgstr "" #: ../data/currencies.xml.in.h:203 -msgid "Djiboutian Franc" +msgid "Cuban Peso" msgstr "" #: ../data/currencies.xml.in.h:204 -msgid "ar:DJF" +msgid "ar:CUP" msgstr "" #: ../data/currencies.xml.in.h:205 -msgid "Djibouti" +msgid "Cuba" msgstr "" #: ../data/currencies.xml.in.h:206 -msgid "Dominican Peso" +msgid "Djiboutian Franc" msgstr "" #: ../data/currencies.xml.in.h:207 -msgid "ar:DOP" +msgid "ar:DJF" msgstr "" #: ../data/currencies.xml.in.h:208 -msgid "Dominican Republic" +msgid "Djibouti" msgstr "" #: ../data/currencies.xml.in.h:209 -msgid "Egyptian Pound" +msgid "Dominican Peso" msgstr "" #: ../data/currencies.xml.in.h:210 -msgid "ar:EGP" +msgid "ar:DOP" msgstr "" #: ../data/currencies.xml.in.h:211 -msgid "Egypt" +msgid "Dominican Republic" msgstr "" #: ../data/currencies.xml.in.h:212 -msgid "El Salvadoran Colon (obsolete)" +msgid "Egyptian Pound" msgstr "" #: ../data/currencies.xml.in.h:213 -msgid "ar:SVC" +msgid "ar:EGP" msgstr "" #: ../data/currencies.xml.in.h:214 -msgid "Eritrean Nafka" +msgid "Egypt" msgstr "" #: ../data/currencies.xml.in.h:215 -msgid "ar:ERN" +msgid "El Salvadoran Colon (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:216 -msgid "Eritrea" +msgid "ar:SVC" msgstr "" #: ../data/currencies.xml.in.h:217 -msgid "Ethiopian Birr" +msgid "Eritrean Nafka" msgstr "" #: ../data/currencies.xml.in.h:218 -msgid "ar:ETB" +msgid "ar:ERN" msgstr "" #: ../data/currencies.xml.in.h:219 -msgid "Ethiopia" +msgid "Eritrea" msgstr "" #: ../data/currencies.xml.in.h:220 -msgid "Falkland Islands Pound" +msgid "Ethiopian Birr" msgstr "" #: ../data/currencies.xml.in.h:221 -msgid "ar:FKP" +msgid "ar:ETB" msgstr "" #: ../data/currencies.xml.in.h:222 -msgid "Falkland Islands" +msgid "Ethiopia" msgstr "" #: ../data/currencies.xml.in.h:223 -msgid "Fijian Dollar" +msgid "Falkland Islands Pound" msgstr "" #: ../data/currencies.xml.in.h:224 -msgid "ar:FJD" +msgid "ar:FKP" msgstr "" #: ../data/currencies.xml.in.h:225 -msgid "Fiji" +msgid "Falkland Islands" msgstr "" #: ../data/currencies.xml.in.h:226 -msgid "CFP franc" +msgid "Fijian Dollar" msgstr "" #: ../data/currencies.xml.in.h:227 -msgid "ar:XPF" +msgid "ar:FJD" msgstr "" #: ../data/currencies.xml.in.h:228 -msgid "French Polynesia, New Caledonia, Wallis and Futuna" +msgid "Fiji" msgstr "" #: ../data/currencies.xml.in.h:229 -msgid "Gambian Dalasi" +msgid "CFP franc" msgstr "" #: ../data/currencies.xml.in.h:230 -msgid "ar:GMD" +msgid "ar:XPF" msgstr "" #: ../data/currencies.xml.in.h:231 -msgid "Gambia" +msgid "French Polynesia, New Caledonia, Wallis and Futuna" msgstr "" #: ../data/currencies.xml.in.h:232 -msgid "Georgian Lari" +msgid "Gambian Dalasi" msgstr "" #: ../data/currencies.xml.in.h:233 -msgid "ar:GEL,au:₾" +msgid "ar:GMD" msgstr "" #: ../data/currencies.xml.in.h:234 -msgid "Georgia" +msgid "Gambia" msgstr "" #: ../data/currencies.xml.in.h:235 -msgid "Ghanaian Cedi" +msgid "Georgian Lari" msgstr "" #: ../data/currencies.xml.in.h:236 -msgid "ar:GHS,au:₵" +msgid "ar:GEL,au:₾" msgstr "" #: ../data/currencies.xml.in.h:237 -msgid "Ghana" +msgid "Georgia" msgstr "" #: ../data/currencies.xml.in.h:238 -msgid "Gibraltar Pound" +msgid "Ghanaian Cedi" msgstr "" #: ../data/currencies.xml.in.h:239 -msgid "ar:GIP" +msgid "ar:GHS,au:₵" msgstr "" #: ../data/currencies.xml.in.h:240 -msgid "Gibraltar" +msgid "Ghana" msgstr "" #: ../data/currencies.xml.in.h:241 -msgid "Guatemalan Quetzal" +msgid "Gibraltar Pound" msgstr "" #: ../data/currencies.xml.in.h:242 -msgid "ar:GTQ" +msgid "ar:GIP" msgstr "" #: ../data/currencies.xml.in.h:243 -msgid "Guatemala" +msgid "Gibraltar" msgstr "" #: ../data/currencies.xml.in.h:244 -msgid "Guernsey Pound" +msgid "Guatemalan Quetzal" msgstr "" #: ../data/currencies.xml.in.h:245 -msgid "ar:GGP" +msgid "ar:GTQ" msgstr "" #: ../data/currencies.xml.in.h:246 -msgid "Guernsey" +msgid "Guatemala" msgstr "" #: ../data/currencies.xml.in.h:247 -msgid "Guinean Franc" +msgid "Guernsey Pound" msgstr "" #: ../data/currencies.xml.in.h:248 -msgid "ar:GNF" +msgid "ar:GGP" msgstr "" #: ../data/currencies.xml.in.h:249 -msgid "Guinea" +msgid "Guernsey" msgstr "" #: ../data/currencies.xml.in.h:250 -msgid "Guyanese Dollar" +msgid "Guinean Franc" msgstr "" #: ../data/currencies.xml.in.h:251 -msgid "ar:GYD" +msgid "ar:GNF" msgstr "" #: ../data/currencies.xml.in.h:252 -msgid "Guyana" +msgid "Guinea" msgstr "" #: ../data/currencies.xml.in.h:253 -msgid "Haitian Gourde" +msgid "Guyanese Dollar" msgstr "" #: ../data/currencies.xml.in.h:254 -msgid "ar:HTG" +msgid "ar:GYD" msgstr "" #: ../data/currencies.xml.in.h:255 -msgid "Haiti" +msgid "Guyana" msgstr "" #: ../data/currencies.xml.in.h:256 -msgid "Honduran Lempira" +msgid "Haitian Gourde" msgstr "" #: ../data/currencies.xml.in.h:257 -msgid "ar:HNL" +msgid "ar:HTG" msgstr "" #: ../data/currencies.xml.in.h:258 -msgid "Honduras" +msgid "Haiti" msgstr "" #: ../data/currencies.xml.in.h:259 -msgid "Iranian Rial" +msgid "Honduran Lempira" msgstr "" #: ../data/currencies.xml.in.h:260 -msgid "ar:IRR,aiu:﷼" +msgid "ar:HNL" msgstr "" #: ../data/currencies.xml.in.h:261 -msgid "Iran" +msgid "Honduras" msgstr "" #: ../data/currencies.xml.in.h:262 -msgid "Iraqi Dinar" +msgid "Iranian Rial" msgstr "" #: ../data/currencies.xml.in.h:263 -msgid "ar:IQD" +msgid "ar:IRR,aiu:﷼" msgstr "" #: ../data/currencies.xml.in.h:264 -msgid "Iraq" +msgid "Iran" msgstr "" #: ../data/currencies.xml.in.h:265 -msgid "Jamaican Dollar" +msgid "Iraqi Dinar" msgstr "" #: ../data/currencies.xml.in.h:266 -msgid "ar:JMD" +msgid "ar:IQD" msgstr "" #: ../data/currencies.xml.in.h:267 -msgid "Jamaica" +msgid "Iraq" msgstr "" #: ../data/currencies.xml.in.h:268 -msgid "Jordanian Dinar" +msgid "Jamaican Dollar" msgstr "" #: ../data/currencies.xml.in.h:269 -msgid "ar:JOD" +msgid "ar:JMD" msgstr "" #: ../data/currencies.xml.in.h:270 -msgid "Jordan" +msgid "Jamaica" msgstr "" #: ../data/currencies.xml.in.h:271 -msgid "Kazakhstani Tenge" +msgid "Jordanian Dinar" msgstr "" #: ../data/currencies.xml.in.h:272 -msgid "ar:KZT,au:₸" +msgid "ar:JOD" msgstr "" #: ../data/currencies.xml.in.h:273 -msgid "Kazakhstan" +msgid "Jordan" msgstr "" #: ../data/currencies.xml.in.h:274 -msgid "North Korean Won" +msgid "Kazakhstani Tenge" msgstr "" #: ../data/currencies.xml.in.h:275 -msgid "ar:KPW" +msgid "ar:KZT,au:₸" msgstr "" #: ../data/currencies.xml.in.h:276 -msgid "North Korea" +msgid "Kazakhstan" msgstr "" #: ../data/currencies.xml.in.h:277 -msgid "Kuwaiti Dinar" +msgid "North Korean Won" msgstr "" #: ../data/currencies.xml.in.h:278 -msgid "ar:KWD" +msgid "ar:KPW" msgstr "" #: ../data/currencies.xml.in.h:279 -msgid "Kuwait" +msgid "North Korea" msgstr "" #: ../data/currencies.xml.in.h:280 -msgid "Kyrgyzstani Som" +msgid "Kuwaiti Dinar" msgstr "" #: ../data/currencies.xml.in.h:281 -msgid "ar:KGS,au:с" +msgid "ar:KWD" msgstr "" #: ../data/currencies.xml.in.h:282 -msgid "Kyrgyzstan" +msgid "Kuwait" msgstr "" #: ../data/currencies.xml.in.h:283 -msgid "Lao Kip" +msgid "Kyrgyzstani Som" msgstr "" #: ../data/currencies.xml.in.h:284 -msgid "ar:LAK,au:₭" +msgid "ar:KGS,au:с" msgstr "" #: ../data/currencies.xml.in.h:285 -msgid "Laos" +msgid "Kyrgyzstan" msgstr "" #: ../data/currencies.xml.in.h:286 -msgid "Lebanese Pound" +msgid "Lao Kip" msgstr "" #: ../data/currencies.xml.in.h:287 -msgid "ar:LBP" +msgid "ar:LAK,au:₭" msgstr "" #: ../data/currencies.xml.in.h:288 -msgid "Lebanon" +msgid "Laos" msgstr "" #: ../data/currencies.xml.in.h:289 -msgid "Lesotho Loti" +msgid "Lebanese Pound" msgstr "" #: ../data/currencies.xml.in.h:290 -msgid "ar:LSL" +msgid "ar:LBP" msgstr "" #: ../data/currencies.xml.in.h:291 -msgid "Lesotho" +msgid "Lebanon" msgstr "" #: ../data/currencies.xml.in.h:292 -msgid "Liberian Dollar" +msgid "Lesotho Loti" msgstr "" #: ../data/currencies.xml.in.h:293 -msgid "ar:LRD" +msgid "ar:LSL" msgstr "" #: ../data/currencies.xml.in.h:294 -msgid "Liberia" +msgid "Lesotho" msgstr "" #: ../data/currencies.xml.in.h:295 -msgid "Libyan Dinar" +msgid "Liberian Dollar" msgstr "" #: ../data/currencies.xml.in.h:296 -msgid "ar:LYD" +msgid "ar:LRD" msgstr "" #: ../data/currencies.xml.in.h:297 -msgid "Libya" +msgid "Liberia" msgstr "" #: ../data/currencies.xml.in.h:298 -msgid "Macanese Pataca" +msgid "Libyan Dinar" msgstr "" #: ../data/currencies.xml.in.h:299 -msgid "ar:MOP" +msgid "ar:LYD" msgstr "" #: ../data/currencies.xml.in.h:300 -msgid "Macau" +msgid "Libya" msgstr "" #: ../data/currencies.xml.in.h:301 -msgid "Macedonian Denar" +msgid "Macanese Pataca" msgstr "" #: ../data/currencies.xml.in.h:302 -msgid "ar:MKD" +msgid "ar:MOP" msgstr "" #: ../data/currencies.xml.in.h:303 -msgid "Macedonia" +msgid "Macau" msgstr "" #: ../data/currencies.xml.in.h:304 -msgid "Malagasy Ariary" +msgid "Macedonian Denar" msgstr "" #: ../data/currencies.xml.in.h:305 -msgid "ar:MGA" +msgid "ar:MKD" msgstr "" #: ../data/currencies.xml.in.h:306 -msgid "Madagascar" +msgid "Macedonia" msgstr "" #: ../data/currencies.xml.in.h:307 -msgid "Malawian Kwacha" +msgid "Malagasy Ariary" msgstr "" #: ../data/currencies.xml.in.h:308 -msgid "ar:MWK" +msgid "ar:MGA" msgstr "" #: ../data/currencies.xml.in.h:309 -msgid "Malawi" +msgid "Madagascar" msgstr "" #: ../data/currencies.xml.in.h:310 -msgid "Maldivian Rufiyaa" +msgid "Malawian Kwacha" msgstr "" #: ../data/currencies.xml.in.h:311 -msgid "ar:MVR" +msgid "ar:MWK" msgstr "" #: ../data/currencies.xml.in.h:312 -msgid "Maldives" +msgid "Malawi" msgstr "" #: ../data/currencies.xml.in.h:313 -msgid "Mauritanian Ouguiya (obsolete)" +msgid "Maldivian Rufiyaa" msgstr "" #: ../data/currencies.xml.in.h:314 -msgid "ar:MRO" +msgid "ar:MVR" msgstr "" #: ../data/currencies.xml.in.h:315 -msgid "Mauritian Rupee" +msgid "Maldives" msgstr "" #: ../data/currencies.xml.in.h:316 -msgid "ar:MUR" +msgid "Mauritanian Ouguiya (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:317 -msgid "Mauritius" +msgid "ar:MRO" msgstr "" #: ../data/currencies.xml.in.h:318 -msgid "Moldovan Leu" +msgid "Mauritian Rupee" msgstr "" #: ../data/currencies.xml.in.h:319 -msgid "ar:MDL" +msgid "ar:MUR" msgstr "" #: ../data/currencies.xml.in.h:320 -msgid "Moldova" +msgid "Mauritius" msgstr "" #: ../data/currencies.xml.in.h:321 -msgid "Mongolian Tögrög" +msgid "Moldovan Leu" msgstr "" #: ../data/currencies.xml.in.h:322 -msgid "ar:MNT,au:₮" +msgid "ar:MDL" msgstr "" #: ../data/currencies.xml.in.h:323 -msgid "Mongolia" +msgid "Moldova" msgstr "" #: ../data/currencies.xml.in.h:324 -msgid "Moroccan Dirham" +msgid "Mongolian Tögrög" msgstr "" #: ../data/currencies.xml.in.h:325 -msgid "ar:MAD" +msgid "ar:MNT,au:₮" msgstr "" #: ../data/currencies.xml.in.h:326 -msgid "Morocco" +msgid "Mongolia" msgstr "" #: ../data/currencies.xml.in.h:327 -msgid "Mozambican Metical" +msgid "Moroccan Dirham" msgstr "" #: ../data/currencies.xml.in.h:328 -msgid "ar:MZN" +msgid "ar:MAD" msgstr "" #: ../data/currencies.xml.in.h:329 -msgid "Mozambique" +msgid "Morocco" msgstr "" #: ../data/currencies.xml.in.h:330 -msgid "Myanmar (Burmese Kyat)" +msgid "Mozambican Metical" msgstr "" #: ../data/currencies.xml.in.h:331 -msgid "ar:MMK" +msgid "ar:MZN" msgstr "" #: ../data/currencies.xml.in.h:332 -msgid "Myanmar" +msgid "Mozambique" msgstr "" #: ../data/currencies.xml.in.h:333 -msgid "Namibian Dollar" +msgid "Myanmar (Burmese Kyat)" msgstr "" #: ../data/currencies.xml.in.h:334 -msgid "ar:NAD" +msgid "ar:MMK" msgstr "" #: ../data/currencies.xml.in.h:335 -msgid "Namibia" +msgid "Myanmar" msgstr "" #: ../data/currencies.xml.in.h:336 -msgid "Nepalese Rupee" +msgid "Namibian Dollar" msgstr "" #: ../data/currencies.xml.in.h:337 -msgid "ar:NPR" +msgid "ar:NAD" msgstr "" #: ../data/currencies.xml.in.h:338 -msgid "Nepal" +msgid "Namibia" msgstr "" #: ../data/currencies.xml.in.h:339 -msgid "Nicaraguan Córdoba" +msgid "Nepalese Rupee" msgstr "" #: ../data/currencies.xml.in.h:340 -msgid "ar:NIO" +msgid "ar:NPR" msgstr "" #: ../data/currencies.xml.in.h:341 -msgid "Nicaragua" +msgid "Nepal" msgstr "" #: ../data/currencies.xml.in.h:342 -msgid "Nigerian Naira" +msgid "Nicaraguan Córdoba" msgstr "" #: ../data/currencies.xml.in.h:343 -msgid "ar:NGN,au:₦" +msgid "ar:NIO" msgstr "" #: ../data/currencies.xml.in.h:344 -msgid "Nigeria" +msgid "Nicaragua" msgstr "" #: ../data/currencies.xml.in.h:345 -msgid "Omani Rial" +msgid "Nigerian Naira" msgstr "" #: ../data/currencies.xml.in.h:346 -msgid "ar:OMR" +msgid "ar:NGN,au:₦" msgstr "" #: ../data/currencies.xml.in.h:347 -msgid "Oman" +msgid "Nigeria" msgstr "" #: ../data/currencies.xml.in.h:348 -msgid "Pakistani Rupee" +msgid "Omani Rial" msgstr "" #: ../data/currencies.xml.in.h:349 -msgid "ar:PKR" +msgid "ar:OMR" msgstr "" #: ../data/currencies.xml.in.h:350 -msgid "Pakistan" +msgid "Oman" msgstr "" #: ../data/currencies.xml.in.h:351 -msgid "Panamaian Balboa" +msgid "Pakistani Rupee" msgstr "" #: ../data/currencies.xml.in.h:352 -msgid "ar:PAB" +msgid "ar:PKR" msgstr "" #: ../data/currencies.xml.in.h:353 -msgid "Panama" +msgid "Pakistan" msgstr "" #: ../data/currencies.xml.in.h:354 -msgid "Papua New Guinean Kina" +msgid "Panamaian Balboa" msgstr "" #: ../data/currencies.xml.in.h:355 -msgid "ar:PGK" +msgid "ar:PAB" msgstr "" #: ../data/currencies.xml.in.h:356 -msgid "Papua New Guinea" +msgid "Panama" msgstr "" #: ../data/currencies.xml.in.h:357 -msgid "Paraguayan Guaraní" +msgid "Papua New Guinean Kina" msgstr "" #: ../data/currencies.xml.in.h:358 -msgid "ar:PYG,au:₲" +msgid "ar:PGK" msgstr "" #: ../data/currencies.xml.in.h:359 -msgid "Paraguay" +msgid "Papua New Guinea" msgstr "" #: ../data/currencies.xml.in.h:360 -msgid "Peruvian Sol" +msgid "Paraguayan Guaraní" msgstr "" #: ../data/currencies.xml.in.h:361 -msgid "ar:PEN" +msgid "ar:PYG,au:₲" msgstr "" #: ../data/currencies.xml.in.h:362 -msgid "Peru" +msgid "Paraguay" msgstr "" #: ../data/currencies.xml.in.h:363 -msgid "Qatari Riyal" +msgid "Peruvian Sol" msgstr "" #: ../data/currencies.xml.in.h:364 -msgid "ar:QAR" +msgid "ar:PEN" msgstr "" #: ../data/currencies.xml.in.h:365 -msgid "Qatar" +msgid "Peru" msgstr "" #: ../data/currencies.xml.in.h:366 -msgid "Rwandan Franc" +msgid "Qatari Riyal" msgstr "" #: ../data/currencies.xml.in.h:367 -msgid "ar:RWF" +msgid "ar:QAR" msgstr "" #: ../data/currencies.xml.in.h:368 -msgid "Rwanda" +msgid "Qatar" msgstr "" #: ../data/currencies.xml.in.h:369 -msgid "São Tomé and Príncipe Dobra" +msgid "Rwandan Franc" msgstr "" #: ../data/currencies.xml.in.h:370 -msgid "ar:STD" +msgid "ar:RWF" msgstr "" #: ../data/currencies.xml.in.h:371 -msgid "Sao Tome and Principe" +msgid "Rwanda" msgstr "" #: ../data/currencies.xml.in.h:372 -msgid "Saudi Riyal" +msgid "São Tomé and Príncipe Dobra" msgstr "" #: ../data/currencies.xml.in.h:373 -msgid "ar:SAR" +msgid "ar:STD" msgstr "" #: ../data/currencies.xml.in.h:374 -msgid "Saudi Arabia" +msgid "Sao Tome and Principe" msgstr "" #: ../data/currencies.xml.in.h:375 -msgid "Serbian Dinar" +msgid "Saudi Riyal" msgstr "" #: ../data/currencies.xml.in.h:376 -msgid "ar:RSD" +msgid "ar:SAR" msgstr "" #: ../data/currencies.xml.in.h:377 -msgid "Serbia" +msgid "Saudi Arabia" msgstr "" #: ../data/currencies.xml.in.h:378 -msgid "Seychellois Rupee" +msgid "Serbian Dinar" msgstr "" #: ../data/currencies.xml.in.h:379 -msgid "ar:SCR" +msgid "ar:RSD" msgstr "" #: ../data/currencies.xml.in.h:380 -msgid "Seychelles" +msgid "Serbia" msgstr "" #: ../data/currencies.xml.in.h:381 -msgid "Sierra Leonean Leone" +msgid "Seychellois Rupee" msgstr "" #: ../data/currencies.xml.in.h:382 -msgid "ar:SLL" +msgid "ar:SCR" msgstr "" #: ../data/currencies.xml.in.h:383 -msgid "Sierra Leone" +msgid "Seychelles" msgstr "" #: ../data/currencies.xml.in.h:384 -msgid "Solomon Islands Dollar" +msgid "Sierra Leonean Leone" msgstr "" #: ../data/currencies.xml.in.h:385 -msgid "ar:SBD" +msgid "ar:SLL" msgstr "" #: ../data/currencies.xml.in.h:386 -msgid "Solomon Islands" +msgid "Sierra Leone" msgstr "" #: ../data/currencies.xml.in.h:387 -msgid "Somali Shilling" +msgid "Solomon Islands Dollar" msgstr "" #: ../data/currencies.xml.in.h:388 -msgid "ar:SOS" +msgid "ar:SBD" msgstr "" #: ../data/currencies.xml.in.h:389 -msgid "Somalia" +msgid "Solomon Islands" msgstr "" #: ../data/currencies.xml.in.h:390 -msgid "Sri Lankan Rupee" +msgid "Somali Shilling" msgstr "" #: ../data/currencies.xml.in.h:391 -msgid "ar:LKR,au:௹" +msgid "ar:SOS" msgstr "" #: ../data/currencies.xml.in.h:392 -msgid "Sri Lanka" +msgid "Somalia" msgstr "" #: ../data/currencies.xml.in.h:393 -msgid "Sudanese Pound" +msgid "Sri Lankan Rupee" msgstr "" #: ../data/currencies.xml.in.h:394 -msgid "ar:SDG" +msgid "ar:LKR,au:௹" msgstr "" #: ../data/currencies.xml.in.h:395 -msgid "Sudan" +msgid "Sri Lanka" msgstr "" #: ../data/currencies.xml.in.h:396 -msgid "Surinamese Dollar" +msgid "Sudanese Pound" msgstr "" #: ../data/currencies.xml.in.h:397 -msgid "ar:SRD" +msgid "ar:SDG" msgstr "" #: ../data/currencies.xml.in.h:398 -msgid "Suriname" +msgid "Sudan" msgstr "" #: ../data/currencies.xml.in.h:399 -msgid "Swazi Lilangeni" +msgid "Surinamese Dollar" msgstr "" #: ../data/currencies.xml.in.h:400 -msgid "ar:SZL" +msgid "ar:SRD" msgstr "" #: ../data/currencies.xml.in.h:401 -msgid "Swaziland" +msgid "Suriname" msgstr "" #: ../data/currencies.xml.in.h:402 -msgid "Syrian Pound" +msgid "Swazi Lilangeni" msgstr "" #: ../data/currencies.xml.in.h:403 -msgid "ar:SYP" +msgid "ar:SZL" msgstr "" #: ../data/currencies.xml.in.h:404 -msgid "Syria" +msgid "Swaziland" msgstr "" #: ../data/currencies.xml.in.h:405 -msgid "New Taiwan Dollar" +msgid "Syrian Pound" msgstr "" #: ../data/currencies.xml.in.h:406 -msgid "ar:TWD" +msgid "ar:SYP" msgstr "" #: ../data/currencies.xml.in.h:407 -msgid "Taiwan" +msgid "Syria" msgstr "" #: ../data/currencies.xml.in.h:408 -msgid "Tajikistani Somoni" +msgid "New Taiwan Dollar" msgstr "" #: ../data/currencies.xml.in.h:409 -msgid "ar:TJS" +msgid "ar:TWD" msgstr "" #: ../data/currencies.xml.in.h:410 -msgid "Tajikistan" +msgid "Taiwan" msgstr "" #: ../data/currencies.xml.in.h:411 -msgid "Tanzanian Shilling" +msgid "Tajikistani Somoni" msgstr "" #: ../data/currencies.xml.in.h:412 -msgid "ar:TZS" +msgid "ar:TJS" msgstr "" #: ../data/currencies.xml.in.h:413 -msgid "Tanzania" +msgid "Tajikistan" msgstr "" #: ../data/currencies.xml.in.h:414 -msgid "Tongan Paʻanga" +msgid "Tanzanian Shilling" msgstr "" #: ../data/currencies.xml.in.h:415 -msgid "ar:TOP" +msgid "ar:TZS" msgstr "" #: ../data/currencies.xml.in.h:416 -msgid "Tonga" +msgid "Tanzania" msgstr "" #: ../data/currencies.xml.in.h:417 -msgid "Trinidad and Tobago dollar" +msgid "Tongan Paʻanga" msgstr "" #: ../data/currencies.xml.in.h:418 -msgid "ar:TTD" +msgid "ar:TOP" msgstr "" #: ../data/currencies.xml.in.h:419 -msgid "Trinidad and Tobago" +msgid "Tonga" msgstr "" #: ../data/currencies.xml.in.h:420 -msgid "Tunisian Dinar" +msgid "Trinidad and Tobago dollar" msgstr "" #: ../data/currencies.xml.in.h:421 -msgid "ar:TND" +msgid "ar:TTD" msgstr "" #: ../data/currencies.xml.in.h:422 -msgid "Tunisia" +msgid "Trinidad and Tobago" msgstr "" #: ../data/currencies.xml.in.h:423 -msgid "Turkmenistan Manat" +msgid "Tunisian Dinar" msgstr "" #: ../data/currencies.xml.in.h:424 -msgid "ar:TMT" +msgid "ar:TND" msgstr "" #: ../data/currencies.xml.in.h:425 -msgid "Turkmenistan" +msgid "Tunisia" msgstr "" #: ../data/currencies.xml.in.h:426 -msgid "Ugandan Shilling" +msgid "Turkmenistan Manat" msgstr "" #: ../data/currencies.xml.in.h:427 -msgid "ar:UGX" +msgid "ar:TMT" msgstr "" #: ../data/currencies.xml.in.h:428 -msgid "Uganda" +msgid "Turkmenistan" msgstr "" #: ../data/currencies.xml.in.h:429 -msgid "Ukrainian Hryvnia" +msgid "Ugandan Shilling" msgstr "" #: ../data/currencies.xml.in.h:430 -msgid "ar:UAH,au:₴" +msgid "ar:UGX" msgstr "" #: ../data/currencies.xml.in.h:431 -msgid "Ukraine" +msgid "Uganda" msgstr "" #: ../data/currencies.xml.in.h:432 -msgid "United Arab Emirates Dirham" +msgid "Ukrainian Hryvnia" msgstr "" #: ../data/currencies.xml.in.h:433 -msgid "ar:AED" +msgid "ar:UAH,au:₴" msgstr "" #: ../data/currencies.xml.in.h:434 -msgid "United Arab Emirates" +msgid "Ukraine" msgstr "" #: ../data/currencies.xml.in.h:435 -msgid "Uruguayan Peso" +msgid "United Arab Emirates Dirham" msgstr "" #: ../data/currencies.xml.in.h:436 -msgid "ar:UYU" +msgid "ar:AED" msgstr "" #: ../data/currencies.xml.in.h:437 -msgid "Uruguay" +msgid "United Arab Emirates" msgstr "" #: ../data/currencies.xml.in.h:438 -msgid "Uzbekistan Soʻm" +msgid "Uruguayan Peso" msgstr "" #: ../data/currencies.xml.in.h:439 -msgid "ar:UZS" +msgid "ar:UYU" msgstr "" #: ../data/currencies.xml.in.h:440 -msgid "Uzbekistan" +msgid "Uruguay" msgstr "" #: ../data/currencies.xml.in.h:441 -msgid "Vanuatu Vatu" +msgid "Uzbekistan Soʻm" msgstr "" #: ../data/currencies.xml.in.h:442 -msgid "ar:VUV" +msgid "ar:UZS" msgstr "" #: ../data/currencies.xml.in.h:443 -msgid "Vanuatu" +msgid "Uzbekistan" msgstr "" #: ../data/currencies.xml.in.h:444 -msgid "Venezuelan Bolívar (obsolete)" +msgid "Vanuatu Vatu" msgstr "" #: ../data/currencies.xml.in.h:445 -msgid "ar:VEF" +msgid "ar:VUV" msgstr "" #: ../data/currencies.xml.in.h:446 -msgid "Vietnamese Dồng" +msgid "Vanuatu" msgstr "" #: ../data/currencies.xml.in.h:447 -msgid "ar:VND,au:₫" +msgid "Venezuelan Bolívar (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:448 -msgid "Vietnam" +msgid "ar:VEF" msgstr "" #: ../data/currencies.xml.in.h:449 -msgid "Yemeni Rial" +msgid "Vietnamese Dồng" msgstr "" #: ../data/currencies.xml.in.h:450 -msgid "ar:YER" +msgid "ar:VND,au:₫" msgstr "" #: ../data/currencies.xml.in.h:451 -msgid "Yemen" +msgid "Vietnam" msgstr "" #: ../data/currencies.xml.in.h:452 -msgid "Zambian Kwacha (obsolete)" +msgid "Yemeni Rial" msgstr "" #: ../data/currencies.xml.in.h:453 -msgid "ar:ZMK" +msgid "ar:YER" msgstr "" #: ../data/currencies.xml.in.h:454 -msgid "Euro Cent" +msgid "Yemen" msgstr "" #: ../data/currencies.xml.in.h:455 -msgid "r:eurocent,p:eurocents" +msgid "Zambian Kwacha (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:456 -msgid "Cent (USD)" +msgid "ar:ZMK" msgstr "" #: ../data/currencies.xml.in.h:457 -msgid "au:¢,r:cent,p:cents" +msgid "Euro Cent" msgstr "" #: ../data/currencies.xml.in.h:458 -msgid "Belgian Franc (obsolete)" +msgid "r:eurocent,p:eurocents" msgstr "" #: ../data/currencies.xml.in.h:459 -msgid "ar:BEF" +msgid "Cent (USD)" msgstr "" #: ../data/currencies.xml.in.h:460 -msgid "Greek Drachma (obsolete)" +msgid "au:¢,r:cent,p:cents" msgstr "" #: ../data/currencies.xml.in.h:461 -msgid "ar:GRD,au:₯" +msgid "Belgian Franc (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:462 -msgid "French Franc (obsolete)" +msgid "ar:BEF" msgstr "" #: ../data/currencies.xml.in.h:463 -msgid "ar:FRF,au:₣" +msgid "Greek Drachma (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:464 -msgid "Italian Lira (obsolete)" +msgid "ar:GRD,au:₯" msgstr "" #: ../data/currencies.xml.in.h:465 -msgid "ar:ITL" +msgid "French Franc (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:466 -msgid "Dutch Guilder (obsolete)" +msgid "ar:FRF,au:₣" msgstr "" #: ../data/currencies.xml.in.h:467 -msgid "ar:NLG" +msgid "Italian Lira (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:468 -msgid "Portuguese Escudo (obsolete)" +msgid "ar:ITL" msgstr "" #: ../data/currencies.xml.in.h:469 -msgid "ar:PTE" +msgid "Dutch Guilder (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:470 -msgid "Deutsche Mark (obsolete)" +msgid "ar:NLG" msgstr "" #: ../data/currencies.xml.in.h:471 -msgid "ar:DEM" +msgid "Portuguese Escudo (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:472 -msgid "Spanish Peseta (obsolete)" +msgid "ar:PTE" msgstr "" #: ../data/currencies.xml.in.h:473 -msgid "ar:ESP,au:₧" +msgid "Deutsche Mark (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:474 -msgid "Irish Pound (obsolete)" +msgid "ar:DEM" msgstr "" #: ../data/currencies.xml.in.h:475 -msgid "ar:IEP" +msgid "Spanish Peseta (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:476 -msgid "Luxembourg Franc (obsolete)" +msgid "ar:ESP,au:₧" msgstr "" #: ../data/currencies.xml.in.h:477 -msgid "ar:LUF" +msgid "Irish Pound (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:478 -msgid "Austrian Schilling (obsolete)" +msgid "ar:IEP" msgstr "" #: ../data/currencies.xml.in.h:479 -msgid "ar:ATS" +msgid "Luxembourg Franc (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:480 -msgid "Finnish Markka (obsolete)" +msgid "ar:LUF" msgstr "" #: ../data/currencies.xml.in.h:481 -msgid "ar:FIM" +msgid "Austrian Schilling (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:482 -msgid "Slovenian Tolar (obsolete)" +msgid "ar:ATS" msgstr "" #: ../data/currencies.xml.in.h:483 -msgid "ar:SIT" +msgid "Finnish Markka (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:484 -msgid "Cypriot Pound (obsolete)" +msgid "ar:FIM" msgstr "" #: ../data/currencies.xml.in.h:485 -msgid "ar:CYP" +msgid "Slovenian Tolar (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:486 -msgid "Estonian Kroon (obsolete)" +msgid "ar:SIT" msgstr "" #: ../data/currencies.xml.in.h:487 -msgid "ar:EEK" +msgid "Cypriot Pound (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:488 -msgid "Slovak Koruna (obsolete)" +msgid "ar:CYP" msgstr "" #: ../data/currencies.xml.in.h:489 -msgid "ar:SKK" +msgid "Estonian Kroon (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:490 -msgid "Maltese Lira (obsolete)" +msgid "ar:EEK" msgstr "" #: ../data/currencies.xml.in.h:491 -msgid "ar:MTL" +msgid "Slovak Koruna (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:492 -msgid "Latvian Lats (obsolete)" +msgid "ar:SKK" msgstr "" #: ../data/currencies.xml.in.h:493 -msgid "ar:LVL" +msgid "Maltese Lira (obsolete)" msgstr "" #: ../data/currencies.xml.in.h:494 -msgid "Lithuanian Litas (obsolete)" +msgid "ar:MTL" msgstr "" #: ../data/currencies.xml.in.h:495 +msgid "Latvian Lats (obsolete)" +msgstr "" + +#: ../data/currencies.xml.in.h:496 +msgid "ar:LVL" +msgstr "" + +#: ../data/currencies.xml.in.h:497 +msgid "Lithuanian Litas (obsolete)" +msgstr "" + +#: ../data/currencies.xml.in.h:498 msgid "ar:LTL" msgstr "" @@ -2043,7 +2055,7 @@ msgid "!datasets!r:number" msgstr "" -#: ../data/datasets.xml.in.h:13 ../data/functions.xml.in.h:709 +#: ../data/datasets.xml.in.h:13 ../data/functions.xml.in.h:716 msgid "Name" msgstr "" @@ -2067,7 +2079,7 @@ msgid "r:class" msgstr "" -#: ../data/datasets.xml.in.h:18 ../data/functions.xml.in.h:424 +#: ../data/datasets.xml.in.h:18 ../data/functions.xml.in.h:431 msgid "Weight" msgstr "" @@ -3585,15 +3597,17 @@ msgstr "" #: ../data/functions.xml.in.h:216 -msgid "Fibonacci Number" +msgid "Bernoulli Number/Polynomial" msgstr "" #: ../data/functions.xml.in.h:217 -msgid "r:fibonacci" +msgid "" +"Returns the nth Bernoulli number or polynomial (if the second argument is " +"non-zero)." msgstr "" #: ../data/functions.xml.in.h:218 -msgid "Returns the n-th term of the Fibonacci sequence." +msgid "r:bernoulli" msgstr "" #: ../data/functions.xml.in.h:219 @@ -3601,70 +3615,82 @@ msgstr "" #: ../data/functions.xml.in.h:220 -msgid "Rounding" +msgid "Fibonacci Number" msgstr "" #: ../data/functions.xml.in.h:221 -msgid "Round" +msgid "r:fibonacci" msgstr "" #: ../data/functions.xml.in.h:222 -msgid "r:round" +msgid "Returns the n-th term of the Fibonacci sequence." msgstr "" #: ../data/functions.xml.in.h:223 -msgid "Round Downwards" +msgid "Rounding" msgstr "" #: ../data/functions.xml.in.h:224 -msgid "r:floor" +msgid "Round" msgstr "" #: ../data/functions.xml.in.h:225 -msgid "Round Upwards" +msgid "r:round" msgstr "" #: ../data/functions.xml.in.h:226 -msgid "r:ceil" +msgid "Round Downwards" msgstr "" #: ../data/functions.xml.in.h:227 -msgid "Round Towards Zero" +msgid "r:floor" msgstr "" #: ../data/functions.xml.in.h:228 -msgid "r:trunc" +msgid "Round Upwards" msgstr "" #: ../data/functions.xml.in.h:229 -msgid "Integer Part" +msgid "r:ceil" msgstr "" #: ../data/functions.xml.in.h:230 -msgid "r:int" +msgid "Round Towards Zero" msgstr "" #: ../data/functions.xml.in.h:231 -msgid "Fractional Part" +msgid "r:trunc" msgstr "" #: ../data/functions.xml.in.h:232 -msgid "r:frac" +msgid "Integer Part" msgstr "" #: ../data/functions.xml.in.h:233 -msgid "Number Bases" +msgid "r:int" msgstr "" #: ../data/functions.xml.in.h:234 -msgid "Number Base" +msgid "Fractional Part" msgstr "" #: ../data/functions.xml.in.h:235 -msgid "r:base" +msgid "r:frac" msgstr "" #: ../data/functions.xml.in.h:236 +msgid "Number Bases" +msgstr "" + +#: ../data/functions.xml.in.h:237 +msgid "Number Base" +msgstr "" + +#: ../data/functions.xml.in.h:238 +msgid "r:base" +msgstr "" + +#: ../data/functions.xml.in.h:239 msgid "" "Returns a value from an expression using the specified number base (radix). " "For bases between -62 and 62 full mathematical expressions (including " @@ -3685,769 +3711,785 @@ "selected, the specified expression is always converted to a single number." msgstr "" -#: ../data/functions.xml.in.h:237 +#: ../data/functions.xml.in.h:240 msgid "Set of digits" msgstr "" -#: ../data/functions.xml.in.h:238 +#: ../data/functions.xml.in.h:241 msgid "Binary" msgstr "" -#: ../data/functions.xml.in.h:239 +#: ../data/functions.xml.in.h:242 msgid "r:bin" msgstr "" -#: ../data/functions.xml.in.h:240 +#: ../data/functions.xml.in.h:243 msgid "" "Returns a value from a binary expression. If two's complement is true, " "numbers beginning with '1' is interpreted as negative binary numbers using " "two's complement." msgstr "" -#: ../data/functions.xml.in.h:241 +#: ../data/functions.xml.in.h:244 msgid "Binary number" msgstr "" -#: ../data/functions.xml.in.h:242 +#: ../data/functions.xml.in.h:245 msgid "Two's complement" msgstr "" -#: ../data/functions.xml.in.h:243 +#: ../data/functions.xml.in.h:246 msgid "Octal" msgstr "" -#: ../data/functions.xml.in.h:244 +#: ../data/functions.xml.in.h:247 msgid "r:oct" msgstr "" -#: ../data/functions.xml.in.h:245 +#: ../data/functions.xml.in.h:248 msgid "Returns a value from an octal expression." msgstr "" -#: ../data/functions.xml.in.h:246 +#: ../data/functions.xml.in.h:249 msgid "Octal number" msgstr "" -#: ../data/functions.xml.in.h:247 +#: ../data/functions.xml.in.h:250 msgid "Decimal" msgstr "" -#: ../data/functions.xml.in.h:248 +#: ../data/functions.xml.in.h:251 msgid "r:dec" msgstr "" -#: ../data/functions.xml.in.h:249 +#: ../data/functions.xml.in.h:252 msgid "Returns a value from a decimal expression." msgstr "" -#: ../data/functions.xml.in.h:250 +#: ../data/functions.xml.in.h:253 msgid "Decimal number" msgstr "" -#: ../data/functions.xml.in.h:251 +#: ../data/functions.xml.in.h:254 msgid "Hexadecimal" msgstr "" -#: ../data/functions.xml.in.h:252 +#: ../data/functions.xml.in.h:255 msgid "r:hex" msgstr "" -#: ../data/functions.xml.in.h:253 +#: ../data/functions.xml.in.h:256 msgid "" "Returns a value from a hexadecimal expression. If two's complement is true, " "numbers beginning with 8 or higher is interpreted as negative hexadecimal " "numbers using two's complement." msgstr "" -#: ../data/functions.xml.in.h:254 +#: ../data/functions.xml.in.h:257 msgid "Hexadecimal number" msgstr "" -#: ../data/functions.xml.in.h:255 +#: ../data/functions.xml.in.h:258 msgid "Bijective base-26" msgstr "" -#: ../data/functions.xml.in.h:256 +#: ../data/functions.xml.in.h:259 msgid "r:bijective" msgstr "" -#: ../data/functions.xml.in.h:257 +#: ../data/functions.xml.in.h:260 msgid "" "Returns a value from an expression in bijective base-26. Conversion in the " "opposite direction is also supported." msgstr "" -#: ../data/functions.xml.in.h:258 +#: ../data/functions.xml.in.h:261 msgid "Bijective base-26 number" msgstr "" -#: ../data/functions.xml.in.h:259 +#: ../data/functions.xml.in.h:262 msgid "Integers" msgstr "" -#: ../data/functions.xml.in.h:260 +#: ../data/functions.xml.in.h:263 msgid "Even" msgstr "" -#: ../data/functions.xml.in.h:261 +#: ../data/functions.xml.in.h:264 msgid "r:even" msgstr "" -#: ../data/functions.xml.in.h:262 +#: ../data/functions.xml.in.h:265 msgid "Odd" msgstr "" -#: ../data/functions.xml.in.h:263 +#: ../data/functions.xml.in.h:266 msgid "r:odd" msgstr "" -#: ../data/functions.xml.in.h:264 +#: ../data/functions.xml.in.h:267 msgid "Special Functions" msgstr "" -#: ../data/functions.xml.in.h:265 +#: ../data/functions.xml.in.h:268 msgid "Gamma Function" msgstr "" -#: ../data/functions.xml.in.h:266 +#: ../data/functions.xml.in.h:269 msgid "r:gamma" msgstr "" -#: ../data/functions.xml.in.h:267 +#: ../data/functions.xml.in.h:270 msgid "Digamma Function" msgstr "" -#: ../data/functions.xml.in.h:268 +#: ../data/functions.xml.in.h:271 msgid "r:digamma,psi" msgstr "" -#: ../data/functions.xml.in.h:269 +#: ../data/functions.xml.in.h:272 msgid "Beta Function" msgstr "" -#: ../data/functions.xml.in.h:270 +#: ../data/functions.xml.in.h:273 msgid "r:beta" msgstr "" -#: ../data/functions.xml.in.h:271 +#: ../data/functions.xml.in.h:274 msgid "Error Function" msgstr "" -#: ../data/functions.xml.in.h:272 +#: ../data/functions.xml.in.h:275 msgid "r:erf" msgstr "" -#: ../data/functions.xml.in.h:273 +#: ../data/functions.xml.in.h:276 msgid "Complementary Error Function" msgstr "" -#: ../data/functions.xml.in.h:274 +#: ../data/functions.xml.in.h:277 msgid "r:erfc" msgstr "" -#: ../data/functions.xml.in.h:275 +#: ../data/functions.xml.in.h:278 +msgid "Imaginary Error Function" +msgstr "" + +#: ../data/functions.xml.in.h:279 +msgid "r:erfi" +msgstr "" + +#: ../data/functions.xml.in.h:280 msgid "Polylogarithm" msgstr "" -#: ../data/functions.xml.in.h:276 +#: ../data/functions.xml.in.h:281 msgid "rc:Li,polylog" msgstr "" -#: ../data/functions.xml.in.h:277 +#: ../data/functions.xml.in.h:282 msgid "Order" msgstr "" -#: ../data/functions.xml.in.h:278 +#: ../data/functions.xml.in.h:283 msgid "Argument" msgstr "" -#: ../data/functions.xml.in.h:279 +#: ../data/functions.xml.in.h:284 msgid "Airy Function" msgstr "" -#: ../data/functions.xml.in.h:280 +#: ../data/functions.xml.in.h:285 msgid "r:airy" msgstr "" -#: ../data/functions.xml.in.h:281 +#: ../data/functions.xml.in.h:286 msgid "Bessel Function of the First Kind" msgstr "" -#: ../data/functions.xml.in.h:282 +#: ../data/functions.xml.in.h:287 msgid "r:besselj" msgstr "" -#: ../data/functions.xml.in.h:283 +#: ../data/functions.xml.in.h:288 msgid "Bessel Function of the Second Kind" msgstr "" -#: ../data/functions.xml.in.h:284 +#: ../data/functions.xml.in.h:289 msgid "r:bessely" msgstr "" -#: ../data/functions.xml.in.h:285 +#: ../data/functions.xml.in.h:290 msgid "Riemann Zeta" msgstr "" -#: ../data/functions.xml.in.h:286 +#: ../data/functions.xml.in.h:291 +msgid "Calculates Hurwitz zeta function if the second argument is not 1." +msgstr "" + +#: ../data/functions.xml.in.h:292 msgid "r:zeta" msgstr "" -#: ../data/functions.xml.in.h:287 +#: ../data/functions.xml.in.h:293 msgid "Integral point" msgstr "" -#: ../data/functions.xml.in.h:288 +#: ../data/functions.xml.in.h:294 +msgid "Hurwitz zeta argument" +msgstr "" + +#: ../data/functions.xml.in.h:295 msgid "Kronecker Delta" msgstr "" -#: ../data/functions.xml.in.h:289 +#: ../data/functions.xml.in.h:296 msgid "r:kronecker" msgstr "" -#: ../data/functions.xml.in.h:290 +#: ../data/functions.xml.in.h:297 msgid "Returns 0 if i != j and 1 if i = j." msgstr "" -#: ../data/functions.xml.in.h:291 +#: ../data/functions.xml.in.h:298 msgid "Value 1 (i)" msgstr "" -#: ../data/functions.xml.in.h:292 +#: ../data/functions.xml.in.h:299 msgid "Value 2 (j)" msgstr "" -#: ../data/functions.xml.in.h:293 +#: ../data/functions.xml.in.h:300 msgid "Logit Transformation" msgstr "" -#: ../data/functions.xml.in.h:294 +#: ../data/functions.xml.in.h:301 msgid "r:logit" msgstr "" -#: ../data/functions.xml.in.h:295 +#: ../data/functions.xml.in.h:302 msgid "Sigmoid Function" msgstr "" -#: ../data/functions.xml.in.h:296 +#: ../data/functions.xml.in.h:303 msgid "r:sigmoid" msgstr "" -#: ../data/functions.xml.in.h:297 +#: ../data/functions.xml.in.h:304 msgid "Step Functions" msgstr "" -#: ../data/functions.xml.in.h:298 +#: ../data/functions.xml.in.h:305 msgid "Heaviside Step Function" msgstr "" -#: ../data/functions.xml.in.h:299 +#: ../data/functions.xml.in.h:306 msgid "r:heaviside,au:θ" msgstr "" -#: ../data/functions.xml.in.h:300 +#: ../data/functions.xml.in.h:307 msgid "" "Discontinuous function also known as \"unit step function\". Returns 0 if x " "< 0, 1 if x > 0, and 1/2 if x = 0." msgstr "" -#: ../data/functions.xml.in.h:301 +#: ../data/functions.xml.in.h:308 msgid "Dirac Delta Function" msgstr "" -#: ../data/functions.xml.in.h:302 +#: ../data/functions.xml.in.h:309 msgid "r:dirac,au:δ" msgstr "" -#: ../data/functions.xml.in.h:303 +#: ../data/functions.xml.in.h:310 msgid "Returns 0 if x is non-zero, and infinity if x is zero." msgstr "" -#: ../data/functions.xml.in.h:304 +#: ../data/functions.xml.in.h:311 msgid "Ramp Function" msgstr "" -#: ../data/functions.xml.in.h:305 +#: ../data/functions.xml.in.h:312 msgid "r:ramp" msgstr "" -#: ../data/functions.xml.in.h:306 +#: ../data/functions.xml.in.h:313 msgid "Rectangular Function" msgstr "" -#: ../data/functions.xml.in.h:307 +#: ../data/functions.xml.in.h:314 msgid "r:rectangular" msgstr "" -#: ../data/functions.xml.in.h:308 +#: ../data/functions.xml.in.h:315 msgid "Triangular Function" msgstr "" -#: ../data/functions.xml.in.h:309 +#: ../data/functions.xml.in.h:316 msgid "r:triangular" msgstr "" -#: ../data/functions.xml.in.h:310 +#: ../data/functions.xml.in.h:317 msgid "Complex Numbers" msgstr "" -#: ../data/functions.xml.in.h:311 +#: ../data/functions.xml.in.h:318 msgid "Real Part" msgstr "" -#: ../data/functions.xml.in.h:312 +#: ../data/functions.xml.in.h:319 msgid "r:re,au:ℜ" msgstr "" -#: ../data/functions.xml.in.h:313 +#: ../data/functions.xml.in.h:320 msgid "Complex number" msgstr "" -#: ../data/functions.xml.in.h:314 +#: ../data/functions.xml.in.h:321 msgid "Imaginary Part" msgstr "" -#: ../data/functions.xml.in.h:315 +#: ../data/functions.xml.in.h:322 msgid "r:im,au:ℑ" msgstr "" -#: ../data/functions.xml.in.h:316 +#: ../data/functions.xml.in.h:323 msgid "Principal Argument" msgstr "" -#: ../data/functions.xml.in.h:317 +#: ../data/functions.xml.in.h:324 msgid "r:arg" msgstr "" -#: ../data/functions.xml.in.h:318 +#: ../data/functions.xml.in.h:325 msgid "Complex Conjugate" msgstr "" -#: ../data/functions.xml.in.h:319 +#: ../data/functions.xml.in.h:326 msgid "r:conj" msgstr "" -#: ../data/functions.xml.in.h:320 +#: ../data/functions.xml.in.h:327 msgid "Exponents & Logarithms" msgstr "" -#: ../data/functions.xml.in.h:321 +#: ../data/functions.xml.in.h:328 msgid "Square Root" msgstr "" -#: ../data/functions.xml.in.h:322 +#: ../data/functions.xml.in.h:329 msgid "au:√,r:sqrt" msgstr "" -#: ../data/functions.xml.in.h:323 +#: ../data/functions.xml.in.h:330 msgid "" "Returns the principal square root (for positive values the positive root is " "returned)." msgstr "" -#: ../data/functions.xml.in.h:324 +#: ../data/functions.xml.in.h:331 msgid "Cube Root" msgstr "" -#: ../data/functions.xml.in.h:325 +#: ../data/functions.xml.in.h:332 msgid "au:∛,r:cbrt" msgstr "" -#: ../data/functions.xml.in.h:326 +#: ../data/functions.xml.in.h:333 msgid "Returns the third real root." msgstr "" -#: ../data/functions.xml.in.h:327 +#: ../data/functions.xml.in.h:334 msgid "Nth root" msgstr "" -#: ../data/functions.xml.in.h:328 +#: ../data/functions.xml.in.h:335 msgid "r:root" msgstr "" -#: ../data/functions.xml.in.h:329 +#: ../data/functions.xml.in.h:336 msgid "" "Returns the real root. For negative values the degree must be odd. Complex " "values are not allowed." msgstr "" -#: ../data/functions.xml.in.h:330 ../data/units.xml.in.h:65 +#: ../data/functions.xml.in.h:337 ../data/units.xml.in.h:65 msgid "Degree" msgstr "" -#: ../data/functions.xml.in.h:331 +#: ../data/functions.xml.in.h:338 msgid "Square" msgstr "" -#: ../data/functions.xml.in.h:332 +#: ../data/functions.xml.in.h:339 msgid "r:sq" msgstr "" -#: ../data/functions.xml.in.h:333 +#: ../data/functions.xml.in.h:340 msgid "Exponential (e^x)" msgstr "" -#: ../data/functions.xml.in.h:334 +#: ../data/functions.xml.in.h:341 msgid "r:exp" msgstr "" -#: ../data/functions.xml.in.h:335 +#: ../data/functions.xml.in.h:342 msgid "Natural Logarithm" msgstr "" -#: ../data/functions.xml.in.h:336 +#: ../data/functions.xml.in.h:343 msgid "r:ln" msgstr "" -#: ../data/functions.xml.in.h:337 +#: ../data/functions.xml.in.h:344 msgid "Base-N Logarithm" msgstr "" -#: ../data/functions.xml.in.h:338 +#: ../data/functions.xml.in.h:345 msgid "r:log" msgstr "" -#: ../data/functions.xml.in.h:339 +#: ../data/functions.xml.in.h:346 msgid "Lambert W Function (Omega Function, Product Log)" msgstr "" -#: ../data/functions.xml.in.h:340 +#: ../data/functions.xml.in.h:347 msgid "r:lambertw,productlog" msgstr "" -#: ../data/functions.xml.in.h:341 +#: ../data/functions.xml.in.h:348 msgid "" "Returns the inverse function for mx*e^x as ln() does for e^x. Only the " "principal branch and real valued results are currently supported." msgstr "" -#: ../data/functions.xml.in.h:342 +#: ../data/functions.xml.in.h:349 msgid "Branch" msgstr "" -#: ../data/functions.xml.in.h:343 +#: ../data/functions.xml.in.h:350 msgid "Complex Exponential (Cis)" msgstr "" -#: ../data/functions.xml.in.h:344 +#: ../data/functions.xml.in.h:351 msgid "r:cis" msgstr "" -#: ../data/functions.xml.in.h:345 +#: ../data/functions.xml.in.h:352 msgid "Base-2 Logarithm" msgstr "" -#: ../data/functions.xml.in.h:346 +#: ../data/functions.xml.in.h:353 msgid "rs:log2" msgstr "" -#: ../data/functions.xml.in.h:347 +#: ../data/functions.xml.in.h:354 msgid "Returns the base n logarithm." msgstr "" -#: ../data/functions.xml.in.h:348 +#: ../data/functions.xml.in.h:355 msgid "Base-10 Logarithm" msgstr "" -#: ../data/functions.xml.in.h:349 +#: ../data/functions.xml.in.h:356 msgid "rs:log10" msgstr "" -#: ../data/functions.xml.in.h:350 +#: ../data/functions.xml.in.h:357 msgid "2 raised to the power X" msgstr "" -#: ../data/functions.xml.in.h:351 +#: ../data/functions.xml.in.h:358 msgid "rs:exp2" msgstr "" -#: ../data/functions.xml.in.h:352 +#: ../data/functions.xml.in.h:359 msgid "10 raised to the power X" msgstr "" -#: ../data/functions.xml.in.h:353 +#: ../data/functions.xml.in.h:360 msgid "rs:exp10" msgstr "" -#: ../data/functions.xml.in.h:354 +#: ../data/functions.xml.in.h:361 msgid "X raised to the power Y" msgstr "" -#: ../data/functions.xml.in.h:355 +#: ../data/functions.xml.in.h:362 msgid "r:pow" msgstr "" -#: ../data/functions.xml.in.h:356 +#: ../data/functions.xml.in.h:363 msgid "Square root (x * pi)" msgstr "" -#: ../data/functions.xml.in.h:357 +#: ../data/functions.xml.in.h:364 msgid "r:sqrtpi" msgstr "" -#: ../data/functions.xml.in.h:358 +#: ../data/functions.xml.in.h:365 msgid "Returns the non-negative square root of x * pi" msgstr "" -#: ../data/functions.xml.in.h:359 +#: ../data/functions.xml.in.h:366 msgid "Non-negative value" msgstr "" -#: ../data/functions.xml.in.h:360 +#: ../data/functions.xml.in.h:367 msgid "Trigonometry" msgstr "" -#: ../data/functions.xml.in.h:361 +#: ../data/functions.xml.in.h:368 msgid "Sine" msgstr "" -#: ../data/functions.xml.in.h:362 +#: ../data/functions.xml.in.h:369 msgid "r:sin" msgstr "" -#: ../data/functions.xml.in.h:363 +#: ../data/functions.xml.in.h:370 msgid "Angle" msgstr "" -#: ../data/functions.xml.in.h:364 +#: ../data/functions.xml.in.h:371 msgid "Cosine" msgstr "" -#: ../data/functions.xml.in.h:365 +#: ../data/functions.xml.in.h:372 msgid "r:cos" msgstr "" -#: ../data/functions.xml.in.h:366 +#: ../data/functions.xml.in.h:373 msgid "Tangent" msgstr "" -#: ../data/functions.xml.in.h:367 +#: ../data/functions.xml.in.h:374 msgid "r:tan" msgstr "" -#: ../data/functions.xml.in.h:368 +#: ../data/functions.xml.in.h:375 msgid "Inverse Sine" msgstr "" -#: ../data/functions.xml.in.h:369 +#: ../data/functions.xml.in.h:376 msgid "r:asin" msgstr "" -#: ../data/functions.xml.in.h:370 +#: ../data/functions.xml.in.h:377 msgid "Inverse Cosine" msgstr "" -#: ../data/functions.xml.in.h:371 +#: ../data/functions.xml.in.h:378 msgid "r:acos" msgstr "" -#: ../data/functions.xml.in.h:372 +#: ../data/functions.xml.in.h:379 msgid "Inverse Tangent" msgstr "" -#: ../data/functions.xml.in.h:373 +#: ../data/functions.xml.in.h:380 msgid "r:atan" msgstr "" -#: ../data/functions.xml.in.h:374 +#: ../data/functions.xml.in.h:381 msgid "Hyperbolic Sine" msgstr "" -#: ../data/functions.xml.in.h:375 +#: ../data/functions.xml.in.h:382 msgid "r:sinh" msgstr "" -#: ../data/functions.xml.in.h:376 +#: ../data/functions.xml.in.h:383 msgid "Hyperbolic Cosine" msgstr "" -#: ../data/functions.xml.in.h:377 +#: ../data/functions.xml.in.h:384 msgid "r:cosh" msgstr "" -#: ../data/functions.xml.in.h:378 +#: ../data/functions.xml.in.h:385 msgid "Hyperbolic Tangent" msgstr "" -#: ../data/functions.xml.in.h:379 +#: ../data/functions.xml.in.h:386 msgid "r:tanh" msgstr "" -#: ../data/functions.xml.in.h:380 +#: ../data/functions.xml.in.h:387 msgid "Inverse Hyperbolic Sine" msgstr "" -#: ../data/functions.xml.in.h:381 +#: ../data/functions.xml.in.h:388 msgid "r:asinh" msgstr "" -#: ../data/functions.xml.in.h:382 +#: ../data/functions.xml.in.h:389 msgid "Inverse Hyperbolic Cosine" msgstr "" -#: ../data/functions.xml.in.h:383 +#: ../data/functions.xml.in.h:390 msgid "r:acosh" msgstr "" -#: ../data/functions.xml.in.h:384 +#: ../data/functions.xml.in.h:391 msgid "Inverse Hyperbolic Tangent" msgstr "" -#: ../data/functions.xml.in.h:385 +#: ../data/functions.xml.in.h:392 msgid "r:atanh" msgstr "" -#: ../data/functions.xml.in.h:386 +#: ../data/functions.xml.in.h:393 msgid "Four-quadrant Inverse Tangent" msgstr "" -#: ../data/functions.xml.in.h:387 +#: ../data/functions.xml.in.h:394 msgid "r:atan2" msgstr "" -#: ../data/functions.xml.in.h:388 +#: ../data/functions.xml.in.h:395 msgid "" "Computes the principal value of the argument function applied to the complex " "number x+iy." msgstr "" -#: ../data/functions.xml.in.h:389 +#: ../data/functions.xml.in.h:396 msgid "Y" msgstr "" -#: ../data/functions.xml.in.h:390 +#: ../data/functions.xml.in.h:397 msgid "X" msgstr "" -#: ../data/functions.xml.in.h:391 +#: ../data/functions.xml.in.h:398 msgid "Cardinal Sine (Sinc Function)" msgstr "" -#: ../data/functions.xml.in.h:392 +#: ../data/functions.xml.in.h:399 msgid "r:sinc" msgstr "" -#: ../data/functions.xml.in.h:393 +#: ../data/functions.xml.in.h:400 msgid "Radians to Default Angle Unit" msgstr "" -#: ../data/functions.xml.in.h:394 +#: ../data/functions.xml.in.h:401 msgid "r:radtodef" msgstr "" -#: ../data/functions.xml.in.h:395 +#: ../data/functions.xml.in.h:402 msgid "Radians" msgstr "" -#: ../data/functions.xml.in.h:396 +#: ../data/functions.xml.in.h:403 msgid "Secant" msgstr "" -#: ../data/functions.xml.in.h:397 +#: ../data/functions.xml.in.h:404 msgid "r:sec" msgstr "" -#: ../data/functions.xml.in.h:398 +#: ../data/functions.xml.in.h:405 msgid "Cosecant" msgstr "" -#: ../data/functions.xml.in.h:399 +#: ../data/functions.xml.in.h:406 msgid "r:csc" msgstr "" -#: ../data/functions.xml.in.h:400 +#: ../data/functions.xml.in.h:407 msgid "Cotangent" msgstr "" -#: ../data/functions.xml.in.h:401 +#: ../data/functions.xml.in.h:408 msgid "r:cot" msgstr "" -#: ../data/functions.xml.in.h:402 +#: ../data/functions.xml.in.h:409 msgid "Hyperbolic Secant" msgstr "" -#: ../data/functions.xml.in.h:403 +#: ../data/functions.xml.in.h:410 msgid "r:sech" msgstr "" -#: ../data/functions.xml.in.h:404 +#: ../data/functions.xml.in.h:411 msgid "Hyperbolic Cosecant" msgstr "" -#: ../data/functions.xml.in.h:405 +#: ../data/functions.xml.in.h:412 msgid "r:csch" msgstr "" -#: ../data/functions.xml.in.h:406 +#: ../data/functions.xml.in.h:413 msgid "Hyperbolic Cotangent" msgstr "" -#: ../data/functions.xml.in.h:407 +#: ../data/functions.xml.in.h:414 msgid "r:coth" msgstr "" -#: ../data/functions.xml.in.h:408 +#: ../data/functions.xml.in.h:415 msgid "Inverse Secant" msgstr "" -#: ../data/functions.xml.in.h:409 +#: ../data/functions.xml.in.h:416 msgid "r:asec" msgstr "" -#: ../data/functions.xml.in.h:410 +#: ../data/functions.xml.in.h:417 msgid "Inverse Cosecant" msgstr "" -#: ../data/functions.xml.in.h:411 +#: ../data/functions.xml.in.h:418 msgid "r:acsc" msgstr "" -#: ../data/functions.xml.in.h:412 +#: ../data/functions.xml.in.h:419 msgid "Inverse Cotangent" msgstr "" -#: ../data/functions.xml.in.h:413 +#: ../data/functions.xml.in.h:420 msgid "r:acot" msgstr "" -#: ../data/functions.xml.in.h:414 +#: ../data/functions.xml.in.h:421 msgid "Inverse Hyperbolic Secant" msgstr "" -#: ../data/functions.xml.in.h:415 +#: ../data/functions.xml.in.h:422 msgid "r:asech" msgstr "" -#: ../data/functions.xml.in.h:416 +#: ../data/functions.xml.in.h:423 msgid "Inverse Hyperbolic Cosecant" msgstr "" -#: ../data/functions.xml.in.h:417 +#: ../data/functions.xml.in.h:424 msgid "r:acsch" msgstr "" -#: ../data/functions.xml.in.h:418 +#: ../data/functions.xml.in.h:425 msgid "Inverse Hyperbolic Cotangent" msgstr "" -#: ../data/functions.xml.in.h:419 +#: ../data/functions.xml.in.h:426 msgid "r:acoth" msgstr "" -#: ../data/functions.xml.in.h:420 +#: ../data/functions.xml.in.h:427 msgid "Miscellaneous" msgstr "" -#: ../data/functions.xml.in.h:421 +#: ../data/functions.xml.in.h:428 msgid "Body Mass Index (BMI)" msgstr "" -#: ../data/functions.xml.in.h:422 +#: ../data/functions.xml.in.h:429 msgid "-r:bmi" msgstr "" -#: ../data/functions.xml.in.h:423 +#: ../data/functions.xml.in.h:430 msgid "" "Calculates the Body Mass Index. The resulting BMI-value is sometimes " "interpreted as follows (although varies with age, sex, etc.): " @@ -4456,19 +4498,19 @@ "and length (ex. 174cm)." msgstr "" -#: ../data/functions.xml.in.h:425 +#: ../data/functions.xml.in.h:432 msgid "Length" msgstr "" -#: ../data/functions.xml.in.h:426 +#: ../data/functions.xml.in.h:433 msgid "RAID Space" msgstr "" -#: ../data/functions.xml.in.h:427 +#: ../data/functions.xml.in.h:434 msgid "r:raid" msgstr "" -#: ../data/functions.xml.in.h:428 +#: ../data/functions.xml.in.h:435 msgid "" "Calculates RAID array disk capacity usable for data storage. If the " "combination of number of disks and RAID level is invalid, zero is returned. " @@ -4477,47 +4519,47 @@ "1+0)." msgstr "" -#: ../data/functions.xml.in.h:429 +#: ../data/functions.xml.in.h:436 msgid "RAID level" msgstr "" -#: ../data/functions.xml.in.h:430 +#: ../data/functions.xml.in.h:437 msgid "Capacity of each disk" msgstr "" -#: ../data/functions.xml.in.h:431 +#: ../data/functions.xml.in.h:438 msgid "Number of disks" msgstr "" -#: ../data/functions.xml.in.h:432 +#: ../data/functions.xml.in.h:439 msgid "Stripes" msgstr "" -#: ../data/functions.xml.in.h:433 +#: ../data/functions.xml.in.h:440 msgid "Roman Number" msgstr "" -#: ../data/functions.xml.in.h:434 +#: ../data/functions.xml.in.h:441 msgid "r:roman" msgstr "" -#: ../data/functions.xml.in.h:435 +#: ../data/functions.xml.in.h:442 msgid "Returns the value of a roman number." msgstr "" -#: ../data/functions.xml.in.h:436 +#: ../data/functions.xml.in.h:443 msgid "Roman number" msgstr "" -#: ../data/functions.xml.in.h:437 +#: ../data/functions.xml.in.h:444 msgid "Depth of Field" msgstr "" -#: ../data/functions.xml.in.h:438 +#: ../data/functions.xml.in.h:445 msgid "r:dof" msgstr "" -#: ../data/functions.xml.in.h:439 +#: ../data/functions.xml.in.h:446 msgid "" "Returns the estimated distance between the nearest and the farthest objects " "that are in acceptably sharp focus in a photo. Enter focal length (e.g. 50 " @@ -4529,629 +4571,629 @@ "on d/1500." msgstr "" -#: ../data/functions.xml.in.h:440 +#: ../data/functions.xml.in.h:447 msgid "Focal Length" msgstr "" -#: ../data/functions.xml.in.h:441 +#: ../data/functions.xml.in.h:448 msgid "F-stop (aperture)" msgstr "" -#: ../data/functions.xml.in.h:442 +#: ../data/functions.xml.in.h:449 msgid "Distance" msgstr "" -#: ../data/functions.xml.in.h:443 +#: ../data/functions.xml.in.h:450 msgid "Circle of confusion or sensor size" msgstr "" -#: ../data/functions.xml.in.h:444 +#: ../data/functions.xml.in.h:451 msgid "American Wire Gauge Cross-Section Area" msgstr "" -#: ../data/functions.xml.in.h:445 +#: ../data/functions.xml.in.h:452 msgid "r:awg" msgstr "" -#: ../data/functions.xml.in.h:446 +#: ../data/functions.xml.in.h:453 msgid "" "For gauges larger than 0000 (4/0), please use negative values (00=-1, " "000=-2, 0000=-3, 00000=-4, etc). For conversion to AWG, use an equation (e." "g. awg(x) = 20 mm^2)." msgstr "" -#: ../data/functions.xml.in.h:447 +#: ../data/functions.xml.in.h:454 msgid "American Wire Gauge Diameter" msgstr "" -#: ../data/functions.xml.in.h:448 +#: ../data/functions.xml.in.h:455 msgid "r:awgd" msgstr "" -#: ../data/functions.xml.in.h:449 +#: ../data/functions.xml.in.h:456 msgid "" "For gauges larger than 0000 (4/0), please use negative values (00=-1, " "000=-2, 0000=-3, 00000=-4, etc). For conversion to AWG, use an equation (e." "g. awgd(x) = 5 mm)." msgstr "" -#: ../data/functions.xml.in.h:450 +#: ../data/functions.xml.in.h:457 msgid "Statistics" msgstr "" -#: ../data/functions.xml.in.h:451 +#: ../data/functions.xml.in.h:458 msgid "Descriptive Statistics" msgstr "" -#: ../data/functions.xml.in.h:452 +#: ../data/functions.xml.in.h:459 msgid "Sum (total)" msgstr "" -#: ../data/functions.xml.in.h:453 +#: ../data/functions.xml.in.h:460 msgid "r:total" msgstr "" -#: ../data/functions.xml.in.h:454 +#: ../data/functions.xml.in.h:461 msgid "Data" msgstr "" -#: ../data/functions.xml.in.h:455 +#: ../data/functions.xml.in.h:462 msgid "Percentile" msgstr "" -#: ../data/functions.xml.in.h:456 +#: ../data/functions.xml.in.h:463 msgid "r:percentile" msgstr "" -#: ../data/functions.xml.in.h:458 +#: ../data/functions.xml.in.h:465 #, no-c-format msgid "Percentile (%)" msgstr "" -#: ../data/functions.xml.in.h:459 +#: ../data/functions.xml.in.h:466 msgid "Quantile algorithm (as in R)" msgstr "" -#: ../data/functions.xml.in.h:460 +#: ../data/functions.xml.in.h:467 msgid "r:min" msgstr "" -#: ../data/functions.xml.in.h:461 +#: ../data/functions.xml.in.h:468 msgid "Returns the lowest value." msgstr "" -#: ../data/functions.xml.in.h:462 +#: ../data/functions.xml.in.h:469 msgid "r:max" msgstr "" -#: ../data/functions.xml.in.h:463 +#: ../data/functions.xml.in.h:470 msgid "Returns the highest value." msgstr "" -#: ../data/functions.xml.in.h:464 +#: ../data/functions.xml.in.h:471 msgid "Mode" msgstr "" -#: ../data/functions.xml.in.h:465 +#: ../data/functions.xml.in.h:472 msgid "r:mode" msgstr "" -#: ../data/functions.xml.in.h:466 +#: ../data/functions.xml.in.h:473 msgid "Returns the most frequently occurring value." msgstr "" -#: ../data/functions.xml.in.h:467 +#: ../data/functions.xml.in.h:474 msgid "Range" msgstr "" -#: ../data/functions.xml.in.h:468 +#: ../data/functions.xml.in.h:475 msgid "r:range" msgstr "" -#: ../data/functions.xml.in.h:469 +#: ../data/functions.xml.in.h:476 msgid "Calculates the difference between the min and max value." msgstr "" -#: ../data/functions.xml.in.h:470 +#: ../data/functions.xml.in.h:477 msgid "Median" msgstr "" -#: ../data/functions.xml.in.h:471 +#: ../data/functions.xml.in.h:478 msgid "r:median" msgstr "" -#: ../data/functions.xml.in.h:472 +#: ../data/functions.xml.in.h:479 msgid "Quartile" msgstr "" -#: ../data/functions.xml.in.h:473 +#: ../data/functions.xml.in.h:480 msgid "r:quartile" msgstr "" -#: ../data/functions.xml.in.h:474 +#: ../data/functions.xml.in.h:481 msgid "Quantile Algorithm (as in R)" msgstr "" -#: ../data/functions.xml.in.h:475 +#: ../data/functions.xml.in.h:482 msgid "Decile" msgstr "" -#: ../data/functions.xml.in.h:476 +#: ../data/functions.xml.in.h:483 msgid "r:decile" msgstr "" -#: ../data/functions.xml.in.h:477 +#: ../data/functions.xml.in.h:484 msgid "Interquartile Range" msgstr "" -#: ../data/functions.xml.in.h:478 +#: ../data/functions.xml.in.h:485 msgid "r:iqr" msgstr "" -#: ../data/functions.xml.in.h:479 +#: ../data/functions.xml.in.h:486 msgid "Calculates the difference between the first and third quartile." msgstr "" -#: ../data/functions.xml.in.h:480 +#: ../data/functions.xml.in.h:487 msgid "Number of Samples" msgstr "" #. Number of samples -#: ../data/functions.xml.in.h:482 +#: ../data/functions.xml.in.h:489 msgid "r:number" msgstr "" -#: ../data/functions.xml.in.h:483 +#: ../data/functions.xml.in.h:490 msgid "Returns the number of samples." msgstr "" -#: ../data/functions.xml.in.h:484 +#: ../data/functions.xml.in.h:491 msgid "Random Numbers" msgstr "" -#: ../data/functions.xml.in.h:485 +#: ../data/functions.xml.in.h:492 msgid "Random Number" msgstr "" -#: ../data/functions.xml.in.h:486 +#: ../data/functions.xml.in.h:493 msgid "r:rand" msgstr "" -#: ../data/functions.xml.in.h:487 +#: ../data/functions.xml.in.h:494 msgid "" "Generates a pseudo-random number. Returns a real number between 0 and 1, if " "ceil is zero (default), or an integer between 1 and (including) ceil." msgstr "" -#: ../data/functions.xml.in.h:488 +#: ../data/functions.xml.in.h:495 msgid "Ceil" msgstr "" -#: ../data/functions.xml.in.h:489 +#: ../data/functions.xml.in.h:496 msgid "Number of values" msgstr "" -#: ../data/functions.xml.in.h:490 +#: ../data/functions.xml.in.h:497 msgid "Normally Distributed Random Number" msgstr "" -#: ../data/functions.xml.in.h:491 +#: ../data/functions.xml.in.h:498 msgid "r:randnorm" msgstr "" -#: ../data/functions.xml.in.h:492 +#: ../data/functions.xml.in.h:499 msgid "Mean" msgstr "" -#: ../data/functions.xml.in.h:493 +#: ../data/functions.xml.in.h:500 msgid "Standard deviation" msgstr "" -#: ../data/functions.xml.in.h:494 +#: ../data/functions.xml.in.h:501 msgid "Poisson Distributed Random Number" msgstr "" -#: ../data/functions.xml.in.h:495 +#: ../data/functions.xml.in.h:502 msgid "r:randpoisson" msgstr "" -#: ../data/functions.xml.in.h:496 +#: ../data/functions.xml.in.h:503 msgid "Uniformly Distributed Random Number" msgstr "" -#: ../data/functions.xml.in.h:497 +#: ../data/functions.xml.in.h:504 msgid "r:randuniform" msgstr "" -#: ../data/functions.xml.in.h:498 +#: ../data/functions.xml.in.h:505 msgid "Random Number Between Limits" msgstr "" -#: ../data/functions.xml.in.h:499 +#: ../data/functions.xml.in.h:506 msgid "r:randbetween" msgstr "" -#: ../data/functions.xml.in.h:500 +#: ../data/functions.xml.in.h:507 msgid "Returns an integer between (including) bottom and top." msgstr "" -#: ../data/functions.xml.in.h:501 +#: ../data/functions.xml.in.h:508 msgid "Bottom" msgstr "" -#: ../data/functions.xml.in.h:502 +#: ../data/functions.xml.in.h:509 msgid "Top" msgstr "" -#: ../data/functions.xml.in.h:503 +#: ../data/functions.xml.in.h:510 msgid "Exponential Random Number" msgstr "" -#: ../data/functions.xml.in.h:504 +#: ../data/functions.xml.in.h:511 msgid "r:randexp" msgstr "" -#: ../data/functions.xml.in.h:505 +#: ../data/functions.xml.in.h:512 msgid "Rate parameter" msgstr "" -#: ../data/functions.xml.in.h:506 +#: ../data/functions.xml.in.h:513 msgid "Rayleigh Distributed Random Number" msgstr "" -#: ../data/functions.xml.in.h:507 +#: ../data/functions.xml.in.h:514 msgid "r:randrayleigh" msgstr "" -#: ../data/functions.xml.in.h:508 +#: ../data/functions.xml.in.h:515 msgid "Sigma" msgstr "" -#: ../data/functions.xml.in.h:509 +#: ../data/functions.xml.in.h:516 msgid "Means" msgstr "" -#: ../data/functions.xml.in.h:510 +#: ../data/functions.xml.in.h:517 msgid "r:mean,average,au:x̄" msgstr "" -#: ../data/functions.xml.in.h:511 +#: ../data/functions.xml.in.h:518 msgid "Harmonic Mean" msgstr "" -#: ../data/functions.xml.in.h:512 +#: ../data/functions.xml.in.h:519 msgid "r:harmmean" msgstr "" -#: ../data/functions.xml.in.h:513 +#: ../data/functions.xml.in.h:520 msgid "Geometric Mean" msgstr "" -#: ../data/functions.xml.in.h:514 +#: ../data/functions.xml.in.h:521 msgid "r:geomean" msgstr "" -#: ../data/functions.xml.in.h:515 +#: ../data/functions.xml.in.h:522 msgid "Trimmed Mean" msgstr "" -#: ../data/functions.xml.in.h:516 +#: ../data/functions.xml.in.h:523 msgid "r:trimmean" msgstr "" -#: ../data/functions.xml.in.h:517 +#: ../data/functions.xml.in.h:524 msgid "Trimmed percentage (at each end)" msgstr "" -#: ../data/functions.xml.in.h:518 +#: ../data/functions.xml.in.h:525 msgid "Winsorized Mean" msgstr "" -#: ../data/functions.xml.in.h:519 +#: ../data/functions.xml.in.h:526 msgid "r:winsormean" msgstr "" -#: ../data/functions.xml.in.h:520 +#: ../data/functions.xml.in.h:527 msgid "Winsorized percentage (at each end)" msgstr "" -#: ../data/functions.xml.in.h:521 +#: ../data/functions.xml.in.h:528 msgid "Weighted Mean" msgstr "" -#: ../data/functions.xml.in.h:522 +#: ../data/functions.xml.in.h:529 msgid "r:weighmean" msgstr "" -#: ../data/functions.xml.in.h:523 +#: ../data/functions.xml.in.h:530 msgid "Weights" msgstr "" -#: ../data/functions.xml.in.h:524 +#: ../data/functions.xml.in.h:531 msgid "Quadratic Mean (RMS)" msgstr "" -#: ../data/functions.xml.in.h:525 +#: ../data/functions.xml.in.h:532 msgid "r:rms" msgstr "" -#: ../data/functions.xml.in.h:526 +#: ../data/functions.xml.in.h:533 msgid "Moments" msgstr "" -#: ../data/functions.xml.in.h:527 +#: ../data/functions.xml.in.h:534 msgid "Standard Deviation (entire population)" msgstr "" -#: ../data/functions.xml.in.h:528 +#: ../data/functions.xml.in.h:535 msgid "r:stdevp" msgstr "" -#: ../data/functions.xml.in.h:529 +#: ../data/functions.xml.in.h:536 msgid "Standard Deviation (random sampling)" msgstr "" -#: ../data/functions.xml.in.h:530 +#: ../data/functions.xml.in.h:537 msgid "r:stdev" msgstr "" -#: ../data/functions.xml.in.h:531 +#: ../data/functions.xml.in.h:538 msgid "Variance (entire population)" msgstr "" -#: ../data/functions.xml.in.h:532 +#: ../data/functions.xml.in.h:539 msgid "r:varp" msgstr "" -#: ../data/functions.xml.in.h:533 +#: ../data/functions.xml.in.h:540 msgid "Variance (random sampling)" msgstr "" -#: ../data/functions.xml.in.h:534 +#: ../data/functions.xml.in.h:541 msgid "r:var" msgstr "" -#: ../data/functions.xml.in.h:535 +#: ../data/functions.xml.in.h:542 msgid "Standard Error" msgstr "" -#: ../data/functions.xml.in.h:536 +#: ../data/functions.xml.in.h:543 msgid "r:stderr" msgstr "" -#: ../data/functions.xml.in.h:537 +#: ../data/functions.xml.in.h:544 msgid "Mean Deviation" msgstr "" -#: ../data/functions.xml.in.h:538 +#: ../data/functions.xml.in.h:545 msgid "r:meandev" msgstr "" -#: ../data/functions.xml.in.h:539 +#: ../data/functions.xml.in.h:546 msgid "Covariance" msgstr "" -#: ../data/functions.xml.in.h:540 +#: ../data/functions.xml.in.h:547 msgid "r:cov,r:covar" msgstr "" -#: ../data/functions.xml.in.h:541 +#: ../data/functions.xml.in.h:548 msgid "Data 1" msgstr "" -#: ../data/functions.xml.in.h:542 +#: ../data/functions.xml.in.h:549 msgid "Data 2" msgstr "" -#: ../data/functions.xml.in.h:543 +#: ../data/functions.xml.in.h:550 msgid "Pooled Variance" msgstr "" -#: ../data/functions.xml.in.h:544 +#: ../data/functions.xml.in.h:551 msgid "r:poolvar" msgstr "" -#: ../data/functions.xml.in.h:545 +#: ../data/functions.xml.in.h:552 msgid "Regression" msgstr "" -#: ../data/functions.xml.in.h:546 +#: ../data/functions.xml.in.h:553 msgid "Statistical Correlation" msgstr "" -#: ../data/functions.xml.in.h:547 +#: ../data/functions.xml.in.h:554 msgid "r:cor" msgstr "" -#: ../data/functions.xml.in.h:548 +#: ../data/functions.xml.in.h:555 msgid "Pearson's Correlation Coefficient" msgstr "" -#: ../data/functions.xml.in.h:549 +#: ../data/functions.xml.in.h:556 msgid "r:pearson,r:correl" msgstr "" -#: ../data/functions.xml.in.h:550 +#: ../data/functions.xml.in.h:557 msgid "Spearman's Rho" msgstr "" -#: ../data/functions.xml.in.h:551 +#: ../data/functions.xml.in.h:558 msgid "r:spearman" msgstr "" -#: ../data/functions.xml.in.h:552 +#: ../data/functions.xml.in.h:559 msgid "Statistical Tests" msgstr "" -#: ../data/functions.xml.in.h:553 +#: ../data/functions.xml.in.h:560 msgid "Unpaired T-Test" msgstr "" -#: ../data/functions.xml.in.h:554 +#: ../data/functions.xml.in.h:561 msgid "r:ttest" msgstr "" -#: ../data/functions.xml.in.h:555 +#: ../data/functions.xml.in.h:562 msgid "Paired T-Test" msgstr "" -#: ../data/functions.xml.in.h:556 +#: ../data/functions.xml.in.h:563 msgid "r:pttest" msgstr "" -#: ../data/functions.xml.in.h:557 +#: ../data/functions.xml.in.h:564 msgid "Distribution" msgstr "" -#: ../data/functions.xml.in.h:558 +#: ../data/functions.xml.in.h:565 msgid "Binomial Distribution" msgstr "" -#: ../data/functions.xml.in.h:559 +#: ../data/functions.xml.in.h:566 msgid "r:binomdist" msgstr "" -#: ../data/functions.xml.in.h:560 +#: ../data/functions.xml.in.h:567 msgid "" "Returns the probability mass or cumulative distribution function of the " "binomial distribution." msgstr "" -#: ../data/functions.xml.in.h:561 +#: ../data/functions.xml.in.h:568 msgid "Number of successes" msgstr "" -#: ../data/functions.xml.in.h:562 +#: ../data/functions.xml.in.h:569 msgid "Number of trials" msgstr "" -#: ../data/functions.xml.in.h:563 +#: ../data/functions.xml.in.h:570 msgid "Probability" msgstr "" -#: ../data/functions.xml.in.h:564 +#: ../data/functions.xml.in.h:571 msgid "Cumulative" msgstr "" -#: ../data/functions.xml.in.h:565 +#: ../data/functions.xml.in.h:572 msgid "Exponential Distribution" msgstr "" -#: ../data/functions.xml.in.h:566 +#: ../data/functions.xml.in.h:573 msgid "r:expondist" msgstr "" -#: ../data/functions.xml.in.h:567 +#: ../data/functions.xml.in.h:574 msgid "" "Returns the probability density or cumulative distribution function of the " "exponential distribution." msgstr "" -#: ../data/functions.xml.in.h:568 +#: ../data/functions.xml.in.h:575 msgid "Logistic Distribution" msgstr "" -#: ../data/functions.xml.in.h:569 +#: ../data/functions.xml.in.h:576 msgid "r:logistic" msgstr "" -#: ../data/functions.xml.in.h:570 +#: ../data/functions.xml.in.h:577 msgid "" "Returns the probability density p(x) at x for a logistic distribution with " "scale parameter. (from Gnumeric)" msgstr "" -#: ../data/functions.xml.in.h:571 +#: ../data/functions.xml.in.h:578 msgid "Scale" msgstr "" -#: ../data/functions.xml.in.h:572 +#: ../data/functions.xml.in.h:579 msgid "Normal Distribution" msgstr "" -#: ../data/functions.xml.in.h:573 +#: ../data/functions.xml.in.h:580 msgid "r:normdist" msgstr "" -#: ../data/functions.xml.in.h:574 +#: ../data/functions.xml.in.h:581 msgid "" "Returns the probability density or cumulative distribution function of a " "normal distribution." msgstr "" -#: ../data/functions.xml.in.h:575 +#: ../data/functions.xml.in.h:582 msgid "Pareto Distribution" msgstr "" -#: ../data/functions.xml.in.h:576 +#: ../data/functions.xml.in.h:583 msgid "r:pareto" msgstr "" -#: ../data/functions.xml.in.h:577 +#: ../data/functions.xml.in.h:584 msgid "" "Returns the probability density p(x) at x for a Pareto distribution with " "exponent and scale. (from Gnumeric)" msgstr "" -#: ../data/functions.xml.in.h:578 +#: ../data/functions.xml.in.h:585 msgid "Poisson Distribution" msgstr "" -#: ../data/functions.xml.in.h:579 +#: ../data/functions.xml.in.h:586 msgid "r:poisson" msgstr "" -#: ../data/functions.xml.in.h:580 +#: ../data/functions.xml.in.h:587 msgid "" "Returns the probability mass or cumulative distribution of the Poisson " "distribution." msgstr "" -#: ../data/functions.xml.in.h:581 +#: ../data/functions.xml.in.h:588 msgid "Number of events (x)" msgstr "" -#: ../data/functions.xml.in.h:582 +#: ../data/functions.xml.in.h:589 msgid "Rayleigh Distribution" msgstr "" -#: ../data/functions.xml.in.h:583 +#: ../data/functions.xml.in.h:590 msgid "r:rayleigh" msgstr "" -#: ../data/functions.xml.in.h:584 +#: ../data/functions.xml.in.h:591 msgid "" "Returns the probability density p(x) at x for a Rayleigh distribution with " "scale parameter sigma. (from Gnumeric)" msgstr "" -#: ../data/functions.xml.in.h:585 +#: ../data/functions.xml.in.h:592 msgid "Rayleigh Tail Distribution" msgstr "" -#: ../data/functions.xml.in.h:586 +#: ../data/functions.xml.in.h:593 msgid "r:rayleightail" msgstr "" -#: ../data/functions.xml.in.h:587 +#: ../data/functions.xml.in.h:594 msgid "" "Returns the probability density p(x) at x for a Rayleigh tail distribution " "with scale parameter sigma and a lower limit. (from Gnumeric)" msgstr "" -#: ../data/functions.xml.in.h:588 ../data/variables.xml.in.h:204 +#: ../data/functions.xml.in.h:595 ../data/variables.xml.in.h:204 msgid "Date & Time" msgstr "" -#: ../data/functions.xml.in.h:589 +#: ../data/functions.xml.in.h:596 msgid "Construct Date" msgstr "" -#: ../data/functions.xml.in.h:590 +#: ../data/functions.xml.in.h:597 msgid "r:date" msgstr "" -#: ../data/functions.xml.in.h:591 +#: ../data/functions.xml.in.h:598 msgid "" "Returns a date. Available calendars gregorian (1), hebrew (2), islamic (3), " "persian (4), indian (5), chinese (6), julian (7), milankovic (8), coptic " @@ -5160,260 +5202,260 @@ "(e.g. leap month 4 = 16)." msgstr "" -#: ../data/functions.xml.in.h:592 +#: ../data/functions.xml.in.h:599 msgid "Year" msgstr "" -#: ../data/functions.xml.in.h:593 ../data/units.xml.in.h:153 +#: ../data/functions.xml.in.h:600 ../data/units.xml.in.h:153 msgid "Month" msgstr "" -#: ../data/functions.xml.in.h:594 ../data/units.xml.in.h:145 +#: ../data/functions.xml.in.h:601 ../data/units.xml.in.h:145 msgid "Day" msgstr "" -#: ../data/functions.xml.in.h:595 +#: ../data/functions.xml.in.h:602 msgid "Calendar" msgstr "" -#: ../data/functions.xml.in.h:596 +#: ../data/functions.xml.in.h:603 msgid "Construct Date and Time" msgstr "" -#: ../data/functions.xml.in.h:597 +#: ../data/functions.xml.in.h:604 msgid "r:datetime" msgstr "" -#: ../data/functions.xml.in.h:598 ../data/units.xml.in.h:143 +#: ../data/functions.xml.in.h:605 ../data/units.xml.in.h:143 msgid "Hour" msgstr "" -#: ../data/functions.xml.in.h:599 ../data/units.xml.in.h:141 +#: ../data/functions.xml.in.h:606 ../data/units.xml.in.h:141 msgid "Minute" msgstr "" -#: ../data/functions.xml.in.h:600 ../data/units.xml.in.h:139 +#: ../data/functions.xml.in.h:607 ../data/units.xml.in.h:139 msgid "Second" msgstr "" -#: ../data/functions.xml.in.h:601 +#: ../data/functions.xml.in.h:608 msgid "Days between two dates" msgstr "" -#: ../data/functions.xml.in.h:602 +#: ../data/functions.xml.in.h:609 msgid "r:days" msgstr "" -#: ../data/functions.xml.in.h:603 +#: ../data/functions.xml.in.h:610 msgid "" "Returns the number of days between two dates. Basis is the type of " "day counting you want to use: 0: US 30/360, 1: real days (default), 2: real " "days/360, 3: real days/365 or 4: European 30/360." msgstr "" -#: ../data/functions.xml.in.h:604 +#: ../data/functions.xml.in.h:611 msgid "First date" msgstr "" -#: ../data/functions.xml.in.h:605 +#: ../data/functions.xml.in.h:612 msgid "Second date" msgstr "" -#: ../data/functions.xml.in.h:606 +#: ../data/functions.xml.in.h:613 msgid "Day counting basis" msgstr "" -#: ../data/functions.xml.in.h:607 +#: ../data/functions.xml.in.h:614 msgid "Financial function mode" msgstr "" -#: ../data/functions.xml.in.h:608 +#: ../data/functions.xml.in.h:615 msgid "Years between two dates" msgstr "" -#: ../data/functions.xml.in.h:609 +#: ../data/functions.xml.in.h:616 msgid "r:yearfrac" msgstr "" -#: ../data/functions.xml.in.h:610 +#: ../data/functions.xml.in.h:617 msgid "" "Returns the number of years (fractional) between two dates. Basis " "is the type of day counting you want to use: 0: US 30/360, 1: real days " "(default), 2: real days/360, 3: real days/365 or 4: European 30/360." msgstr "" -#: ../data/functions.xml.in.h:611 +#: ../data/functions.xml.in.h:618 msgid "Week of Year" msgstr "" -#: ../data/functions.xml.in.h:612 +#: ../data/functions.xml.in.h:619 msgid "r:week" msgstr "" -#: ../data/functions.xml.in.h:613 +#: ../data/functions.xml.in.h:620 msgid "Date" msgstr "" -#: ../data/functions.xml.in.h:614 +#: ../data/functions.xml.in.h:621 msgid "Week begins on Sunday" msgstr "" -#: ../data/functions.xml.in.h:615 +#: ../data/functions.xml.in.h:622 msgid "Day of Week" msgstr "" -#: ../data/functions.xml.in.h:616 +#: ../data/functions.xml.in.h:623 msgid "r:weekday" msgstr "" -#: ../data/functions.xml.in.h:617 +#: ../data/functions.xml.in.h:624 msgid "r:month" msgstr "" -#: ../data/functions.xml.in.h:618 +#: ../data/functions.xml.in.h:625 msgid "Day of Month" msgstr "" -#: ../data/functions.xml.in.h:619 +#: ../data/functions.xml.in.h:626 msgid "r:day" msgstr "" -#: ../data/functions.xml.in.h:620 +#: ../data/functions.xml.in.h:627 msgid "r:year" msgstr "" -#: ../data/functions.xml.in.h:621 +#: ../data/functions.xml.in.h:628 msgid "Day of Year" msgstr "" -#: ../data/functions.xml.in.h:622 +#: ../data/functions.xml.in.h:629 msgid "r:yearday" msgstr "" -#: ../data/functions.xml.in.h:623 +#: ../data/functions.xml.in.h:630 msgid "Current Time" msgstr "" -#: ../data/functions.xml.in.h:624 +#: ../data/functions.xml.in.h:631 msgid "r:time" msgstr "" -#: ../data/functions.xml.in.h:625 +#: ../data/functions.xml.in.h:632 msgid "Time Value" msgstr "" -#: ../data/functions.xml.in.h:626 +#: ../data/functions.xml.in.h:633 msgid "r:timevalue" msgstr "" -#: ../data/functions.xml.in.h:627 +#: ../data/functions.xml.in.h:634 msgid "Returns the time part, in fractional hours, of a date and time value." msgstr "" -#: ../data/functions.xml.in.h:628 +#: ../data/functions.xml.in.h:635 msgid "Date to Unix Timestamp" msgstr "" -#: ../data/functions.xml.in.h:629 +#: ../data/functions.xml.in.h:636 msgid "r:timestamp" msgstr "" -#: ../data/functions.xml.in.h:630 +#: ../data/functions.xml.in.h:637 msgid "Unix Timestamp to Date" msgstr "" -#: ../data/functions.xml.in.h:631 +#: ../data/functions.xml.in.h:638 msgid "r:stamptodate,unix2date" msgstr "" -#: ../data/functions.xml.in.h:632 +#: ../data/functions.xml.in.h:639 msgid "" "Returns the local date and time represented by the specified Unix timestamp " "(seconds, excluding leap seconds, since 1970-01-01). Supports time units." msgstr "" -#: ../data/functions.xml.in.h:633 +#: ../data/functions.xml.in.h:640 msgid "Timestamp" msgstr "" -#: ../data/functions.xml.in.h:634 +#: ../data/functions.xml.in.h:641 msgid "Add Days" msgstr "" -#: ../data/functions.xml.in.h:635 +#: ../data/functions.xml.in.h:642 msgid "r:addDays" msgstr "" -#: ../data/functions.xml.in.h:636 +#: ../data/functions.xml.in.h:643 msgid "Days" msgstr "" -#: ../data/functions.xml.in.h:637 +#: ../data/functions.xml.in.h:644 msgid "Add Months" msgstr "" -#: ../data/functions.xml.in.h:638 +#: ../data/functions.xml.in.h:645 msgid "r:addMonths" msgstr "" -#: ../data/functions.xml.in.h:639 +#: ../data/functions.xml.in.h:646 msgid "Months" msgstr "" -#: ../data/functions.xml.in.h:640 +#: ../data/functions.xml.in.h:647 msgid "Add Years" msgstr "" -#: ../data/functions.xml.in.h:641 +#: ../data/functions.xml.in.h:648 msgid "r:addYears" msgstr "" -#: ../data/functions.xml.in.h:642 +#: ../data/functions.xml.in.h:649 msgid "Years" msgstr "" -#: ../data/functions.xml.in.h:643 +#: ../data/functions.xml.in.h:650 msgid "Add Time" msgstr "" -#: ../data/functions.xml.in.h:644 +#: ../data/functions.xml.in.h:651 msgid "r:addTime" msgstr "" -#: ../data/functions.xml.in.h:645 +#: ../data/functions.xml.in.h:652 msgid "" "Adds a time value to a date. The value can be positive or negative, but must " "use a unit based on seconds (such as day and year). Fractions of days are " "truncated." msgstr "" -#: ../data/functions.xml.in.h:646 ../data/units.xml.in.h:138 +#: ../data/functions.xml.in.h:653 ../data/units.xml.in.h:138 msgid "Time" msgstr "" -#: ../data/functions.xml.in.h:647 +#: ../data/functions.xml.in.h:654 msgid "Lunar Phase" msgstr "" -#: ../data/functions.xml.in.h:648 +#: ../data/functions.xml.in.h:655 msgid "r:lunarphase" msgstr "" -#: ../data/functions.xml.in.h:649 +#: ../data/functions.xml.in.h:656 msgid "" "Returns the lunar phase, as a number between 0 and 1, for the specified " "date. 0 represents new moon, 0.5 full moon, and 0.25 and 0.75 quarter moons." msgstr "" -#: ../data/functions.xml.in.h:650 +#: ../data/functions.xml.in.h:657 msgid "Find Lunar Phase" msgstr "" -#: ../data/functions.xml.in.h:651 +#: ../data/functions.xml.in.h:658 msgid "r:nextlunarphase" msgstr "" -#: ../data/functions.xml.in.h:652 +#: ../data/functions.xml.in.h:659 msgid "" "Returns the date when the specified lunar phase occurs. The function " "searches forward beginning at the specified date. The lunar phase are " @@ -5421,43 +5463,43 @@ "moon, and 0.25 and 0.75 quarter moons." msgstr "" -#: ../data/functions.xml.in.h:653 +#: ../data/functions.xml.in.h:660 msgid "Start Date" msgstr "" -#: ../data/functions.xml.in.h:654 ../data/variables.xml.in.h:197 +#: ../data/functions.xml.in.h:661 ../data/variables.xml.in.h:197 msgid "Utilities" msgstr "" -#: ../data/functions.xml.in.h:655 +#: ../data/functions.xml.in.h:662 msgid "Plot Functions and Vectors" msgstr "" -#: ../data/functions.xml.in.h:656 +#: ../data/functions.xml.in.h:663 msgid "r:plot" msgstr "" -#: ../data/functions.xml.in.h:657 +#: ../data/functions.xml.in.h:664 msgid "Expression or vector" msgstr "" -#: ../data/functions.xml.in.h:658 +#: ../data/functions.xml.in.h:665 msgid "Minimum x value" msgstr "" -#: ../data/functions.xml.in.h:659 +#: ../data/functions.xml.in.h:666 msgid "Maximum x value" msgstr "" -#: ../data/functions.xml.in.h:660 +#: ../data/functions.xml.in.h:667 msgid "Number of samples / Step size" msgstr "" -#: ../data/functions.xml.in.h:661 +#: ../data/functions.xml.in.h:668 msgid "X variable" msgstr "" -#: ../data/functions.xml.in.h:662 +#: ../data/functions.xml.in.h:669 msgid "" "Plots one or more expressions or vectors. Use a vector for the first " "argument to plot multiple series. Only the first argument is used for vector " @@ -5465,487 +5507,487 @@ "and y values." msgstr "" -#: ../data/functions.xml.in.h:663 +#: ../data/functions.xml.in.h:670 msgid "Unicode Value" msgstr "" -#: ../data/functions.xml.in.h:664 +#: ../data/functions.xml.in.h:671 msgid "r:code" msgstr "" -#: ../data/functions.xml.in.h:665 +#: ../data/functions.xml.in.h:672 msgid "Character" msgstr "" -#: ../data/functions.xml.in.h:666 +#: ../data/functions.xml.in.h:673 msgid "Unicode Character" msgstr "" -#: ../data/functions.xml.in.h:667 +#: ../data/functions.xml.in.h:674 msgid "r:char" msgstr "" -#: ../data/functions.xml.in.h:668 +#: ../data/functions.xml.in.h:675 msgid "Length of string" msgstr "" -#: ../data/functions.xml.in.h:669 +#: ../data/functions.xml.in.h:676 msgid "r:len" msgstr "" -#: ../data/functions.xml.in.h:670 +#: ../data/functions.xml.in.h:677 msgid "Text" msgstr "" -#: ../data/functions.xml.in.h:671 +#: ../data/functions.xml.in.h:678 msgid "Concatenate Strings" msgstr "" -#: ../data/functions.xml.in.h:672 +#: ../data/functions.xml.in.h:679 msgid "r:concatenate" msgstr "" -#: ../data/functions.xml.in.h:673 +#: ../data/functions.xml.in.h:680 msgid "Text string 1" msgstr "" -#: ../data/functions.xml.in.h:674 +#: ../data/functions.xml.in.h:681 msgid "Text string 2" msgstr "" -#: ../data/functions.xml.in.h:675 +#: ../data/functions.xml.in.h:682 msgid "Replace" msgstr "" -#: ../data/functions.xml.in.h:676 +#: ../data/functions.xml.in.h:683 msgid "r:replace" msgstr "" -#: ../data/functions.xml.in.h:677 +#: ../data/functions.xml.in.h:684 msgid "" "Replaces a certain value in an expression with a new value. The expression " "is calculated before the replacement if the fourth argument is true." msgstr "" -#: ../data/functions.xml.in.h:678 +#: ../data/functions.xml.in.h:685 msgid "Expression" msgstr "" -#: ../data/functions.xml.in.h:679 +#: ../data/functions.xml.in.h:686 msgid "Original value" msgstr "" -#: ../data/functions.xml.in.h:680 +#: ../data/functions.xml.in.h:687 msgid "New value" msgstr "" -#: ../data/functions.xml.in.h:681 +#: ../data/functions.xml.in.h:688 msgid "Precalculate expression" msgstr "" -#: ../data/functions.xml.in.h:682 +#: ../data/functions.xml.in.h:689 msgid "Strip Units" msgstr "" -#: ../data/functions.xml.in.h:683 +#: ../data/functions.xml.in.h:690 msgid "r:nounit,strip_units" msgstr "" -#: ../data/functions.xml.in.h:684 +#: ../data/functions.xml.in.h:691 msgid "" "Removes all units from an expression. The expression is calculated before " "the removal." msgstr "" -#: ../data/functions.xml.in.h:685 +#: ../data/functions.xml.in.h:692 msgid "Process Vector Elements" msgstr "" -#: ../data/functions.xml.in.h:686 +#: ../data/functions.xml.in.h:693 msgid "r:process" msgstr "" -#: ../data/functions.xml.in.h:687 +#: ../data/functions.xml.in.h:694 msgid "Element variable" msgstr "" -#: ../data/functions.xml.in.h:688 +#: ../data/functions.xml.in.h:695 msgid "Index variable" msgstr "" -#: ../data/functions.xml.in.h:689 +#: ../data/functions.xml.in.h:696 msgid "Vector variable" msgstr "" -#: ../data/functions.xml.in.h:690 +#: ../data/functions.xml.in.h:697 msgid "Process Matrix Elements" msgstr "" -#: ../data/functions.xml.in.h:691 +#: ../data/functions.xml.in.h:698 msgid "r:processm" msgstr "" -#: ../data/functions.xml.in.h:692 +#: ../data/functions.xml.in.h:699 msgid "Row variable" msgstr "" -#: ../data/functions.xml.in.h:693 +#: ../data/functions.xml.in.h:700 msgid "Column variable" msgstr "" -#: ../data/functions.xml.in.h:694 +#: ../data/functions.xml.in.h:701 msgid "Matrix variable" msgstr "" -#: ../data/functions.xml.in.h:695 +#: ../data/functions.xml.in.h:702 msgid "Custom Sum of Elements" msgstr "" -#: ../data/functions.xml.in.h:696 +#: ../data/functions.xml.in.h:703 msgid "r:csum" msgstr "" -#: ../data/functions.xml.in.h:697 +#: ../data/functions.xml.in.h:704 msgid "First element" msgstr "" -#: ../data/functions.xml.in.h:698 +#: ../data/functions.xml.in.h:705 msgid "Last element" msgstr "" -#: ../data/functions.xml.in.h:699 +#: ../data/functions.xml.in.h:706 msgid "Initial value" msgstr "" -#: ../data/functions.xml.in.h:700 +#: ../data/functions.xml.in.h:707 msgid "Value variable" msgstr "" -#: ../data/functions.xml.in.h:701 +#: ../data/functions.xml.in.h:708 msgid "Select Vector Elements" msgstr "" -#: ../data/functions.xml.in.h:702 +#: ../data/functions.xml.in.h:709 msgid "r:select" msgstr "" -#: ../data/functions.xml.in.h:703 +#: ../data/functions.xml.in.h:710 msgid "Condition" msgstr "" -#: ../data/functions.xml.in.h:704 +#: ../data/functions.xml.in.h:711 msgid "Select first match" msgstr "" -#: ../data/functions.xml.in.h:705 +#: ../data/functions.xml.in.h:712 msgid "r:function" msgstr "" -#: ../data/functions.xml.in.h:706 +#: ../data/functions.xml.in.h:713 msgid "Arguments" msgstr "" -#: ../data/functions.xml.in.h:707 +#: ../data/functions.xml.in.h:714 msgid "Title" msgstr "" -#: ../data/functions.xml.in.h:708 +#: ../data/functions.xml.in.h:715 msgid "r:title" msgstr "" -#: ../data/functions.xml.in.h:710 +#: ../data/functions.xml.in.h:717 msgid "Display Error" msgstr "" -#: ../data/functions.xml.in.h:711 +#: ../data/functions.xml.in.h:718 msgid "r:error" msgstr "" -#: ../data/functions.xml.in.h:712 +#: ../data/functions.xml.in.h:719 msgid "Message" msgstr "" -#: ../data/functions.xml.in.h:713 +#: ../data/functions.xml.in.h:720 msgid "Display Warning" msgstr "" -#: ../data/functions.xml.in.h:714 +#: ../data/functions.xml.in.h:721 msgid "r:warning" msgstr "" -#: ../data/functions.xml.in.h:715 +#: ../data/functions.xml.in.h:722 msgid "Display Message" msgstr "" -#: ../data/functions.xml.in.h:716 +#: ../data/functions.xml.in.h:723 msgid "r:message" msgstr "" -#: ../data/functions.xml.in.h:717 +#: ../data/functions.xml.in.h:724 msgid "Save as Variable" msgstr "" -#: ../data/functions.xml.in.h:718 +#: ../data/functions.xml.in.h:725 msgid "r:save" msgstr "" -#: ../data/functions.xml.in.h:719 +#: ../data/functions.xml.in.h:726 msgid "Category" msgstr "" -#: ../data/functions.xml.in.h:720 +#: ../data/functions.xml.in.h:727 msgid "RPN Stack Register" msgstr "" -#: ../data/functions.xml.in.h:721 +#: ../data/functions.xml.in.h:728 msgid "r:register" msgstr "" -#: ../data/functions.xml.in.h:722 +#: ../data/functions.xml.in.h:729 msgid "Returns the value of a RPN stack register." msgstr "" -#: ../data/functions.xml.in.h:723 +#: ../data/functions.xml.in.h:730 msgid "Index" msgstr "" -#: ../data/functions.xml.in.h:724 +#: ../data/functions.xml.in.h:731 msgid "RPN Stack Vector" msgstr "" -#: ../data/functions.xml.in.h:725 +#: ../data/functions.xml.in.h:732 msgid "r:stack" msgstr "" -#: ../data/functions.xml.in.h:726 +#: ../data/functions.xml.in.h:733 msgid "Returns the RPN stack as a vector." msgstr "" -#: ../data/functions.xml.in.h:727 +#: ../data/functions.xml.in.h:734 msgid "Is Number" msgstr "" -#: ../data/functions.xml.in.h:728 +#: ../data/functions.xml.in.h:735 msgid "r:isNumber" msgstr "" -#: ../data/functions.xml.in.h:729 +#: ../data/functions.xml.in.h:736 msgid "Is Real" msgstr "" -#: ../data/functions.xml.in.h:730 +#: ../data/functions.xml.in.h:737 msgid "r:isReal" msgstr "" -#: ../data/functions.xml.in.h:731 +#: ../data/functions.xml.in.h:738 msgid "Is Rational" msgstr "" -#: ../data/functions.xml.in.h:732 +#: ../data/functions.xml.in.h:739 msgid "r:isRational" msgstr "" -#: ../data/functions.xml.in.h:733 +#: ../data/functions.xml.in.h:740 msgid "Is Integer" msgstr "" -#: ../data/functions.xml.in.h:734 +#: ../data/functions.xml.in.h:741 msgid "r:isInteger" msgstr "" -#: ../data/functions.xml.in.h:735 +#: ../data/functions.xml.in.h:742 msgid "Represents Number" msgstr "" -#: ../data/functions.xml.in.h:736 +#: ../data/functions.xml.in.h:743 msgid "r:representsNumber" msgstr "" -#: ../data/functions.xml.in.h:737 +#: ../data/functions.xml.in.h:744 msgid "Represents Real" msgstr "" -#: ../data/functions.xml.in.h:738 +#: ../data/functions.xml.in.h:745 msgid "r:representsReal" msgstr "" -#: ../data/functions.xml.in.h:739 +#: ../data/functions.xml.in.h:746 msgid "Represents Rational" msgstr "" -#: ../data/functions.xml.in.h:740 +#: ../data/functions.xml.in.h:747 msgid "r:representsRational" msgstr "" -#: ../data/functions.xml.in.h:741 +#: ../data/functions.xml.in.h:748 msgid "Represents Integer" msgstr "" -#: ../data/functions.xml.in.h:742 +#: ../data/functions.xml.in.h:749 msgid "r:representsInteger" msgstr "" -#: ../data/functions.xml.in.h:743 +#: ../data/functions.xml.in.h:750 msgid "Interval" msgstr "" -#: ../data/functions.xml.in.h:744 +#: ../data/functions.xml.in.h:751 msgid "r:interval" msgstr "" -#: ../data/functions.xml.in.h:745 +#: ../data/functions.xml.in.h:752 msgid "Lower endpoint" msgstr "" -#: ../data/functions.xml.in.h:746 +#: ../data/functions.xml.in.h:753 msgid "Upper endpoint" msgstr "" -#: ../data/functions.xml.in.h:747 +#: ../data/functions.xml.in.h:754 msgid "Uncertainty" msgstr "" -#: ../data/functions.xml.in.h:748 +#: ../data/functions.xml.in.h:755 msgid "r:uncertainty" msgstr "" -#: ../data/functions.xml.in.h:749 +#: ../data/functions.xml.in.h:756 msgid "Uncertainty is relative" msgstr "" -#: ../data/functions.xml.in.h:750 +#: ../data/functions.xml.in.h:757 msgid "Logical" msgstr "" -#: ../data/functions.xml.in.h:751 +#: ../data/functions.xml.in.h:758 msgid "For...Do" msgstr "" -#: ../data/functions.xml.in.h:752 +#: ../data/functions.xml.in.h:759 msgid "r:for" msgstr "" -#: ../data/functions.xml.in.h:753 +#: ../data/functions.xml.in.h:760 msgid "Initial value of counter" msgstr "" -#: ../data/functions.xml.in.h:754 +#: ../data/functions.xml.in.h:761 msgid "Counter variable" msgstr "" -#: ../data/functions.xml.in.h:755 +#: ../data/functions.xml.in.h:762 msgid "For condition" msgstr "" -#: ../data/functions.xml.in.h:756 +#: ../data/functions.xml.in.h:763 msgid "Counter update function" msgstr "" -#: ../data/functions.xml.in.h:757 +#: ../data/functions.xml.in.h:764 msgid "Do function" msgstr "" -#: ../data/functions.xml.in.h:758 +#: ../data/functions.xml.in.h:765 msgid "If...Then...Else" msgstr "" -#: ../data/functions.xml.in.h:759 +#: ../data/functions.xml.in.h:766 msgid "r:if" msgstr "" -#: ../data/functions.xml.in.h:760 +#: ../data/functions.xml.in.h:767 msgid "" "Tests a condition and returns a value depending on the result. Vectors can " "be used for argument 1 and 2, instead of nested functions." msgstr "" -#: ../data/functions.xml.in.h:761 +#: ../data/functions.xml.in.h:768 msgid "Expression if condition is met" msgstr "" -#: ../data/functions.xml.in.h:762 +#: ../data/functions.xml.in.h:769 msgid "Expression if condition is NOT met" msgstr "" -#: ../data/functions.xml.in.h:763 +#: ../data/functions.xml.in.h:770 msgid "Assume false if not true" msgstr "" -#: ../data/functions.xml.in.h:764 +#: ../data/functions.xml.in.h:771 msgid "Bitwise Exclusive OR" msgstr "" -#: ../data/functions.xml.in.h:765 +#: ../data/functions.xml.in.h:772 msgid "r:xor" msgstr "" -#: ../data/functions.xml.in.h:766 +#: ../data/functions.xml.in.h:773 msgid "Value 1" msgstr "" -#: ../data/functions.xml.in.h:767 +#: ../data/functions.xml.in.h:774 msgid "Value 2" msgstr "" -#: ../data/functions.xml.in.h:768 +#: ../data/functions.xml.in.h:775 msgid "Logical Exclusive OR" msgstr "" -#: ../data/functions.xml.in.h:769 +#: ../data/functions.xml.in.h:776 msgid "r:lxor" msgstr "" -#: ../data/functions.xml.in.h:770 +#: ../data/functions.xml.in.h:777 msgid "Bitwise Shift" msgstr "" -#: ../data/functions.xml.in.h:771 +#: ../data/functions.xml.in.h:778 msgid "" "Applies logical or arithmetic bitwise shift to an integer. The second " "argument specifies the number of steps that each binary bit is shifted to " "the left (use negative values for right shift)." msgstr "" -#: ../data/functions.xml.in.h:772 +#: ../data/functions.xml.in.h:779 msgid "r:shift" msgstr "" -#: ../data/functions.xml.in.h:773 +#: ../data/functions.xml.in.h:780 msgid "Steps" msgstr "" -#: ../data/functions.xml.in.h:774 +#: ../data/functions.xml.in.h:781 msgid "Arithmetic shift using two's complement" msgstr "" -#: ../data/functions.xml.in.h:775 +#: ../data/functions.xml.in.h:782 msgid "Bitwise Complement (Not)" msgstr "" -#: ../data/functions.xml.in.h:776 +#: ../data/functions.xml.in.h:783 msgid "" "Applies bitwise NOT to an integer of specified bit width and signedness (use " "1 for signed and 0 for unsigned). If bit width is zero, the smallest " "necessary number of bits (of 8, 16, 32, 64, 128, ...) will be used." msgstr "" -#: ../data/functions.xml.in.h:777 +#: ../data/functions.xml.in.h:784 msgid "r:bitcmp" msgstr "" -#: ../data/functions.xml.in.h:778 +#: ../data/functions.xml.in.h:785 msgid "Bit Width" msgstr "" -#: ../data/functions.xml.in.h:779 +#: ../data/functions.xml.in.h:786 msgid "Signed Integer" msgstr "" -#: ../data/functions.xml.in.h:780 +#: ../data/functions.xml.in.h:787 msgid "Bit Rotation" msgstr "" -#: ../data/functions.xml.in.h:781 +#: ../data/functions.xml.in.h:788 msgid "" "Applies circular bitwise shift to an integer of specified bit width and " "signedness (use 1 for signed and 0 for unsigned). The second argument " @@ -5954,734 +5996,758 @@ "necessary number of bits (of 8, 16, 32, 64, 128, ...) will be used." msgstr "" -#: ../data/functions.xml.in.h:782 +#: ../data/functions.xml.in.h:789 msgid "r:bitrot" msgstr "" -#: ../data/functions.xml.in.h:783 +#: ../data/functions.xml.in.h:790 msgid "Algebra" msgstr "" -#: ../data/functions.xml.in.h:784 +#: ../data/functions.xml.in.h:791 msgid "Summation" msgstr "" -#: ../data/functions.xml.in.h:785 +#: ../data/functions.xml.in.h:792 msgid "au:Σ,r:sum" msgstr "" -#: ../data/functions.xml.in.h:786 +#: ../data/functions.xml.in.h:793 msgid "" "Corresponds to the summation symbol. Adds terms for each x ranging from the " "lower to the upper limit." msgstr "" -#: ../data/functions.xml.in.h:787 +#: ../data/functions.xml.in.h:794 msgid "Term expression" msgstr "" -#: ../data/functions.xml.in.h:788 +#: ../data/functions.xml.in.h:795 msgid "Lower limit (i)" msgstr "" -#: ../data/functions.xml.in.h:789 +#: ../data/functions.xml.in.h:796 msgid "Upper limit (n)" msgstr "" -#: ../data/functions.xml.in.h:790 +#: ../data/functions.xml.in.h:797 msgid "Product of a sequence" msgstr "" -#: ../data/functions.xml.in.h:791 +#: ../data/functions.xml.in.h:798 msgid "au:Π,r:product" msgstr "" -#: ../data/functions.xml.in.h:792 +#: ../data/functions.xml.in.h:799 msgid "" "Corresponds to the product symbol. Multiplies factors for each x ranging " "from the lower to the upper limit." msgstr "" -#: ../data/functions.xml.in.h:793 +#: ../data/functions.xml.in.h:800 msgid "Factor expression" msgstr "" -#: ../data/functions.xml.in.h:794 +#: ../data/functions.xml.in.h:801 msgid "Solve for multiple variables" msgstr "" -#: ../data/functions.xml.in.h:795 +#: ../data/functions.xml.in.h:802 msgid "r:multisolve" msgstr "" -#: ../data/functions.xml.in.h:796 +#: ../data/functions.xml.in.h:803 msgid "Equation vector" msgstr "" -#: ../data/functions.xml.in.h:797 +#: ../data/functions.xml.in.h:804 msgid "Variable vector" msgstr "" -#: ../data/functions.xml.in.h:798 +#: ../data/functions.xml.in.h:805 msgid "Solve equation" msgstr "" -#: ../data/functions.xml.in.h:799 +#: ../data/functions.xml.in.h:806 msgid "r:solve" msgstr "" -#: ../data/functions.xml.in.h:800 +#: ../data/functions.xml.in.h:807 msgid "Equation" msgstr "" -#: ../data/functions.xml.in.h:801 +#: ../data/functions.xml.in.h:808 msgid "With respect to" msgstr "" -#: ../data/functions.xml.in.h:802 +#: ../data/functions.xml.in.h:809 msgid "Solve differential equation" msgstr "" -#: ../data/functions.xml.in.h:803 +#: ../data/functions.xml.in.h:810 msgid "r:dsolve" msgstr "" -#: ../data/functions.xml.in.h:804 +#: ../data/functions.xml.in.h:811 msgid "Initial condition: function value (y)" msgstr "" -#: ../data/functions.xml.in.h:805 +#: ../data/functions.xml.in.h:812 msgid "Initial condition: argument value (x)" msgstr "" -#: ../data/functions.xml.in.h:806 +#: ../data/functions.xml.in.h:813 msgid "" "Solves a differential equation and returns the value of y(x). The derivative " "in the equation should be in the format diff(y, x). Only first-order " "differential equations are currently supported." msgstr "" -#: ../data/functions.xml.in.h:807 +#: ../data/functions.xml.in.h:814 msgid "Solve for two variables" msgstr "" -#: ../data/functions.xml.in.h:808 +#: ../data/functions.xml.in.h:815 msgid "r:solve2" msgstr "" -#: ../data/functions.xml.in.h:809 +#: ../data/functions.xml.in.h:816 msgid "" "Solves two equations with two unknown variables. Returns the value of the " "first variable." msgstr "" -#: ../data/functions.xml.in.h:810 +#: ../data/functions.xml.in.h:817 msgid "Equation 1" msgstr "" -#: ../data/functions.xml.in.h:811 +#: ../data/functions.xml.in.h:818 msgid "Equation 2" msgstr "" -#: ../data/functions.xml.in.h:812 +#: ../data/functions.xml.in.h:819 msgid "Variable 1" msgstr "" -#: ../data/functions.xml.in.h:813 +#: ../data/functions.xml.in.h:820 msgid "Variable 2" msgstr "" -#: ../data/functions.xml.in.h:814 +#: ../data/functions.xml.in.h:821 msgid "Find Linear Function" msgstr "" -#: ../data/functions.xml.in.h:815 +#: ../data/functions.xml.in.h:822 msgid "r:linearfunction" msgstr "" -#: ../data/functions.xml.in.h:816 +#: ../data/functions.xml.in.h:823 msgid "" "Finds the linear function for the straight line between two distinct points." msgstr "" -#: ../data/functions.xml.in.h:817 +#: ../data/functions.xml.in.h:824 msgid "x1" msgstr "" -#: ../data/functions.xml.in.h:818 +#: ../data/functions.xml.in.h:825 msgid "y1" msgstr "" -#: ../data/functions.xml.in.h:819 +#: ../data/functions.xml.in.h:826 msgid "x2" msgstr "" -#: ../data/functions.xml.in.h:820 +#: ../data/functions.xml.in.h:827 msgid "y2" msgstr "" -#: ../data/functions.xml.in.h:821 +#: ../data/functions.xml.in.h:828 msgid "Calculus" msgstr "" -#: ../data/functions.xml.in.h:822 +#: ../data/functions.xml.in.h:829 msgid "Differentiate" msgstr "" -#: ../data/functions.xml.in.h:823 +#: ../data/functions.xml.in.h:830 msgid "r:diff,derivative" msgstr "" -#: ../data/functions.xml.in.h:824 +#: ../data/functions.xml.in.h:831 msgid "Variable value" msgstr "" -#: ../data/functions.xml.in.h:825 +#: ../data/functions.xml.in.h:832 msgid "Integrate" msgstr "" -#: ../data/functions.xml.in.h:826 +#: ../data/functions.xml.in.h:833 msgid "r:integrate,integral,au:∫" msgstr "" -#: ../data/functions.xml.in.h:827 +#: ../data/functions.xml.in.h:834 msgid "Variable of integration" msgstr "" -#: ../data/functions.xml.in.h:828 +#: ../data/functions.xml.in.h:835 msgid "Force numerical integration" msgstr "" -#: ../data/functions.xml.in.h:829 +#: ../data/functions.xml.in.h:836 msgid "Romberg Integration" msgstr "" -#: ../data/functions.xml.in.h:830 +#: ../data/functions.xml.in.h:837 msgid "r:romberg" msgstr "" -#: ../data/functions.xml.in.h:831 +#: ../data/functions.xml.in.h:838 msgid "Min iterations" msgstr "" -#: ../data/functions.xml.in.h:832 +#: ../data/functions.xml.in.h:839 msgid "Max iterations" msgstr "" -#: ../data/functions.xml.in.h:833 +#: ../data/functions.xml.in.h:840 msgid "Monte Carlo Integration" msgstr "" -#: ../data/functions.xml.in.h:834 +#: ../data/functions.xml.in.h:841 msgid "r:montecarlo" msgstr "" -#: ../data/functions.xml.in.h:835 +#: ../data/functions.xml.in.h:842 msgid "Number of samples" msgstr "" -#: ../data/functions.xml.in.h:836 +#: ../data/functions.xml.in.h:843 msgid "Limit" msgstr "" -#: ../data/functions.xml.in.h:837 +#: ../data/functions.xml.in.h:844 msgid "" "Returns the two-sided limit of the function if direction is zero, limit from " "left (below) if direction is -1, or limit from right (above) if direction is " "+1." msgstr "" -#: ../data/functions.xml.in.h:838 +#: ../data/functions.xml.in.h:845 msgid "r:limit" msgstr "" -#: ../data/functions.xml.in.h:839 +#: ../data/functions.xml.in.h:846 msgid "Value to approach" msgstr "" -#: ../data/functions.xml.in.h:840 +#: ../data/functions.xml.in.h:847 msgid "Direction" msgstr "" -#: ../data/functions.xml.in.h:841 +#: ../data/functions.xml.in.h:848 msgid "Extreme Values" msgstr "" -#: ../data/functions.xml.in.h:842 +#: ../data/functions.xml.in.h:849 msgid "r:extremum" msgstr "" -#: ../data/functions.xml.in.h:843 +#: ../data/functions.xml.in.h:850 msgid "Named Integrals" msgstr "" -#: ../data/functions.xml.in.h:844 +#: ../data/functions.xml.in.h:851 msgid "Logarithmic Integral" msgstr "" -#: ../data/functions.xml.in.h:845 +#: ../data/functions.xml.in.h:852 msgid "rc:li,logint" msgstr "" -#: ../data/functions.xml.in.h:846 +#: ../data/functions.xml.in.h:853 msgid "The integral of 1/ln(x)." msgstr "" -#: ../data/functions.xml.in.h:847 +#: ../data/functions.xml.in.h:854 msgid "Exponential Integral" msgstr "" -#: ../data/functions.xml.in.h:848 +#: ../data/functions.xml.in.h:855 msgid "rc:Ei,expint" msgstr "" -#: ../data/functions.xml.in.h:849 +#: ../data/functions.xml.in.h:856 msgid "The integral of e^x/x." msgstr "" -#: ../data/functions.xml.in.h:850 +#: ../data/functions.xml.in.h:857 msgid "Sine Integral" msgstr "" -#: ../data/functions.xml.in.h:851 +#: ../data/functions.xml.in.h:858 msgid "rc:Si,sinint" msgstr "" -#: ../data/functions.xml.in.h:852 +#: ../data/functions.xml.in.h:859 msgid "The integral of sin(x)/x." msgstr "" -#: ../data/functions.xml.in.h:853 +#: ../data/functions.xml.in.h:860 msgid "Cosine Integral" msgstr "" -#: ../data/functions.xml.in.h:854 +#: ../data/functions.xml.in.h:861 msgid "rc:Ci,cosint" msgstr "" -#: ../data/functions.xml.in.h:855 +#: ../data/functions.xml.in.h:862 msgid "The integral of cos(x)/x." msgstr "" -#: ../data/functions.xml.in.h:856 +#: ../data/functions.xml.in.h:863 msgid "Hyperbolic Sine Integral" msgstr "" -#: ../data/functions.xml.in.h:857 +#: ../data/functions.xml.in.h:864 msgid "rc:Shi,sinhint" msgstr "" -#: ../data/functions.xml.in.h:858 +#: ../data/functions.xml.in.h:865 msgid "The integral of sinh(x)/x." msgstr "" -#: ../data/functions.xml.in.h:859 +#: ../data/functions.xml.in.h:866 msgid "Hyperbolic Cosine Integral" msgstr "" -#: ../data/functions.xml.in.h:860 +#: ../data/functions.xml.in.h:867 msgid "rc:Chi,coshint" msgstr "" -#: ../data/functions.xml.in.h:861 +#: ../data/functions.xml.in.h:868 msgid "The integral of cosh(x)/x." msgstr "" -#: ../data/functions.xml.in.h:862 +#: ../data/functions.xml.in.h:869 +msgid "Fresnel Integral S" +msgstr "" + +#: ../data/functions.xml.in.h:870 +msgid "r:fresnels" +msgstr "" + +#: ../data/functions.xml.in.h:871 +msgid "The integral of sin(pi*x^2/2)." +msgstr "" + +#: ../data/functions.xml.in.h:872 +msgid "Fresnel Integral C" +msgstr "" + +#: ../data/functions.xml.in.h:873 +msgid "r:fresnelc" +msgstr "" + +#: ../data/functions.xml.in.h:874 +msgid "The integral of cos(pi*x^2/2)." +msgstr "" + +#: ../data/functions.xml.in.h:875 msgid "Upper Incomplete Gamma Function" msgstr "" -#: ../data/functions.xml.in.h:863 +#: ../data/functions.xml.in.h:876 msgid "r:igamma" msgstr "" -#: ../data/functions.xml.in.h:864 +#: ../data/functions.xml.in.h:877 msgid "Lower Incomplete Gamma Function" msgstr "" -#: ../data/functions.xml.in.h:865 +#: ../data/functions.xml.in.h:878 msgid "r:gammainc" msgstr "" -#: ../data/functions.xml.in.h:866 +#: ../data/functions.xml.in.h:879 msgid "Geometry" msgstr "" -#: ../data/functions.xml.in.h:867 +#: ../data/functions.xml.in.h:880 msgid "Triangle" msgstr "" -#: ../data/functions.xml.in.h:868 +#: ../data/functions.xml.in.h:881 msgid "Hypotenuse" msgstr "" -#: ../data/functions.xml.in.h:869 +#: ../data/functions.xml.in.h:882 msgid "r:hypot" msgstr "" -#: ../data/functions.xml.in.h:870 +#: ../data/functions.xml.in.h:883 msgid "Side A" msgstr "" -#: ../data/functions.xml.in.h:871 +#: ../data/functions.xml.in.h:884 msgid "Side B" msgstr "" -#: ../data/functions.xml.in.h:872 +#: ../data/functions.xml.in.h:885 msgid "Triangle Area" msgstr "" -#: ../data/functions.xml.in.h:873 +#: ../data/functions.xml.in.h:886 msgid "r:triangle" msgstr "" -#: ../data/functions.xml.in.h:874 +#: ../data/functions.xml.in.h:887 msgid "Height" msgstr "" -#: ../data/functions.xml.in.h:875 +#: ../data/functions.xml.in.h:888 msgid "Triangle Perimeter" msgstr "" -#: ../data/functions.xml.in.h:876 +#: ../data/functions.xml.in.h:889 msgid "r:triangle_perimeter" msgstr "" -#: ../data/functions.xml.in.h:877 +#: ../data/functions.xml.in.h:890 msgid "Side C" msgstr "" -#: ../data/functions.xml.in.h:878 +#: ../data/functions.xml.in.h:891 msgid "Circle" msgstr "" -#: ../data/functions.xml.in.h:879 +#: ../data/functions.xml.in.h:892 msgid "Circle Area" msgstr "" -#: ../data/functions.xml.in.h:880 +#: ../data/functions.xml.in.h:893 msgid "r:circle" msgstr "" -#: ../data/functions.xml.in.h:881 +#: ../data/functions.xml.in.h:894 msgid "Calculates the area of a circle using the radius" msgstr "" -#: ../data/functions.xml.in.h:882 +#: ../data/functions.xml.in.h:895 msgid "Radius" msgstr "" -#: ../data/functions.xml.in.h:883 +#: ../data/functions.xml.in.h:896 msgid "Circle Circumference" msgstr "" -#: ../data/functions.xml.in.h:884 +#: ../data/functions.xml.in.h:897 msgid "r:circumference" msgstr "" -#: ../data/functions.xml.in.h:885 +#: ../data/functions.xml.in.h:898 msgid "Cylinder" msgstr "" -#: ../data/functions.xml.in.h:886 +#: ../data/functions.xml.in.h:899 msgid "Cylinder Volume" msgstr "" -#: ../data/functions.xml.in.h:887 +#: ../data/functions.xml.in.h:900 msgid "r:cylinder" msgstr "" -#: ../data/functions.xml.in.h:888 +#: ../data/functions.xml.in.h:901 msgid "Surface Area of Cylinder" msgstr "" -#: ../data/functions.xml.in.h:889 +#: ../data/functions.xml.in.h:902 msgid "r:cylinder_sa" msgstr "" -#: ../data/functions.xml.in.h:890 +#: ../data/functions.xml.in.h:903 msgid "Cone" msgstr "" -#: ../data/functions.xml.in.h:891 +#: ../data/functions.xml.in.h:904 msgid "Cone Volume" msgstr "" -#: ../data/functions.xml.in.h:892 +#: ../data/functions.xml.in.h:905 msgid "r:cone" msgstr "" -#: ../data/functions.xml.in.h:893 +#: ../data/functions.xml.in.h:906 msgid "Surface Area of Cone" msgstr "" -#: ../data/functions.xml.in.h:894 +#: ../data/functions.xml.in.h:907 msgid "r:cone_sa" msgstr "" -#: ../data/functions.xml.in.h:895 +#: ../data/functions.xml.in.h:908 msgid "Sphere" msgstr "" -#: ../data/functions.xml.in.h:896 +#: ../data/functions.xml.in.h:909 msgid "Sphere Volume" msgstr "" -#: ../data/functions.xml.in.h:897 +#: ../data/functions.xml.in.h:910 msgid "r:sphere" msgstr "" -#: ../data/functions.xml.in.h:898 +#: ../data/functions.xml.in.h:911 msgid "Surface Area of Sphere" msgstr "" -#: ../data/functions.xml.in.h:899 +#: ../data/functions.xml.in.h:912 msgid "r:sphere_sa" msgstr "" -#: ../data/functions.xml.in.h:900 +#: ../data/functions.xml.in.h:913 msgid "Square Area" msgstr "" -#: ../data/functions.xml.in.h:901 +#: ../data/functions.xml.in.h:914 msgid "r:square" msgstr "" -#: ../data/functions.xml.in.h:902 +#: ../data/functions.xml.in.h:915 msgid "Length of side" msgstr "" -#: ../data/functions.xml.in.h:903 +#: ../data/functions.xml.in.h:916 msgid "Square Perimeter" msgstr "" -#: ../data/functions.xml.in.h:904 +#: ../data/functions.xml.in.h:917 msgid "r:square_perimeter" msgstr "" -#: ../data/functions.xml.in.h:905 +#: ../data/functions.xml.in.h:918 msgid "Cube" msgstr "" -#: ../data/functions.xml.in.h:906 +#: ../data/functions.xml.in.h:919 msgid "Cube Volume" msgstr "" -#: ../data/functions.xml.in.h:907 +#: ../data/functions.xml.in.h:920 msgid "r:cube" msgstr "" -#: ../data/functions.xml.in.h:908 +#: ../data/functions.xml.in.h:921 msgid "Surface Area of Cube" msgstr "" -#: ../data/functions.xml.in.h:909 +#: ../data/functions.xml.in.h:922 msgid "r:cube_sa" msgstr "" -#: ../data/functions.xml.in.h:910 +#: ../data/functions.xml.in.h:923 msgid "Rectangle" msgstr "" -#: ../data/functions.xml.in.h:911 +#: ../data/functions.xml.in.h:924 msgid "Rectangle Area" msgstr "" -#: ../data/functions.xml.in.h:912 +#: ../data/functions.xml.in.h:925 msgid "r:rect" msgstr "" -#: ../data/functions.xml.in.h:913 +#: ../data/functions.xml.in.h:926 msgid "Width" msgstr "" -#: ../data/functions.xml.in.h:914 +#: ../data/functions.xml.in.h:927 msgid "Rectangle Perimeter" msgstr "" -#: ../data/functions.xml.in.h:915 +#: ../data/functions.xml.in.h:928 msgid "r:rect_perimeter" msgstr "" -#: ../data/functions.xml.in.h:916 +#: ../data/functions.xml.in.h:929 msgid "Prism" msgstr "" -#: ../data/functions.xml.in.h:917 +#: ../data/functions.xml.in.h:930 msgid "Volume of Rectangular Prism" msgstr "" -#: ../data/functions.xml.in.h:918 +#: ../data/functions.xml.in.h:931 msgid "r:rectprism" msgstr "" -#: ../data/functions.xml.in.h:919 +#: ../data/functions.xml.in.h:932 msgid "Calculates the volume of a prism with rectangular base." msgstr "" -#: ../data/functions.xml.in.h:920 +#: ../data/functions.xml.in.h:933 msgid "Surface Area of Rectangular Prism" msgstr "" -#: ../data/functions.xml.in.h:921 +#: ../data/functions.xml.in.h:934 msgid "r:rectprism_sa" msgstr "" -#: ../data/functions.xml.in.h:922 +#: ../data/functions.xml.in.h:935 msgid "Calculates the surface area of a prism with rectangular base." msgstr "" -#: ../data/functions.xml.in.h:923 +#: ../data/functions.xml.in.h:936 msgid "Volume of Triangular Prism" msgstr "" -#: ../data/functions.xml.in.h:924 +#: ../data/functions.xml.in.h:937 msgid "r:triangleprism" msgstr "" -#: ../data/functions.xml.in.h:925 +#: ../data/functions.xml.in.h:938 msgid "Calculates the volume of a prism with triangular base." msgstr "" -#: ../data/functions.xml.in.h:926 +#: ../data/functions.xml.in.h:939 msgid "Pyramid" msgstr "" -#: ../data/functions.xml.in.h:927 +#: ../data/functions.xml.in.h:940 msgid "Pyramid Volume" msgstr "" -#: ../data/functions.xml.in.h:928 +#: ../data/functions.xml.in.h:941 msgid "r:pyramid" msgstr "" -#: ../data/functions.xml.in.h:929 +#: ../data/functions.xml.in.h:942 msgid "" "Calculates the volume of a 3-dimensional shape standing on a rectangular " "base and terminating in a point at the top." msgstr "" -#: ../data/functions.xml.in.h:930 +#: ../data/functions.xml.in.h:943 msgid "Length of base" msgstr "" -#: ../data/functions.xml.in.h:931 +#: ../data/functions.xml.in.h:944 msgid "Width of base" msgstr "" -#: ../data/functions.xml.in.h:932 +#: ../data/functions.xml.in.h:945 msgid "Volume of Regular Tetrahedron" msgstr "" -#: ../data/functions.xml.in.h:933 +#: ../data/functions.xml.in.h:946 msgid "r:tetrahedron" msgstr "" -#: ../data/functions.xml.in.h:934 +#: ../data/functions.xml.in.h:947 msgid "Surface Area of Regular Tetrahedron" msgstr "" -#: ../data/functions.xml.in.h:935 +#: ../data/functions.xml.in.h:948 msgid "r:tetrahedron_sa" msgstr "" -#: ../data/functions.xml.in.h:936 +#: ../data/functions.xml.in.h:949 msgid "Height of Regular Tetrahedron" msgstr "" -#: ../data/functions.xml.in.h:937 +#: ../data/functions.xml.in.h:950 msgid "r:tetrahedron_height" msgstr "" -#: ../data/functions.xml.in.h:938 +#: ../data/functions.xml.in.h:951 msgid "Volume of Square Pyramid" msgstr "" -#: ../data/functions.xml.in.h:939 +#: ../data/functions.xml.in.h:952 msgid "r:sqpyramid" msgstr "" -#: ../data/functions.xml.in.h:940 +#: ../data/functions.xml.in.h:953 msgid "Surface Area of Square Pyramid" msgstr "" -#: ../data/functions.xml.in.h:941 +#: ../data/functions.xml.in.h:954 msgid "r:sqpyramid_sa" msgstr "" -#: ../data/functions.xml.in.h:942 +#: ../data/functions.xml.in.h:955 msgid "Height of Square Pyramid" msgstr "" -#: ../data/functions.xml.in.h:943 +#: ../data/functions.xml.in.h:956 msgid "r:sqpyramid_height" msgstr "" -#: ../data/functions.xml.in.h:944 +#: ../data/functions.xml.in.h:957 msgid "Parallelogram" msgstr "" -#: ../data/functions.xml.in.h:945 +#: ../data/functions.xml.in.h:958 msgid "Parallelogram Area" msgstr "" -#: ../data/functions.xml.in.h:946 +#: ../data/functions.xml.in.h:959 msgid "r:parallelogram" msgstr "" -#: ../data/functions.xml.in.h:947 +#: ../data/functions.xml.in.h:960 msgid "" "Calculates the area of a four-sided figure whose opposite sides are both " "parallel and equal in length." msgstr "" -#: ../data/functions.xml.in.h:948 +#: ../data/functions.xml.in.h:961 msgid "Parallelogram Perimeter" msgstr "" -#: ../data/functions.xml.in.h:949 +#: ../data/functions.xml.in.h:962 msgid "r:parallelogram_perimeter" msgstr "" -#: ../data/functions.xml.in.h:950 +#: ../data/functions.xml.in.h:963 msgid "" "Calculates the perimeter of a four-sided figure whose opposite sides are " "both parallel and equal in length." msgstr "" -#: ../data/functions.xml.in.h:951 +#: ../data/functions.xml.in.h:964 msgid "Trapezoid" msgstr "" -#: ../data/functions.xml.in.h:952 +#: ../data/functions.xml.in.h:965 msgid "Trapezoid Area" msgstr "" -#: ../data/functions.xml.in.h:953 +#: ../data/functions.xml.in.h:966 msgid "r:trapezoid" msgstr "" -#: ../data/functions.xml.in.h:954 +#: ../data/functions.xml.in.h:967 msgid "Calculates the area of a four-sided figure with two parallel sides." msgstr "" -#: ../data/functions.xml.in.h:955 +#: ../data/functions.xml.in.h:968 msgid "Economics" msgstr "" -#: ../data/functions.xml.in.h:956 +#: ../data/functions.xml.in.h:969 msgid "Microeconomics" msgstr "" -#: ../data/functions.xml.in.h:957 +#: ../data/functions.xml.in.h:970 msgid "Elasticity" msgstr "" -#: ../data/functions.xml.in.h:958 +#: ../data/functions.xml.in.h:971 msgid "r:elasticity" msgstr "" -#: ../data/functions.xml.in.h:959 +#: ../data/functions.xml.in.h:972 msgid "" "Calculates the demand elasticity. Also works for supply elasticity, income " "elasticity, cross-price elasticity, etc. Just replace demand with supply, or " @@ -6690,27 +6756,27 @@ "where x is the default price variable." msgstr "" -#: ../data/functions.xml.in.h:960 +#: ../data/functions.xml.in.h:973 msgid "Demand function" msgstr "" -#: ../data/functions.xml.in.h:961 +#: ../data/functions.xml.in.h:974 msgid "Price" msgstr "" -#: ../data/functions.xml.in.h:962 +#: ../data/functions.xml.in.h:975 msgid "Price variable" msgstr "" -#: ../data/functions.xml.in.h:963 +#: ../data/functions.xml.in.h:976 msgid "Sum-of-Years Digits Depreciation" msgstr "" -#: ../data/functions.xml.in.h:964 +#: ../data/functions.xml.in.h:977 msgid "r:syd" msgstr "" -#: ../data/functions.xml.in.h:965 +#: ../data/functions.xml.in.h:978 msgid "" "Calculates the sum-of-years digits depreciation for an asset based on its " "cost, salvage value, anticipated life, and a particular period. This method " @@ -6720,31 +6786,31 @@ "periods (typically years) over which the asset is depreciated." msgstr "" -#: ../data/functions.xml.in.h:966 +#: ../data/functions.xml.in.h:979 msgid "Cost" msgstr "" -#: ../data/functions.xml.in.h:967 +#: ../data/functions.xml.in.h:980 msgid "Salvage value" msgstr "" -#: ../data/functions.xml.in.h:968 +#: ../data/functions.xml.in.h:981 msgid "Life" msgstr "" -#: ../data/functions.xml.in.h:969 +#: ../data/functions.xml.in.h:982 msgid "Period" msgstr "" -#: ../data/functions.xml.in.h:970 +#: ../data/functions.xml.in.h:983 msgid "Straight Line Depreciation" msgstr "" -#: ../data/functions.xml.in.h:971 +#: ../data/functions.xml.in.h:984 msgid "r:sln" msgstr "" -#: ../data/functions.xml.in.h:972 +#: ../data/functions.xml.in.h:985 msgid "" "Determines the straight line depreciation of an asset for a single period." " Cost is the amount you paid for the asset. Salvage is the value of " @@ -6753,164 +6819,164 @@ "asset." msgstr "" -#: ../data/functions.xml.in.h:973 +#: ../data/functions.xml.in.h:986 msgid "Present Value" msgstr "" -#: ../data/functions.xml.in.h:974 +#: ../data/functions.xml.in.h:987 msgid "r:pv" msgstr "" -#: ../data/functions.xml.in.h:975 +#: ../data/functions.xml.in.h:988 msgid "" "Returns the present value of an investment. If type = 1 then the " "payment is made at the beginning of the period, If type = 0 (or omitted) it " "is made at the end of each period." msgstr "" -#: ../data/functions.xml.in.h:976 +#: ../data/functions.xml.in.h:989 msgid "Interest rate" msgstr "" -#: ../data/functions.xml.in.h:977 +#: ../data/functions.xml.in.h:990 msgid "Number of periods" msgstr "" -#: ../data/functions.xml.in.h:978 +#: ../data/functions.xml.in.h:991 msgid "Payment made each period" msgstr "" -#: ../data/functions.xml.in.h:979 +#: ../data/functions.xml.in.h:992 msgid "Future value" msgstr "" -#: ../data/functions.xml.in.h:980 +#: ../data/functions.xml.in.h:993 msgid "Type" msgstr "" -#: ../data/functions.xml.in.h:981 +#: ../data/functions.xml.in.h:994 msgid "Nominal Interest Rate" msgstr "" -#: ../data/functions.xml.in.h:982 +#: ../data/functions.xml.in.h:995 msgid "r:nominal" msgstr "" -#: ../data/functions.xml.in.h:983 +#: ../data/functions.xml.in.h:996 msgid "" "Calculates the nominal interest rate from a given effective interest rate " "compounded at given intervals." msgstr "" -#: ../data/functions.xml.in.h:984 +#: ../data/functions.xml.in.h:997 msgid "Effective interest rate" msgstr "" -#: ../data/functions.xml.in.h:985 +#: ../data/functions.xml.in.h:998 msgid "Periods" msgstr "" -#: ../data/functions.xml.in.h:986 +#: ../data/functions.xml.in.h:999 msgid "Zero Coupon" msgstr "" -#: ../data/functions.xml.in.h:987 +#: ../data/functions.xml.in.h:1000 msgid "r:zero_coupon" msgstr "" -#: ../data/functions.xml.in.h:988 +#: ../data/functions.xml.in.h:1001 msgid "Calculates the value of a zero-coupon (pure discount) bond." msgstr "" -#: ../data/functions.xml.in.h:989 +#: ../data/functions.xml.in.h:1002 msgid "Face value" msgstr "" -#: ../data/functions.xml.in.h:990 +#: ../data/functions.xml.in.h:1003 msgid "Treasury Bill Yield" msgstr "" -#: ../data/functions.xml.in.h:991 +#: ../data/functions.xml.in.h:1004 msgid "r:tbillyield" msgstr "" -#: ../data/functions.xml.in.h:992 +#: ../data/functions.xml.in.h:1005 msgid "Returns the yield for a treasury bill." msgstr "" -#: ../data/functions.xml.in.h:993 +#: ../data/functions.xml.in.h:1006 msgid "Settlement date" msgstr "" -#: ../data/functions.xml.in.h:994 +#: ../data/functions.xml.in.h:1007 msgid "Maturity date" msgstr "" -#: ../data/functions.xml.in.h:995 +#: ../data/functions.xml.in.h:1008 msgid "Price per $100 face value" msgstr "" -#: ../data/functions.xml.in.h:996 +#: ../data/functions.xml.in.h:1009 msgid "Treasury Bill Price" msgstr "" -#: ../data/functions.xml.in.h:997 +#: ../data/functions.xml.in.h:1010 msgid "r:tbillprice" msgstr "" -#: ../data/functions.xml.in.h:998 +#: ../data/functions.xml.in.h:1011 msgid "Returns the price per $100 value for a treasury bill." msgstr "" -#: ../data/functions.xml.in.h:999 +#: ../data/functions.xml.in.h:1012 msgid "Discount rate" msgstr "" -#: ../data/functions.xml.in.h:1000 +#: ../data/functions.xml.in.h:1013 msgid "Treasury Bill Equivalent" msgstr "" -#: ../data/functions.xml.in.h:1001 +#: ../data/functions.xml.in.h:1014 msgid "r:tbilleq" msgstr "" -#: ../data/functions.xml.in.h:1002 +#: ../data/functions.xml.in.h:1015 msgid "Returns the bond equivalent for a treasury bill." msgstr "" -#: ../data/functions.xml.in.h:1003 +#: ../data/functions.xml.in.h:1016 msgid "Interest paid on a given period of an investment (ISPMT)" msgstr "" -#: ../data/functions.xml.in.h:1004 +#: ../data/functions.xml.in.h:1017 msgid "r:ispmt" msgstr "" -#: ../data/functions.xml.in.h:1005 +#: ../data/functions.xml.in.h:1018 msgid "Calculates the interest paid on a given period of an investment." msgstr "" -#: ../data/functions.xml.in.h:1006 +#: ../data/functions.xml.in.h:1019 msgid "Periodic interest rate" msgstr "" -#: ../data/functions.xml.in.h:1007 +#: ../data/functions.xml.in.h:1020 msgid "Amortizement period" msgstr "" -#: ../data/functions.xml.in.h:1008 +#: ../data/functions.xml.in.h:1021 msgid "Present value" msgstr "" -#: ../data/functions.xml.in.h:1009 +#: ../data/functions.xml.in.h:1022 msgid "Payment for a loan" msgstr "" -#: ../data/functions.xml.in.h:1010 +#: ../data/functions.xml.in.h:1023 msgid "r:pmt" msgstr "" -#: ../data/functions.xml.in.h:1011 +#: ../data/functions.xml.in.h:1024 msgid "" "Returns the amount of payment (negative) each period for a loan based on a " "constant interest rate and constant payments (each payment is equal amount)." @@ -6923,19 +6989,19 @@ "periods field." msgstr "" -#: ../data/functions.xml.in.h:1012 +#: ../data/functions.xml.in.h:1025 msgid "Rate" msgstr "" -#: ../data/functions.xml.in.h:1013 +#: ../data/functions.xml.in.h:1026 msgid "Periods of an investment" msgstr "" -#: ../data/functions.xml.in.h:1014 +#: ../data/functions.xml.in.h:1027 msgid "r:nper" msgstr "" -#: ../data/functions.xml.in.h:1015 +#: ../data/functions.xml.in.h:1028 msgid "" "Calculates number of periods of an investment based on periodic constant " "payments and a constant interest rate. Type defines the due date. 1 " @@ -6943,64 +7009,64 @@ "end of a period." msgstr "" -#: ../data/functions.xml.in.h:1016 +#: ../data/functions.xml.in.h:1029 msgid "Periods for investment to attain desired value" msgstr "" -#: ../data/functions.xml.in.h:1017 +#: ../data/functions.xml.in.h:1030 msgid "r:g_duration" msgstr "" -#: ../data/functions.xml.in.h:1018 +#: ../data/functions.xml.in.h:1031 msgid "" "Returns the number of periods needed for an investment to attain a desired " "value." msgstr "" -#: ../data/functions.xml.in.h:1019 +#: ../data/functions.xml.in.h:1032 msgid "Payment of an annuity going towards principal (PPMT)" msgstr "" -#: ../data/functions.xml.in.h:1020 +#: ../data/functions.xml.in.h:1033 msgid "r:ppmt" msgstr "" -#: ../data/functions.xml.in.h:1021 +#: ../data/functions.xml.in.h:1034 msgid "" "Calculates the amount of a payment of an annuity going towards principal." " Type defines the due date. 1 for payment at the beginning of a " "period and 0 (default) for payment at the end of a period." msgstr "" -#: ../data/functions.xml.in.h:1022 +#: ../data/functions.xml.in.h:1035 msgid "Desired future value" msgstr "" -#: ../data/functions.xml.in.h:1023 +#: ../data/functions.xml.in.h:1036 msgid "Effective Interest Rate" msgstr "" -#: ../data/functions.xml.in.h:1024 +#: ../data/functions.xml.in.h:1037 msgid "r:effect" msgstr "" -#: ../data/functions.xml.in.h:1025 +#: ../data/functions.xml.in.h:1038 msgid "Calculates the effective interest for a given nominal rate." msgstr "" -#: ../data/functions.xml.in.h:1026 +#: ../data/functions.xml.in.h:1039 msgid "Nominal interest rate" msgstr "" -#: ../data/functions.xml.in.h:1027 +#: ../data/functions.xml.in.h:1040 msgid "Future Value" msgstr "" -#: ../data/functions.xml.in.h:1028 +#: ../data/functions.xml.in.h:1041 msgid "r:fv" msgstr "" -#: ../data/functions.xml.in.h:1029 +#: ../data/functions.xml.in.h:1042 msgid "" "Computes the future value of an investment. This is based on periodic, " "constant payments and a constant interest rate. If type = 1 then " @@ -7008,128 +7074,128 @@ "it is made at the end of each period." msgstr "" -#: ../data/functions.xml.in.h:1030 +#: ../data/functions.xml.in.h:1043 msgid "Return on continuously compounded interest" msgstr "" -#: ../data/functions.xml.in.h:1031 +#: ../data/functions.xml.in.h:1044 msgid "r:continuous" msgstr "" -#: ../data/functions.xml.in.h:1032 +#: ../data/functions.xml.in.h:1045 msgid "" "Calculates the return on continuously compounded interest, given the " "principal, nominal rate and time in years." msgstr "" -#: ../data/functions.xml.in.h:1033 +#: ../data/functions.xml.in.h:1046 msgid "Principal" msgstr "" -#: ../data/functions.xml.in.h:1034 +#: ../data/functions.xml.in.h:1047 msgid "Compound" msgstr "" -#: ../data/functions.xml.in.h:1035 +#: ../data/functions.xml.in.h:1048 msgid "r:compound" msgstr "" -#: ../data/functions.xml.in.h:1036 +#: ../data/functions.xml.in.h:1049 msgid "" "Returns the value of an investment, given the principal, nominal interest " "rate, compounding frequency and time." msgstr "" -#: ../data/functions.xml.in.h:1037 +#: ../data/functions.xml.in.h:1050 msgid "Periods per year" msgstr "" -#: ../data/functions.xml.in.h:1038 +#: ../data/functions.xml.in.h:1051 msgid "Payment of an annuity going towards interest (IPMT)" msgstr "" -#: ../data/functions.xml.in.h:1039 +#: ../data/functions.xml.in.h:1052 msgid "r:ipmt" msgstr "" -#: ../data/functions.xml.in.h:1040 +#: ../data/functions.xml.in.h:1053 msgid "" "Calculates the amount of a payment of an annuity going towards interest. " " Type defines the due date. 1 for payment at the beginning of a period " "and 0 (default) for payment at the end of a period." msgstr "" -#: ../data/functions.xml.in.h:1041 +#: ../data/functions.xml.in.h:1054 msgid "Interest rate for a fully invested security" msgstr "" -#: ../data/functions.xml.in.h:1042 +#: ../data/functions.xml.in.h:1055 msgid "r:intrate" msgstr "" -#: ../data/functions.xml.in.h:1043 +#: ../data/functions.xml.in.h:1056 msgid "" "Returns the interest rate for a fully invested security. Basis is " "the type of day counting you want to use: 0: US 30/360 (default), 1: real " "days, 2: real days/360, 3: real days/365 or 4: European 30/360." msgstr "" -#: ../data/functions.xml.in.h:1044 +#: ../data/functions.xml.in.h:1057 msgid "Investment" msgstr "" -#: ../data/functions.xml.in.h:1045 +#: ../data/functions.xml.in.h:1058 msgid "Redemption" msgstr "" -#: ../data/functions.xml.in.h:1046 +#: ../data/functions.xml.in.h:1059 msgid "Dollar Fraction" msgstr "" -#: ../data/functions.xml.in.h:1047 +#: ../data/functions.xml.in.h:1060 msgid "r:dollarfr" msgstr "" -#: ../data/functions.xml.in.h:1048 +#: ../data/functions.xml.in.h:1061 msgid "" "Converts a decimal dollar price into a dollar price expressed as a fraction." msgstr "" -#: ../data/functions.xml.in.h:1049 +#: ../data/functions.xml.in.h:1062 msgid "Decimal dollar" msgstr "" -#: ../data/functions.xml.in.h:1050 +#: ../data/functions.xml.in.h:1063 msgid "Denominator of fraction" msgstr "" -#: ../data/functions.xml.in.h:1051 +#: ../data/functions.xml.in.h:1064 msgid "Dollar Decimal" msgstr "" -#: ../data/functions.xml.in.h:1052 +#: ../data/functions.xml.in.h:1065 msgid "r:dollarde" msgstr "" -#: ../data/functions.xml.in.h:1053 +#: ../data/functions.xml.in.h:1066 msgid "" "Converts a dollar price expressed as a fraction into a dollar price " "expressed as a decimal number." msgstr "" -#: ../data/functions.xml.in.h:1054 +#: ../data/functions.xml.in.h:1067 msgid "Fractional dollar" msgstr "" -#: ../data/functions.xml.in.h:1055 +#: ../data/functions.xml.in.h:1068 msgid "Amount received at maturity for a security bond" msgstr "" -#: ../data/functions.xml.in.h:1056 +#: ../data/functions.xml.in.h:1069 msgid "r:received" msgstr "" -#: ../data/functions.xml.in.h:1057 +#: ../data/functions.xml.in.h:1070 msgid "" "Returns the amount received at the maturity date for an invested security." " Basis is the type of day counting you want to use: 0: US 30/360 " @@ -7137,30 +7203,30 @@ "30/360. The settlement date must be before maturity date." msgstr "" -#: ../data/functions.xml.in.h:1058 +#: ../data/functions.xml.in.h:1071 msgid "Discount rate for a security" msgstr "" -#: ../data/functions.xml.in.h:1059 +#: ../data/functions.xml.in.h:1072 msgid "r:disc" msgstr "" -#: ../data/functions.xml.in.h:1060 +#: ../data/functions.xml.in.h:1073 msgid "" "Returns the discount rate for a security. Basis is the type of day " "counting you want to use: 0: US 30/360 (default), 1: real days, 2: real " "days/360, 3: real days/365 or 4: European 30/360." msgstr "" -#: ../data/functions.xml.in.h:1061 +#: ../data/functions.xml.in.h:1074 msgid "Accrued interest of security paying at maturity" msgstr "" -#: ../data/functions.xml.in.h:1062 +#: ../data/functions.xml.in.h:1075 msgid "r:accrintm" msgstr "" -#: ../data/functions.xml.in.h:1063 +#: ../data/functions.xml.in.h:1076 msgid "" "Returns the accrued interest for a security which pays interest at maturity " "date. Basis is the type of day counting you want to use: 0: US " @@ -7168,27 +7234,27 @@ "European 30/360." msgstr "" -#: ../data/functions.xml.in.h:1064 +#: ../data/functions.xml.in.h:1077 msgid "Issue date" msgstr "" -#: ../data/functions.xml.in.h:1065 +#: ../data/functions.xml.in.h:1078 msgid "Annual rate of security" msgstr "" -#: ../data/functions.xml.in.h:1066 +#: ../data/functions.xml.in.h:1079 msgid "Par value" msgstr "" -#: ../data/functions.xml.in.h:1067 +#: ../data/functions.xml.in.h:1080 msgid "Accrued interest of security with periodic interest payments" msgstr "" -#: ../data/functions.xml.in.h:1068 +#: ../data/functions.xml.in.h:1081 msgid "r:accrint" msgstr "" -#: ../data/functions.xml.in.h:1069 +#: ../data/functions.xml.in.h:1082 msgid "" "Returns accrued interest for a security which pays periodic interest. " " Allowed frequencies are 1 - annual, 2 - semi-annual or 4 - quarterly. " @@ -7196,23 +7262,23 @@ "1: real days, 2: real days/360, 3: real days/365 or 4: European 30/360." msgstr "" -#: ../data/functions.xml.in.h:1070 +#: ../data/functions.xml.in.h:1083 msgid "First interest" msgstr "" -#: ../data/functions.xml.in.h:1071 +#: ../data/functions.xml.in.h:1084 msgid "Frequency" msgstr "" -#: ../data/functions.xml.in.h:1072 +#: ../data/functions.xml.in.h:1085 msgid "Number of coupons to be paid" msgstr "" -#: ../data/functions.xml.in.h:1073 +#: ../data/functions.xml.in.h:1086 msgid "r:coupnum" msgstr "" -#: ../data/functions.xml.in.h:1074 +#: ../data/functions.xml.in.h:1087 msgid "" "Returns the number of coupons to be paid between the settlement and the " "maturity. Basis is the type of day counting you want to use: 0: US " @@ -7220,15 +7286,15 @@ "European 30/360." msgstr "" -#: ../data/functions.xml.in.h:1075 +#: ../data/functions.xml.in.h:1088 msgid "Price per $100 face value of a discounted security" msgstr "" -#: ../data/functions.xml.in.h:1076 +#: ../data/functions.xml.in.h:1089 msgid "r:pricedisc" msgstr "" -#: ../data/functions.xml.in.h:1077 +#: ../data/functions.xml.in.h:1090 msgid "" "Calculates and returns the price per $100 face value of a discounted " "security. The security does not pay interest at maturity. Basis is " @@ -7236,19 +7302,19 @@ "days, 2: real days/360, 3: real days/365 or 4: European 30/360." msgstr "" -#: ../data/functions.xml.in.h:1078 +#: ../data/functions.xml.in.h:1091 msgid "Discount" msgstr "" -#: ../data/functions.xml.in.h:1079 +#: ../data/functions.xml.in.h:1092 msgid "Price per $100 face value of a security" msgstr "" -#: ../data/functions.xml.in.h:1080 +#: ../data/functions.xml.in.h:1093 msgid "r:pricemat" msgstr "" -#: ../data/functions.xml.in.h:1081 +#: ../data/functions.xml.in.h:1094 msgid "" "Calculates and returns the price per $100 face value of a security. The " "security pays interest at maturity. Basis is the type of day " @@ -7256,31 +7322,31 @@ "days/360, 3: real days/365 or 4: European 30/360." msgstr "" -#: ../data/functions.xml.in.h:1082 +#: ../data/functions.xml.in.h:1095 msgid "Annual yield" msgstr "" -#: ../data/functions.xml.in.h:1083 +#: ../data/functions.xml.in.h:1096 msgid "Level-Coupon Bond" msgstr "" -#: ../data/functions.xml.in.h:1084 +#: ../data/functions.xml.in.h:1097 msgid "r:level_coupon" msgstr "" -#: ../data/functions.xml.in.h:1085 +#: ../data/functions.xml.in.h:1098 msgid "Calculates the value of a level-coupon bond." msgstr "" -#: ../data/functions.xml.in.h:1086 +#: ../data/functions.xml.in.h:1099 msgid "Coupon rate" msgstr "" -#: ../data/functions.xml.in.h:1087 +#: ../data/functions.xml.in.h:1100 msgid "Coupons per year" msgstr "" -#: ../data/functions.xml.in.h:1088 +#: ../data/functions.xml.in.h:1101 msgid "Market interest rate" msgstr "" diff -Nru libqalculate-3.6.0/po-defs/nl.po libqalculate-3.7.0/po-defs/nl.po --- libqalculate-3.6.0/po-defs/nl.po 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/po-defs/nl.po 2020-01-21 22:54:40.000000000 +0000 @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: libqalculate-defs\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-25 10:27+0100\n" +"POT-Creation-Date: 2020-01-12 11:29+0100\n" "PO-Revision-Date: 2007-05-18 15:47+0200\n" "Last-Translator: Jaap Woldringh \n" "Language-Team: \n" @@ -638,1474 +638,1488 @@ msgstr "" #: ../data/currencies.xml.in.h:147 +#, fuzzy +msgid "Belarusian Ruble" +msgstr "Russische roebel" + +#: ../data/currencies.xml.in.h:148 +msgid "ar:BYN" +msgstr "" + +#: ../data/currencies.xml.in.h:149 +#, fuzzy +msgid "Belarus" +msgstr "Russische roebel" + +#: ../data/currencies.xml.in.h:150 msgid "Belarusian Ruble p. (obsolete)" msgstr "" -#: ../data/currencies.xml.in.h:148 +#: ../data/currencies.xml.in.h:151 msgid "ar:BYR" msgstr "" -#: ../data/currencies.xml.in.h:149 +#: ../data/currencies.xml.in.h:152 #, fuzzy msgid "Belize Dollar" msgstr "Singapore dollar" -#: ../data/currencies.xml.in.h:150 +#: ../data/currencies.xml.in.h:153 msgid "ar:BZD" msgstr "" -#: ../data/currencies.xml.in.h:151 +#: ../data/currencies.xml.in.h:154 msgid "Belize" msgstr "" -#: ../data/currencies.xml.in.h:152 +#: ../data/currencies.xml.in.h:155 #, fuzzy msgid "West African CFA Franc" msgstr "Zuid-Afrikaanse rand" -#: ../data/currencies.xml.in.h:153 +#: ../data/currencies.xml.in.h:156 msgid "ar:XOF,a:CFA" msgstr "" -#: ../data/currencies.xml.in.h:154 +#: ../data/currencies.xml.in.h:157 msgid "" "Benin, Burkina Faso, Guinea-Bissau, Ivory Coast, Mali, Niger, Senegal, Togo" msgstr "" -#: ../data/currencies.xml.in.h:155 +#: ../data/currencies.xml.in.h:158 #, fuzzy msgid "Bermudian Dollar" msgstr "Canadese dollar" -#: ../data/currencies.xml.in.h:156 +#: ../data/currencies.xml.in.h:159 msgid "ar:BMD" msgstr "" -#: ../data/currencies.xml.in.h:157 +#: ../data/currencies.xml.in.h:160 msgid "Bermuda" msgstr "" -#: ../data/currencies.xml.in.h:158 +#: ../data/currencies.xml.in.h:161 msgid "Bolivian Boliviano Bs" msgstr "" -#: ../data/currencies.xml.in.h:159 +#: ../data/currencies.xml.in.h:162 msgid "ar:BOB" msgstr "" -#: ../data/currencies.xml.in.h:160 +#: ../data/currencies.xml.in.h:163 msgid "Bolivia" msgstr "" -#: ../data/currencies.xml.in.h:161 +#: ../data/currencies.xml.in.h:164 msgid "Bosnia and Herzegovina Convertible Mark" msgstr "" -#: ../data/currencies.xml.in.h:162 +#: ../data/currencies.xml.in.h:165 msgid "ar:BAM" msgstr "" -#: ../data/currencies.xml.in.h:163 +#: ../data/currencies.xml.in.h:166 msgid "Bosnia and Herzegovina" msgstr "" -#: ../data/currencies.xml.in.h:164 +#: ../data/currencies.xml.in.h:167 msgid "Botswana Pula" msgstr "" -#: ../data/currencies.xml.in.h:165 +#: ../data/currencies.xml.in.h:168 msgid "ar:BWP" msgstr "" -#: ../data/currencies.xml.in.h:166 +#: ../data/currencies.xml.in.h:169 msgid "Botswana" msgstr "" -#: ../data/currencies.xml.in.h:167 +#: ../data/currencies.xml.in.h:170 #, fuzzy msgid "Brunei Dollar" msgstr "Canadese dollar" -#: ../data/currencies.xml.in.h:168 +#: ../data/currencies.xml.in.h:171 msgid "ar:BND" msgstr "" -#: ../data/currencies.xml.in.h:169 +#: ../data/currencies.xml.in.h:172 msgid "Brunei" msgstr "" -#: ../data/currencies.xml.in.h:170 +#: ../data/currencies.xml.in.h:173 #, fuzzy msgid "Burundian Franc" msgstr "Belgische frank" -#: ../data/currencies.xml.in.h:171 +#: ../data/currencies.xml.in.h:174 msgid "ar:BIF" msgstr "" -#: ../data/currencies.xml.in.h:172 +#: ../data/currencies.xml.in.h:175 msgid "Burundi" msgstr "" -#: ../data/currencies.xml.in.h:173 +#: ../data/currencies.xml.in.h:176 msgid "Cambodian Riel" msgstr "" -#: ../data/currencies.xml.in.h:174 +#: ../data/currencies.xml.in.h:177 #, fuzzy msgid "ar:KHR,aiu:៛" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:175 +#: ../data/currencies.xml.in.h:178 msgid "Cambodia" msgstr "" -#: ../data/currencies.xml.in.h:176 +#: ../data/currencies.xml.in.h:179 msgid "Central African CFA Franc" msgstr "" -#: ../data/currencies.xml.in.h:177 +#: ../data/currencies.xml.in.h:180 msgid "ar:XAF,a:FCFA" msgstr "" -#: ../data/currencies.xml.in.h:178 +#: ../data/currencies.xml.in.h:181 msgid "" "Cameroon, Central African Republic, Chad, Republic of the Congo, Equatorial " "Guinea, Gabon" msgstr "" -#: ../data/currencies.xml.in.h:179 +#: ../data/currencies.xml.in.h:182 msgid "Cape Verdean Escudo" msgstr "" -#: ../data/currencies.xml.in.h:180 +#: ../data/currencies.xml.in.h:183 msgid "ar:CVE" msgstr "" -#: ../data/currencies.xml.in.h:181 +#: ../data/currencies.xml.in.h:184 msgid "Cape Verde" msgstr "" -#: ../data/currencies.xml.in.h:182 +#: ../data/currencies.xml.in.h:185 #, fuzzy msgid "Cayman Islands Dollar" msgstr "Canadese dollar" -#: ../data/currencies.xml.in.h:183 +#: ../data/currencies.xml.in.h:186 msgid "ar:KYD" msgstr "" -#: ../data/currencies.xml.in.h:184 +#: ../data/currencies.xml.in.h:187 msgid "Cayman Islands" msgstr "" -#: ../data/currencies.xml.in.h:185 +#: ../data/currencies.xml.in.h:188 #, fuzzy msgid "Chilean Peso" msgstr "Filippijnse peso" -#: ../data/currencies.xml.in.h:186 +#: ../data/currencies.xml.in.h:189 msgid "ar:CLP" msgstr "" -#: ../data/currencies.xml.in.h:187 +#: ../data/currencies.xml.in.h:190 msgid "Chile" msgstr "" -#: ../data/currencies.xml.in.h:188 +#: ../data/currencies.xml.in.h:191 #, fuzzy msgid "Colombian Peso" msgstr "Combinaties" -#: ../data/currencies.xml.in.h:189 +#: ../data/currencies.xml.in.h:192 msgid "ar:COP" msgstr "" -#: ../data/currencies.xml.in.h:190 +#: ../data/currencies.xml.in.h:193 #, fuzzy msgid "Colombia" msgstr "Combinaties" -#: ../data/currencies.xml.in.h:191 +#: ../data/currencies.xml.in.h:194 #, fuzzy msgid "Comorian Franc" msgstr "Belgische frank" -#: ../data/currencies.xml.in.h:192 +#: ../data/currencies.xml.in.h:195 msgid "ar:KMF" msgstr "" -#: ../data/currencies.xml.in.h:193 +#: ../data/currencies.xml.in.h:196 msgid "Comoros" msgstr "" -#: ../data/currencies.xml.in.h:194 +#: ../data/currencies.xml.in.h:197 msgid "Democratic Republic of the Congo (Congolese Franc)" msgstr "" -#: ../data/currencies.xml.in.h:195 +#: ../data/currencies.xml.in.h:198 msgid "ar:CDF" msgstr "" -#: ../data/currencies.xml.in.h:196 +#: ../data/currencies.xml.in.h:199 msgid "Democratic Republic of the Congo" msgstr "" -#: ../data/currencies.xml.in.h:197 +#: ../data/currencies.xml.in.h:200 msgid "Costa Rican colón" msgstr "" -#: ../data/currencies.xml.in.h:198 +#: ../data/currencies.xml.in.h:201 msgid "ar:CRC" msgstr "" -#: ../data/currencies.xml.in.h:199 +#: ../data/currencies.xml.in.h:202 msgid "Costa Rica" msgstr "" -#: ../data/currencies.xml.in.h:200 +#: ../data/currencies.xml.in.h:203 msgid "Cuban Peso" msgstr "" -#: ../data/currencies.xml.in.h:201 +#: ../data/currencies.xml.in.h:204 msgid "ar:CUP" msgstr "" -#: ../data/currencies.xml.in.h:202 +#: ../data/currencies.xml.in.h:205 msgid "Cuba" msgstr "" -#: ../data/currencies.xml.in.h:203 +#: ../data/currencies.xml.in.h:206 #, fuzzy msgid "Djiboutian Franc" msgstr "Belgische frank" -#: ../data/currencies.xml.in.h:204 +#: ../data/currencies.xml.in.h:207 msgid "ar:DJF" msgstr "" -#: ../data/currencies.xml.in.h:205 +#: ../data/currencies.xml.in.h:208 msgid "Djibouti" msgstr "" -#: ../data/currencies.xml.in.h:206 +#: ../data/currencies.xml.in.h:209 msgid "Dominican Peso" msgstr "" -#: ../data/currencies.xml.in.h:207 +#: ../data/currencies.xml.in.h:210 msgid "ar:DOP" msgstr "" -#: ../data/currencies.xml.in.h:208 +#: ../data/currencies.xml.in.h:211 msgid "Dominican Republic" msgstr "" -#: ../data/currencies.xml.in.h:209 +#: ../data/currencies.xml.in.h:212 #, fuzzy msgid "Egyptian Pound" msgstr "Cypriotische pond" -#: ../data/currencies.xml.in.h:210 +#: ../data/currencies.xml.in.h:213 msgid "ar:EGP" msgstr "" -#: ../data/currencies.xml.in.h:211 +#: ../data/currencies.xml.in.h:214 msgid "Egypt" msgstr "" -#: ../data/currencies.xml.in.h:212 +#: ../data/currencies.xml.in.h:215 msgid "El Salvadoran Colon (obsolete)" msgstr "" -#: ../data/currencies.xml.in.h:213 +#: ../data/currencies.xml.in.h:216 msgid "ar:SVC" msgstr "" -#: ../data/currencies.xml.in.h:214 +#: ../data/currencies.xml.in.h:217 msgid "Eritrean Nafka" msgstr "" -#: ../data/currencies.xml.in.h:215 +#: ../data/currencies.xml.in.h:218 msgid "ar:ERN" msgstr "" -#: ../data/currencies.xml.in.h:216 +#: ../data/currencies.xml.in.h:219 msgid "Eritrea" msgstr "" -#: ../data/currencies.xml.in.h:217 +#: ../data/currencies.xml.in.h:220 msgid "Ethiopian Birr" msgstr "" -#: ../data/currencies.xml.in.h:218 +#: ../data/currencies.xml.in.h:221 msgid "ar:ETB" msgstr "" -#: ../data/currencies.xml.in.h:219 +#: ../data/currencies.xml.in.h:222 msgid "Ethiopia" msgstr "" -#: ../data/currencies.xml.in.h:220 +#: ../data/currencies.xml.in.h:223 msgid "Falkland Islands Pound" msgstr "" -#: ../data/currencies.xml.in.h:221 +#: ../data/currencies.xml.in.h:224 msgid "ar:FKP" msgstr "" -#: ../data/currencies.xml.in.h:222 +#: ../data/currencies.xml.in.h:225 msgid "Falkland Islands" msgstr "" -#: ../data/currencies.xml.in.h:223 +#: ../data/currencies.xml.in.h:226 #, fuzzy msgid "Fijian Dollar" msgstr "Canadese dollar" -#: ../data/currencies.xml.in.h:224 +#: ../data/currencies.xml.in.h:227 msgid "ar:FJD" msgstr "" -#: ../data/currencies.xml.in.h:225 +#: ../data/currencies.xml.in.h:228 msgid "Fiji" msgstr "" -#: ../data/currencies.xml.in.h:226 +#: ../data/currencies.xml.in.h:229 msgid "CFP franc" msgstr "" -#: ../data/currencies.xml.in.h:227 +#: ../data/currencies.xml.in.h:230 msgid "ar:XPF" msgstr "" -#: ../data/currencies.xml.in.h:228 +#: ../data/currencies.xml.in.h:231 msgid "French Polynesia, New Caledonia, Wallis and Futuna" msgstr "" -#: ../data/currencies.xml.in.h:229 +#: ../data/currencies.xml.in.h:232 #, fuzzy msgid "Gambian Dalasi" msgstr "Canadese dollar" -#: ../data/currencies.xml.in.h:230 +#: ../data/currencies.xml.in.h:233 msgid "ar:GMD" msgstr "" -#: ../data/currencies.xml.in.h:231 +#: ../data/currencies.xml.in.h:234 msgid "Gambia" msgstr "" -#: ../data/currencies.xml.in.h:232 +#: ../data/currencies.xml.in.h:235 msgid "Georgian Lari" msgstr "" -#: ../data/currencies.xml.in.h:233 +#: ../data/currencies.xml.in.h:236 #, fuzzy msgid "ar:GEL,au:₾" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:234 +#: ../data/currencies.xml.in.h:237 msgid "Georgia" msgstr "" -#: ../data/currencies.xml.in.h:235 +#: ../data/currencies.xml.in.h:238 msgid "Ghanaian Cedi" msgstr "" -#: ../data/currencies.xml.in.h:236 +#: ../data/currencies.xml.in.h:239 #, fuzzy msgid "ar:GHS,au:₵" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:237 +#: ../data/currencies.xml.in.h:240 msgid "Ghana" msgstr "" -#: ../data/currencies.xml.in.h:238 +#: ../data/currencies.xml.in.h:241 msgid "Gibraltar Pound" msgstr "" -#: ../data/currencies.xml.in.h:239 +#: ../data/currencies.xml.in.h:242 msgid "ar:GIP" msgstr "" -#: ../data/currencies.xml.in.h:240 +#: ../data/currencies.xml.in.h:243 msgid "Gibraltar" msgstr "" -#: ../data/currencies.xml.in.h:241 +#: ../data/currencies.xml.in.h:244 msgid "Guatemalan Quetzal" msgstr "" -#: ../data/currencies.xml.in.h:242 +#: ../data/currencies.xml.in.h:245 msgid "ar:GTQ" msgstr "" -#: ../data/currencies.xml.in.h:243 +#: ../data/currencies.xml.in.h:246 msgid "Guatemala" msgstr "" -#: ../data/currencies.xml.in.h:244 +#: ../data/currencies.xml.in.h:247 #, fuzzy msgid "Guernsey Pound" msgstr "Ierse pond" -#: ../data/currencies.xml.in.h:245 +#: ../data/currencies.xml.in.h:248 msgid "ar:GGP" msgstr "" -#: ../data/currencies.xml.in.h:246 +#: ../data/currencies.xml.in.h:249 msgid "Guernsey" msgstr "" -#: ../data/currencies.xml.in.h:247 +#: ../data/currencies.xml.in.h:250 #, fuzzy msgid "Guinean Franc" msgstr "Belgische frank" -#: ../data/currencies.xml.in.h:248 +#: ../data/currencies.xml.in.h:251 msgid "ar:GNF" msgstr "" -#: ../data/currencies.xml.in.h:249 +#: ../data/currencies.xml.in.h:252 msgid "Guinea" msgstr "" -#: ../data/currencies.xml.in.h:250 +#: ../data/currencies.xml.in.h:253 #, fuzzy msgid "Guyanese Dollar" msgstr "Australische dollar" -#: ../data/currencies.xml.in.h:251 +#: ../data/currencies.xml.in.h:254 msgid "ar:GYD" msgstr "" -#: ../data/currencies.xml.in.h:252 +#: ../data/currencies.xml.in.h:255 msgid "Guyana" msgstr "" -#: ../data/currencies.xml.in.h:253 +#: ../data/currencies.xml.in.h:256 msgid "Haitian Gourde" msgstr "" -#: ../data/currencies.xml.in.h:254 +#: ../data/currencies.xml.in.h:257 msgid "ar:HTG" msgstr "" -#: ../data/currencies.xml.in.h:255 +#: ../data/currencies.xml.in.h:258 msgid "Haiti" msgstr "" -#: ../data/currencies.xml.in.h:256 +#: ../data/currencies.xml.in.h:259 msgid "Honduran Lempira" msgstr "" -#: ../data/currencies.xml.in.h:257 +#: ../data/currencies.xml.in.h:260 msgid "ar:HNL" msgstr "" -#: ../data/currencies.xml.in.h:258 +#: ../data/currencies.xml.in.h:261 msgid "Honduras" msgstr "" -#: ../data/currencies.xml.in.h:259 +#: ../data/currencies.xml.in.h:262 #, fuzzy msgid "Iranian Rial" msgstr "Italiaanse lire" -#: ../data/currencies.xml.in.h:260 +#: ../data/currencies.xml.in.h:263 #, fuzzy msgid "ar:IRR,aiu:﷼" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:261 +#: ../data/currencies.xml.in.h:264 msgid "Iran" msgstr "" -#: ../data/currencies.xml.in.h:262 +#: ../data/currencies.xml.in.h:265 msgid "Iraqi Dinar" msgstr "" -#: ../data/currencies.xml.in.h:263 +#: ../data/currencies.xml.in.h:266 msgid "ar:IQD" msgstr "" -#: ../data/currencies.xml.in.h:264 +#: ../data/currencies.xml.in.h:267 msgid "Iraq" msgstr "" -#: ../data/currencies.xml.in.h:265 +#: ../data/currencies.xml.in.h:268 #, fuzzy msgid "Jamaican Dollar" msgstr "Canadese dollar" -#: ../data/currencies.xml.in.h:266 +#: ../data/currencies.xml.in.h:269 msgid "ar:JMD" msgstr "" -#: ../data/currencies.xml.in.h:267 +#: ../data/currencies.xml.in.h:270 msgid "Jamaica" msgstr "" -#: ../data/currencies.xml.in.h:268 +#: ../data/currencies.xml.in.h:271 msgid "Jordanian Dinar" msgstr "" -#: ../data/currencies.xml.in.h:269 +#: ../data/currencies.xml.in.h:272 msgid "ar:JOD" msgstr "" -#: ../data/currencies.xml.in.h:270 +#: ../data/currencies.xml.in.h:273 msgid "Jordan" msgstr "" -#: ../data/currencies.xml.in.h:271 +#: ../data/currencies.xml.in.h:274 msgid "Kazakhstani Tenge" msgstr "" -#: ../data/currencies.xml.in.h:272 +#: ../data/currencies.xml.in.h:275 #, fuzzy msgid "ar:KZT,au:₸" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:273 +#: ../data/currencies.xml.in.h:276 msgid "Kazakhstan" msgstr "" -#: ../data/currencies.xml.in.h:274 +#: ../data/currencies.xml.in.h:277 #, fuzzy msgid "North Korean Won" msgstr "Zuid-Koreaanse won" -#: ../data/currencies.xml.in.h:275 +#: ../data/currencies.xml.in.h:278 msgid "ar:KPW" msgstr "" -#: ../data/currencies.xml.in.h:276 +#: ../data/currencies.xml.in.h:279 #, fuzzy msgid "North Korea" msgstr "Zuid-Koreaanse won" -#: ../data/currencies.xml.in.h:277 +#: ../data/currencies.xml.in.h:280 msgid "Kuwaiti Dinar" msgstr "" -#: ../data/currencies.xml.in.h:278 +#: ../data/currencies.xml.in.h:281 msgid "ar:KWD" msgstr "" -#: ../data/currencies.xml.in.h:279 +#: ../data/currencies.xml.in.h:282 msgid "Kuwait" msgstr "" -#: ../data/currencies.xml.in.h:280 +#: ../data/currencies.xml.in.h:283 msgid "Kyrgyzstani Som" msgstr "" -#: ../data/currencies.xml.in.h:281 +#: ../data/currencies.xml.in.h:284 #, fuzzy msgid "ar:KGS,au:с" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:282 +#: ../data/currencies.xml.in.h:285 msgid "Kyrgyzstan" msgstr "" -#: ../data/currencies.xml.in.h:283 +#: ../data/currencies.xml.in.h:286 msgid "Lao Kip" msgstr "" -#: ../data/currencies.xml.in.h:284 +#: ../data/currencies.xml.in.h:287 #, fuzzy msgid "ar:LAK,au:₭" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:285 +#: ../data/currencies.xml.in.h:288 msgid "Laos" msgstr "" -#: ../data/currencies.xml.in.h:286 +#: ../data/currencies.xml.in.h:289 msgid "Lebanese Pound" msgstr "" -#: ../data/currencies.xml.in.h:287 +#: ../data/currencies.xml.in.h:290 msgid "ar:LBP" msgstr "" -#: ../data/currencies.xml.in.h:288 +#: ../data/currencies.xml.in.h:291 msgid "Lebanon" msgstr "" -#: ../data/currencies.xml.in.h:289 +#: ../data/currencies.xml.in.h:292 msgid "Lesotho Loti" msgstr "" -#: ../data/currencies.xml.in.h:290 +#: ../data/currencies.xml.in.h:293 msgid "ar:LSL" msgstr "" -#: ../data/currencies.xml.in.h:291 +#: ../data/currencies.xml.in.h:294 msgid "Lesotho" msgstr "" -#: ../data/currencies.xml.in.h:292 +#: ../data/currencies.xml.in.h:295 #, fuzzy msgid "Liberian Dollar" msgstr "Australische dollar" -#: ../data/currencies.xml.in.h:293 +#: ../data/currencies.xml.in.h:296 msgid "ar:LRD" msgstr "" -#: ../data/currencies.xml.in.h:294 +#: ../data/currencies.xml.in.h:297 msgid "Liberia" msgstr "" -#: ../data/currencies.xml.in.h:295 +#: ../data/currencies.xml.in.h:298 msgid "Libyan Dinar" msgstr "" -#: ../data/currencies.xml.in.h:296 +#: ../data/currencies.xml.in.h:299 msgid "ar:LYD" msgstr "" -#: ../data/currencies.xml.in.h:297 +#: ../data/currencies.xml.in.h:300 msgid "Libya" msgstr "" -#: ../data/currencies.xml.in.h:298 +#: ../data/currencies.xml.in.h:301 msgid "Macanese Pataca" msgstr "" -#: ../data/currencies.xml.in.h:299 +#: ../data/currencies.xml.in.h:302 msgid "ar:MOP" msgstr "" -#: ../data/currencies.xml.in.h:300 +#: ../data/currencies.xml.in.h:303 msgid "Macau" msgstr "" -#: ../data/currencies.xml.in.h:301 +#: ../data/currencies.xml.in.h:304 msgid "Macedonian Denar" msgstr "" -#: ../data/currencies.xml.in.h:302 +#: ../data/currencies.xml.in.h:305 msgid "ar:MKD" msgstr "" -#: ../data/currencies.xml.in.h:303 +#: ../data/currencies.xml.in.h:306 msgid "Macedonia" msgstr "" -#: ../data/currencies.xml.in.h:304 +#: ../data/currencies.xml.in.h:307 msgid "Malagasy Ariary" msgstr "" -#: ../data/currencies.xml.in.h:305 +#: ../data/currencies.xml.in.h:308 msgid "ar:MGA" msgstr "" -#: ../data/currencies.xml.in.h:306 +#: ../data/currencies.xml.in.h:309 msgid "Madagascar" msgstr "" -#: ../data/currencies.xml.in.h:307 +#: ../data/currencies.xml.in.h:310 msgid "Malawian Kwacha" msgstr "" -#: ../data/currencies.xml.in.h:308 +#: ../data/currencies.xml.in.h:311 msgid "ar:MWK" msgstr "" -#: ../data/currencies.xml.in.h:309 +#: ../data/currencies.xml.in.h:312 msgid "Malawi" msgstr "" -#: ../data/currencies.xml.in.h:310 +#: ../data/currencies.xml.in.h:313 msgid "Maldivian Rufiyaa" msgstr "" -#: ../data/currencies.xml.in.h:311 +#: ../data/currencies.xml.in.h:314 msgid "ar:MVR" msgstr "" -#: ../data/currencies.xml.in.h:312 +#: ../data/currencies.xml.in.h:315 msgid "Maldives" msgstr "" -#: ../data/currencies.xml.in.h:313 +#: ../data/currencies.xml.in.h:316 msgid "Mauritanian Ouguiya (obsolete)" msgstr "" -#: ../data/currencies.xml.in.h:314 +#: ../data/currencies.xml.in.h:317 msgid "ar:MRO" msgstr "" -#: ../data/currencies.xml.in.h:315 +#: ../data/currencies.xml.in.h:318 msgid "Mauritian Rupee" msgstr "" -#: ../data/currencies.xml.in.h:316 +#: ../data/currencies.xml.in.h:319 msgid "ar:MUR" msgstr "" -#: ../data/currencies.xml.in.h:317 +#: ../data/currencies.xml.in.h:320 msgid "Mauritius" msgstr "" -#: ../data/currencies.xml.in.h:318 +#: ../data/currencies.xml.in.h:321 msgid "Moldovan Leu" msgstr "" -#: ../data/currencies.xml.in.h:319 +#: ../data/currencies.xml.in.h:322 msgid "ar:MDL" msgstr "" -#: ../data/currencies.xml.in.h:320 +#: ../data/currencies.xml.in.h:323 msgid "Moldova" msgstr "" -#: ../data/currencies.xml.in.h:321 +#: ../data/currencies.xml.in.h:324 msgid "Mongolian Tögrög" msgstr "" -#: ../data/currencies.xml.in.h:322 +#: ../data/currencies.xml.in.h:325 #, fuzzy msgid "ar:MNT,au:₮" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:323 +#: ../data/currencies.xml.in.h:326 msgid "Mongolia" msgstr "" -#: ../data/currencies.xml.in.h:324 +#: ../data/currencies.xml.in.h:327 msgid "Moroccan Dirham" msgstr "" -#: ../data/currencies.xml.in.h:325 +#: ../data/currencies.xml.in.h:328 msgid "ar:MAD" msgstr "" -#: ../data/currencies.xml.in.h:326 +#: ../data/currencies.xml.in.h:329 msgid "Morocco" msgstr "" -#: ../data/currencies.xml.in.h:327 +#: ../data/currencies.xml.in.h:330 msgid "Mozambican Metical" msgstr "" -#: ../data/currencies.xml.in.h:328 +#: ../data/currencies.xml.in.h:331 msgid "ar:MZN" msgstr "" -#: ../data/currencies.xml.in.h:329 +#: ../data/currencies.xml.in.h:332 msgid "Mozambique" msgstr "" -#: ../data/currencies.xml.in.h:330 +#: ../data/currencies.xml.in.h:333 msgid "Myanmar (Burmese Kyat)" msgstr "" -#: ../data/currencies.xml.in.h:331 +#: ../data/currencies.xml.in.h:334 msgid "ar:MMK" msgstr "" -#: ../data/currencies.xml.in.h:332 +#: ../data/currencies.xml.in.h:335 msgid "Myanmar" msgstr "" -#: ../data/currencies.xml.in.h:333 +#: ../data/currencies.xml.in.h:336 #, fuzzy msgid "Namibian Dollar" msgstr "Canadese dollar" -#: ../data/currencies.xml.in.h:334 +#: ../data/currencies.xml.in.h:337 #, fuzzy msgid "ar:NAD" msgstr "a:NLG,gulden" -#: ../data/currencies.xml.in.h:335 +#: ../data/currencies.xml.in.h:338 msgid "Namibia" msgstr "" -#: ../data/currencies.xml.in.h:336 +#: ../data/currencies.xml.in.h:339 msgid "Nepalese Rupee" msgstr "" -#: ../data/currencies.xml.in.h:337 +#: ../data/currencies.xml.in.h:340 #, fuzzy msgid "ar:NPR" msgstr "a:NLG,gulden" -#: ../data/currencies.xml.in.h:338 +#: ../data/currencies.xml.in.h:341 msgid "Nepal" msgstr "" -#: ../data/currencies.xml.in.h:339 +#: ../data/currencies.xml.in.h:342 msgid "Nicaraguan Córdoba" msgstr "" -#: ../data/currencies.xml.in.h:340 +#: ../data/currencies.xml.in.h:343 #, fuzzy msgid "ar:NIO" msgstr "a:NLG,gulden" -#: ../data/currencies.xml.in.h:341 +#: ../data/currencies.xml.in.h:344 msgid "Nicaragua" msgstr "" -#: ../data/currencies.xml.in.h:342 +#: ../data/currencies.xml.in.h:345 msgid "Nigerian Naira" msgstr "" -#: ../data/currencies.xml.in.h:343 +#: ../data/currencies.xml.in.h:346 #, fuzzy msgid "ar:NGN,au:₦" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:344 +#: ../data/currencies.xml.in.h:347 msgid "Nigeria" msgstr "" -#: ../data/currencies.xml.in.h:345 +#: ../data/currencies.xml.in.h:348 msgid "Omani Rial" msgstr "" -#: ../data/currencies.xml.in.h:346 +#: ../data/currencies.xml.in.h:349 msgid "ar:OMR" msgstr "" -#: ../data/currencies.xml.in.h:347 +#: ../data/currencies.xml.in.h:350 msgid "Oman" msgstr "" -#: ../data/currencies.xml.in.h:348 +#: ../data/currencies.xml.in.h:351 msgid "Pakistani Rupee" msgstr "" -#: ../data/currencies.xml.in.h:349 +#: ../data/currencies.xml.in.h:352 msgid "ar:PKR" msgstr "" -#: ../data/currencies.xml.in.h:350 +#: ../data/currencies.xml.in.h:353 #, fuzzy msgid "Pakistan" msgstr "Planck constante" -#: ../data/currencies.xml.in.h:351 +#: ../data/currencies.xml.in.h:354 msgid "Panamaian Balboa" msgstr "" -#: ../data/currencies.xml.in.h:352 +#: ../data/currencies.xml.in.h:355 msgid "ar:PAB" msgstr "" -#: ../data/currencies.xml.in.h:353 +#: ../data/currencies.xml.in.h:356 msgid "Panama" msgstr "" -#: ../data/currencies.xml.in.h:354 +#: ../data/currencies.xml.in.h:357 msgid "Papua New Guinean Kina" msgstr "" -#: ../data/currencies.xml.in.h:355 +#: ../data/currencies.xml.in.h:358 msgid "ar:PGK" msgstr "" -#: ../data/currencies.xml.in.h:356 +#: ../data/currencies.xml.in.h:359 msgid "Papua New Guinea" msgstr "" -#: ../data/currencies.xml.in.h:357 +#: ../data/currencies.xml.in.h:360 msgid "Paraguayan Guaraní" msgstr "" -#: ../data/currencies.xml.in.h:358 +#: ../data/currencies.xml.in.h:361 #, fuzzy msgid "ar:PYG,au:₲" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:359 +#: ../data/currencies.xml.in.h:362 msgid "Paraguay" msgstr "" -#: ../data/currencies.xml.in.h:360 +#: ../data/currencies.xml.in.h:363 msgid "Peruvian Sol" msgstr "" -#: ../data/currencies.xml.in.h:361 +#: ../data/currencies.xml.in.h:364 msgid "ar:PEN" msgstr "" -#: ../data/currencies.xml.in.h:362 +#: ../data/currencies.xml.in.h:365 msgid "Peru" msgstr "" -#: ../data/currencies.xml.in.h:363 +#: ../data/currencies.xml.in.h:366 msgid "Qatari Riyal" msgstr "" -#: ../data/currencies.xml.in.h:364 +#: ../data/currencies.xml.in.h:367 msgid "ar:QAR" msgstr "" -#: ../data/currencies.xml.in.h:365 +#: ../data/currencies.xml.in.h:368 msgid "Qatar" msgstr "" -#: ../data/currencies.xml.in.h:366 +#: ../data/currencies.xml.in.h:369 #, fuzzy msgid "Rwandan Franc" msgstr "Belgische frank" -#: ../data/currencies.xml.in.h:367 +#: ../data/currencies.xml.in.h:370 msgid "ar:RWF" msgstr "" -#: ../data/currencies.xml.in.h:368 +#: ../data/currencies.xml.in.h:371 msgid "Rwanda" msgstr "" -#: ../data/currencies.xml.in.h:369 +#: ../data/currencies.xml.in.h:372 msgid "São Tomé and Príncipe Dobra" msgstr "" -#: ../data/currencies.xml.in.h:370 +#: ../data/currencies.xml.in.h:373 msgid "ar:STD" msgstr "" -#: ../data/currencies.xml.in.h:371 +#: ../data/currencies.xml.in.h:374 msgid "Sao Tome and Principe" msgstr "" -#: ../data/currencies.xml.in.h:372 +#: ../data/currencies.xml.in.h:375 msgid "Saudi Riyal" msgstr "" -#: ../data/currencies.xml.in.h:373 +#: ../data/currencies.xml.in.h:376 msgid "ar:SAR" msgstr "" -#: ../data/currencies.xml.in.h:374 +#: ../data/currencies.xml.in.h:377 msgid "Saudi Arabia" msgstr "" -#: ../data/currencies.xml.in.h:375 +#: ../data/currencies.xml.in.h:378 msgid "Serbian Dinar" msgstr "" -#: ../data/currencies.xml.in.h:376 +#: ../data/currencies.xml.in.h:379 msgid "ar:RSD" msgstr "" -#: ../data/currencies.xml.in.h:377 +#: ../data/currencies.xml.in.h:380 msgid "Serbia" msgstr "" -#: ../data/currencies.xml.in.h:378 +#: ../data/currencies.xml.in.h:381 msgid "Seychellois Rupee" msgstr "" -#: ../data/currencies.xml.in.h:379 +#: ../data/currencies.xml.in.h:382 msgid "ar:SCR" msgstr "" -#: ../data/currencies.xml.in.h:380 +#: ../data/currencies.xml.in.h:383 msgid "Seychelles" msgstr "" -#: ../data/currencies.xml.in.h:381 +#: ../data/currencies.xml.in.h:384 msgid "Sierra Leonean Leone" msgstr "" -#: ../data/currencies.xml.in.h:382 +#: ../data/currencies.xml.in.h:385 msgid "ar:SLL" msgstr "" -#: ../data/currencies.xml.in.h:383 +#: ../data/currencies.xml.in.h:386 msgid "Sierra Leone" msgstr "" -#: ../data/currencies.xml.in.h:384 +#: ../data/currencies.xml.in.h:387 msgid "Solomon Islands Dollar" msgstr "" -#: ../data/currencies.xml.in.h:385 +#: ../data/currencies.xml.in.h:388 msgid "ar:SBD" msgstr "" -#: ../data/currencies.xml.in.h:386 +#: ../data/currencies.xml.in.h:389 msgid "Solomon Islands" msgstr "" -#: ../data/currencies.xml.in.h:387 +#: ../data/currencies.xml.in.h:390 #, fuzzy msgid "Somali Shilling" msgstr "Oostenrijkse schilling" -#: ../data/currencies.xml.in.h:388 +#: ../data/currencies.xml.in.h:391 msgid "ar:SOS" msgstr "" -#: ../data/currencies.xml.in.h:389 +#: ../data/currencies.xml.in.h:392 msgid "Somalia" msgstr "" -#: ../data/currencies.xml.in.h:390 +#: ../data/currencies.xml.in.h:393 msgid "Sri Lankan Rupee" msgstr "" -#: ../data/currencies.xml.in.h:391 +#: ../data/currencies.xml.in.h:394 #, fuzzy msgid "ar:LKR,au:௹" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:392 +#: ../data/currencies.xml.in.h:395 msgid "Sri Lanka" msgstr "" -#: ../data/currencies.xml.in.h:393 +#: ../data/currencies.xml.in.h:396 msgid "Sudanese Pound" msgstr "" -#: ../data/currencies.xml.in.h:394 +#: ../data/currencies.xml.in.h:397 msgid "ar:SDG" msgstr "" -#: ../data/currencies.xml.in.h:395 +#: ../data/currencies.xml.in.h:398 msgid "Sudan" msgstr "" -#: ../data/currencies.xml.in.h:396 +#: ../data/currencies.xml.in.h:399 #, fuzzy msgid "Surinamese Dollar" msgstr "Singapore dollar" -#: ../data/currencies.xml.in.h:397 +#: ../data/currencies.xml.in.h:400 msgid "ar:SRD" msgstr "" -#: ../data/currencies.xml.in.h:398 +#: ../data/currencies.xml.in.h:401 #, fuzzy msgid "Suriname" msgstr "naam" -#: ../data/currencies.xml.in.h:399 +#: ../data/currencies.xml.in.h:402 msgid "Swazi Lilangeni" msgstr "" -#: ../data/currencies.xml.in.h:400 +#: ../data/currencies.xml.in.h:403 msgid "ar:SZL" msgstr "" -#: ../data/currencies.xml.in.h:401 +#: ../data/currencies.xml.in.h:404 msgid "Swaziland" msgstr "" -#: ../data/currencies.xml.in.h:402 +#: ../data/currencies.xml.in.h:405 #, fuzzy msgid "Syrian Pound" msgstr "Cypriotische pond" -#: ../data/currencies.xml.in.h:403 +#: ../data/currencies.xml.in.h:406 msgid "ar:SYP" msgstr "" -#: ../data/currencies.xml.in.h:404 +#: ../data/currencies.xml.in.h:407 msgid "Syria" msgstr "" -#: ../data/currencies.xml.in.h:405 +#: ../data/currencies.xml.in.h:408 #, fuzzy msgid "New Taiwan Dollar" msgstr "Nieuwzeelandse dollar" -#: ../data/currencies.xml.in.h:406 +#: ../data/currencies.xml.in.h:409 msgid "ar:TWD" msgstr "" -#: ../data/currencies.xml.in.h:407 +#: ../data/currencies.xml.in.h:410 msgid "Taiwan" msgstr "" -#: ../data/currencies.xml.in.h:408 +#: ../data/currencies.xml.in.h:411 msgid "Tajikistani Somoni" msgstr "" -#: ../data/currencies.xml.in.h:409 +#: ../data/currencies.xml.in.h:412 msgid "ar:TJS" msgstr "" -#: ../data/currencies.xml.in.h:410 +#: ../data/currencies.xml.in.h:413 msgid "Tajikistan" msgstr "" -#: ../data/currencies.xml.in.h:411 +#: ../data/currencies.xml.in.h:414 #, fuzzy msgid "Tanzanian Shilling" msgstr "Oostenrijkse schilling" -#: ../data/currencies.xml.in.h:412 +#: ../data/currencies.xml.in.h:415 msgid "ar:TZS" msgstr "" -#: ../data/currencies.xml.in.h:413 +#: ../data/currencies.xml.in.h:416 msgid "Tanzania" msgstr "" -#: ../data/currencies.xml.in.h:414 +#: ../data/currencies.xml.in.h:417 msgid "Tongan Paʻanga" msgstr "" -#: ../data/currencies.xml.in.h:415 +#: ../data/currencies.xml.in.h:418 msgid "ar:TOP" msgstr "" -#: ../data/currencies.xml.in.h:416 +#: ../data/currencies.xml.in.h:419 msgid "Tonga" msgstr "" -#: ../data/currencies.xml.in.h:417 +#: ../data/currencies.xml.in.h:420 msgid "Trinidad and Tobago dollar" msgstr "" -#: ../data/currencies.xml.in.h:418 +#: ../data/currencies.xml.in.h:421 msgid "ar:TTD" msgstr "" -#: ../data/currencies.xml.in.h:419 +#: ../data/currencies.xml.in.h:422 msgid "Trinidad and Tobago" msgstr "" -#: ../data/currencies.xml.in.h:420 +#: ../data/currencies.xml.in.h:423 msgid "Tunisian Dinar" msgstr "" -#: ../data/currencies.xml.in.h:421 +#: ../data/currencies.xml.in.h:424 msgid "ar:TND" msgstr "" -#: ../data/currencies.xml.in.h:422 +#: ../data/currencies.xml.in.h:425 msgid "Tunisia" msgstr "" -#: ../data/currencies.xml.in.h:423 +#: ../data/currencies.xml.in.h:426 msgid "Turkmenistan Manat" msgstr "" -#: ../data/currencies.xml.in.h:424 +#: ../data/currencies.xml.in.h:427 msgid "ar:TMT" msgstr "" -#: ../data/currencies.xml.in.h:425 +#: ../data/currencies.xml.in.h:428 msgid "Turkmenistan" msgstr "" -#: ../data/currencies.xml.in.h:426 +#: ../data/currencies.xml.in.h:429 #, fuzzy msgid "Ugandan Shilling" msgstr "Oostenrijkse schilling" -#: ../data/currencies.xml.in.h:427 +#: ../data/currencies.xml.in.h:430 msgid "ar:UGX" msgstr "" -#: ../data/currencies.xml.in.h:428 +#: ../data/currencies.xml.in.h:431 msgid "Uganda" msgstr "" -#: ../data/currencies.xml.in.h:429 +#: ../data/currencies.xml.in.h:432 msgid "Ukrainian Hryvnia" msgstr "" -#: ../data/currencies.xml.in.h:430 +#: ../data/currencies.xml.in.h:433 #, fuzzy msgid "ar:UAH,au:₴" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:431 +#: ../data/currencies.xml.in.h:434 msgid "Ukraine" msgstr "" -#: ../data/currencies.xml.in.h:432 +#: ../data/currencies.xml.in.h:435 msgid "United Arab Emirates Dirham" msgstr "" -#: ../data/currencies.xml.in.h:433 +#: ../data/currencies.xml.in.h:436 msgid "ar:AED" msgstr "" -#: ../data/currencies.xml.in.h:434 +#: ../data/currencies.xml.in.h:437 msgid "United Arab Emirates" msgstr "" -#: ../data/currencies.xml.in.h:435 +#: ../data/currencies.xml.in.h:438 msgid "Uruguayan Peso" msgstr "" -#: ../data/currencies.xml.in.h:436 +#: ../data/currencies.xml.in.h:439 msgid "ar:UYU" msgstr "" -#: ../data/currencies.xml.in.h:437 +#: ../data/currencies.xml.in.h:440 msgid "Uruguay" msgstr "" -#: ../data/currencies.xml.in.h:438 +#: ../data/currencies.xml.in.h:441 msgid "Uzbekistan Soʻm" msgstr "" -#: ../data/currencies.xml.in.h:439 +#: ../data/currencies.xml.in.h:442 msgid "ar:UZS" msgstr "" -#: ../data/currencies.xml.in.h:440 +#: ../data/currencies.xml.in.h:443 msgid "Uzbekistan" msgstr "" -#: ../data/currencies.xml.in.h:441 +#: ../data/currencies.xml.in.h:444 msgid "Vanuatu Vatu" msgstr "" -#: ../data/currencies.xml.in.h:442 +#: ../data/currencies.xml.in.h:445 msgid "ar:VUV" msgstr "" -#: ../data/currencies.xml.in.h:443 +#: ../data/currencies.xml.in.h:446 msgid "Vanuatu" msgstr "" -#: ../data/currencies.xml.in.h:444 +#: ../data/currencies.xml.in.h:447 #, fuzzy msgid "Venezuelan Bolívar (obsolete)" msgstr "Sloveense tolar" -#: ../data/currencies.xml.in.h:445 +#: ../data/currencies.xml.in.h:448 msgid "ar:VEF" msgstr "" -#: ../data/currencies.xml.in.h:446 +#: ../data/currencies.xml.in.h:449 msgid "Vietnamese Dồng" msgstr "" -#: ../data/currencies.xml.in.h:447 +#: ../data/currencies.xml.in.h:450 #, fuzzy msgid "ar:VND,au:₫" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:448 +#: ../data/currencies.xml.in.h:451 msgid "Vietnam" msgstr "" -#: ../data/currencies.xml.in.h:449 +#: ../data/currencies.xml.in.h:452 msgid "Yemeni Rial" msgstr "" -#: ../data/currencies.xml.in.h:450 +#: ../data/currencies.xml.in.h:453 msgid "ar:YER" msgstr "" -#: ../data/currencies.xml.in.h:451 +#: ../data/currencies.xml.in.h:454 #, fuzzy msgid "Yemen" msgstr "Elementen" -#: ../data/currencies.xml.in.h:452 +#: ../data/currencies.xml.in.h:455 msgid "Zambian Kwacha (obsolete)" msgstr "" -#: ../data/currencies.xml.in.h:453 +#: ../data/currencies.xml.in.h:456 msgid "ar:ZMK" msgstr "" -#: ../data/currencies.xml.in.h:454 +#: ../data/currencies.xml.in.h:457 msgid "Euro Cent" msgstr "Eurocent" -#: ../data/currencies.xml.in.h:455 +#: ../data/currencies.xml.in.h:458 msgid "r:eurocent,p:eurocents" msgstr "eurocent,p:eurocenten" -#: ../data/currencies.xml.in.h:456 +#: ../data/currencies.xml.in.h:459 msgid "Cent (USD)" msgstr "Cent (USD)" -#: ../data/currencies.xml.in.h:457 +#: ../data/currencies.xml.in.h:460 msgid "au:¢,r:cent,p:cents" msgstr "au:¢,cent,p:centen" -#: ../data/currencies.xml.in.h:458 +#: ../data/currencies.xml.in.h:461 #, fuzzy msgid "Belgian Franc (obsolete)" msgstr "Belgische frank" -#: ../data/currencies.xml.in.h:459 +#: ../data/currencies.xml.in.h:462 msgid "ar:BEF" msgstr "" -#: ../data/currencies.xml.in.h:460 +#: ../data/currencies.xml.in.h:463 #, fuzzy msgid "Greek Drachma (obsolete)" msgstr "Griekse drachme" -#: ../data/currencies.xml.in.h:461 +#: ../data/currencies.xml.in.h:464 #, fuzzy msgid "ar:GRD,au:₯" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:462 +#: ../data/currencies.xml.in.h:465 #, fuzzy msgid "French Franc (obsolete)" msgstr "Franse franc" -#: ../data/currencies.xml.in.h:463 +#: ../data/currencies.xml.in.h:466 #, fuzzy msgid "ar:FRF,au:₣" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:464 +#: ../data/currencies.xml.in.h:467 #, fuzzy msgid "Italian Lira (obsolete)" msgstr "Italiaanse lire" -#: ../data/currencies.xml.in.h:465 +#: ../data/currencies.xml.in.h:468 msgid "ar:ITL" msgstr "" -#: ../data/currencies.xml.in.h:466 +#: ../data/currencies.xml.in.h:469 #, fuzzy msgid "Dutch Guilder (obsolete)" msgstr "Nederlandse gulden" -#: ../data/currencies.xml.in.h:467 +#: ../data/currencies.xml.in.h:470 #, fuzzy msgid "ar:NLG" msgstr "a:NLG,gulden" -#: ../data/currencies.xml.in.h:468 +#: ../data/currencies.xml.in.h:471 #, fuzzy msgid "Portuguese Escudo (obsolete)" msgstr "Portugese escudo" -#: ../data/currencies.xml.in.h:469 +#: ../data/currencies.xml.in.h:472 msgid "ar:PTE" msgstr "" -#: ../data/currencies.xml.in.h:470 +#: ../data/currencies.xml.in.h:473 #, fuzzy msgid "Deutsche Mark (obsolete)" msgstr "Duitse mark" -#: ../data/currencies.xml.in.h:471 +#: ../data/currencies.xml.in.h:474 msgid "ar:DEM" msgstr "" -#: ../data/currencies.xml.in.h:472 +#: ../data/currencies.xml.in.h:475 #, fuzzy msgid "Spanish Peseta (obsolete)" msgstr "Spaanse peseta" -#: ../data/currencies.xml.in.h:473 +#: ../data/currencies.xml.in.h:476 #, fuzzy msgid "ar:ESP,au:₧" msgstr "a:ITL,au:₤,lire" -#: ../data/currencies.xml.in.h:474 +#: ../data/currencies.xml.in.h:477 #, fuzzy msgid "Irish Pound (obsolete)" msgstr "Ierse pond" -#: ../data/currencies.xml.in.h:475 +#: ../data/currencies.xml.in.h:478 msgid "ar:IEP" msgstr "" -#: ../data/currencies.xml.in.h:476 +#: ../data/currencies.xml.in.h:479 #, fuzzy msgid "Luxembourg Franc (obsolete)" msgstr "Luxemburgse frank" -#: ../data/currencies.xml.in.h:477 +#: ../data/currencies.xml.in.h:480 msgid "ar:LUF" msgstr "" -#: ../data/currencies.xml.in.h:478 +#: ../data/currencies.xml.in.h:481 #, fuzzy msgid "Austrian Schilling (obsolete)" msgstr "Oostenrijkse schilling" -#: ../data/currencies.xml.in.h:479 +#: ../data/currencies.xml.in.h:482 msgid "ar:ATS" msgstr "" -#: ../data/currencies.xml.in.h:480 +#: ../data/currencies.xml.in.h:483 #, fuzzy msgid "Finnish Markka (obsolete)" msgstr "Finse mark" -#: ../data/currencies.xml.in.h:481 +#: ../data/currencies.xml.in.h:484 msgid "ar:FIM" msgstr "" -#: ../data/currencies.xml.in.h:482 +#: ../data/currencies.xml.in.h:485 #, fuzzy msgid "Slovenian Tolar (obsolete)" msgstr "Sloveense tolar" -#: ../data/currencies.xml.in.h:483 +#: ../data/currencies.xml.in.h:486 msgid "ar:SIT" msgstr "" -#: ../data/currencies.xml.in.h:484 +#: ../data/currencies.xml.in.h:487 #, fuzzy msgid "Cypriot Pound (obsolete)" msgstr "Cypriotische pond" -#: ../data/currencies.xml.in.h:485 +#: ../data/currencies.xml.in.h:488 msgid "ar:CYP" msgstr "" -#: ../data/currencies.xml.in.h:486 +#: ../data/currencies.xml.in.h:489 #, fuzzy msgid "Estonian Kroon (obsolete)" msgstr "Estlandse kroon" -#: ../data/currencies.xml.in.h:487 +#: ../data/currencies.xml.in.h:490 msgid "ar:EEK" msgstr "" -#: ../data/currencies.xml.in.h:488 +#: ../data/currencies.xml.in.h:491 #, fuzzy msgid "Slovak Koruna (obsolete)" msgstr "Slowaakse kroon" -#: ../data/currencies.xml.in.h:489 +#: ../data/currencies.xml.in.h:492 msgid "ar:SKK" msgstr "" -#: ../data/currencies.xml.in.h:490 +#: ../data/currencies.xml.in.h:493 #, fuzzy msgid "Maltese Lira (obsolete)" msgstr "Maltese Lira" -#: ../data/currencies.xml.in.h:491 +#: ../data/currencies.xml.in.h:494 msgid "ar:MTL" msgstr "" -#: ../data/currencies.xml.in.h:492 +#: ../data/currencies.xml.in.h:495 #, fuzzy msgid "Latvian Lats (obsolete)" msgstr "Letlandse lat" -#: ../data/currencies.xml.in.h:493 +#: ../data/currencies.xml.in.h:496 msgid "ar:LVL" msgstr "" -#: ../data/currencies.xml.in.h:494 +#: ../data/currencies.xml.in.h:497 #, fuzzy msgid "Lithuanian Litas (obsolete)" msgstr "Litouwse litas" -#: ../data/currencies.xml.in.h:495 +#: ../data/currencies.xml.in.h:498 msgid "ar:LTL" msgstr "" @@ -2145,7 +2159,7 @@ msgid "!datasets!r:number" msgstr "getal" -#: ../data/datasets.xml.in.h:13 ../data/functions.xml.in.h:709 +#: ../data/datasets.xml.in.h:13 ../data/functions.xml.in.h:716 msgid "Name" msgstr "Naam" @@ -2174,7 +2188,7 @@ msgid "r:class" msgstr "klasse" -#: ../data/datasets.xml.in.h:18 ../data/functions.xml.in.h:424 +#: ../data/datasets.xml.in.h:18 ../data/functions.xml.in.h:431 msgid "Weight" msgstr "Gewicht" @@ -3745,17 +3759,18 @@ msgstr "kgv" #: ../data/functions.xml.in.h:216 -msgid "Fibonacci Number" -msgstr "Getal van Fibonacci" +msgid "Bernoulli Number/Polynomial" +msgstr "" #: ../data/functions.xml.in.h:217 -msgid "r:fibonacci" +msgid "" +"Returns the nth Bernoulli number or polynomial (if the second argument is " +"non-zero)." msgstr "" #: ../data/functions.xml.in.h:218 -#, fuzzy -msgid "Returns the n-th term of the Fibonacci sequence." -msgstr "Retourneert het aantal elementen in een vector." +msgid "r:bernoulli" +msgstr "" #: ../data/functions.xml.in.h:219 #, fuzzy @@ -3763,70 +3778,83 @@ msgstr "Index" #: ../data/functions.xml.in.h:220 +msgid "Fibonacci Number" +msgstr "Getal van Fibonacci" + +#: ../data/functions.xml.in.h:221 +msgid "r:fibonacci" +msgstr "" + +#: ../data/functions.xml.in.h:222 +#, fuzzy +msgid "Returns the n-th term of the Fibonacci sequence." +msgstr "Retourneert het aantal elementen in een vector." + +#: ../data/functions.xml.in.h:223 msgid "Rounding" msgstr "Afronding" -#: ../data/functions.xml.in.h:221 +#: ../data/functions.xml.in.h:224 msgid "Round" msgstr "Afronden" -#: ../data/functions.xml.in.h:222 +#: ../data/functions.xml.in.h:225 msgid "r:round" msgstr "afronden" -#: ../data/functions.xml.in.h:223 +#: ../data/functions.xml.in.h:226 msgid "Round Downwards" msgstr "Naar beneden afronden" -#: ../data/functions.xml.in.h:224 +#: ../data/functions.xml.in.h:227 msgid "r:floor" msgstr "" -#: ../data/functions.xml.in.h:225 +#: ../data/functions.xml.in.h:228 msgid "Round Upwards" msgstr "Naar boven afronden" -#: ../data/functions.xml.in.h:226 +#: ../data/functions.xml.in.h:229 msgid "r:ceil" msgstr "" -#: ../data/functions.xml.in.h:227 +#: ../data/functions.xml.in.h:230 msgid "Round Towards Zero" msgstr "Afronden in de richting van nul" -#: ../data/functions.xml.in.h:228 +#: ../data/functions.xml.in.h:231 msgid "r:trunc" msgstr "afkap" -#: ../data/functions.xml.in.h:229 +#: ../data/functions.xml.in.h:232 msgid "Integer Part" msgstr "Gehele deel uit (getal)" -#: ../data/functions.xml.in.h:230 +#: ../data/functions.xml.in.h:233 msgid "r:int" msgstr "" -#: ../data/functions.xml.in.h:231 +#: ../data/functions.xml.in.h:234 msgid "Fractional Part" msgstr "Fractionele deel uit (getal)" -#: ../data/functions.xml.in.h:232 +#: ../data/functions.xml.in.h:235 msgid "r:frac" msgstr "" -#: ../data/functions.xml.in.h:233 +#: ../data/functions.xml.in.h:236 msgid "Number Bases" msgstr "Grondtallen voor talstelsels" -#: ../data/functions.xml.in.h:234 +#: ../data/functions.xml.in.h:237 msgid "Number Base" msgstr "Grondtal talstelsel" -#: ../data/functions.xml.in.h:235 +#: ../data/functions.xml.in.h:238 msgid "r:base" msgstr "grondtal" -#: ../data/functions.xml.in.h:236 +#: ../data/functions.xml.in.h:239 msgid "" "Returns a value from an expression using the specified number base (radix). " "For bases between -62 and 62 full mathematical expressions (including " @@ -3847,97 +3875,97 @@ "selected, the specified expression is always converted to a single number." msgstr "" -#: ../data/functions.xml.in.h:237 +#: ../data/functions.xml.in.h:240 msgid "Set of digits" msgstr "" -#: ../data/functions.xml.in.h:238 +#: ../data/functions.xml.in.h:241 msgid "Binary" msgstr "Binair" -#: ../data/functions.xml.in.h:239 +#: ../data/functions.xml.in.h:242 msgid "r:bin" msgstr "" -#: ../data/functions.xml.in.h:240 +#: ../data/functions.xml.in.h:243 msgid "" "Returns a value from a binary expression. If two's complement is true, " "numbers beginning with '1' is interpreted as negative binary numbers using " "two's complement." msgstr "" -#: ../data/functions.xml.in.h:241 +#: ../data/functions.xml.in.h:244 msgid "Binary number" msgstr "Binair getal" -#: ../data/functions.xml.in.h:242 +#: ../data/functions.xml.in.h:245 msgid "Two's complement" msgstr "" -#: ../data/functions.xml.in.h:243 +#: ../data/functions.xml.in.h:246 msgid "Octal" msgstr "Octaal" -#: ../data/functions.xml.in.h:244 +#: ../data/functions.xml.in.h:247 msgid "r:oct" msgstr "" -#: ../data/functions.xml.in.h:245 +#: ../data/functions.xml.in.h:248 #, fuzzy msgid "Returns a value from an octal expression." msgstr "Converteert een hexadecimaal getal naar een getal" -#: ../data/functions.xml.in.h:246 +#: ../data/functions.xml.in.h:249 msgid "Octal number" msgstr "Octaal getal" -#: ../data/functions.xml.in.h:247 +#: ../data/functions.xml.in.h:250 msgid "Decimal" msgstr "Decimaal" -#: ../data/functions.xml.in.h:248 +#: ../data/functions.xml.in.h:251 #, fuzzy msgid "r:dec" msgstr "deciel" -#: ../data/functions.xml.in.h:249 +#: ../data/functions.xml.in.h:252 #, fuzzy msgid "Returns a value from a decimal expression." msgstr "Converteert een hexadecimaal getal naar een getal" -#: ../data/functions.xml.in.h:250 +#: ../data/functions.xml.in.h:253 #, fuzzy msgid "Decimal number" msgstr "Hexadecimaal getal" -#: ../data/functions.xml.in.h:251 +#: ../data/functions.xml.in.h:254 msgid "Hexadecimal" msgstr "Hexadecimaal" -#: ../data/functions.xml.in.h:252 +#: ../data/functions.xml.in.h:255 msgid "r:hex" msgstr "" -#: ../data/functions.xml.in.h:253 +#: ../data/functions.xml.in.h:256 msgid "" "Returns a value from a hexadecimal expression. If two's complement is true, " "numbers beginning with 8 or higher is interpreted as negative hexadecimal " "numbers using two's complement." msgstr "" -#: ../data/functions.xml.in.h:254 +#: ../data/functions.xml.in.h:257 msgid "Hexadecimal number" msgstr "Hexadecimaal getal" -#: ../data/functions.xml.in.h:255 +#: ../data/functions.xml.in.h:258 msgid "Bijective base-26" msgstr "" -#: ../data/functions.xml.in.h:256 +#: ../data/functions.xml.in.h:259 msgid "r:bijective" msgstr "" -#: ../data/functions.xml.in.h:257 +#: ../data/functions.xml.in.h:260 #, fuzzy msgid "" "Returns a value from an expression in bijective base-26. Conversion in the " @@ -3946,177 +3974,193 @@ "Converteert een getal in een opgegeven basis tussen 2 en 36 naar een geheel " "getal" -#: ../data/functions.xml.in.h:258 +#: ../data/functions.xml.in.h:261 msgid "Bijective base-26 number" msgstr "" -#: ../data/functions.xml.in.h:259 +#: ../data/functions.xml.in.h:262 msgid "Integers" msgstr "Gehele getallen" -#: ../data/functions.xml.in.h:260 +#: ../data/functions.xml.in.h:263 msgid "Even" msgstr "" -#: ../data/functions.xml.in.h:261 +#: ../data/functions.xml.in.h:264 msgid "r:even" msgstr "" -#: ../data/functions.xml.in.h:262 +#: ../data/functions.xml.in.h:265 msgid "Odd" msgstr "Oneven" -#: ../data/functions.xml.in.h:263 +#: ../data/functions.xml.in.h:266 msgid "r:odd" msgstr "oneven" -#: ../data/functions.xml.in.h:264 +#: ../data/functions.xml.in.h:267 msgid "Special Functions" msgstr "Speciale functie" -#: ../data/functions.xml.in.h:265 +#: ../data/functions.xml.in.h:268 msgid "Gamma Function" msgstr "Gamma-functie" -#: ../data/functions.xml.in.h:266 +#: ../data/functions.xml.in.h:269 msgid "r:gamma" msgstr "" -#: ../data/functions.xml.in.h:267 +#: ../data/functions.xml.in.h:270 msgid "Digamma Function" msgstr "Digamma-functie" -#: ../data/functions.xml.in.h:268 +#: ../data/functions.xml.in.h:271 msgid "r:digamma,psi" msgstr "" -#: ../data/functions.xml.in.h:269 +#: ../data/functions.xml.in.h:272 msgid "Beta Function" msgstr "Beta-functie" -#: ../data/functions.xml.in.h:270 +#: ../data/functions.xml.in.h:273 msgid "r:beta" msgstr "" -#: ../data/functions.xml.in.h:271 +#: ../data/functions.xml.in.h:274 msgid "Error Function" msgstr "Errorfunctie" -#: ../data/functions.xml.in.h:272 +#: ../data/functions.xml.in.h:275 msgid "r:erf" msgstr "" -#: ../data/functions.xml.in.h:273 +#: ../data/functions.xml.in.h:276 msgid "Complementary Error Function" msgstr "Complementaire errorfunctie" -#: ../data/functions.xml.in.h:274 +#: ../data/functions.xml.in.h:277 msgid "r:erfc" msgstr "" -#: ../data/functions.xml.in.h:275 +#: ../data/functions.xml.in.h:278 +msgid "Imaginary Error Function" +msgstr "Imaginaire errorfunctie" + +#: ../data/functions.xml.in.h:279 +msgid "r:erfi" +msgstr "" + +#: ../data/functions.xml.in.h:280 msgid "Polylogarithm" msgstr "Polylogaritme" -#: ../data/functions.xml.in.h:276 +#: ../data/functions.xml.in.h:281 msgid "rc:Li,polylog" msgstr "" -#: ../data/functions.xml.in.h:277 +#: ../data/functions.xml.in.h:282 msgid "Order" msgstr "Orde" -#: ../data/functions.xml.in.h:278 +#: ../data/functions.xml.in.h:283 #, fuzzy msgid "Argument" msgstr "Argumenten" -#: ../data/functions.xml.in.h:279 +#: ../data/functions.xml.in.h:284 #, fuzzy msgid "Airy Function" msgstr "Airy-functie" -#: ../data/functions.xml.in.h:280 +#: ../data/functions.xml.in.h:285 msgid "r:airy" msgstr "" -#: ../data/functions.xml.in.h:281 +#: ../data/functions.xml.in.h:286 msgid "Bessel Function of the First Kind" msgstr "" -#: ../data/functions.xml.in.h:282 +#: ../data/functions.xml.in.h:287 msgid "r:besselj" msgstr "" -#: ../data/functions.xml.in.h:283 +#: ../data/functions.xml.in.h:288 msgid "Bessel Function of the Second Kind" msgstr "" -#: ../data/functions.xml.in.h:284 +#: ../data/functions.xml.in.h:289 msgid "r:bessely" msgstr "" -#: ../data/functions.xml.in.h:285 +#: ../data/functions.xml.in.h:290 msgid "Riemann Zeta" msgstr "Riemann Zeta" -#: ../data/functions.xml.in.h:286 +#: ../data/functions.xml.in.h:291 +msgid "Calculates Hurwitz zeta function if the second argument is not 1." +msgstr "" + +#: ../data/functions.xml.in.h:292 msgid "r:zeta" msgstr "" -#: ../data/functions.xml.in.h:287 +#: ../data/functions.xml.in.h:293 msgid "Integral point" msgstr "Gehele waarde" -#: ../data/functions.xml.in.h:288 +#: ../data/functions.xml.in.h:294 +msgid "Hurwitz zeta argument" +msgstr "" + +#: ../data/functions.xml.in.h:295 msgid "Kronecker Delta" msgstr "Kronecker Delta" -#: ../data/functions.xml.in.h:289 +#: ../data/functions.xml.in.h:296 msgid "r:kronecker" msgstr "" -#: ../data/functions.xml.in.h:290 +#: ../data/functions.xml.in.h:297 msgid "Returns 0 if i != j and 1 if i = j." msgstr "Retourneert 0 indien i != j en 1 if i = j." -#: ../data/functions.xml.in.h:291 +#: ../data/functions.xml.in.h:298 msgid "Value 1 (i)" msgstr "Waarde 1 (i)" -#: ../data/functions.xml.in.h:292 +#: ../data/functions.xml.in.h:299 msgid "Value 2 (j)" msgstr "Waarde 2 (j)" -#: ../data/functions.xml.in.h:293 +#: ../data/functions.xml.in.h:300 msgid "Logit Transformation" msgstr "Logit transformatie" -#: ../data/functions.xml.in.h:294 +#: ../data/functions.xml.in.h:301 msgid "r:logit" msgstr "" -#: ../data/functions.xml.in.h:295 +#: ../data/functions.xml.in.h:302 msgid "Sigmoid Function" msgstr "Sigmoïde functie" -#: ../data/functions.xml.in.h:296 +#: ../data/functions.xml.in.h:303 msgid "r:sigmoid" msgstr "sigmoïde" -#: ../data/functions.xml.in.h:297 +#: ../data/functions.xml.in.h:304 msgid "Step Functions" msgstr "Stapfuncties" -#: ../data/functions.xml.in.h:298 +#: ../data/functions.xml.in.h:305 msgid "Heaviside Step Function" msgstr "Heaviside stapfunctie" -#: ../data/functions.xml.in.h:299 +#: ../data/functions.xml.in.h:306 msgid "r:heaviside,au:θ" msgstr "" -#: ../data/functions.xml.in.h:300 +#: ../data/functions.xml.in.h:307 msgid "" "Discontinuous function also known as \"unit step function\". Returns 0 if x " "< 0, 1 if x > 0, and 1/2 if x = 0." @@ -4124,176 +4168,176 @@ "Discontinue functie die ook bekend staat als de \"eenheids stapfunctie\". " "Retourneert 0 indien x < 0, 1 indien x ;gt; 0, en 1/2 indien x=0." -#: ../data/functions.xml.in.h:301 +#: ../data/functions.xml.in.h:308 msgid "Dirac Delta Function" msgstr "Diracdelta" -#: ../data/functions.xml.in.h:302 +#: ../data/functions.xml.in.h:309 msgid "r:dirac,au:δ" msgstr "" -#: ../data/functions.xml.in.h:303 +#: ../data/functions.xml.in.h:310 #, fuzzy msgid "Returns 0 if x is non-zero, and infinity if x is zero." msgstr "Retourneert 0 indien i != j en 1 if i = j." -#: ../data/functions.xml.in.h:304 +#: ../data/functions.xml.in.h:311 msgid "Ramp Function" msgstr "Rampfunctie" -#: ../data/functions.xml.in.h:305 +#: ../data/functions.xml.in.h:312 msgid "r:ramp" msgstr "" -#: ../data/functions.xml.in.h:306 +#: ../data/functions.xml.in.h:313 msgid "Rectangular Function" msgstr "Rechthoekige functie" -#: ../data/functions.xml.in.h:307 +#: ../data/functions.xml.in.h:314 msgid "r:rectangular" msgstr "rechthoekig" -#: ../data/functions.xml.in.h:308 +#: ../data/functions.xml.in.h:315 msgid "Triangular Function" msgstr "Driehoekige functie" -#: ../data/functions.xml.in.h:309 +#: ../data/functions.xml.in.h:316 msgid "r:triangular" msgstr "driehoekig" -#: ../data/functions.xml.in.h:310 +#: ../data/functions.xml.in.h:317 msgid "Complex Numbers" msgstr "Complexe getallen" -#: ../data/functions.xml.in.h:311 +#: ../data/functions.xml.in.h:318 msgid "Real Part" msgstr "Reële deel" -#: ../data/functions.xml.in.h:312 +#: ../data/functions.xml.in.h:319 #, fuzzy msgid "r:re,au:ℜ" msgstr "a:ITL,au:₤,lire" -#: ../data/functions.xml.in.h:313 +#: ../data/functions.xml.in.h:320 msgid "Complex number" msgstr "Complex getal" -#: ../data/functions.xml.in.h:314 +#: ../data/functions.xml.in.h:321 msgid "Imaginary Part" msgstr "Imaginaire deel" -#: ../data/functions.xml.in.h:315 +#: ../data/functions.xml.in.h:322 #, fuzzy msgid "r:im,au:ℑ" msgstr "gouden,φ" -#: ../data/functions.xml.in.h:316 +#: ../data/functions.xml.in.h:323 #, fuzzy msgid "Principal Argument" msgstr "Argument" -#: ../data/functions.xml.in.h:317 +#: ../data/functions.xml.in.h:324 msgid "r:arg" msgstr "" -#: ../data/functions.xml.in.h:318 +#: ../data/functions.xml.in.h:325 msgid "Complex Conjugate" msgstr "Complex geconjugeerde" -#: ../data/functions.xml.in.h:319 +#: ../data/functions.xml.in.h:326 msgid "r:conj" msgstr "" -#: ../data/functions.xml.in.h:320 +#: ../data/functions.xml.in.h:327 msgid "Exponents & Logarithms" msgstr "Exponenten & Logaritmen" -#: ../data/functions.xml.in.h:321 +#: ../data/functions.xml.in.h:328 msgid "Square Root" msgstr "Vierkantswortel" -#: ../data/functions.xml.in.h:322 +#: ../data/functions.xml.in.h:329 msgid "au:√,r:sqrt" msgstr "" -#: ../data/functions.xml.in.h:323 +#: ../data/functions.xml.in.h:330 msgid "" "Returns the principal square root (for positive values the positive root is " "returned)." msgstr "" -#: ../data/functions.xml.in.h:324 +#: ../data/functions.xml.in.h:331 msgid "Cube Root" msgstr "Derdemachtswortel" -#: ../data/functions.xml.in.h:325 +#: ../data/functions.xml.in.h:332 msgid "au:∛,r:cbrt" msgstr "" -#: ../data/functions.xml.in.h:326 +#: ../data/functions.xml.in.h:333 #, fuzzy msgid "Returns the third real root." msgstr "Retourneert de grootste waarde." -#: ../data/functions.xml.in.h:327 +#: ../data/functions.xml.in.h:334 msgid "Nth root" msgstr "N-de wortel" -#: ../data/functions.xml.in.h:328 +#: ../data/functions.xml.in.h:335 msgid "r:root" msgstr "wortel" -#: ../data/functions.xml.in.h:329 +#: ../data/functions.xml.in.h:336 msgid "" "Returns the real root. For negative values the degree must be odd. Complex " "values are not allowed." msgstr "" -#: ../data/functions.xml.in.h:330 ../data/units.xml.in.h:65 +#: ../data/functions.xml.in.h:337 ../data/units.xml.in.h:65 msgid "Degree" msgstr "Graad" -#: ../data/functions.xml.in.h:331 +#: ../data/functions.xml.in.h:338 msgid "Square" msgstr "Vierkant" -#: ../data/functions.xml.in.h:332 +#: ../data/functions.xml.in.h:339 msgid "r:sq" msgstr "" -#: ../data/functions.xml.in.h:333 +#: ../data/functions.xml.in.h:340 msgid "Exponential (e^x)" msgstr "Exponent (e^x)" -#: ../data/functions.xml.in.h:334 +#: ../data/functions.xml.in.h:341 msgid "r:exp" msgstr "" -#: ../data/functions.xml.in.h:335 +#: ../data/functions.xml.in.h:342 msgid "Natural Logarithm" msgstr "Natuurlijke logaritme" -#: ../data/functions.xml.in.h:336 +#: ../data/functions.xml.in.h:343 msgid "r:ln" msgstr "" -#: ../data/functions.xml.in.h:337 +#: ../data/functions.xml.in.h:344 msgid "Base-N Logarithm" msgstr "Logaritme met grondtal N" -#: ../data/functions.xml.in.h:338 +#: ../data/functions.xml.in.h:345 msgid "r:log" msgstr "" -#: ../data/functions.xml.in.h:339 +#: ../data/functions.xml.in.h:346 msgid "Lambert W Function (Omega Function, Product Log)" msgstr "Lambert W Functie (Omega Functie, Product Log)" -#: ../data/functions.xml.in.h:340 +#: ../data/functions.xml.in.h:347 msgid "r:lambertw,productlog" msgstr "" -#: ../data/functions.xml.in.h:341 +#: ../data/functions.xml.in.h:348 #, fuzzy msgid "" "Returns the inverse function for mx*e^x as ln() does for e^x. Only the " @@ -4302,335 +4346,335 @@ "Retourneert de inverse functie van mx*e^x (zoals ln(x) de inverse functie is " "van e^x)." -#: ../data/functions.xml.in.h:342 +#: ../data/functions.xml.in.h:349 msgid "Branch" msgstr "" -#: ../data/functions.xml.in.h:343 +#: ../data/functions.xml.in.h:350 msgid "Complex Exponential (Cis)" msgstr "Complex Exponentieel (Cis)" -#: ../data/functions.xml.in.h:344 +#: ../data/functions.xml.in.h:351 msgid "r:cis" msgstr "" -#: ../data/functions.xml.in.h:345 +#: ../data/functions.xml.in.h:352 msgid "Base-2 Logarithm" msgstr "Logaritme met grondtal 2" -#: ../data/functions.xml.in.h:346 +#: ../data/functions.xml.in.h:353 msgid "rs:log2" msgstr "" -#: ../data/functions.xml.in.h:347 +#: ../data/functions.xml.in.h:354 msgid "Returns the base n logarithm." msgstr "Retourneert de logaritme met grondtal n." -#: ../data/functions.xml.in.h:348 +#: ../data/functions.xml.in.h:355 msgid "Base-10 Logarithm" msgstr "Logaritme met grondtal 10" -#: ../data/functions.xml.in.h:349 +#: ../data/functions.xml.in.h:356 msgid "rs:log10" msgstr "" -#: ../data/functions.xml.in.h:350 +#: ../data/functions.xml.in.h:357 msgid "2 raised to the power X" msgstr "2 tot de macht X" -#: ../data/functions.xml.in.h:351 +#: ../data/functions.xml.in.h:358 msgid "rs:exp2" msgstr "" -#: ../data/functions.xml.in.h:352 +#: ../data/functions.xml.in.h:359 msgid "10 raised to the power X" msgstr "10 tot de macht X" -#: ../data/functions.xml.in.h:353 +#: ../data/functions.xml.in.h:360 msgid "rs:exp10" msgstr "" -#: ../data/functions.xml.in.h:354 +#: ../data/functions.xml.in.h:361 msgid "X raised to the power Y" msgstr "X tot de macht Y" -#: ../data/functions.xml.in.h:355 +#: ../data/functions.xml.in.h:362 msgid "r:pow" msgstr "macht" -#: ../data/functions.xml.in.h:356 +#: ../data/functions.xml.in.h:363 msgid "Square root (x * pi)" msgstr "Vierkantswortel (x * pi)" -#: ../data/functions.xml.in.h:357 +#: ../data/functions.xml.in.h:364 msgid "r:sqrtpi" msgstr "" -#: ../data/functions.xml.in.h:358 +#: ../data/functions.xml.in.h:365 msgid "Returns the non-negative square root of x * pi" msgstr "Retourneert de niet-negatieve vierkantswortel van x * pi" -#: ../data/functions.xml.in.h:359 +#: ../data/functions.xml.in.h:366 msgid "Non-negative value" msgstr "Niet-negatieve waarde" -#: ../data/functions.xml.in.h:360 +#: ../data/functions.xml.in.h:367 msgid "Trigonometry" msgstr "Goniometrie" -#: ../data/functions.xml.in.h:361 +#: ../data/functions.xml.in.h:368 msgid "Sine" msgstr "Sinus" -#: ../data/functions.xml.in.h:362 +#: ../data/functions.xml.in.h:369 msgid "r:sin" msgstr "" -#: ../data/functions.xml.in.h:363 +#: ../data/functions.xml.in.h:370 msgid "Angle" msgstr "Hoek" -#: ../data/functions.xml.in.h:364 +#: ../data/functions.xml.in.h:371 msgid "Cosine" msgstr "Cosinus" -#: ../data/functions.xml.in.h:365 +#: ../data/functions.xml.in.h:372 msgid "r:cos" msgstr "" -#: ../data/functions.xml.in.h:366 +#: ../data/functions.xml.in.h:373 msgid "Tangent" msgstr "Tangens" -#: ../data/functions.xml.in.h:367 +#: ../data/functions.xml.in.h:374 msgid "r:tan" msgstr "" -#: ../data/functions.xml.in.h:368 +#: ../data/functions.xml.in.h:375 msgid "Inverse Sine" msgstr "Inverse sinus" -#: ../data/functions.xml.in.h:369 +#: ../data/functions.xml.in.h:376 msgid "r:asin" msgstr "" -#: ../data/functions.xml.in.h:370 +#: ../data/functions.xml.in.h:377 msgid "Inverse Cosine" msgstr "Inverse cosinus" -#: ../data/functions.xml.in.h:371 +#: ../data/functions.xml.in.h:378 msgid "r:acos" msgstr "" -#: ../data/functions.xml.in.h:372 +#: ../data/functions.xml.in.h:379 msgid "Inverse Tangent" msgstr "Inverse tangens" -#: ../data/functions.xml.in.h:373 +#: ../data/functions.xml.in.h:380 msgid "r:atan" msgstr "" -#: ../data/functions.xml.in.h:374 +#: ../data/functions.xml.in.h:381 msgid "Hyperbolic Sine" msgstr "Hyperbolische sinus" -#: ../data/functions.xml.in.h:375 +#: ../data/functions.xml.in.h:382 msgid "r:sinh" msgstr "" -#: ../data/functions.xml.in.h:376 +#: ../data/functions.xml.in.h:383 msgid "Hyperbolic Cosine" msgstr "Hyperbolische cosinus" -#: ../data/functions.xml.in.h:377 +#: ../data/functions.xml.in.h:384 msgid "r:cosh" msgstr "" -#: ../data/functions.xml.in.h:378 +#: ../data/functions.xml.in.h:385 msgid "Hyperbolic Tangent" msgstr "Hyperbolische tangens" -#: ../data/functions.xml.in.h:379 +#: ../data/functions.xml.in.h:386 msgid "r:tanh" msgstr "" -#: ../data/functions.xml.in.h:380 +#: ../data/functions.xml.in.h:387 msgid "Inverse Hyperbolic Sine" msgstr "Inverse hyperbolische sinus" -#: ../data/functions.xml.in.h:381 +#: ../data/functions.xml.in.h:388 msgid "r:asinh" msgstr "" -#: ../data/functions.xml.in.h:382 +#: ../data/functions.xml.in.h:389 msgid "Inverse Hyperbolic Cosine" msgstr "Inverse hyperbolische cosinus" -#: ../data/functions.xml.in.h:383 +#: ../data/functions.xml.in.h:390 msgid "r:acosh" msgstr "" -#: ../data/functions.xml.in.h:384 +#: ../data/functions.xml.in.h:391 msgid "Inverse Hyperbolic Tangent" msgstr "Inverse hyperbolische tangens" -#: ../data/functions.xml.in.h:385 +#: ../data/functions.xml.in.h:392 msgid "r:atanh" msgstr "" -#: ../data/functions.xml.in.h:386 +#: ../data/functions.xml.in.h:393 #, fuzzy msgid "Four-quadrant Inverse Tangent" msgstr "Inverse tangens" -#: ../data/functions.xml.in.h:387 +#: ../data/functions.xml.in.h:394 #, fuzzy msgid "r:atan2" msgstr "atoom" -#: ../data/functions.xml.in.h:388 +#: ../data/functions.xml.in.h:395 msgid "" "Computes the principal value of the argument function applied to the complex " "number x+iy." msgstr "" -#: ../data/functions.xml.in.h:389 +#: ../data/functions.xml.in.h:396 msgid "Y" msgstr "" -#: ../data/functions.xml.in.h:390 +#: ../data/functions.xml.in.h:397 msgid "X" msgstr "X" -#: ../data/functions.xml.in.h:391 +#: ../data/functions.xml.in.h:398 msgid "Cardinal Sine (Sinc Function)" msgstr "Sinus cardinalis (sinc-functie)" -#: ../data/functions.xml.in.h:392 +#: ../data/functions.xml.in.h:399 msgid "r:sinc" msgstr "" -#: ../data/functions.xml.in.h:393 +#: ../data/functions.xml.in.h:400 msgid "Radians to Default Angle Unit" msgstr "Radialen naar standaard hoekeenheid" -#: ../data/functions.xml.in.h:394 +#: ../data/functions.xml.in.h:401 msgid "r:radtodef" msgstr "radnaardef" -#: ../data/functions.xml.in.h:395 +#: ../data/functions.xml.in.h:402 msgid "Radians" msgstr "Radialen" -#: ../data/functions.xml.in.h:396 +#: ../data/functions.xml.in.h:403 msgid "Secant" msgstr "Secans" -#: ../data/functions.xml.in.h:397 +#: ../data/functions.xml.in.h:404 msgid "r:sec" msgstr "" -#: ../data/functions.xml.in.h:398 +#: ../data/functions.xml.in.h:405 msgid "Cosecant" msgstr "Cosecant" -#: ../data/functions.xml.in.h:399 +#: ../data/functions.xml.in.h:406 msgid "r:csc" msgstr "" -#: ../data/functions.xml.in.h:400 +#: ../data/functions.xml.in.h:407 msgid "Cotangent" msgstr "Cotangens" -#: ../data/functions.xml.in.h:401 +#: ../data/functions.xml.in.h:408 msgid "r:cot" msgstr "" -#: ../data/functions.xml.in.h:402 +#: ../data/functions.xml.in.h:409 msgid "Hyperbolic Secant" msgstr "Hyperbolische secans" -#: ../data/functions.xml.in.h:403 +#: ../data/functions.xml.in.h:410 msgid "r:sech" msgstr "" -#: ../data/functions.xml.in.h:404 +#: ../data/functions.xml.in.h:411 msgid "Hyperbolic Cosecant" msgstr "Hyperbolische cosecans" -#: ../data/functions.xml.in.h:405 +#: ../data/functions.xml.in.h:412 msgid "r:csch" msgstr "" -#: ../data/functions.xml.in.h:406 +#: ../data/functions.xml.in.h:413 msgid "Hyperbolic Cotangent" msgstr "Hyperbolische cotangens" -#: ../data/functions.xml.in.h:407 +#: ../data/functions.xml.in.h:414 msgid "r:coth" msgstr "" -#: ../data/functions.xml.in.h:408 +#: ../data/functions.xml.in.h:415 msgid "Inverse Secant" msgstr "Inverse secans" -#: ../data/functions.xml.in.h:409 +#: ../data/functions.xml.in.h:416 msgid "r:asec" msgstr "" -#: ../data/functions.xml.in.h:410 +#: ../data/functions.xml.in.h:417 msgid "Inverse Cosecant" msgstr "Inverse cosecans" -#: ../data/functions.xml.in.h:411 +#: ../data/functions.xml.in.h:418 msgid "r:acsc" msgstr "" -#: ../data/functions.xml.in.h:412 +#: ../data/functions.xml.in.h:419 msgid "Inverse Cotangent" msgstr "Inverse cotangens" -#: ../data/functions.xml.in.h:413 +#: ../data/functions.xml.in.h:420 msgid "r:acot" msgstr "" -#: ../data/functions.xml.in.h:414 +#: ../data/functions.xml.in.h:421 msgid "Inverse Hyperbolic Secant" msgstr "Inverse hyperbolische secans" -#: ../data/functions.xml.in.h:415 +#: ../data/functions.xml.in.h:422 msgid "r:asech" msgstr "" -#: ../data/functions.xml.in.h:416 +#: ../data/functions.xml.in.h:423 msgid "Inverse Hyperbolic Cosecant" msgstr "Inverse hyperbolische cosecans" -#: ../data/functions.xml.in.h:417 +#: ../data/functions.xml.in.h:424 msgid "r:acsch" msgstr "" -#: ../data/functions.xml.in.h:418 +#: ../data/functions.xml.in.h:425 msgid "Inverse Hyperbolic Cotangent" msgstr "Inverse hyperbolische cotangens" -#: ../data/functions.xml.in.h:419 +#: ../data/functions.xml.in.h:426 msgid "r:acoth" msgstr "" -#: ../data/functions.xml.in.h:420 +#: ../data/functions.xml.in.h:427 msgid "Miscellaneous" msgstr "Diversen" -#: ../data/functions.xml.in.h:421 +#: ../data/functions.xml.in.h:428 msgid "Body Mass Index (BMI)" msgstr "Body Mass Index (BMI) (Index voor lichaamsmassa)" -#: ../data/functions.xml.in.h:422 +#: ../data/functions.xml.in.h:429 msgid "-r:bmi" msgstr "" -#: ../data/functions.xml.in.h:423 +#: ../data/functions.xml.in.h:430 msgid "" "Calculates the Body Mass Index. The resulting BMI-value is sometimes " "interpreted as follows (although varies with age, sex, etc.): " @@ -4644,20 +4688,20 @@ "Te hoog gewicht& 25-30 Zwaarlijvigheid > 30 Let er opdat u " "eenheden gebruikt voor gewicht (bv. 59kg) en lengte (bv. 174cm)." -#: ../data/functions.xml.in.h:425 +#: ../data/functions.xml.in.h:432 msgid "Length" msgstr "Lengte" -#: ../data/functions.xml.in.h:426 +#: ../data/functions.xml.in.h:433 msgid "RAID Space" msgstr "" -#: ../data/functions.xml.in.h:427 +#: ../data/functions.xml.in.h:434 #, fuzzy msgid "r:raid" msgstr "wilk" -#: ../data/functions.xml.in.h:428 +#: ../data/functions.xml.in.h:435 msgid "" "Calculates RAID array disk capacity usable for data storage. If the " "combination of number of disks and RAID level is invalid, zero is returned. " @@ -4666,50 +4710,50 @@ "1+0)." msgstr "" -#: ../data/functions.xml.in.h:429 +#: ../data/functions.xml.in.h:436 msgid "RAID level" msgstr "" -#: ../data/functions.xml.in.h:430 +#: ../data/functions.xml.in.h:437 msgid "Capacity of each disk" msgstr "" -#: ../data/functions.xml.in.h:431 +#: ../data/functions.xml.in.h:438 #, fuzzy msgid "Number of disks" msgstr "Aantal termijnen" -#: ../data/functions.xml.in.h:432 +#: ../data/functions.xml.in.h:439 #, fuzzy msgid "Stripes" msgstr "Eenheden verwijderen" -#: ../data/functions.xml.in.h:433 +#: ../data/functions.xml.in.h:440 msgid "Roman Number" msgstr "Romeins getal" -#: ../data/functions.xml.in.h:434 +#: ../data/functions.xml.in.h:441 msgid "r:roman" msgstr "romeins" -#: ../data/functions.xml.in.h:435 +#: ../data/functions.xml.in.h:442 msgid "Returns the value of a roman number." msgstr "Retourneert de waarde van een Romeins getal." -#: ../data/functions.xml.in.h:436 +#: ../data/functions.xml.in.h:443 msgid "Roman number" msgstr "Romeins getal" -#: ../data/functions.xml.in.h:437 +#: ../data/functions.xml.in.h:444 #, fuzzy msgid "Depth of Field" msgstr "Lengte van zijde" -#: ../data/functions.xml.in.h:438 +#: ../data/functions.xml.in.h:445 msgid "r:dof" msgstr "" -#: ../data/functions.xml.in.h:439 +#: ../data/functions.xml.in.h:446 msgid "" "Returns the estimated distance between the nearest and the farthest objects " "that are in acceptably sharp focus in a photo. Enter focal length (e.g. 50 " @@ -4721,197 +4765,197 @@ "on d/1500." msgstr "" -#: ../data/functions.xml.in.h:440 +#: ../data/functions.xml.in.h:447 #, fuzzy msgid "Focal Length" msgstr "Lengte" -#: ../data/functions.xml.in.h:441 +#: ../data/functions.xml.in.h:448 msgid "F-stop (aperture)" msgstr "" -#: ../data/functions.xml.in.h:442 +#: ../data/functions.xml.in.h:449 #, fuzzy msgid "Distance" msgstr "Stofhoeveelheid" -#: ../data/functions.xml.in.h:443 +#: ../data/functions.xml.in.h:450 msgid "Circle of confusion or sensor size" msgstr "" -#: ../data/functions.xml.in.h:444 +#: ../data/functions.xml.in.h:451 msgid "American Wire Gauge Cross-Section Area" msgstr "" -#: ../data/functions.xml.in.h:445 +#: ../data/functions.xml.in.h:452 msgid "r:awg" msgstr "" -#: ../data/functions.xml.in.h:446 +#: ../data/functions.xml.in.h:453 msgid "" "For gauges larger than 0000 (4/0), please use negative values (00=-1, " "000=-2, 0000=-3, 00000=-4, etc). For conversion to AWG, use an equation (e." "g. awg(x) = 20 mm^2)." msgstr "" -#: ../data/functions.xml.in.h:447 +#: ../data/functions.xml.in.h:454 msgid "American Wire Gauge Diameter" msgstr "" -#: ../data/functions.xml.in.h:448 +#: ../data/functions.xml.in.h:455 msgid "r:awgd" msgstr "" -#: ../data/functions.xml.in.h:449 +#: ../data/functions.xml.in.h:456 msgid "" "For gauges larger than 0000 (4/0), please use negative values (00=-1, " "000=-2, 0000=-3, 00000=-4, etc). For conversion to AWG, use an equation (e." "g. awgd(x) = 5 mm)." msgstr "" -#: ../data/functions.xml.in.h:450 +#: ../data/functions.xml.in.h:457 msgid "Statistics" msgstr "Statistiek" -#: ../data/functions.xml.in.h:451 +#: ../data/functions.xml.in.h:458 msgid "Descriptive Statistics" msgstr "Beschrijvende statistiek" -#: ../data/functions.xml.in.h:452 +#: ../data/functions.xml.in.h:459 msgid "Sum (total)" msgstr "Som (totaal)" -#: ../data/functions.xml.in.h:453 +#: ../data/functions.xml.in.h:460 msgid "r:total" msgstr "totaal" -#: ../data/functions.xml.in.h:454 +#: ../data/functions.xml.in.h:461 msgid "Data" msgstr "Gegevens" -#: ../data/functions.xml.in.h:455 +#: ../data/functions.xml.in.h:462 msgid "Percentile" msgstr "Percentiel" -#: ../data/functions.xml.in.h:456 +#: ../data/functions.xml.in.h:463 msgid "r:percentile" msgstr "percentiel" -#: ../data/functions.xml.in.h:458 +#: ../data/functions.xml.in.h:465 #, no-c-format msgid "Percentile (%)" msgstr "Percentiel (%)" -#: ../data/functions.xml.in.h:459 +#: ../data/functions.xml.in.h:466 msgid "Quantile algorithm (as in R)" msgstr "" -#: ../data/functions.xml.in.h:460 +#: ../data/functions.xml.in.h:467 msgid "r:min" msgstr "" -#: ../data/functions.xml.in.h:461 +#: ../data/functions.xml.in.h:468 msgid "Returns the lowest value." msgstr "Retourneert de kleinste waarde." -#: ../data/functions.xml.in.h:462 +#: ../data/functions.xml.in.h:469 msgid "r:max" msgstr "" -#: ../data/functions.xml.in.h:463 +#: ../data/functions.xml.in.h:470 msgid "Returns the highest value." msgstr "Retourneert de grootste waarde." -#: ../data/functions.xml.in.h:464 +#: ../data/functions.xml.in.h:471 msgid "Mode" msgstr "Modus" -#: ../data/functions.xml.in.h:465 +#: ../data/functions.xml.in.h:472 msgid "r:mode" msgstr "modus" -#: ../data/functions.xml.in.h:466 +#: ../data/functions.xml.in.h:473 msgid "Returns the most frequently occurring value." msgstr "Retourneert de meest voorkomende waarde." -#: ../data/functions.xml.in.h:467 +#: ../data/functions.xml.in.h:474 msgid "Range" msgstr "Bereik" -#: ../data/functions.xml.in.h:468 +#: ../data/functions.xml.in.h:475 msgid "r:range" msgstr "bereik" -#: ../data/functions.xml.in.h:469 +#: ../data/functions.xml.in.h:476 msgid "Calculates the difference between the min and max value." msgstr "Berekent het verschil tussen de kleinste en de grootste waarde." -#: ../data/functions.xml.in.h:470 +#: ../data/functions.xml.in.h:477 msgid "Median" msgstr "Mediaan" -#: ../data/functions.xml.in.h:471 +#: ../data/functions.xml.in.h:478 msgid "r:median" msgstr "mediaan" -#: ../data/functions.xml.in.h:472 +#: ../data/functions.xml.in.h:479 msgid "Quartile" msgstr "Kwartiel" -#: ../data/functions.xml.in.h:473 +#: ../data/functions.xml.in.h:480 msgid "r:quartile" msgstr "kwartiel" -#: ../data/functions.xml.in.h:474 +#: ../data/functions.xml.in.h:481 msgid "Quantile Algorithm (as in R)" msgstr "" -#: ../data/functions.xml.in.h:475 +#: ../data/functions.xml.in.h:482 msgid "Decile" msgstr "Deciel" -#: ../data/functions.xml.in.h:476 +#: ../data/functions.xml.in.h:483 msgid "r:decile" msgstr "deciel" -#: ../data/functions.xml.in.h:477 +#: ../data/functions.xml.in.h:484 msgid "Interquartile Range" msgstr "Interkwartiel bereik" -#: ../data/functions.xml.in.h:478 +#: ../data/functions.xml.in.h:485 msgid "r:iqr" msgstr "" -#: ../data/functions.xml.in.h:479 +#: ../data/functions.xml.in.h:486 msgid "Calculates the difference between the first and third quartile." msgstr "Berekent het verschil tussen het eerste en het derde kwartiel." -#: ../data/functions.xml.in.h:480 +#: ../data/functions.xml.in.h:487 msgid "Number of Samples" msgstr "Aantal monsters" #. Number of samples -#: ../data/functions.xml.in.h:482 +#: ../data/functions.xml.in.h:489 msgid "r:number" msgstr "getal" -#: ../data/functions.xml.in.h:483 +#: ../data/functions.xml.in.h:490 msgid "Returns the number of samples." msgstr "Retourneert het aantal monsters." -#: ../data/functions.xml.in.h:484 +#: ../data/functions.xml.in.h:491 msgid "Random Numbers" msgstr "Willekeurige getallen" -#: ../data/functions.xml.in.h:485 +#: ../data/functions.xml.in.h:492 msgid "Random Number" msgstr "Willekeurig getal" -#: ../data/functions.xml.in.h:486 +#: ../data/functions.xml.in.h:493 msgid "r:rand" msgstr "wilk" -#: ../data/functions.xml.in.h:487 +#: ../data/functions.xml.in.h:494 msgid "" "Generates a pseudo-random number. Returns a real number between 0 and 1, if " "ceil is zero (default), or an integer between 1 and (including) ceil." @@ -4919,339 +4963,339 @@ "Levert een pseudowillekeurig getal. Retourneert een reëel getal tussen 0 en " "1 als ceil nul is (standaard), of een getal tussen 1 en ceil (inclusief)." -#: ../data/functions.xml.in.h:488 +#: ../data/functions.xml.in.h:495 msgid "Ceil" msgstr "Ceil" -#: ../data/functions.xml.in.h:489 +#: ../data/functions.xml.in.h:496 #, fuzzy msgid "Number of values" msgstr "Aantal monsters" -#: ../data/functions.xml.in.h:490 +#: ../data/functions.xml.in.h:497 msgid "Normally Distributed Random Number" msgstr "" -#: ../data/functions.xml.in.h:491 +#: ../data/functions.xml.in.h:498 #, fuzzy msgid "r:randnorm" msgstr "wilk" -#: ../data/functions.xml.in.h:492 +#: ../data/functions.xml.in.h:499 msgid "Mean" msgstr "Gemiddelde" -#: ../data/functions.xml.in.h:493 +#: ../data/functions.xml.in.h:500 #, fuzzy msgid "Standard deviation" msgstr "Gemiddelde afwijking" -#: ../data/functions.xml.in.h:494 +#: ../data/functions.xml.in.h:501 #, fuzzy msgid "Poisson Distributed Random Number" msgstr "Logistische verdeling" -#: ../data/functions.xml.in.h:495 +#: ../data/functions.xml.in.h:502 #, fuzzy msgid "r:randpoisson" msgstr "wilk" -#: ../data/functions.xml.in.h:496 +#: ../data/functions.xml.in.h:503 msgid "Uniformly Distributed Random Number" msgstr "" -#: ../data/functions.xml.in.h:497 +#: ../data/functions.xml.in.h:504 #, fuzzy msgid "r:randuniform" msgstr "wilk" -#: ../data/functions.xml.in.h:498 +#: ../data/functions.xml.in.h:505 msgid "Random Number Between Limits" msgstr "Willekeurig getal tussen twee grenswaarden" -#: ../data/functions.xml.in.h:499 +#: ../data/functions.xml.in.h:506 msgid "r:randbetween" msgstr "wilktussen" -#: ../data/functions.xml.in.h:500 +#: ../data/functions.xml.in.h:507 msgid "Returns an integer between (including) bottom and top." msgstr "Retourneert een geheel getal tussen onder- en bovengrens (inclusief)." -#: ../data/functions.xml.in.h:501 +#: ../data/functions.xml.in.h:508 msgid "Bottom" msgstr "Onder" -#: ../data/functions.xml.in.h:502 +#: ../data/functions.xml.in.h:509 msgid "Top" msgstr "Boven" -#: ../data/functions.xml.in.h:503 +#: ../data/functions.xml.in.h:510 #, fuzzy msgid "Exponential Random Number" msgstr "Willekeurig getal" -#: ../data/functions.xml.in.h:504 +#: ../data/functions.xml.in.h:511 #, fuzzy msgid "r:randexp" msgstr "wilk" -#: ../data/functions.xml.in.h:505 +#: ../data/functions.xml.in.h:512 #, fuzzy msgid "Rate parameter" msgstr "Meter per meter" -#: ../data/functions.xml.in.h:506 +#: ../data/functions.xml.in.h:513 #, fuzzy msgid "Rayleigh Distributed Random Number" msgstr "Logistische verdeling" -#: ../data/functions.xml.in.h:507 +#: ../data/functions.xml.in.h:514 #, fuzzy msgid "r:randrayleigh" msgstr "rayleighstaart" -#: ../data/functions.xml.in.h:508 +#: ../data/functions.xml.in.h:515 msgid "Sigma" msgstr "Sigma" -#: ../data/functions.xml.in.h:509 +#: ../data/functions.xml.in.h:516 msgid "Means" msgstr "Gemiddelden" -#: ../data/functions.xml.in.h:510 +#: ../data/functions.xml.in.h:517 msgid "r:mean,average,au:x̄" msgstr "gemiddelde,au:x̄" -#: ../data/functions.xml.in.h:511 +#: ../data/functions.xml.in.h:518 msgid "Harmonic Mean" msgstr "Harmonisch gemiddelde" -#: ../data/functions.xml.in.h:512 +#: ../data/functions.xml.in.h:519 msgid "r:harmmean" msgstr "harmgem" -#: ../data/functions.xml.in.h:513 +#: ../data/functions.xml.in.h:520 msgid "Geometric Mean" msgstr "Meetkundig gemiddelde" -#: ../data/functions.xml.in.h:514 +#: ../data/functions.xml.in.h:521 msgid "r:geomean" msgstr "meetkgem" -#: ../data/functions.xml.in.h:515 +#: ../data/functions.xml.in.h:522 msgid "Trimmed Mean" msgstr "Getrimd gemiddelde" -#: ../data/functions.xml.in.h:516 +#: ../data/functions.xml.in.h:523 msgid "r:trimmean" msgstr "trimgemidd" -#: ../data/functions.xml.in.h:517 +#: ../data/functions.xml.in.h:524 msgid "Trimmed percentage (at each end)" msgstr "Getrimd percentage (aan beide kanten)" -#: ../data/functions.xml.in.h:518 +#: ../data/functions.xml.in.h:525 msgid "Winsorized Mean" msgstr "Gewinsoriseerd gemiddelde" -#: ../data/functions.xml.in.h:519 +#: ../data/functions.xml.in.h:526 msgid "r:winsormean" msgstr "winsorgemidd" -#: ../data/functions.xml.in.h:520 +#: ../data/functions.xml.in.h:527 msgid "Winsorized percentage (at each end)" msgstr "Gewinsoriseerd percentage (aan beide kanten)" -#: ../data/functions.xml.in.h:521 +#: ../data/functions.xml.in.h:528 msgid "Weighted Mean" msgstr "Gewogen gemiddelde" -#: ../data/functions.xml.in.h:522 +#: ../data/functions.xml.in.h:529 msgid "r:weighmean" msgstr "gewogengemidd" -#: ../data/functions.xml.in.h:523 +#: ../data/functions.xml.in.h:530 msgid "Weights" msgstr "Gewichten" -#: ../data/functions.xml.in.h:524 +#: ../data/functions.xml.in.h:531 msgid "Quadratic Mean (RMS)" msgstr "Kwadratisch gemiddelde (RMS)" -#: ../data/functions.xml.in.h:525 +#: ../data/functions.xml.in.h:532 msgid "r:rms" msgstr "" -#: ../data/functions.xml.in.h:526 +#: ../data/functions.xml.in.h:533 msgid "Moments" msgstr "Momenten" -#: ../data/functions.xml.in.h:527 +#: ../data/functions.xml.in.h:534 msgid "Standard Deviation (entire population)" msgstr "Standaarddeviatie (gehele populatie)" -#: ../data/functions.xml.in.h:528 +#: ../data/functions.xml.in.h:535 msgid "r:stdevp" msgstr "" -#: ../data/functions.xml.in.h:529 +#: ../data/functions.xml.in.h:536 msgid "Standard Deviation (random sampling)" msgstr "Standaarddeviatie (willekeurige steekproef)" -#: ../data/functions.xml.in.h:530 +#: ../data/functions.xml.in.h:537 msgid "r:stdev" msgstr "" -#: ../data/functions.xml.in.h:531 +#: ../data/functions.xml.in.h:538 msgid "Variance (entire population)" msgstr "Variantie (gehele populatie)" -#: ../data/functions.xml.in.h:532 +#: ../data/functions.xml.in.h:539 msgid "r:varp" msgstr "" -#: ../data/functions.xml.in.h:533 +#: ../data/functions.xml.in.h:540 msgid "Variance (random sampling)" msgstr "Variantie (willekeurige steekproef)" -#: ../data/functions.xml.in.h:534 +#: ../data/functions.xml.in.h:541 msgid "r:var" msgstr "" -#: ../data/functions.xml.in.h:535 +#: ../data/functions.xml.in.h:542 msgid "Standard Error" msgstr "Standaardfout" -#: ../data/functions.xml.in.h:536 +#: ../data/functions.xml.in.h:543 msgid "r:stderr" msgstr "" -#: ../data/functions.xml.in.h:537 +#: ../data/functions.xml.in.h:544 msgid "Mean Deviation" msgstr "Gemiddelde afwijking" -#: ../data/functions.xml.in.h:538 +#: ../data/functions.xml.in.h:545 msgid "r:meandev" msgstr "gemiddev" -#: ../data/functions.xml.in.h:539 +#: ../data/functions.xml.in.h:546 msgid "Covariance" msgstr "Covariantie" -#: ../data/functions.xml.in.h:540 +#: ../data/functions.xml.in.h:547 msgid "r:cov,r:covar" msgstr "" -#: ../data/functions.xml.in.h:541 +#: ../data/functions.xml.in.h:548 msgid "Data 1" msgstr "Gegevens 1" -#: ../data/functions.xml.in.h:542 +#: ../data/functions.xml.in.h:549 msgid "Data 2" msgstr "Gegevens 2" -#: ../data/functions.xml.in.h:543 +#: ../data/functions.xml.in.h:550 msgid "Pooled Variance" msgstr "Pooled variantie" -#: ../data/functions.xml.in.h:544 +#: ../data/functions.xml.in.h:551 msgid "r:poolvar" msgstr "" -#: ../data/functions.xml.in.h:545 +#: ../data/functions.xml.in.h:552 msgid "Regression" msgstr "Regressie" -#: ../data/functions.xml.in.h:546 +#: ../data/functions.xml.in.h:553 msgid "Statistical Correlation" msgstr "Statistische correlatie" -#: ../data/functions.xml.in.h:547 +#: ../data/functions.xml.in.h:554 msgid "r:cor" msgstr "" -#: ../data/functions.xml.in.h:548 +#: ../data/functions.xml.in.h:555 msgid "Pearson's Correlation Coefficient" msgstr "Pearson's correlatiecoëfficiënt" -#: ../data/functions.xml.in.h:549 +#: ../data/functions.xml.in.h:556 msgid "r:pearson,r:correl" msgstr "" -#: ../data/functions.xml.in.h:550 +#: ../data/functions.xml.in.h:557 msgid "Spearman's Rho" msgstr "Spearman's Rho" -#: ../data/functions.xml.in.h:551 +#: ../data/functions.xml.in.h:558 msgid "r:spearman" msgstr "" -#: ../data/functions.xml.in.h:552 +#: ../data/functions.xml.in.h:559 msgid "Statistical Tests" msgstr "Statistische testen" -#: ../data/functions.xml.in.h:553 +#: ../data/functions.xml.in.h:560 msgid "Unpaired T-Test" msgstr "Ongepaarde T-proef" -#: ../data/functions.xml.in.h:554 +#: ../data/functions.xml.in.h:561 msgid "r:ttest" msgstr "" -#: ../data/functions.xml.in.h:555 +#: ../data/functions.xml.in.h:562 msgid "Paired T-Test" msgstr "Gepaarde t-proef" -#: ../data/functions.xml.in.h:556 +#: ../data/functions.xml.in.h:563 msgid "r:pttest" msgstr "" -#: ../data/functions.xml.in.h:557 +#: ../data/functions.xml.in.h:564 msgid "Distribution" msgstr "Distributie" -#: ../data/functions.xml.in.h:558 +#: ../data/functions.xml.in.h:565 msgid "Binomial Distribution" msgstr "Binomiale verdeling" -#: ../data/functions.xml.in.h:559 +#: ../data/functions.xml.in.h:566 msgid "r:binomdist" msgstr "" -#: ../data/functions.xml.in.h:560 +#: ../data/functions.xml.in.h:567 msgid "" "Returns the probability mass or cumulative distribution function of the " "binomial distribution." msgstr "" -#: ../data/functions.xml.in.h:561 +#: ../data/functions.xml.in.h:568 #, fuzzy msgid "Number of successes" msgstr "Aantal termijnen" -#: ../data/functions.xml.in.h:562 +#: ../data/functions.xml.in.h:569 #, fuzzy msgid "Number of trials" msgstr "Aantal monsters" -#: ../data/functions.xml.in.h:563 +#: ../data/functions.xml.in.h:570 #, fuzzy msgid "Probability" msgstr "Permeabiliteit" -#: ../data/functions.xml.in.h:564 +#: ../data/functions.xml.in.h:571 msgid "Cumulative" msgstr "" -#: ../data/functions.xml.in.h:565 +#: ../data/functions.xml.in.h:572 msgid "Exponential Distribution" msgstr "Exponentiële verdeling" -#: ../data/functions.xml.in.h:566 +#: ../data/functions.xml.in.h:573 msgid "r:expondist" msgstr "" -#: ../data/functions.xml.in.h:567 +#: ../data/functions.xml.in.h:574 #, fuzzy msgid "" "Returns the probability density or cumulative distribution function of the " @@ -5260,15 +5304,15 @@ "Retourneert de kansdichtheid p(x) in x voor een Pareto-verdeling met " "exponent en schaal. (van Gnumeric)" -#: ../data/functions.xml.in.h:568 +#: ../data/functions.xml.in.h:575 msgid "Logistic Distribution" msgstr "Logistische verdeling" -#: ../data/functions.xml.in.h:569 +#: ../data/functions.xml.in.h:576 msgid "r:logistic" msgstr "logistisch" -#: ../data/functions.xml.in.h:570 +#: ../data/functions.xml.in.h:577 msgid "" "Returns the probability density p(x) at x for a logistic distribution with " "scale parameter. (from Gnumeric)" @@ -5276,21 +5320,21 @@ "Retourneert de kansdichtheid p(x) in x voor een logistische verdeling met " "schaalparameter. (van Gnumeric)" -#: ../data/functions.xml.in.h:571 +#: ../data/functions.xml.in.h:578 msgid "Scale" msgstr "Schaal" -#: ../data/functions.xml.in.h:572 +#: ../data/functions.xml.in.h:579 #, fuzzy msgid "Normal Distribution" msgstr "Distributie" -#: ../data/functions.xml.in.h:573 +#: ../data/functions.xml.in.h:580 #, fuzzy msgid "r:normdist" msgstr "nominaal" -#: ../data/functions.xml.in.h:574 +#: ../data/functions.xml.in.h:581 #, fuzzy msgid "" "Returns the probability density or cumulative distribution function of a " @@ -5299,15 +5343,15 @@ "Retourneert de kansdichtheid p(x) in x voor een Pareto-verdeling met " "exponent en schaal. (van Gnumeric)" -#: ../data/functions.xml.in.h:575 +#: ../data/functions.xml.in.h:582 msgid "Pareto Distribution" msgstr "Paretoverdeling" -#: ../data/functions.xml.in.h:576 +#: ../data/functions.xml.in.h:583 msgid "r:pareto" msgstr "" -#: ../data/functions.xml.in.h:577 +#: ../data/functions.xml.in.h:584 msgid "" "Returns the probability density p(x) at x for a Pareto distribution with " "exponent and scale. (from Gnumeric)" @@ -5315,34 +5359,34 @@ "Retourneert de kansdichtheid p(x) in x voor een Pareto-verdeling met " "exponent en schaal. (van Gnumeric)" -#: ../data/functions.xml.in.h:578 +#: ../data/functions.xml.in.h:585 msgid "Poisson Distribution" msgstr "Poissonverdeling" -#: ../data/functions.xml.in.h:579 +#: ../data/functions.xml.in.h:586 msgid "r:poisson" msgstr "" -#: ../data/functions.xml.in.h:580 +#: ../data/functions.xml.in.h:587 msgid "" "Returns the probability mass or cumulative distribution of the Poisson " "distribution." msgstr "" -#: ../data/functions.xml.in.h:581 +#: ../data/functions.xml.in.h:588 #, fuzzy msgid "Number of events (x)" msgstr "Aantal elementen" -#: ../data/functions.xml.in.h:582 +#: ../data/functions.xml.in.h:589 msgid "Rayleigh Distribution" msgstr "Rayleigh-verdeling" -#: ../data/functions.xml.in.h:583 +#: ../data/functions.xml.in.h:590 msgid "r:rayleigh" msgstr "" -#: ../data/functions.xml.in.h:584 +#: ../data/functions.xml.in.h:591 msgid "" "Returns the probability density p(x) at x for a Rayleigh distribution with " "scale parameter sigma. (from Gnumeric)" @@ -5350,15 +5394,15 @@ "Retourneert de kansdichtheid p(x) in x voor een Rayleigh-verdeling met " "schaalparameter sigma. (van Gnumeric)" -#: ../data/functions.xml.in.h:585 +#: ../data/functions.xml.in.h:592 msgid "Rayleigh Tail Distribution" msgstr "Rayleigh-staartverdeling" -#: ../data/functions.xml.in.h:586 +#: ../data/functions.xml.in.h:593 msgid "r:rayleightail" msgstr "rayleighstaart" -#: ../data/functions.xml.in.h:587 +#: ../data/functions.xml.in.h:594 msgid "" "Returns the probability density p(x) at x for a Rayleigh tail distribution " "with scale parameter sigma and a lower limit. (from Gnumeric)" @@ -5366,21 +5410,21 @@ "Retourneert de kansdichtheid p(x) in x voor een Rayleigh-staartverdeling met " "schaalparameter sigma en een ondergrens. (van Gnumeric)" -#: ../data/functions.xml.in.h:588 ../data/variables.xml.in.h:204 +#: ../data/functions.xml.in.h:595 ../data/variables.xml.in.h:204 msgid "Date & Time" msgstr "Datum & Tijd" -#: ../data/functions.xml.in.h:589 +#: ../data/functions.xml.in.h:596 #, fuzzy msgid "Construct Date" msgstr "Matrix construeren" -#: ../data/functions.xml.in.h:590 +#: ../data/functions.xml.in.h:597 #, fuzzy msgid "r:date" msgstr "dag" -#: ../data/functions.xml.in.h:591 +#: ../data/functions.xml.in.h:598 msgid "" "Returns a date. Available calendars gregorian (1), hebrew (2), islamic (3), " "persian (4), indian (5), chinese (6), julian (7), milankovic (8), coptic " @@ -5389,53 +5433,53 @@ "(e.g. leap month 4 = 16)." msgstr "" -#: ../data/functions.xml.in.h:592 +#: ../data/functions.xml.in.h:599 msgid "Year" msgstr "Jaar" -#: ../data/functions.xml.in.h:593 ../data/units.xml.in.h:153 +#: ../data/functions.xml.in.h:600 ../data/units.xml.in.h:153 msgid "Month" msgstr "Maand" -#: ../data/functions.xml.in.h:594 ../data/units.xml.in.h:145 +#: ../data/functions.xml.in.h:601 ../data/units.xml.in.h:145 msgid "Day" msgstr "Dag" -#: ../data/functions.xml.in.h:595 +#: ../data/functions.xml.in.h:602 msgid "Calendar" msgstr "" -#: ../data/functions.xml.in.h:596 +#: ../data/functions.xml.in.h:603 #, fuzzy msgid "Construct Date and Time" msgstr "Matrix construeren" -#: ../data/functions.xml.in.h:597 +#: ../data/functions.xml.in.h:604 #, fuzzy msgid "r:datetime" msgstr "dag" -#: ../data/functions.xml.in.h:598 ../data/units.xml.in.h:143 +#: ../data/functions.xml.in.h:605 ../data/units.xml.in.h:143 msgid "Hour" msgstr "Uur" -#: ../data/functions.xml.in.h:599 ../data/units.xml.in.h:141 +#: ../data/functions.xml.in.h:606 ../data/units.xml.in.h:141 msgid "Minute" msgstr "Minuut" -#: ../data/functions.xml.in.h:600 ../data/units.xml.in.h:139 +#: ../data/functions.xml.in.h:607 ../data/units.xml.in.h:139 msgid "Second" msgstr "Seconde" -#: ../data/functions.xml.in.h:601 +#: ../data/functions.xml.in.h:608 msgid "Days between two dates" msgstr "Aantal dagen tussen twee data" -#: ../data/functions.xml.in.h:602 +#: ../data/functions.xml.in.h:609 msgid "r:days" msgstr "dagen" -#: ../data/functions.xml.in.h:603 +#: ../data/functions.xml.in.h:610 msgid "" "Returns the number of days between two dates. Basis is the type of " "day counting you want to use: 0: US 30/360, 1: real days (default), 2: real " @@ -5446,31 +5490,31 @@ "dagen, 2: werkelijke dagen/360, 3: werkelijke dagen/365 of 4: Europees " "30/360." -#: ../data/functions.xml.in.h:604 +#: ../data/functions.xml.in.h:611 msgid "First date" msgstr "Eerste datum" -#: ../data/functions.xml.in.h:605 +#: ../data/functions.xml.in.h:612 msgid "Second date" msgstr "Tweede datum" -#: ../data/functions.xml.in.h:606 +#: ../data/functions.xml.in.h:613 msgid "Day counting basis" msgstr "Basis dagtelling" -#: ../data/functions.xml.in.h:607 +#: ../data/functions.xml.in.h:614 msgid "Financial function mode" msgstr "Financiële functiemodus" -#: ../data/functions.xml.in.h:608 +#: ../data/functions.xml.in.h:615 msgid "Years between two dates" msgstr "Jaren tussen twee data" -#: ../data/functions.xml.in.h:609 +#: ../data/functions.xml.in.h:616 msgid "r:yearfrac" msgstr "jaarfrac" -#: ../data/functions.xml.in.h:610 +#: ../data/functions.xml.in.h:617 msgid "" "Returns the number of years (fractional) between two dates. Basis " "is the type of day counting you want to use: 0: US 30/360, 1: real days " @@ -5481,148 +5525,148 @@ "(standaard), 1: werkelijke dagen, 2: werkelijke dagen/360, 3: werkelijke " "dagen/365 of 4: Europees 30/360." -#: ../data/functions.xml.in.h:611 +#: ../data/functions.xml.in.h:618 msgid "Week of Year" msgstr "Week van het jaar" -#: ../data/functions.xml.in.h:612 +#: ../data/functions.xml.in.h:619 msgid "r:week" msgstr "" -#: ../data/functions.xml.in.h:613 +#: ../data/functions.xml.in.h:620 msgid "Date" msgstr "Datum" -#: ../data/functions.xml.in.h:614 +#: ../data/functions.xml.in.h:621 msgid "Week begins on Sunday" msgstr "Week begint op zondag" -#: ../data/functions.xml.in.h:615 +#: ../data/functions.xml.in.h:622 msgid "Day of Week" msgstr "Dag van de week" -#: ../data/functions.xml.in.h:616 +#: ../data/functions.xml.in.h:623 msgid "r:weekday" msgstr "weekdag" -#: ../data/functions.xml.in.h:617 +#: ../data/functions.xml.in.h:624 msgid "r:month" msgstr "maand" -#: ../data/functions.xml.in.h:618 +#: ../data/functions.xml.in.h:625 msgid "Day of Month" msgstr "Dag van de maand" -#: ../data/functions.xml.in.h:619 +#: ../data/functions.xml.in.h:626 msgid "r:day" msgstr "dag" -#: ../data/functions.xml.in.h:620 +#: ../data/functions.xml.in.h:627 msgid "r:year" msgstr "jaar" -#: ../data/functions.xml.in.h:621 +#: ../data/functions.xml.in.h:628 msgid "Day of Year" msgstr "Dag van het jaar" -#: ../data/functions.xml.in.h:622 +#: ../data/functions.xml.in.h:629 msgid "r:yearday" msgstr "jaardag" -#: ../data/functions.xml.in.h:623 +#: ../data/functions.xml.in.h:630 msgid "Current Time" msgstr "Huidige tijd" -#: ../data/functions.xml.in.h:624 +#: ../data/functions.xml.in.h:631 msgid "r:time" msgstr "tijd" -#: ../data/functions.xml.in.h:625 +#: ../data/functions.xml.in.h:632 #, fuzzy msgid "Time Value" msgstr "Uiterste waarden" -#: ../data/functions.xml.in.h:626 +#: ../data/functions.xml.in.h:633 #, fuzzy msgid "r:timevalue" msgstr "tijd" -#: ../data/functions.xml.in.h:627 +#: ../data/functions.xml.in.h:634 msgid "Returns the time part, in fractional hours, of a date and time value." msgstr "" -#: ../data/functions.xml.in.h:628 +#: ../data/functions.xml.in.h:635 msgid "Date to Unix Timestamp" msgstr "Datum naar Unix-timestamp" -#: ../data/functions.xml.in.h:629 +#: ../data/functions.xml.in.h:636 msgid "r:timestamp" msgstr "" -#: ../data/functions.xml.in.h:630 +#: ../data/functions.xml.in.h:637 msgid "Unix Timestamp to Date" msgstr "Unix Timestamp naar datum" -#: ../data/functions.xml.in.h:631 +#: ../data/functions.xml.in.h:638 #, fuzzy msgid "r:stamptodate,unix2date" msgstr "stampnaardatum" -#: ../data/functions.xml.in.h:632 +#: ../data/functions.xml.in.h:639 msgid "" "Returns the local date and time represented by the specified Unix timestamp " "(seconds, excluding leap seconds, since 1970-01-01). Supports time units." msgstr "" -#: ../data/functions.xml.in.h:633 +#: ../data/functions.xml.in.h:640 msgid "Timestamp" msgstr "Timestamp" -#: ../data/functions.xml.in.h:634 +#: ../data/functions.xml.in.h:641 msgid "Add Days" msgstr "Dagen bijtellen" -#: ../data/functions.xml.in.h:635 +#: ../data/functions.xml.in.h:642 msgid "r:addDays" msgstr "dagen bijtellen" -#: ../data/functions.xml.in.h:636 +#: ../data/functions.xml.in.h:643 msgid "Days" msgstr "Dagen" -#: ../data/functions.xml.in.h:637 +#: ../data/functions.xml.in.h:644 msgid "Add Months" msgstr "Maanden bijtellen" -#: ../data/functions.xml.in.h:638 +#: ../data/functions.xml.in.h:645 msgid "r:addMonths" msgstr "maanden bijtellen" -#: ../data/functions.xml.in.h:639 +#: ../data/functions.xml.in.h:646 msgid "Months" msgstr "Maanden" -#: ../data/functions.xml.in.h:640 +#: ../data/functions.xml.in.h:647 msgid "Add Years" msgstr "Jaren bijtellen" -#: ../data/functions.xml.in.h:641 +#: ../data/functions.xml.in.h:648 msgid "r:addYears" msgstr "jaren bijtellen" -#: ../data/functions.xml.in.h:642 +#: ../data/functions.xml.in.h:649 msgid "Years" msgstr "Jaren" -#: ../data/functions.xml.in.h:643 +#: ../data/functions.xml.in.h:650 msgid "Add Time" msgstr "Tijd optellen" -#: ../data/functions.xml.in.h:644 +#: ../data/functions.xml.in.h:651 msgid "r:addTime" msgstr "tijd bijtellen" -#: ../data/functions.xml.in.h:645 +#: ../data/functions.xml.in.h:652 msgid "" "Adds a time value to a date. The value can be positive or negative, but must " "use a unit based on seconds (such as day and year). Fractions of days are " @@ -5633,33 +5677,33 @@ "gebaseerd (zoals dag of jaar). Fracties van dagen worden afgekapt tot hele " "dagen." -#: ../data/functions.xml.in.h:646 ../data/units.xml.in.h:138 +#: ../data/functions.xml.in.h:653 ../data/units.xml.in.h:138 msgid "Time" msgstr "Tijd" -#: ../data/functions.xml.in.h:647 +#: ../data/functions.xml.in.h:654 msgid "Lunar Phase" msgstr "" -#: ../data/functions.xml.in.h:648 +#: ../data/functions.xml.in.h:655 msgid "r:lunarphase" msgstr "" -#: ../data/functions.xml.in.h:649 +#: ../data/functions.xml.in.h:656 msgid "" "Returns the lunar phase, as a number between 0 and 1, for the specified " "date. 0 represents new moon, 0.5 full moon, and 0.25 and 0.75 quarter moons." msgstr "" -#: ../data/functions.xml.in.h:650 +#: ../data/functions.xml.in.h:657 msgid "Find Lunar Phase" msgstr "" -#: ../data/functions.xml.in.h:651 +#: ../data/functions.xml.in.h:658 msgid "r:nextlunarphase" msgstr "" -#: ../data/functions.xml.in.h:652 +#: ../data/functions.xml.in.h:659 msgid "" "Returns the date when the specified lunar phase occurs. The function " "searches forward beginning at the specified date. The lunar phase are " @@ -5667,48 +5711,48 @@ "moon, and 0.25 and 0.75 quarter moons." msgstr "" -#: ../data/functions.xml.in.h:653 +#: ../data/functions.xml.in.h:660 #, fuzzy msgid "Start Date" msgstr "Matrix construeren" -#: ../data/functions.xml.in.h:654 ../data/variables.xml.in.h:197 +#: ../data/functions.xml.in.h:661 ../data/variables.xml.in.h:197 msgid "Utilities" msgstr "Hulpmiddelen" -#: ../data/functions.xml.in.h:655 +#: ../data/functions.xml.in.h:662 msgid "Plot Functions and Vectors" msgstr "" -#: ../data/functions.xml.in.h:656 +#: ../data/functions.xml.in.h:663 #, fuzzy msgid "r:plot" msgstr "planeet" -#: ../data/functions.xml.in.h:657 +#: ../data/functions.xml.in.h:664 #, fuzzy msgid "Expression or vector" msgstr "Matrix of vector" -#: ../data/functions.xml.in.h:658 +#: ../data/functions.xml.in.h:665 msgid "Minimum x value" msgstr "" -#: ../data/functions.xml.in.h:659 +#: ../data/functions.xml.in.h:666 #, fuzzy msgid "Maximum x value" msgstr "Matrixvariabele" -#: ../data/functions.xml.in.h:660 +#: ../data/functions.xml.in.h:667 msgid "Number of samples / Step size" msgstr "Aantal monsters / stapgrootte" -#: ../data/functions.xml.in.h:661 +#: ../data/functions.xml.in.h:668 #, fuzzy msgid "X variable" msgstr "Rijvariabele" -#: ../data/functions.xml.in.h:662 +#: ../data/functions.xml.in.h:669 msgid "" "Plots one or more expressions or vectors. Use a vector for the first " "argument to plot multiple series. Only the first argument is used for vector " @@ -5716,65 +5760,65 @@ "and y values." msgstr "" -#: ../data/functions.xml.in.h:663 +#: ../data/functions.xml.in.h:670 #, fuzzy msgid "Unicode Value" msgstr "Uiterste waarden" -#: ../data/functions.xml.in.h:664 +#: ../data/functions.xml.in.h:671 msgid "r:code" msgstr "" -#: ../data/functions.xml.in.h:665 +#: ../data/functions.xml.in.h:672 msgid "Character" msgstr "Karakter" -#: ../data/functions.xml.in.h:666 +#: ../data/functions.xml.in.h:673 #, fuzzy msgid "Unicode Character" msgstr "Karakter" -#: ../data/functions.xml.in.h:667 +#: ../data/functions.xml.in.h:674 msgid "r:char" msgstr "" -#: ../data/functions.xml.in.h:668 +#: ../data/functions.xml.in.h:675 msgid "Length of string" msgstr "Lengte van karakterrij" -#: ../data/functions.xml.in.h:669 +#: ../data/functions.xml.in.h:676 msgid "r:len" msgstr "" -#: ../data/functions.xml.in.h:670 +#: ../data/functions.xml.in.h:677 msgid "Text" msgstr "Tekst" -#: ../data/functions.xml.in.h:671 +#: ../data/functions.xml.in.h:678 msgid "Concatenate Strings" msgstr "Karakterrijen samenvoegen" -#: ../data/functions.xml.in.h:672 +#: ../data/functions.xml.in.h:679 msgid "r:concatenate" msgstr "samenvoegen" -#: ../data/functions.xml.in.h:673 +#: ../data/functions.xml.in.h:680 msgid "Text string 1" msgstr "Tekstrij 1" -#: ../data/functions.xml.in.h:674 +#: ../data/functions.xml.in.h:681 msgid "Text string 2" msgstr "Tekstrij 2" -#: ../data/functions.xml.in.h:675 +#: ../data/functions.xml.in.h:682 msgid "Replace" msgstr "Vervangen" -#: ../data/functions.xml.in.h:676 +#: ../data/functions.xml.in.h:683 msgid "r:replace" msgstr "vervangen" -#: ../data/functions.xml.in.h:677 +#: ../data/functions.xml.in.h:684 msgid "" "Replaces a certain value in an expression with a new value. The expression " "is calculated before the replacement if the fourth argument is true." @@ -5782,31 +5826,31 @@ "Vervangt een waarde in een expressie door een nieuwe waarde. Eerst wordt de " "expressie berekend indien het vierde argument waar (true) is." -#: ../data/functions.xml.in.h:678 +#: ../data/functions.xml.in.h:685 msgid "Expression" msgstr "Expressie" -#: ../data/functions.xml.in.h:679 +#: ../data/functions.xml.in.h:686 msgid "Original value" msgstr "Originele waarde" -#: ../data/functions.xml.in.h:680 +#: ../data/functions.xml.in.h:687 msgid "New value" msgstr "Nieuwe waarde" -#: ../data/functions.xml.in.h:681 +#: ../data/functions.xml.in.h:688 msgid "Precalculate expression" msgstr "Voorbereken expressie" -#: ../data/functions.xml.in.h:682 +#: ../data/functions.xml.in.h:689 msgid "Strip Units" msgstr "Eenheden verwijderen" -#: ../data/functions.xml.in.h:683 +#: ../data/functions.xml.in.h:690 msgid "r:nounit,strip_units" msgstr "geeneenheid,eenheden_weg" -#: ../data/functions.xml.in.h:684 +#: ../data/functions.xml.in.h:691 msgid "" "Removes all units from an expression. The expression is calculated before " "the removal." @@ -5814,305 +5858,305 @@ "Verwijdert alle eenheden uit een expressie. De expressie wordt hierbij eerst " "berekend." -#: ../data/functions.xml.in.h:685 +#: ../data/functions.xml.in.h:692 msgid "Process Vector Elements" msgstr "Vector-elementen verwerken" -#: ../data/functions.xml.in.h:686 +#: ../data/functions.xml.in.h:693 msgid "r:process" msgstr "verwerken" -#: ../data/functions.xml.in.h:687 +#: ../data/functions.xml.in.h:694 msgid "Element variable" msgstr "Elementvariabele" -#: ../data/functions.xml.in.h:688 +#: ../data/functions.xml.in.h:695 msgid "Index variable" msgstr "Indexvariabele" -#: ../data/functions.xml.in.h:689 +#: ../data/functions.xml.in.h:696 msgid "Vector variable" msgstr "Vectorvariabele" -#: ../data/functions.xml.in.h:690 +#: ../data/functions.xml.in.h:697 msgid "Process Matrix Elements" msgstr "Matrix-elementen verwerken" -#: ../data/functions.xml.in.h:691 +#: ../data/functions.xml.in.h:698 msgid "r:processm" msgstr "" -#: ../data/functions.xml.in.h:692 +#: ../data/functions.xml.in.h:699 msgid "Row variable" msgstr "Rijvariabele" -#: ../data/functions.xml.in.h:693 +#: ../data/functions.xml.in.h:700 msgid "Column variable" msgstr "Kolomvariabele" -#: ../data/functions.xml.in.h:694 +#: ../data/functions.xml.in.h:701 msgid "Matrix variable" msgstr "Matrixvariabele" -#: ../data/functions.xml.in.h:695 +#: ../data/functions.xml.in.h:702 msgid "Custom Sum of Elements" msgstr "Aangepaste som van elementen" -#: ../data/functions.xml.in.h:696 +#: ../data/functions.xml.in.h:703 msgid "r:csum" msgstr "csom" -#: ../data/functions.xml.in.h:697 +#: ../data/functions.xml.in.h:704 msgid "First element" msgstr "Eerste element" -#: ../data/functions.xml.in.h:698 +#: ../data/functions.xml.in.h:705 msgid "Last element" msgstr "Laatste element" -#: ../data/functions.xml.in.h:699 +#: ../data/functions.xml.in.h:706 msgid "Initial value" msgstr "Beginwaarde" -#: ../data/functions.xml.in.h:700 +#: ../data/functions.xml.in.h:707 msgid "Value variable" msgstr "Waarde variabele" -#: ../data/functions.xml.in.h:701 +#: ../data/functions.xml.in.h:708 msgid "Select Vector Elements" msgstr "Vectorelementen selecteren" -#: ../data/functions.xml.in.h:702 +#: ../data/functions.xml.in.h:709 msgid "r:select" msgstr "selecteer" -#: ../data/functions.xml.in.h:703 +#: ../data/functions.xml.in.h:710 msgid "Condition" msgstr "Conditie" -#: ../data/functions.xml.in.h:704 +#: ../data/functions.xml.in.h:711 msgid "Select first match" msgstr "Eerste overeenkomst secteren" -#: ../data/functions.xml.in.h:705 +#: ../data/functions.xml.in.h:712 msgid "r:function" msgstr "functie" -#: ../data/functions.xml.in.h:706 +#: ../data/functions.xml.in.h:713 msgid "Arguments" msgstr "Argumenten" -#: ../data/functions.xml.in.h:707 +#: ../data/functions.xml.in.h:714 msgid "Title" msgstr "Titel" -#: ../data/functions.xml.in.h:708 +#: ../data/functions.xml.in.h:715 msgid "r:title" msgstr "titel" -#: ../data/functions.xml.in.h:710 +#: ../data/functions.xml.in.h:717 msgid "Display Error" msgstr "Weergavefout" -#: ../data/functions.xml.in.h:711 +#: ../data/functions.xml.in.h:718 msgid "r:error" msgstr "fout" -#: ../data/functions.xml.in.h:712 +#: ../data/functions.xml.in.h:719 msgid "Message" msgstr "Bericht" -#: ../data/functions.xml.in.h:713 +#: ../data/functions.xml.in.h:720 msgid "Display Warning" msgstr "Waarschuwing weergeven" -#: ../data/functions.xml.in.h:714 +#: ../data/functions.xml.in.h:721 msgid "r:warning" msgstr "waarschuwing" -#: ../data/functions.xml.in.h:715 +#: ../data/functions.xml.in.h:722 msgid "Display Message" msgstr "Bericht weergeven" -#: ../data/functions.xml.in.h:716 +#: ../data/functions.xml.in.h:723 msgid "r:message" msgstr "bericht" -#: ../data/functions.xml.in.h:717 +#: ../data/functions.xml.in.h:724 msgid "Save as Variable" msgstr "Opslaan als variabele" -#: ../data/functions.xml.in.h:718 +#: ../data/functions.xml.in.h:725 msgid "r:save" msgstr "opslaan" -#: ../data/functions.xml.in.h:719 +#: ../data/functions.xml.in.h:726 msgid "Category" msgstr "Categorie" -#: ../data/functions.xml.in.h:720 +#: ../data/functions.xml.in.h:727 msgid "RPN Stack Register" msgstr "RPN-register in stapelgeheugen" -#: ../data/functions.xml.in.h:721 +#: ../data/functions.xml.in.h:728 msgid "r:register" msgstr "" -#: ../data/functions.xml.in.h:722 +#: ../data/functions.xml.in.h:729 msgid "Returns the value of a RPN stack register." msgstr "Retourneert de waarde in een register van het RPN-stapelgeheugen." -#: ../data/functions.xml.in.h:723 +#: ../data/functions.xml.in.h:730 msgid "Index" msgstr "" -#: ../data/functions.xml.in.h:724 +#: ../data/functions.xml.in.h:731 msgid "RPN Stack Vector" msgstr "RPN-vector in stapelgeheugen" -#: ../data/functions.xml.in.h:725 +#: ../data/functions.xml.in.h:732 msgid "r:stack" msgstr "stapelgeheugen" -#: ../data/functions.xml.in.h:726 +#: ../data/functions.xml.in.h:733 msgid "Returns the RPN stack as a vector." msgstr "Retourneert de inhoud van het RPN-stapelgeheugen als een vector." -#: ../data/functions.xml.in.h:727 +#: ../data/functions.xml.in.h:734 msgid "Is Number" msgstr "Is een getal" -#: ../data/functions.xml.in.h:728 +#: ../data/functions.xml.in.h:735 msgid "r:isNumber" msgstr "isGetal" -#: ../data/functions.xml.in.h:729 +#: ../data/functions.xml.in.h:736 msgid "Is Real" msgstr "Is een reëel getal" -#: ../data/functions.xml.in.h:730 +#: ../data/functions.xml.in.h:737 msgid "r:isReal" msgstr "isReëel" -#: ../data/functions.xml.in.h:731 +#: ../data/functions.xml.in.h:738 msgid "Is Rational" msgstr "Is een rationaal getal" -#: ../data/functions.xml.in.h:732 +#: ../data/functions.xml.in.h:739 msgid "r:isRational" msgstr "isRationaal" -#: ../data/functions.xml.in.h:733 +#: ../data/functions.xml.in.h:740 msgid "Is Integer" msgstr "Is een geheel getal" -#: ../data/functions.xml.in.h:734 +#: ../data/functions.xml.in.h:741 msgid "r:isInteger" msgstr "isGeheel" -#: ../data/functions.xml.in.h:735 +#: ../data/functions.xml.in.h:742 msgid "Represents Number" msgstr "Geeft een getal weer" -#: ../data/functions.xml.in.h:736 +#: ../data/functions.xml.in.h:743 msgid "r:representsNumber" msgstr "isGetal" -#: ../data/functions.xml.in.h:737 +#: ../data/functions.xml.in.h:744 msgid "Represents Real" msgstr "Geeft een reëel getal weer" -#: ../data/functions.xml.in.h:738 +#: ../data/functions.xml.in.h:745 msgid "r:representsReal" msgstr "isReëel" -#: ../data/functions.xml.in.h:739 +#: ../data/functions.xml.in.h:746 msgid "Represents Rational" msgstr "Geeft een rationaal getal weer" -#: ../data/functions.xml.in.h:740 +#: ../data/functions.xml.in.h:747 msgid "r:representsRational" msgstr "isRationaalgetal" -#: ../data/functions.xml.in.h:741 +#: ../data/functions.xml.in.h:748 msgid "Represents Integer" msgstr "Geeft een geheel getal weer" -#: ../data/functions.xml.in.h:742 +#: ../data/functions.xml.in.h:749 msgid "r:representsInteger" msgstr "isGeheelgetal" -#: ../data/functions.xml.in.h:743 +#: ../data/functions.xml.in.h:750 msgid "Interval" msgstr "" -#: ../data/functions.xml.in.h:744 +#: ../data/functions.xml.in.h:751 msgid "r:interval" msgstr "" -#: ../data/functions.xml.in.h:745 +#: ../data/functions.xml.in.h:752 #, fuzzy msgid "Lower endpoint" msgstr "Ondergrens" -#: ../data/functions.xml.in.h:746 +#: ../data/functions.xml.in.h:753 #, fuzzy msgid "Upper endpoint" msgstr "Bovengrens" -#: ../data/functions.xml.in.h:747 +#: ../data/functions.xml.in.h:754 msgid "Uncertainty" msgstr "" -#: ../data/functions.xml.in.h:748 +#: ../data/functions.xml.in.h:755 msgid "r:uncertainty" msgstr "" -#: ../data/functions.xml.in.h:749 +#: ../data/functions.xml.in.h:756 msgid "Uncertainty is relative" msgstr "" -#: ../data/functions.xml.in.h:750 +#: ../data/functions.xml.in.h:757 msgid "Logical" msgstr "Logisch" -#: ../data/functions.xml.in.h:751 +#: ../data/functions.xml.in.h:758 msgid "For...Do" msgstr "For...Do" -#: ../data/functions.xml.in.h:752 +#: ../data/functions.xml.in.h:759 msgid "r:for" msgstr "" -#: ../data/functions.xml.in.h:753 +#: ../data/functions.xml.in.h:760 msgid "Initial value of counter" msgstr "Beginwaarde van teller" -#: ../data/functions.xml.in.h:754 +#: ../data/functions.xml.in.h:761 msgid "Counter variable" msgstr "Tellervariabele" -#: ../data/functions.xml.in.h:755 +#: ../data/functions.xml.in.h:762 msgid "For condition" msgstr "For-voorwaarde" -#: ../data/functions.xml.in.h:756 +#: ../data/functions.xml.in.h:763 msgid "Counter update function" msgstr "Functie voor bijwerken van de teller" -#: ../data/functions.xml.in.h:757 +#: ../data/functions.xml.in.h:764 msgid "Do function" msgstr "Do-functie" -#: ../data/functions.xml.in.h:758 +#: ../data/functions.xml.in.h:765 msgid "If...Then...Else" msgstr "If...Then...Else" -#: ../data/functions.xml.in.h:759 +#: ../data/functions.xml.in.h:766 msgid "r:if" msgstr "" -#: ../data/functions.xml.in.h:760 +#: ../data/functions.xml.in.h:767 #, fuzzy msgid "" "Tests a condition and returns a value depending on the result. Vectors can " @@ -6120,96 +6164,96 @@ msgstr "" "Test een conditie en retourneert een waarde afhankelijk van het resultaat." -#: ../data/functions.xml.in.h:761 +#: ../data/functions.xml.in.h:768 msgid "Expression if condition is met" msgstr "Expressie indien aan conditie wordt voldaan" -#: ../data/functions.xml.in.h:762 +#: ../data/functions.xml.in.h:769 msgid "Expression if condition is NOT met" msgstr "Expressie indien NIET aan conditie wordt voldaan" -#: ../data/functions.xml.in.h:763 +#: ../data/functions.xml.in.h:770 msgid "Assume false if not true" msgstr "" -#: ../data/functions.xml.in.h:764 +#: ../data/functions.xml.in.h:771 msgid "Bitwise Exclusive OR" msgstr "Bitsgewijs XOR" -#: ../data/functions.xml.in.h:765 +#: ../data/functions.xml.in.h:772 msgid "r:xor" msgstr "" -#: ../data/functions.xml.in.h:766 +#: ../data/functions.xml.in.h:773 msgid "Value 1" msgstr "Waarde 1" -#: ../data/functions.xml.in.h:767 +#: ../data/functions.xml.in.h:774 msgid "Value 2" msgstr "Waarde 2" -#: ../data/functions.xml.in.h:768 +#: ../data/functions.xml.in.h:775 msgid "Logical Exclusive OR" msgstr "Booleaanse XOR" -#: ../data/functions.xml.in.h:769 +#: ../data/functions.xml.in.h:776 msgid "r:lxor" msgstr "" -#: ../data/functions.xml.in.h:770 +#: ../data/functions.xml.in.h:777 msgid "Bitwise Shift" msgstr "Bitsgewijs verschuiven (shift)" -#: ../data/functions.xml.in.h:771 +#: ../data/functions.xml.in.h:778 msgid "" "Applies logical or arithmetic bitwise shift to an integer. The second " "argument specifies the number of steps that each binary bit is shifted to " "the left (use negative values for right shift)." msgstr "" -#: ../data/functions.xml.in.h:772 +#: ../data/functions.xml.in.h:779 msgid "r:shift" msgstr "" -#: ../data/functions.xml.in.h:773 +#: ../data/functions.xml.in.h:780 msgid "Steps" msgstr "" -#: ../data/functions.xml.in.h:774 +#: ../data/functions.xml.in.h:781 msgid "Arithmetic shift using two's complement" msgstr "" -#: ../data/functions.xml.in.h:775 +#: ../data/functions.xml.in.h:782 msgid "Bitwise Complement (Not)" msgstr "" -#: ../data/functions.xml.in.h:776 +#: ../data/functions.xml.in.h:783 msgid "" "Applies bitwise NOT to an integer of specified bit width and signedness (use " "1 for signed and 0 for unsigned). If bit width is zero, the smallest " "necessary number of bits (of 8, 16, 32, 64, 128, ...) will be used." msgstr "" -#: ../data/functions.xml.in.h:777 +#: ../data/functions.xml.in.h:784 msgid "r:bitcmp" msgstr "" -#: ../data/functions.xml.in.h:778 +#: ../data/functions.xml.in.h:785 #, fuzzy msgid "Bit Width" msgstr "Breedte" -#: ../data/functions.xml.in.h:779 +#: ../data/functions.xml.in.h:786 #, fuzzy msgid "Signed Integer" msgstr "Sinusintegraal" -#: ../data/functions.xml.in.h:780 +#: ../data/functions.xml.in.h:787 #, fuzzy msgid "Bit Rotation" msgstr "Is een rationaal getal" -#: ../data/functions.xml.in.h:781 +#: ../data/functions.xml.in.h:788 msgid "" "Applies circular bitwise shift to an integer of specified bit width and " "signedness (use 1 for signed and 0 for unsigned). The second argument " @@ -6218,23 +6262,23 @@ "necessary number of bits (of 8, 16, 32, 64, 128, ...) will be used." msgstr "" -#: ../data/functions.xml.in.h:782 +#: ../data/functions.xml.in.h:789 msgid "r:bitrot" msgstr "" -#: ../data/functions.xml.in.h:783 +#: ../data/functions.xml.in.h:790 msgid "Algebra" msgstr "Algebra" -#: ../data/functions.xml.in.h:784 +#: ../data/functions.xml.in.h:791 msgid "Summation" msgstr "Sommatie" -#: ../data/functions.xml.in.h:785 +#: ../data/functions.xml.in.h:792 msgid "au:Σ,r:sum" msgstr "au:Σ,som" -#: ../data/functions.xml.in.h:786 +#: ../data/functions.xml.in.h:793 #, fuzzy msgid "" "Corresponds to the summation symbol. Adds terms for each x ranging from the " @@ -6243,27 +6287,27 @@ "Komt overeen met symbool voor optellen. Telt termen op met een waarde tussen " "de kleinste en de grootste grenswaarde." -#: ../data/functions.xml.in.h:787 +#: ../data/functions.xml.in.h:794 msgid "Term expression" msgstr "Expressie voor term" -#: ../data/functions.xml.in.h:788 +#: ../data/functions.xml.in.h:795 msgid "Lower limit (i)" msgstr "Ondergrens (i)" -#: ../data/functions.xml.in.h:789 +#: ../data/functions.xml.in.h:796 msgid "Upper limit (n)" msgstr "Bovengrens (n)" -#: ../data/functions.xml.in.h:790 +#: ../data/functions.xml.in.h:797 msgid "Product of a sequence" msgstr "Product" -#: ../data/functions.xml.in.h:791 +#: ../data/functions.xml.in.h:798 msgid "au:Π,r:product" msgstr "" -#: ../data/functions.xml.in.h:792 +#: ../data/functions.xml.in.h:799 msgid "" "Corresponds to the product symbol. Multiplies factors for each x ranging " "from the lower to the upper limit." @@ -6271,75 +6315,75 @@ "Komt overeen met het symbool voor vermenigvuldiging. Vermenigvuldigt met " "factoren met een waarde tussen de kleinste en de grootste grenswaarde." -#: ../data/functions.xml.in.h:793 +#: ../data/functions.xml.in.h:800 msgid "Factor expression" msgstr "Expressie voor factor" -#: ../data/functions.xml.in.h:794 +#: ../data/functions.xml.in.h:801 msgid "Solve for multiple variables" msgstr "Oplossen voor meerdere variabelen" -#: ../data/functions.xml.in.h:795 +#: ../data/functions.xml.in.h:802 msgid "r:multisolve" msgstr "meerdereoplossen" -#: ../data/functions.xml.in.h:796 +#: ../data/functions.xml.in.h:803 msgid "Equation vector" msgstr "Vergelijkingsvector" -#: ../data/functions.xml.in.h:797 +#: ../data/functions.xml.in.h:804 msgid "Variable vector" msgstr "Variabele vector" -#: ../data/functions.xml.in.h:798 +#: ../data/functions.xml.in.h:805 msgid "Solve equation" msgstr "Vergelijking oplossen" -#: ../data/functions.xml.in.h:799 +#: ../data/functions.xml.in.h:806 msgid "r:solve" msgstr "oplossen" -#: ../data/functions.xml.in.h:800 +#: ../data/functions.xml.in.h:807 msgid "Equation" msgstr "Vergelijking" -#: ../data/functions.xml.in.h:801 +#: ../data/functions.xml.in.h:808 msgid "With respect to" msgstr "Met betrekking tot" -#: ../data/functions.xml.in.h:802 +#: ../data/functions.xml.in.h:809 msgid "Solve differential equation" msgstr "Differentiaalvergelijking oplossen" -#: ../data/functions.xml.in.h:803 +#: ../data/functions.xml.in.h:810 #, fuzzy msgid "r:dsolve" msgstr "oplossen" -#: ../data/functions.xml.in.h:804 +#: ../data/functions.xml.in.h:811 msgid "Initial condition: function value (y)" msgstr "" -#: ../data/functions.xml.in.h:805 +#: ../data/functions.xml.in.h:812 msgid "Initial condition: argument value (x)" msgstr "" -#: ../data/functions.xml.in.h:806 +#: ../data/functions.xml.in.h:813 msgid "" "Solves a differential equation and returns the value of y(x). The derivative " "in the equation should be in the format diff(y, x). Only first-order " "differential equations are currently supported." msgstr "" -#: ../data/functions.xml.in.h:807 +#: ../data/functions.xml.in.h:814 msgid "Solve for two variables" msgstr "Oplossen voor twee variabelen" -#: ../data/functions.xml.in.h:808 +#: ../data/functions.xml.in.h:815 msgid "r:solve2" msgstr "oplossen2" -#: ../data/functions.xml.in.h:809 +#: ../data/functions.xml.in.h:816 msgid "" "Solves two equations with two unknown variables. Returns the value of the " "first variable." @@ -6347,504 +6391,530 @@ "Lost twee vergelijkingen op in twee variabelen. Retourneert de waarde van de " "eerste variabele." -#: ../data/functions.xml.in.h:810 +#: ../data/functions.xml.in.h:817 msgid "Equation 1" msgstr "Vergelijking 1" -#: ../data/functions.xml.in.h:811 +#: ../data/functions.xml.in.h:818 msgid "Equation 2" msgstr "Vergelijking 2" -#: ../data/functions.xml.in.h:812 +#: ../data/functions.xml.in.h:819 msgid "Variable 1" msgstr "Variabele 1" -#: ../data/functions.xml.in.h:813 +#: ../data/functions.xml.in.h:820 msgid "Variable 2" msgstr "Variabele 2" -#: ../data/functions.xml.in.h:814 +#: ../data/functions.xml.in.h:821 msgid "Find Linear Function" msgstr "Lineaire functie bepalen" -#: ../data/functions.xml.in.h:815 +#: ../data/functions.xml.in.h:822 msgid "r:linearfunction" msgstr "lineairefunctie" -#: ../data/functions.xml.in.h:816 +#: ../data/functions.xml.in.h:823 msgid "" "Finds the linear function for the straight line between two distinct points." msgstr "" "Bepaalt de lineaire functie voor de rechte lijn tussen twee verschillende " "punten." -#: ../data/functions.xml.in.h:817 +#: ../data/functions.xml.in.h:824 msgid "x1" msgstr "" -#: ../data/functions.xml.in.h:818 +#: ../data/functions.xml.in.h:825 msgid "y1" msgstr "" -#: ../data/functions.xml.in.h:819 +#: ../data/functions.xml.in.h:826 msgid "x2" msgstr "" -#: ../data/functions.xml.in.h:820 +#: ../data/functions.xml.in.h:827 msgid "y2" msgstr "" -#: ../data/functions.xml.in.h:821 +#: ../data/functions.xml.in.h:828 msgid "Calculus" msgstr "Calculus" -#: ../data/functions.xml.in.h:822 +#: ../data/functions.xml.in.h:829 msgid "Differentiate" msgstr "Afgeleide" -#: ../data/functions.xml.in.h:823 +#: ../data/functions.xml.in.h:830 msgid "r:diff,derivative" msgstr "diff,afgeleide" -#: ../data/functions.xml.in.h:824 +#: ../data/functions.xml.in.h:831 #, fuzzy msgid "Variable value" msgstr "Variabele vector" -#: ../data/functions.xml.in.h:825 +#: ../data/functions.xml.in.h:832 msgid "Integrate" msgstr "Integreren" -#: ../data/functions.xml.in.h:826 +#: ../data/functions.xml.in.h:833 msgid "r:integrate,integral,au:∫" msgstr "integreren,integraal,au:∫" -#: ../data/functions.xml.in.h:827 +#: ../data/functions.xml.in.h:834 msgid "Variable of integration" msgstr "Integratievariabele" -#: ../data/functions.xml.in.h:828 +#: ../data/functions.xml.in.h:835 #, fuzzy msgid "Force numerical integration" msgstr "Integratievariabele" -#: ../data/functions.xml.in.h:829 +#: ../data/functions.xml.in.h:836 #, fuzzy msgid "Romberg Integration" msgstr "Integratievariabele" -#: ../data/functions.xml.in.h:830 +#: ../data/functions.xml.in.h:837 #, fuzzy msgid "r:romberg" msgstr "getal" -#: ../data/functions.xml.in.h:831 +#: ../data/functions.xml.in.h:838 #, fuzzy msgid "Min iterations" msgstr "Gemiddelde afwijking" -#: ../data/functions.xml.in.h:832 +#: ../data/functions.xml.in.h:839 #, fuzzy msgid "Max iterations" msgstr "Massafractie" -#: ../data/functions.xml.in.h:833 +#: ../data/functions.xml.in.h:840 #, fuzzy msgid "Monte Carlo Integration" msgstr "Integratievariabele" -#: ../data/functions.xml.in.h:834 +#: ../data/functions.xml.in.h:841 #, fuzzy msgid "r:montecarlo" msgstr "maand" -#: ../data/functions.xml.in.h:835 +#: ../data/functions.xml.in.h:842 #, fuzzy msgid "Number of samples" msgstr "Aantal monsters" -#: ../data/functions.xml.in.h:836 +#: ../data/functions.xml.in.h:843 #, fuzzy msgid "Limit" msgstr "Ondergrens" -#: ../data/functions.xml.in.h:837 +#: ../data/functions.xml.in.h:844 msgid "" "Returns the two-sided limit of the function if direction is zero, limit from " "left (below) if direction is -1, or limit from right (above) if direction is " "+1." msgstr "" -#: ../data/functions.xml.in.h:838 +#: ../data/functions.xml.in.h:845 #, fuzzy msgid "r:limit" msgstr "grenzen" -#: ../data/functions.xml.in.h:839 +#: ../data/functions.xml.in.h:846 msgid "Value to approach" msgstr "" -#: ../data/functions.xml.in.h:840 +#: ../data/functions.xml.in.h:847 #, fuzzy msgid "Direction" msgstr "Sectie" -#: ../data/functions.xml.in.h:841 +#: ../data/functions.xml.in.h:848 msgid "Extreme Values" msgstr "Uiterste waarden" -#: ../data/functions.xml.in.h:842 +#: ../data/functions.xml.in.h:849 msgid "r:extremum" msgstr "uiterste" -#: ../data/functions.xml.in.h:843 +#: ../data/functions.xml.in.h:850 #, fuzzy msgid "Named Integrals" msgstr "Gehele getallen" -#: ../data/functions.xml.in.h:844 +#: ../data/functions.xml.in.h:851 msgid "Logarithmic Integral" msgstr "Logaritmische integraal" -#: ../data/functions.xml.in.h:845 +#: ../data/functions.xml.in.h:852 msgid "rc:li,logint" msgstr "" -#: ../data/functions.xml.in.h:846 +#: ../data/functions.xml.in.h:853 msgid "The integral of 1/ln(x)." msgstr "" -#: ../data/functions.xml.in.h:847 +#: ../data/functions.xml.in.h:854 msgid "Exponential Integral" msgstr "Exponentiële integraal" -#: ../data/functions.xml.in.h:848 +#: ../data/functions.xml.in.h:855 msgid "rc:Ei,expint" msgstr "" -#: ../data/functions.xml.in.h:849 +#: ../data/functions.xml.in.h:856 msgid "The integral of e^x/x." msgstr "" -#: ../data/functions.xml.in.h:850 +#: ../data/functions.xml.in.h:857 msgid "Sine Integral" msgstr "Sinusintegraal" -#: ../data/functions.xml.in.h:851 +#: ../data/functions.xml.in.h:858 msgid "rc:Si,sinint" msgstr "" -#: ../data/functions.xml.in.h:852 +#: ../data/functions.xml.in.h:859 msgid "The integral of sin(x)/x." msgstr "" -#: ../data/functions.xml.in.h:853 +#: ../data/functions.xml.in.h:860 msgid "Cosine Integral" msgstr "Cosinusintegraal" -#: ../data/functions.xml.in.h:854 +#: ../data/functions.xml.in.h:861 msgid "rc:Ci,cosint" msgstr "" -#: ../data/functions.xml.in.h:855 +#: ../data/functions.xml.in.h:862 msgid "The integral of cos(x)/x." msgstr "" -#: ../data/functions.xml.in.h:856 +#: ../data/functions.xml.in.h:863 msgid "Hyperbolic Sine Integral" msgstr "Hyperbolische sinusintegraal" -#: ../data/functions.xml.in.h:857 +#: ../data/functions.xml.in.h:864 msgid "rc:Shi,sinhint" msgstr "" -#: ../data/functions.xml.in.h:858 +#: ../data/functions.xml.in.h:865 msgid "The integral of sinh(x)/x." msgstr "" -#: ../data/functions.xml.in.h:859 +#: ../data/functions.xml.in.h:866 msgid "Hyperbolic Cosine Integral" msgstr "Hyperbolische cosinusintegraal" -#: ../data/functions.xml.in.h:860 +#: ../data/functions.xml.in.h:867 msgid "rc:Chi,coshint" msgstr "" -#: ../data/functions.xml.in.h:861 +#: ../data/functions.xml.in.h:868 msgid "The integral of cosh(x)/x." msgstr "" -#: ../data/functions.xml.in.h:862 +#: ../data/functions.xml.in.h:869 +#, fuzzy +msgid "Fresnel Integral S" +msgstr "Cosinusintegraal" + +#: ../data/functions.xml.in.h:870 +msgid "r:fresnels" +msgstr "" + +#: ../data/functions.xml.in.h:871 +msgid "The integral of sin(pi*x^2/2)." +msgstr "" + +#: ../data/functions.xml.in.h:872 +#, fuzzy +msgid "Fresnel Integral C" +msgstr "Cosinusintegraal" + +#: ../data/functions.xml.in.h:873 +msgid "r:fresnelc" +msgstr "" + +#: ../data/functions.xml.in.h:874 +msgid "The integral of cos(pi*x^2/2)." +msgstr "" + +#: ../data/functions.xml.in.h:875 #, fuzzy msgid "Upper Incomplete Gamma Function" msgstr "Gamma-functie" -#: ../data/functions.xml.in.h:863 +#: ../data/functions.xml.in.h:876 msgid "r:igamma" msgstr "" -#: ../data/functions.xml.in.h:864 +#: ../data/functions.xml.in.h:877 #, fuzzy msgid "Lower Incomplete Gamma Function" msgstr "Gamma-functie" -#: ../data/functions.xml.in.h:865 +#: ../data/functions.xml.in.h:878 msgid "r:gammainc" msgstr "" -#: ../data/functions.xml.in.h:866 +#: ../data/functions.xml.in.h:879 msgid "Geometry" msgstr "Meetkunde" -#: ../data/functions.xml.in.h:867 +#: ../data/functions.xml.in.h:880 msgid "Triangle" msgstr "Driehoek" -#: ../data/functions.xml.in.h:868 +#: ../data/functions.xml.in.h:881 msgid "Hypotenuse" msgstr "Hypotenusa" -#: ../data/functions.xml.in.h:869 +#: ../data/functions.xml.in.h:882 msgid "r:hypot" msgstr "" -#: ../data/functions.xml.in.h:870 +#: ../data/functions.xml.in.h:883 msgid "Side A" msgstr "Zijde A" -#: ../data/functions.xml.in.h:871 +#: ../data/functions.xml.in.h:884 msgid "Side B" msgstr "Zijde B" -#: ../data/functions.xml.in.h:872 +#: ../data/functions.xml.in.h:885 msgid "Triangle Area" msgstr "Oppervlakte van driehoek" -#: ../data/functions.xml.in.h:873 +#: ../data/functions.xml.in.h:886 msgid "r:triangle" msgstr "driehoek" -#: ../data/functions.xml.in.h:874 +#: ../data/functions.xml.in.h:887 msgid "Height" msgstr "Hoogte" -#: ../data/functions.xml.in.h:875 +#: ../data/functions.xml.in.h:888 msgid "Triangle Perimeter" msgstr "Omtrek van driehoek" -#: ../data/functions.xml.in.h:876 +#: ../data/functions.xml.in.h:889 msgid "r:triangle_perimeter" msgstr "driehoek_omtrek" -#: ../data/functions.xml.in.h:877 +#: ../data/functions.xml.in.h:890 msgid "Side C" msgstr "Zijde C" -#: ../data/functions.xml.in.h:878 +#: ../data/functions.xml.in.h:891 msgid "Circle" msgstr "Cirkel" -#: ../data/functions.xml.in.h:879 +#: ../data/functions.xml.in.h:892 msgid "Circle Area" msgstr "Cirkeloppervlak" -#: ../data/functions.xml.in.h:880 +#: ../data/functions.xml.in.h:893 msgid "r:circle" msgstr "cirkel" -#: ../data/functions.xml.in.h:881 +#: ../data/functions.xml.in.h:894 msgid "Calculates the area of a circle using the radius" msgstr "Berekent met de straal het oppervlak van een cirkel" -#: ../data/functions.xml.in.h:882 +#: ../data/functions.xml.in.h:895 msgid "Radius" msgstr "Straal" -#: ../data/functions.xml.in.h:883 +#: ../data/functions.xml.in.h:896 msgid "Circle Circumference" msgstr "Cirkelomtrek" -#: ../data/functions.xml.in.h:884 +#: ../data/functions.xml.in.h:897 msgid "r:circumference" msgstr "cirkelomtrek" -#: ../data/functions.xml.in.h:885 +#: ../data/functions.xml.in.h:898 msgid "Cylinder" msgstr "Cilinder" -#: ../data/functions.xml.in.h:886 +#: ../data/functions.xml.in.h:899 msgid "Cylinder Volume" msgstr "Volume van cilinder" -#: ../data/functions.xml.in.h:887 +#: ../data/functions.xml.in.h:900 msgid "r:cylinder" msgstr "cilinder" -#: ../data/functions.xml.in.h:888 +#: ../data/functions.xml.in.h:901 msgid "Surface Area of Cylinder" msgstr "Oppervlaktegrootte van cilinder" -#: ../data/functions.xml.in.h:889 +#: ../data/functions.xml.in.h:902 msgid "r:cylinder_sa" msgstr "cilinder_opp" -#: ../data/functions.xml.in.h:890 +#: ../data/functions.xml.in.h:903 msgid "Cone" msgstr "Kegel" -#: ../data/functions.xml.in.h:891 +#: ../data/functions.xml.in.h:904 msgid "Cone Volume" msgstr "Volume van kegel" -#: ../data/functions.xml.in.h:892 +#: ../data/functions.xml.in.h:905 msgid "r:cone" msgstr "kegel" -#: ../data/functions.xml.in.h:893 +#: ../data/functions.xml.in.h:906 msgid "Surface Area of Cone" msgstr "Oppervlaktegrootte van kegel" -#: ../data/functions.xml.in.h:894 +#: ../data/functions.xml.in.h:907 msgid "r:cone_sa" msgstr "kegel_opp" -#: ../data/functions.xml.in.h:895 +#: ../data/functions.xml.in.h:908 msgid "Sphere" msgstr "Bol" -#: ../data/functions.xml.in.h:896 +#: ../data/functions.xml.in.h:909 msgid "Sphere Volume" msgstr "Volume van bol" -#: ../data/functions.xml.in.h:897 +#: ../data/functions.xml.in.h:910 msgid "r:sphere" msgstr "bol" -#: ../data/functions.xml.in.h:898 +#: ../data/functions.xml.in.h:911 msgid "Surface Area of Sphere" msgstr "Oppervlaktegrootte van bol" -#: ../data/functions.xml.in.h:899 +#: ../data/functions.xml.in.h:912 msgid "r:sphere_sa" msgstr "bol_oppervlak" -#: ../data/functions.xml.in.h:900 +#: ../data/functions.xml.in.h:913 msgid "Square Area" msgstr "Oppervlakte van vierkant" -#: ../data/functions.xml.in.h:901 +#: ../data/functions.xml.in.h:914 msgid "r:square" msgstr "vierkant" -#: ../data/functions.xml.in.h:902 +#: ../data/functions.xml.in.h:915 msgid "Length of side" msgstr "Lengte van zijde" -#: ../data/functions.xml.in.h:903 +#: ../data/functions.xml.in.h:916 msgid "Square Perimeter" msgstr "Omtrek van vierkant" -#: ../data/functions.xml.in.h:904 +#: ../data/functions.xml.in.h:917 msgid "r:square_perimeter" msgstr "vierkant_omtrek" -#: ../data/functions.xml.in.h:905 +#: ../data/functions.xml.in.h:918 msgid "Cube" msgstr "Derdemacht" -#: ../data/functions.xml.in.h:906 +#: ../data/functions.xml.in.h:919 msgid "Cube Volume" msgstr "Volume kubus" -#: ../data/functions.xml.in.h:907 +#: ../data/functions.xml.in.h:920 msgid "r:cube" msgstr "kubus" -#: ../data/functions.xml.in.h:908 +#: ../data/functions.xml.in.h:921 msgid "Surface Area of Cube" msgstr "Oppervlaktegrootte van kubus" -#: ../data/functions.xml.in.h:909 +#: ../data/functions.xml.in.h:922 msgid "r:cube_sa" msgstr "kubus_opp" -#: ../data/functions.xml.in.h:910 +#: ../data/functions.xml.in.h:923 msgid "Rectangle" msgstr "Rechthoek" -#: ../data/functions.xml.in.h:911 +#: ../data/functions.xml.in.h:924 msgid "Rectangle Area" msgstr "Oppervlak rechthoek" -#: ../data/functions.xml.in.h:912 +#: ../data/functions.xml.in.h:925 msgid "r:rect" msgstr "" -#: ../data/functions.xml.in.h:913 +#: ../data/functions.xml.in.h:926 msgid "Width" msgstr "Breedte" -#: ../data/functions.xml.in.h:914 +#: ../data/functions.xml.in.h:927 msgid "Rectangle Perimeter" msgstr "Omtrek rechthoek" -#: ../data/functions.xml.in.h:915 +#: ../data/functions.xml.in.h:928 msgid "r:rect_perimeter" msgstr "rect_omtrek" -#: ../data/functions.xml.in.h:916 +#: ../data/functions.xml.in.h:929 msgid "Prism" msgstr "Prisma" -#: ../data/functions.xml.in.h:917 +#: ../data/functions.xml.in.h:930 msgid "Volume of Rectangular Prism" msgstr "Inhoud van rechthoekig prisma" -#: ../data/functions.xml.in.h:918 +#: ../data/functions.xml.in.h:931 msgid "r:rectprism" msgstr "rectprisma" -#: ../data/functions.xml.in.h:919 +#: ../data/functions.xml.in.h:932 msgid "Calculates the volume of a prism with rectangular base." msgstr "Berekent de inhoud van een prisma met een rechthoekig basisvlak." -#: ../data/functions.xml.in.h:920 +#: ../data/functions.xml.in.h:933 msgid "Surface Area of Rectangular Prism" msgstr "Oppervlaktegrootte van rechthoekig prisma" -#: ../data/functions.xml.in.h:921 +#: ../data/functions.xml.in.h:934 msgid "r:rectprism_sa" msgstr "rectprisma_opp" -#: ../data/functions.xml.in.h:922 +#: ../data/functions.xml.in.h:935 msgid "Calculates the surface area of a prism with rectangular base." msgstr "Berekent de oppervlakte van een prisma met een rechthoekig basisvlak." -#: ../data/functions.xml.in.h:923 +#: ../data/functions.xml.in.h:936 msgid "Volume of Triangular Prism" msgstr "Inhoud van driehoekig prisma" -#: ../data/functions.xml.in.h:924 +#: ../data/functions.xml.in.h:937 msgid "r:triangleprism" msgstr "driehoekprisma" -#: ../data/functions.xml.in.h:925 +#: ../data/functions.xml.in.h:938 msgid "Calculates the volume of a prism with triangular base." msgstr "Berekent de inhoud van een prisma met een driehoekig basisvlak." -#: ../data/functions.xml.in.h:926 +#: ../data/functions.xml.in.h:939 msgid "Pyramid" msgstr "Piramide" -#: ../data/functions.xml.in.h:927 +#: ../data/functions.xml.in.h:940 msgid "Pyramid Volume" msgstr "Volume van piramide" -#: ../data/functions.xml.in.h:928 +#: ../data/functions.xml.in.h:941 msgid "r:pyramid" msgstr "piramide" -#: ../data/functions.xml.in.h:929 +#: ../data/functions.xml.in.h:942 msgid "" "Calculates the volume of a 3-dimensional shape standing on a rectangular " "base and terminating in a point at the top." @@ -6852,75 +6922,75 @@ "Berekent de inhoud van een 3-dimensionaal lichaam met een rechthoekig " "basisvlak en een top in de vorm van een punt." -#: ../data/functions.xml.in.h:930 +#: ../data/functions.xml.in.h:943 msgid "Length of base" msgstr "Lengte van basis" -#: ../data/functions.xml.in.h:931 +#: ../data/functions.xml.in.h:944 msgid "Width of base" msgstr "Basislengte" -#: ../data/functions.xml.in.h:932 +#: ../data/functions.xml.in.h:945 msgid "Volume of Regular Tetrahedron" msgstr "Inhoud van regelmatig viervlak (tetraëder)" -#: ../data/functions.xml.in.h:933 +#: ../data/functions.xml.in.h:946 msgid "r:tetrahedron" msgstr "tetraëder" -#: ../data/functions.xml.in.h:934 +#: ../data/functions.xml.in.h:947 msgid "Surface Area of Regular Tetrahedron" msgstr "Oppervlaktegrootte van regelmatig viervlak (tetraëder)" -#: ../data/functions.xml.in.h:935 +#: ../data/functions.xml.in.h:948 msgid "r:tetrahedron_sa" msgstr "tetraëder_opp" -#: ../data/functions.xml.in.h:936 +#: ../data/functions.xml.in.h:949 msgid "Height of Regular Tetrahedron" msgstr " Hoogte van een regelmatig viervlak (tetraëder)" -#: ../data/functions.xml.in.h:937 +#: ../data/functions.xml.in.h:950 msgid "r:tetrahedron_height" msgstr "tetraëder_hoogte" -#: ../data/functions.xml.in.h:938 +#: ../data/functions.xml.in.h:951 msgid "Volume of Square Pyramid" msgstr "Inhoud van vierkant prisma" -#: ../data/functions.xml.in.h:939 +#: ../data/functions.xml.in.h:952 msgid "r:sqpyramid" msgstr "vierkpiramide" -#: ../data/functions.xml.in.h:940 +#: ../data/functions.xml.in.h:953 msgid "Surface Area of Square Pyramid" msgstr "Oppervlaktegrootte van vierkante piramide" -#: ../data/functions.xml.in.h:941 +#: ../data/functions.xml.in.h:954 msgid "r:sqpyramid_sa" msgstr "vierkpiramide_opp" -#: ../data/functions.xml.in.h:942 +#: ../data/functions.xml.in.h:955 msgid "Height of Square Pyramid" msgstr "Hoogte van een vierkante piramide" -#: ../data/functions.xml.in.h:943 +#: ../data/functions.xml.in.h:956 msgid "r:sqpyramid_height" msgstr "midhoogte_vierkpiramide" -#: ../data/functions.xml.in.h:944 +#: ../data/functions.xml.in.h:957 msgid "Parallelogram" msgstr "Parallellogram" -#: ../data/functions.xml.in.h:945 +#: ../data/functions.xml.in.h:958 msgid "Parallelogram Area" msgstr "Oppervlak van parallellogram" -#: ../data/functions.xml.in.h:946 +#: ../data/functions.xml.in.h:959 msgid "r:parallelogram" msgstr "parallellogram" -#: ../data/functions.xml.in.h:947 +#: ../data/functions.xml.in.h:960 msgid "" "Calculates the area of a four-sided figure whose opposite sides are both " "parallel and equal in length." @@ -6928,15 +6998,15 @@ "Berekent de oppervlakte van een figuur met vier zijden waarvan de " "overstaande zijden zowel evenwijdig als even lang zijn." -#: ../data/functions.xml.in.h:948 +#: ../data/functions.xml.in.h:961 msgid "Parallelogram Perimeter" msgstr "Omtrek van parallellogram" -#: ../data/functions.xml.in.h:949 +#: ../data/functions.xml.in.h:962 msgid "r:parallelogram_perimeter" msgstr "parallellogram_omtrek" -#: ../data/functions.xml.in.h:950 +#: ../data/functions.xml.in.h:963 msgid "" "Calculates the perimeter of a four-sided figure whose opposite sides are " "both parallel and equal in length." @@ -6944,41 +7014,41 @@ "Berekent de omtrek van een figuur met vier zijden waarvan de overstaande " "zijden zowel evenwijdig als even lang zijn." -#: ../data/functions.xml.in.h:951 +#: ../data/functions.xml.in.h:964 msgid "Trapezoid" msgstr "Trapezium" -#: ../data/functions.xml.in.h:952 +#: ../data/functions.xml.in.h:965 msgid "Trapezoid Area" msgstr "Oppervlakte van trapezium" -#: ../data/functions.xml.in.h:953 +#: ../data/functions.xml.in.h:966 msgid "r:trapezoid" msgstr "trapezium" -#: ../data/functions.xml.in.h:954 +#: ../data/functions.xml.in.h:967 msgid "Calculates the area of a four-sided figure with two parallel sides." msgstr "" "Berekent de oppervlakte van een figuur met vier zijden waarvan twee zijden " "evenwijdig zijn." -#: ../data/functions.xml.in.h:955 +#: ../data/functions.xml.in.h:968 msgid "Economics" msgstr "Economie" -#: ../data/functions.xml.in.h:956 +#: ../data/functions.xml.in.h:969 msgid "Microeconomics" msgstr "Microëconomie" -#: ../data/functions.xml.in.h:957 +#: ../data/functions.xml.in.h:970 msgid "Elasticity" msgstr "Elasticiteit" -#: ../data/functions.xml.in.h:958 +#: ../data/functions.xml.in.h:971 msgid "r:elasticity" msgstr "elasticiteit" -#: ../data/functions.xml.in.h:959 +#: ../data/functions.xml.in.h:972 msgid "" "Calculates the demand elasticity. Also works for supply elasticity, income " "elasticity, cross-price elasticity, etc. Just replace demand with supply, or " @@ -6992,27 +7062,27 @@ "bijvoorbeeld berekent de vraagelasticiteit als de prijs 3 is voor de functie " "\"Q = 100 -x^2\". waar x de standaard prijsvariabele is." -#: ../data/functions.xml.in.h:960 +#: ../data/functions.xml.in.h:973 msgid "Demand function" msgstr "Vraagfunctie" -#: ../data/functions.xml.in.h:961 +#: ../data/functions.xml.in.h:974 msgid "Price" msgstr "Prijs" -#: ../data/functions.xml.in.h:962 +#: ../data/functions.xml.in.h:975 msgid "Price variable" msgstr "Prijsvariabele" -#: ../data/functions.xml.in.h:963 +#: ../data/functions.xml.in.h:976 msgid "Sum-of-Years Digits Depreciation" msgstr "Afschrijving volgens som der jaren" -#: ../data/functions.xml.in.h:964 +#: ../data/functions.xml.in.h:977 msgid "r:syd" msgstr "" -#: ../data/functions.xml.in.h:965 +#: ../data/functions.xml.in.h:978 msgid "" "Calculates the sum-of-years digits depreciation for an asset based on its " "cost, salvage value, anticipated life, and a particular period. This method " @@ -7029,31 +7099,31 @@ "aanschaf- en restwaarde. De economische levensduur is het aantal perioden " "(meestal jaren) waarin het actief word afgeschreven." -#: ../data/functions.xml.in.h:966 +#: ../data/functions.xml.in.h:979 msgid "Cost" msgstr "Kosten" -#: ../data/functions.xml.in.h:967 +#: ../data/functions.xml.in.h:980 msgid "Salvage value" msgstr "Restwaarde" -#: ../data/functions.xml.in.h:968 +#: ../data/functions.xml.in.h:981 msgid "Life" msgstr "Levensduur" -#: ../data/functions.xml.in.h:969 +#: ../data/functions.xml.in.h:982 msgid "Period" msgstr "Termijn" -#: ../data/functions.xml.in.h:970 +#: ../data/functions.xml.in.h:983 msgid "Straight Line Depreciation" msgstr "Gelijkblijvende afschrijving" -#: ../data/functions.xml.in.h:971 +#: ../data/functions.xml.in.h:984 msgid "r:sln" msgstr "" -#: ../data/functions.xml.in.h:972 +#: ../data/functions.xml.in.h:985 msgid "" "Determines the straight line depreciation of an asset for a single period." " Cost is the amount you paid for the asset. Salvage is the value of " @@ -7068,15 +7138,15 @@ "afgeschreven. Door deze vorm van afschrijven worden de kosten gelijkelijk " "verdeeld over de gehele afschrijvingsduur." -#: ../data/functions.xml.in.h:973 +#: ../data/functions.xml.in.h:986 msgid "Present Value" msgstr "Huidige waarde" -#: ../data/functions.xml.in.h:974 +#: ../data/functions.xml.in.h:987 msgid "r:pv" msgstr "" -#: ../data/functions.xml.in.h:975 +#: ../data/functions.xml.in.h:988 msgid "" "Returns the present value of an investment. If type = 1 then the " "payment is made at the beginning of the period, If type = 0 (or omitted) it " @@ -7086,35 +7156,35 @@ "de uitbetaling aan het begin van de termijn, indien type = 0 (of weggelaten) " "aan het einde van elke termijn." -#: ../data/functions.xml.in.h:976 +#: ../data/functions.xml.in.h:989 msgid "Interest rate" msgstr "Rentepercentage" -#: ../data/functions.xml.in.h:977 +#: ../data/functions.xml.in.h:990 msgid "Number of periods" msgstr "Aantal termijnen" -#: ../data/functions.xml.in.h:978 +#: ../data/functions.xml.in.h:991 msgid "Payment made each period" msgstr "Termijnbetaling" -#: ../data/functions.xml.in.h:979 +#: ../data/functions.xml.in.h:992 msgid "Future value" msgstr "Toekomstige waarde" -#: ../data/functions.xml.in.h:980 +#: ../data/functions.xml.in.h:993 msgid "Type" msgstr "Type" -#: ../data/functions.xml.in.h:981 +#: ../data/functions.xml.in.h:994 msgid "Nominal Interest Rate" msgstr "Nominaal rentepercentage" -#: ../data/functions.xml.in.h:982 +#: ../data/functions.xml.in.h:995 msgid "r:nominal" msgstr "nominaal" -#: ../data/functions.xml.in.h:983 +#: ../data/functions.xml.in.h:996 msgid "" "Calculates the nominal interest rate from a given effective interest rate " "compounded at given intervals." @@ -7122,120 +7192,120 @@ "Berekent de nominale rente uit de effectieve rente betaald over het " "opgegeven tijdsinterval." -#: ../data/functions.xml.in.h:984 +#: ../data/functions.xml.in.h:997 msgid "Effective interest rate" msgstr "Effectief rentepercentage" -#: ../data/functions.xml.in.h:985 +#: ../data/functions.xml.in.h:998 msgid "Periods" msgstr "Termijnen" -#: ../data/functions.xml.in.h:986 +#: ../data/functions.xml.in.h:999 msgid "Zero Coupon" msgstr "Zonder coupons" -#: ../data/functions.xml.in.h:987 +#: ../data/functions.xml.in.h:1000 msgid "r:zero_coupon" msgstr "geen_coupon" -#: ../data/functions.xml.in.h:988 +#: ../data/functions.xml.in.h:1001 msgid "Calculates the value of a zero-coupon (pure discount) bond." msgstr "Berekent de waarde van een obligatie zonder coupons." -#: ../data/functions.xml.in.h:989 +#: ../data/functions.xml.in.h:1002 msgid "Face value" msgstr "Nominale waarde" -#: ../data/functions.xml.in.h:990 +#: ../data/functions.xml.in.h:1003 msgid "Treasury Bill Yield" msgstr "Opbrengst kortlopende overheidsobligatie zonder coupons" -#: ../data/functions.xml.in.h:991 +#: ../data/functions.xml.in.h:1004 msgid "r:tbillyield" msgstr "" -#: ../data/functions.xml.in.h:992 +#: ../data/functions.xml.in.h:1005 msgid "Returns the yield for a treasury bill." msgstr "" "Berekent de opbrengst van een kortlopende overheidsobligatie zonder coupons." -#: ../data/functions.xml.in.h:993 +#: ../data/functions.xml.in.h:1006 msgid "Settlement date" msgstr "Afwikkeldatum" -#: ../data/functions.xml.in.h:994 +#: ../data/functions.xml.in.h:1007 msgid "Maturity date" msgstr "Vervaldatum" -#: ../data/functions.xml.in.h:995 +#: ../data/functions.xml.in.h:1008 msgid "Price per $100 face value" msgstr "Prijs per €100 nominale waarde" -#: ../data/functions.xml.in.h:996 +#: ../data/functions.xml.in.h:1009 msgid "Treasury Bill Price" msgstr "Prijs kortlopende overheidsobligatie zonder coupons" -#: ../data/functions.xml.in.h:997 +#: ../data/functions.xml.in.h:1010 msgid "r:tbillprice" msgstr "" -#: ../data/functions.xml.in.h:998 +#: ../data/functions.xml.in.h:1011 msgid "Returns the price per $100 value for a treasury bill." msgstr "" "Berekent de prijs per € 100 voor een kortlopende overheidsobligatie zonder " "coupons." -#: ../data/functions.xml.in.h:999 +#: ../data/functions.xml.in.h:1012 msgid "Discount rate" msgstr "Discontopercentage" -#: ../data/functions.xml.in.h:1000 +#: ../data/functions.xml.in.h:1013 msgid "Treasury Bill Equivalent" msgstr "Equivalent van kortlopende overheidsobligatie zonder coupons" -#: ../data/functions.xml.in.h:1001 +#: ../data/functions.xml.in.h:1014 msgid "r:tbilleq" msgstr "" -#: ../data/functions.xml.in.h:1002 +#: ../data/functions.xml.in.h:1015 msgid "Returns the bond equivalent for a treasury bill." msgstr "" "Berekent het obligatie-equivalent voor een kortlopende overheidsobligatie " "zonder coupons." -#: ../data/functions.xml.in.h:1003 +#: ../data/functions.xml.in.h:1016 msgid "Interest paid on a given period of an investment (ISPMT)" msgstr "Rente betaald over een gegeven investeringstermijn (ISPMT)" -#: ../data/functions.xml.in.h:1004 +#: ../data/functions.xml.in.h:1017 msgid "r:ispmt" msgstr "" -#: ../data/functions.xml.in.h:1005 +#: ../data/functions.xml.in.h:1018 msgid "Calculates the interest paid on a given period of an investment." msgstr "Berekent de betaalde rente over de opgegeven investeringstermijn." -#: ../data/functions.xml.in.h:1006 +#: ../data/functions.xml.in.h:1019 msgid "Periodic interest rate" msgstr "Periodiek rentepercentage" -#: ../data/functions.xml.in.h:1007 +#: ../data/functions.xml.in.h:1020 msgid "Amortizement period" msgstr "Amortisatieperiode" -#: ../data/functions.xml.in.h:1008 +#: ../data/functions.xml.in.h:1021 msgid "Present value" msgstr "Huidige waarde" -#: ../data/functions.xml.in.h:1009 +#: ../data/functions.xml.in.h:1022 msgid "Payment for a loan" msgstr "Betaling voor een lening" -#: ../data/functions.xml.in.h:1010 +#: ../data/functions.xml.in.h:1023 msgid "r:pmt" msgstr "" -#: ../data/functions.xml.in.h:1011 +#: ../data/functions.xml.in.h:1024 #, fuzzy msgid "" "Returns the amount of payment (negative) each period for a loan based on a " @@ -7254,19 +7324,19 @@ "de termijn worden betaald, Indien type = 0 (ofweggelaten) aan het einde van " "elke termijn." -#: ../data/functions.xml.in.h:1012 +#: ../data/functions.xml.in.h:1025 msgid "Rate" msgstr "" -#: ../data/functions.xml.in.h:1013 +#: ../data/functions.xml.in.h:1026 msgid "Periods of an investment" msgstr "Termijnen van een investering" -#: ../data/functions.xml.in.h:1014 +#: ../data/functions.xml.in.h:1027 msgid "r:nper" msgstr "nterm" -#: ../data/functions.xml.in.h:1015 +#: ../data/functions.xml.in.h:1028 msgid "" "Calculates number of periods of an investment based on periodic constant " "payments and a constant interest rate. Type defines the due date. 1 " @@ -7278,15 +7348,15 @@ "bepaalt de datum waarop moet worden betaald. 1 voor betalen aan het begin " "van een termijn en 0 (standaard) voor betalen aan het eind van een termijn." -#: ../data/functions.xml.in.h:1016 +#: ../data/functions.xml.in.h:1029 msgid "Periods for investment to attain desired value" msgstr "Termijnen waarin een investering de gewenste waarde bereikt" -#: ../data/functions.xml.in.h:1017 +#: ../data/functions.xml.in.h:1030 msgid "r:g_duration" msgstr "g_duur" -#: ../data/functions.xml.in.h:1018 +#: ../data/functions.xml.in.h:1031 msgid "" "Returns the number of periods needed for an investment to attain a desired " "value." @@ -7294,15 +7364,15 @@ "Retourneert het aantal benodigde termijnen waarna een investering een " "gewenste waarde bereikt." -#: ../data/functions.xml.in.h:1019 +#: ../data/functions.xml.in.h:1032 msgid "Payment of an annuity going towards principal (PPMT)" msgstr "Aflossingsdeel van een termijn van een annuïteit (PPMT)" -#: ../data/functions.xml.in.h:1020 +#: ../data/functions.xml.in.h:1033 msgid "r:ppmt" msgstr "" -#: ../data/functions.xml.in.h:1021 +#: ../data/functions.xml.in.h:1034 msgid "" "Calculates the amount of a payment of an annuity going towards principal." " Type defines the due date. 1 for payment at the beginning of a " @@ -7313,35 +7383,35 @@ "aanhet het begin van de termijn en 0 (standaard) voor betaling aan het einde " "van de termijn." -#: ../data/functions.xml.in.h:1022 +#: ../data/functions.xml.in.h:1035 msgid "Desired future value" msgstr "Gewenste toekomstige waarde" -#: ../data/functions.xml.in.h:1023 +#: ../data/functions.xml.in.h:1036 msgid "Effective Interest Rate" msgstr "Effectief rentepercentage" -#: ../data/functions.xml.in.h:1024 +#: ../data/functions.xml.in.h:1037 msgid "r:effect" msgstr "" -#: ../data/functions.xml.in.h:1025 +#: ../data/functions.xml.in.h:1038 msgid "Calculates the effective interest for a given nominal rate." msgstr "Berekent de effectieve rente bij een gegeven nominale rente." -#: ../data/functions.xml.in.h:1026 +#: ../data/functions.xml.in.h:1039 msgid "Nominal interest rate" msgstr "Nominaal rentepercentage" -#: ../data/functions.xml.in.h:1027 +#: ../data/functions.xml.in.h:1040 msgid "Future Value" msgstr "Toekomstige waarde" -#: ../data/functions.xml.in.h:1028 +#: ../data/functions.xml.in.h:1041 msgid "r:fv" msgstr "" -#: ../data/functions.xml.in.h:1029 +#: ../data/functions.xml.in.h:1042 msgid "" "Computes the future value of an investment. This is based on periodic, " "constant payments and a constant interest rate. If type = 1 then " @@ -7353,15 +7423,15 @@ "type = 1 wordt er betaald aanhet het begin van de termijn, als type = 0 (of " "weggelaten)wordt er betaald aan het einde van elke termijn." -#: ../data/functions.xml.in.h:1030 +#: ../data/functions.xml.in.h:1043 msgid "Return on continuously compounded interest" msgstr "Opbrengst van continu samengestelde rente" -#: ../data/functions.xml.in.h:1031 +#: ../data/functions.xml.in.h:1044 msgid "r:continuous" msgstr "continu" -#: ../data/functions.xml.in.h:1032 +#: ../data/functions.xml.in.h:1045 msgid "" "Calculates the return on continuously compounded interest, given the " "principal, nominal rate and time in years." @@ -7369,19 +7439,19 @@ "Berekent de opbrengst bij een continu samengestelde rente, gegeven de " "hoofdsom, nominale rente en de tijd in jaren." -#: ../data/functions.xml.in.h:1033 +#: ../data/functions.xml.in.h:1046 msgid "Principal" msgstr "Hoofdsom" -#: ../data/functions.xml.in.h:1034 +#: ../data/functions.xml.in.h:1047 msgid "Compound" msgstr "Samengesteld" -#: ../data/functions.xml.in.h:1035 +#: ../data/functions.xml.in.h:1048 msgid "r:compound" msgstr "samenstellen" -#: ../data/functions.xml.in.h:1036 +#: ../data/functions.xml.in.h:1049 msgid "" "Returns the value of an investment, given the principal, nominal interest " "rate, compounding frequency and time." @@ -7389,19 +7459,19 @@ "Berekent de waarde van een investering, gegeven de hoofdsom, nominale rente, " "samenstellingsfrequentie en tijdsduur." -#: ../data/functions.xml.in.h:1037 +#: ../data/functions.xml.in.h:1050 msgid "Periods per year" msgstr "Termijnen per jaar" -#: ../data/functions.xml.in.h:1038 +#: ../data/functions.xml.in.h:1051 msgid "Payment of an annuity going towards interest (IPMT)" msgstr "Interestdeel van een termijn van een annuïteit (IPMT)" -#: ../data/functions.xml.in.h:1039 +#: ../data/functions.xml.in.h:1052 msgid "r:ipmt" msgstr "" -#: ../data/functions.xml.in.h:1040 +#: ../data/functions.xml.in.h:1053 msgid "" "Calculates the amount of a payment of an annuity going towards interest. " " Type defines the due date. 1 for payment at the beginning of a period " @@ -7412,17 +7482,17 @@ "aanhet het begin van de termijn en 0 (standaard) voor betaling aan het einde " "van de termijn." -#: ../data/functions.xml.in.h:1041 +#: ../data/functions.xml.in.h:1054 msgid "Interest rate for a fully invested security" msgstr "" "Interestpercentage voor een waardepapier waarvan de hoofdsom aan het einde " "vrijvalt" -#: ../data/functions.xml.in.h:1042 +#: ../data/functions.xml.in.h:1055 msgid "r:intrate" msgstr "renteperc" -#: ../data/functions.xml.in.h:1043 +#: ../data/functions.xml.in.h:1056 msgid "" "Returns the interest rate for a fully invested security. Basis is " "the type of day counting you want to use: 0: US 30/360 (default), 1: real " @@ -7433,46 +7503,46 @@ "(standaard), 1: werkelijke dagen, 2: werkelijke dagen/360, 3: werkelijke " "dagen/365 of 4: Europees 30/360." -#: ../data/functions.xml.in.h:1044 +#: ../data/functions.xml.in.h:1057 msgid "Investment" msgstr "Investering" -#: ../data/functions.xml.in.h:1045 +#: ../data/functions.xml.in.h:1058 msgid "Redemption" msgstr "Aflossing" -#: ../data/functions.xml.in.h:1046 +#: ../data/functions.xml.in.h:1059 msgid "Dollar Fraction" msgstr "Dollar fractie" -#: ../data/functions.xml.in.h:1047 +#: ../data/functions.xml.in.h:1060 msgid "r:dollarfr" msgstr "" -#: ../data/functions.xml.in.h:1048 +#: ../data/functions.xml.in.h:1061 msgid "" "Converts a decimal dollar price into a dollar price expressed as a fraction." msgstr "" "Converteert een prijs in decimale dollars naar een prijs in dollars " "uitgedrukt als een breuk." -#: ../data/functions.xml.in.h:1049 +#: ../data/functions.xml.in.h:1062 msgid "Decimal dollar" msgstr "Decimale dollar" -#: ../data/functions.xml.in.h:1050 +#: ../data/functions.xml.in.h:1063 msgid "Denominator of fraction" msgstr "Noemer van breuk" -#: ../data/functions.xml.in.h:1051 +#: ../data/functions.xml.in.h:1064 msgid "Dollar Decimal" msgstr "Dollar decimaal" -#: ../data/functions.xml.in.h:1052 +#: ../data/functions.xml.in.h:1065 msgid "r:dollarde" msgstr "" -#: ../data/functions.xml.in.h:1053 +#: ../data/functions.xml.in.h:1066 msgid "" "Converts a dollar price expressed as a fraction into a dollar price " "expressed as a decimal number." @@ -7480,19 +7550,19 @@ "Converteert een prijs in dollars uitgedrukt als een breuk naar een prijs " "uitgedrukt in een decimaal getal." -#: ../data/functions.xml.in.h:1054 +#: ../data/functions.xml.in.h:1067 msgid "Fractional dollar" msgstr "Dollar als breuk" -#: ../data/functions.xml.in.h:1055 +#: ../data/functions.xml.in.h:1068 msgid "Amount received at maturity for a security bond" msgstr "Ontvangen bedrag voor een waardepapier op vervaldatum" -#: ../data/functions.xml.in.h:1056 +#: ../data/functions.xml.in.h:1069 msgid "r:received" msgstr "ontvangen" -#: ../data/functions.xml.in.h:1057 +#: ../data/functions.xml.in.h:1070 msgid "" "Returns the amount received at the maturity date for an invested security." " Basis is the type of day counting you want to use: 0: US 30/360 " @@ -7505,15 +7575,15 @@ "dagen/360, 3: werkelijke dagen/365 of 4: Europees 30/360. De afwikkeling " "moet plaats vinden voor de afloopdatum." -#: ../data/functions.xml.in.h:1058 +#: ../data/functions.xml.in.h:1071 msgid "Discount rate for a security" msgstr "Discontopercentage voor een waardepapier" -#: ../data/functions.xml.in.h:1059 +#: ../data/functions.xml.in.h:1072 msgid "r:disc" msgstr "kort" -#: ../data/functions.xml.in.h:1060 +#: ../data/functions.xml.in.h:1073 msgid "" "Returns the discount rate for a security. Basis is the type of day " "counting you want to use: 0: US 30/360 (default), 1: real days, 2: real " @@ -7524,15 +7594,15 @@ "dagen, 2: werkelijke dagen/360, 3: werkelijke dagen/365 of 4: Europees " "30/360." -#: ../data/functions.xml.in.h:1061 +#: ../data/functions.xml.in.h:1074 msgid "Accrued interest of security paying at maturity" msgstr "Totale rente van waardepapier op vervaldatum" -#: ../data/functions.xml.in.h:1062 +#: ../data/functions.xml.in.h:1075 msgid "r:accrintm" msgstr "" -#: ../data/functions.xml.in.h:1063 +#: ../data/functions.xml.in.h:1076 msgid "" "Returns the accrued interest for a security which pays interest at maturity " "date. Basis is the type of day counting you want to use: 0: US " @@ -7544,27 +7614,27 @@ "gebruiken: 0: US 30/360 (standaard), 1: werkelijke dagen, 2: werkelijke " "dagen/360, 3: werkelijke dagen/365 of 4: Europees 30/360." -#: ../data/functions.xml.in.h:1064 +#: ../data/functions.xml.in.h:1077 msgid "Issue date" msgstr "Uitgiftedatum" -#: ../data/functions.xml.in.h:1065 +#: ../data/functions.xml.in.h:1078 msgid "Annual rate of security" msgstr "Jaarlijkse rente van waardepapier" -#: ../data/functions.xml.in.h:1066 +#: ../data/functions.xml.in.h:1079 msgid "Par value" msgstr "Nominale waarde" -#: ../data/functions.xml.in.h:1067 +#: ../data/functions.xml.in.h:1080 msgid "Accrued interest of security with periodic interest payments" msgstr "Totale rente van waardepapier met periodieke renteuitkeringen" -#: ../data/functions.xml.in.h:1068 +#: ../data/functions.xml.in.h:1081 msgid "r:accrint" msgstr "" -#: ../data/functions.xml.in.h:1069 +#: ../data/functions.xml.in.h:1082 msgid "" "Returns accrued interest for a security which pays periodic interest. " " Allowed frequencies are 1 - annual, 2 - semi-annual or 4 - quarterly. " @@ -7577,23 +7647,23 @@ "gebruiken: 0: US 30/360 (standaard), 1: werkelijke dagen, 2: werkelijke " "dagen/360, 3: werkelijke dagen/365 of 4: Europees 30/360." -#: ../data/functions.xml.in.h:1070 +#: ../data/functions.xml.in.h:1083 msgid "First interest" msgstr "Eerste rente" -#: ../data/functions.xml.in.h:1071 +#: ../data/functions.xml.in.h:1084 msgid "Frequency" msgstr "Frequentie" -#: ../data/functions.xml.in.h:1072 +#: ../data/functions.xml.in.h:1085 msgid "Number of coupons to be paid" msgstr "Aantal te betalen coupons" -#: ../data/functions.xml.in.h:1073 +#: ../data/functions.xml.in.h:1086 msgid "r:coupnum" msgstr "" -#: ../data/functions.xml.in.h:1074 +#: ../data/functions.xml.in.h:1087 msgid "" "Returns the number of coupons to be paid between the settlement and the " "maturity. Basis is the type of day counting you want to use: 0: US " @@ -7605,16 +7675,16 @@ "(standaard), 1: werkelijke dagen, 2: werkelijke dagen/360, 3: werkelijke " "dagen/365 of 4: Europees 30/360." -#: ../data/functions.xml.in.h:1075 +#: ../data/functions.xml.in.h:1088 #, fuzzy msgid "Price per $100 face value of a discounted security" msgstr "Prijs per €100 nominale waarde van een waardepapier" -#: ../data/functions.xml.in.h:1076 +#: ../data/functions.xml.in.h:1089 msgid "r:pricedisc" msgstr "prijskorting" -#: ../data/functions.xml.in.h:1077 +#: ../data/functions.xml.in.h:1090 #, fuzzy msgid "" "Calculates and returns the price per $100 face value of a discounted " @@ -7628,19 +7698,19 @@ "werkelijke dagen, 2: werkelijke dagen/360, 3: werkelijke dagen/365 of 4: " "Europees 30/360." -#: ../data/functions.xml.in.h:1078 +#: ../data/functions.xml.in.h:1091 msgid "Discount" msgstr "Korting" -#: ../data/functions.xml.in.h:1079 +#: ../data/functions.xml.in.h:1092 msgid "Price per $100 face value of a security" msgstr "Prijs per €100 nominale waarde van een waardepapier" -#: ../data/functions.xml.in.h:1080 +#: ../data/functions.xml.in.h:1093 msgid "r:pricemat" msgstr "prijsmat" -#: ../data/functions.xml.in.h:1081 +#: ../data/functions.xml.in.h:1094 msgid "" "Calculates and returns the price per $100 face value of a security. The " "security pays interest at maturity. Basis is the type of day " @@ -7653,31 +7723,31 @@ "werkelijke dagen, 2: werkelijke dagen/360, 3: werkelijke dagen/365 of 4: " "Europees 30/360." -#: ../data/functions.xml.in.h:1082 +#: ../data/functions.xml.in.h:1095 msgid "Annual yield" msgstr "Opbrengst per jaar" -#: ../data/functions.xml.in.h:1083 +#: ../data/functions.xml.in.h:1096 msgid "Level-Coupon Bond" msgstr "Obligatie met gelijkblijvende coupons" -#: ../data/functions.xml.in.h:1084 +#: ../data/functions.xml.in.h:1097 msgid "r:level_coupon" msgstr "gelijke_coupon" -#: ../data/functions.xml.in.h:1085 +#: ../data/functions.xml.in.h:1098 msgid "Calculates the value of a level-coupon bond." msgstr "Berekent de waarde van een obligatie met gelijkblijvende coupons." -#: ../data/functions.xml.in.h:1086 +#: ../data/functions.xml.in.h:1099 msgid "Coupon rate" msgstr "Couponrente" -#: ../data/functions.xml.in.h:1087 +#: ../data/functions.xml.in.h:1100 msgid "Coupons per year" msgstr "Aantal coupons per jaar" -#: ../data/functions.xml.in.h:1088 +#: ../data/functions.xml.in.h:1101 msgid "Market interest rate" msgstr "Marktrente" @@ -10993,10 +11063,6 @@ #~ msgstr "Gulden snede" #, fuzzy -#~ msgid "Belarusian Ruble" -#~ msgstr "Russische roebel" - -#, fuzzy #~ msgid "Mauritania" #~ msgstr "Vervaldatum" diff -Nru libqalculate-3.6.0/po-defs/sv.po libqalculate-3.7.0/po-defs/sv.po --- libqalculate-3.6.0/po-defs/sv.po 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/po-defs/sv.po 2020-01-21 22:54:40.000000000 +0000 @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: sv\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-25 10:27+0100\n" +"POT-Creation-Date: 2020-01-12 11:29+0100\n" "PO-Revision-Date: 2007-06-15 11:13+0100\n" "Last-Translator: Hanna Knutsson \n" "Language-Team: Swedish\n" @@ -615,133 +615,145 @@ msgstr "" #: ../data/currencies.xml.in.h:147 +msgid "Belarusian Ruble" +msgstr "Vitrysk rubel" + +#: ../data/currencies.xml.in.h:148 +msgid "ar:BYN" +msgstr "" + +#: ../data/currencies.xml.in.h:149 +msgid "Belarus" +msgstr "Vitryssland" + +#: ../data/currencies.xml.in.h:150 msgid "Belarusian Ruble p. (obsolete)" msgstr "Vitrysk rubel p. (obsolet)" -#: ../data/currencies.xml.in.h:148 +#: ../data/currencies.xml.in.h:151 msgid "ar:BYR" msgstr "" -#: ../data/currencies.xml.in.h:149 +#: ../data/currencies.xml.in.h:152 msgid "Belize Dollar" msgstr "Belizisk dollar" -#: ../data/currencies.xml.in.h:150 +#: ../data/currencies.xml.in.h:153 msgid "ar:BZD" msgstr "" -#: ../data/currencies.xml.in.h:151 +#: ../data/currencies.xml.in.h:154 msgid "Belize" msgstr "" -#: ../data/currencies.xml.in.h:152 +#: ../data/currencies.xml.in.h:155 msgid "West African CFA Franc" msgstr "Västafrikansk CFA franc" -#: ../data/currencies.xml.in.h:153 +#: ../data/currencies.xml.in.h:156 msgid "ar:XOF,a:CFA" msgstr "" -#: ../data/currencies.xml.in.h:154 +#: ../data/currencies.xml.in.h:157 msgid "" "Benin, Burkina Faso, Guinea-Bissau, Ivory Coast, Mali, Niger, Senegal, Togo" msgstr "" "Benin, Burkina Faso, Guinea-Bissau, Elfenbenskusten, Mali, Niger, Senegal, " "Togo" -#: ../data/currencies.xml.in.h:155 +#: ../data/currencies.xml.in.h:158 msgid "Bermudian Dollar" msgstr "Bermudisk dollar" -#: ../data/currencies.xml.in.h:156 +#: ../data/currencies.xml.in.h:159 msgid "ar:BMD" msgstr "" -#: ../data/currencies.xml.in.h:157 +#: ../data/currencies.xml.in.h:160 msgid "Bermuda" msgstr "" -#: ../data/currencies.xml.in.h:158 +#: ../data/currencies.xml.in.h:161 msgid "Bolivian Boliviano Bs" msgstr "Bolviansk boliviano Bs" -#: ../data/currencies.xml.in.h:159 +#: ../data/currencies.xml.in.h:162 msgid "ar:BOB" msgstr "" -#: ../data/currencies.xml.in.h:160 +#: ../data/currencies.xml.in.h:163 msgid "Bolivia" msgstr "" -#: ../data/currencies.xml.in.h:161 +#: ../data/currencies.xml.in.h:164 msgid "Bosnia and Herzegovina Convertible Mark" msgstr "Bosnisk och hercegovinsk konvertibil mark" -#: ../data/currencies.xml.in.h:162 +#: ../data/currencies.xml.in.h:165 msgid "ar:BAM" msgstr "" -#: ../data/currencies.xml.in.h:163 +#: ../data/currencies.xml.in.h:166 msgid "Bosnia and Herzegovina" msgstr "Bosnien och Hercegovina" -#: ../data/currencies.xml.in.h:164 +#: ../data/currencies.xml.in.h:167 msgid "Botswana Pula" msgstr "Botswansk pula" -#: ../data/currencies.xml.in.h:165 +#: ../data/currencies.xml.in.h:168 msgid "ar:BWP" msgstr "" -#: ../data/currencies.xml.in.h:166 +#: ../data/currencies.xml.in.h:169 msgid "Botswana" msgstr "" -#: ../data/currencies.xml.in.h:167 +#: ../data/currencies.xml.in.h:170 msgid "Brunei Dollar" msgstr "Bruneisk dollar" -#: ../data/currencies.xml.in.h:168 +#: ../data/currencies.xml.in.h:171 msgid "ar:BND" msgstr "" -#: ../data/currencies.xml.in.h:169 +#: ../data/currencies.xml.in.h:172 msgid "Brunei" msgstr "" -#: ../data/currencies.xml.in.h:170 +#: ../data/currencies.xml.in.h:173 msgid "Burundian Franc" msgstr "Burundisk franc" -#: ../data/currencies.xml.in.h:171 +#: ../data/currencies.xml.in.h:174 msgid "ar:BIF" msgstr "" -#: ../data/currencies.xml.in.h:172 +#: ../data/currencies.xml.in.h:175 msgid "Burundi" msgstr "" -#: ../data/currencies.xml.in.h:173 +#: ../data/currencies.xml.in.h:176 msgid "Cambodian Riel" msgstr "Kambodjansk riel" -#: ../data/currencies.xml.in.h:174 +#: ../data/currencies.xml.in.h:177 msgid "ar:KHR,aiu:៛" msgstr "" -#: ../data/currencies.xml.in.h:175 +#: ../data/currencies.xml.in.h:178 msgid "Cambodia" msgstr "Kambodja" -#: ../data/currencies.xml.in.h:176 +#: ../data/currencies.xml.in.h:179 msgid "Central African CFA Franc" msgstr "Centralafrikansk CFA franc" -#: ../data/currencies.xml.in.h:177 +#: ../data/currencies.xml.in.h:180 msgid "ar:XAF,a:FCFA" msgstr "" -#: ../data/currencies.xml.in.h:178 +#: ../data/currencies.xml.in.h:181 msgid "" "Cameroon, Central African Republic, Chad, Republic of the Congo, Equatorial " "Guinea, Gabon" @@ -749,1271 +761,1271 @@ "Kamerun, Centralafrikanska republiken, Tchad, Kongo-Brazzaville, " "Ekvatorialguinea, Gabon" -#: ../data/currencies.xml.in.h:179 +#: ../data/currencies.xml.in.h:182 msgid "Cape Verdean Escudo" msgstr "Kapverdisk escudo" -#: ../data/currencies.xml.in.h:180 +#: ../data/currencies.xml.in.h:183 msgid "ar:CVE" msgstr "" -#: ../data/currencies.xml.in.h:181 +#: ../data/currencies.xml.in.h:184 msgid "Cape Verde" msgstr "Kap Verde" -#: ../data/currencies.xml.in.h:182 +#: ../data/currencies.xml.in.h:185 msgid "Cayman Islands Dollar" msgstr "Caymansk dollar" -#: ../data/currencies.xml.in.h:183 +#: ../data/currencies.xml.in.h:186 msgid "ar:KYD" msgstr "" -#: ../data/currencies.xml.in.h:184 +#: ../data/currencies.xml.in.h:187 msgid "Cayman Islands" msgstr "Caymanöarna" -#: ../data/currencies.xml.in.h:185 +#: ../data/currencies.xml.in.h:188 msgid "Chilean Peso" msgstr "Chilensk pesos" -#: ../data/currencies.xml.in.h:186 +#: ../data/currencies.xml.in.h:189 msgid "ar:CLP" msgstr "" -#: ../data/currencies.xml.in.h:187 +#: ../data/currencies.xml.in.h:190 msgid "Chile" msgstr "" -#: ../data/currencies.xml.in.h:188 +#: ../data/currencies.xml.in.h:191 msgid "Colombian Peso" msgstr "Colombianska peso" -#: ../data/currencies.xml.in.h:189 +#: ../data/currencies.xml.in.h:192 msgid "ar:COP" msgstr "" -#: ../data/currencies.xml.in.h:190 +#: ../data/currencies.xml.in.h:193 msgid "Colombia" msgstr "" -#: ../data/currencies.xml.in.h:191 +#: ../data/currencies.xml.in.h:194 msgid "Comorian Franc" msgstr "Komorisk franc" -#: ../data/currencies.xml.in.h:192 +#: ../data/currencies.xml.in.h:195 msgid "ar:KMF" msgstr "" -#: ../data/currencies.xml.in.h:193 +#: ../data/currencies.xml.in.h:196 msgid "Comoros" msgstr "Komorerna" -#: ../data/currencies.xml.in.h:194 +#: ../data/currencies.xml.in.h:197 msgid "Democratic Republic of the Congo (Congolese Franc)" msgstr "Kongolesisk franc" -#: ../data/currencies.xml.in.h:195 +#: ../data/currencies.xml.in.h:198 msgid "ar:CDF" msgstr "" -#: ../data/currencies.xml.in.h:196 +#: ../data/currencies.xml.in.h:199 msgid "Democratic Republic of the Congo" msgstr "Kongo-Kinshasa" -#: ../data/currencies.xml.in.h:197 +#: ../data/currencies.xml.in.h:200 msgid "Costa Rican colón" msgstr "Costaricansk colón" -#: ../data/currencies.xml.in.h:198 +#: ../data/currencies.xml.in.h:201 msgid "ar:CRC" msgstr "" -#: ../data/currencies.xml.in.h:199 +#: ../data/currencies.xml.in.h:202 msgid "Costa Rica" msgstr "" -#: ../data/currencies.xml.in.h:200 +#: ../data/currencies.xml.in.h:203 msgid "Cuban Peso" msgstr "Kubansk peso" -#: ../data/currencies.xml.in.h:201 +#: ../data/currencies.xml.in.h:204 msgid "ar:CUP" msgstr "" -#: ../data/currencies.xml.in.h:202 +#: ../data/currencies.xml.in.h:205 msgid "Cuba" msgstr "Kuba" -#: ../data/currencies.xml.in.h:203 +#: ../data/currencies.xml.in.h:206 msgid "Djiboutian Franc" msgstr "Djiboutisk franc" -#: ../data/currencies.xml.in.h:204 +#: ../data/currencies.xml.in.h:207 msgid "ar:DJF" msgstr "" -#: ../data/currencies.xml.in.h:205 +#: ../data/currencies.xml.in.h:208 msgid "Djibouti" msgstr "" -#: ../data/currencies.xml.in.h:206 +#: ../data/currencies.xml.in.h:209 msgid "Dominican Peso" msgstr "Dominikansk peso" -#: ../data/currencies.xml.in.h:207 +#: ../data/currencies.xml.in.h:210 msgid "ar:DOP" msgstr "" -#: ../data/currencies.xml.in.h:208 +#: ../data/currencies.xml.in.h:211 msgid "Dominican Republic" msgstr "Dominikanska republiken" -#: ../data/currencies.xml.in.h:209 +#: ../data/currencies.xml.in.h:212 msgid "Egyptian Pound" msgstr "Egyptiskt pund" -#: ../data/currencies.xml.in.h:210 +#: ../data/currencies.xml.in.h:213 msgid "ar:EGP" msgstr "" -#: ../data/currencies.xml.in.h:211 +#: ../data/currencies.xml.in.h:214 msgid "Egypt" msgstr "Egypten" -#: ../data/currencies.xml.in.h:212 +#: ../data/currencies.xml.in.h:215 msgid "El Salvadoran Colon (obsolete)" msgstr "Salvadoransk colon (obsolet)" -#: ../data/currencies.xml.in.h:213 +#: ../data/currencies.xml.in.h:216 msgid "ar:SVC" msgstr "" -#: ../data/currencies.xml.in.h:214 +#: ../data/currencies.xml.in.h:217 msgid "Eritrean Nafka" msgstr "Eritreansk nafka" -#: ../data/currencies.xml.in.h:215 +#: ../data/currencies.xml.in.h:218 msgid "ar:ERN" msgstr "" -#: ../data/currencies.xml.in.h:216 +#: ../data/currencies.xml.in.h:219 msgid "Eritrea" msgstr "" -#: ../data/currencies.xml.in.h:217 +#: ../data/currencies.xml.in.h:220 msgid "Ethiopian Birr" msgstr "Etiopisk birr" -#: ../data/currencies.xml.in.h:218 +#: ../data/currencies.xml.in.h:221 msgid "ar:ETB" msgstr "" -#: ../data/currencies.xml.in.h:219 +#: ../data/currencies.xml.in.h:222 msgid "Ethiopia" msgstr "Etiopien" -#: ../data/currencies.xml.in.h:220 +#: ../data/currencies.xml.in.h:223 msgid "Falkland Islands Pound" msgstr "Falklandspund" -#: ../data/currencies.xml.in.h:221 +#: ../data/currencies.xml.in.h:224 msgid "ar:FKP" msgstr "" -#: ../data/currencies.xml.in.h:222 +#: ../data/currencies.xml.in.h:225 msgid "Falkland Islands" msgstr "Falklandsöarna" -#: ../data/currencies.xml.in.h:223 +#: ../data/currencies.xml.in.h:226 msgid "Fijian Dollar" msgstr "Fijidollar" -#: ../data/currencies.xml.in.h:224 +#: ../data/currencies.xml.in.h:227 msgid "ar:FJD" msgstr "" -#: ../data/currencies.xml.in.h:225 +#: ../data/currencies.xml.in.h:228 msgid "Fiji" msgstr "" -#: ../data/currencies.xml.in.h:226 +#: ../data/currencies.xml.in.h:229 msgid "CFP franc" msgstr "CFP-franc" -#: ../data/currencies.xml.in.h:227 +#: ../data/currencies.xml.in.h:230 msgid "ar:XPF" msgstr "" -#: ../data/currencies.xml.in.h:228 +#: ../data/currencies.xml.in.h:231 msgid "French Polynesia, New Caledonia, Wallis and Futuna" msgstr "Franska Polynesien, Nya Kaledonien, Wallis och Futuna" -#: ../data/currencies.xml.in.h:229 +#: ../data/currencies.xml.in.h:232 msgid "Gambian Dalasi" msgstr "Gambisk dalasi" -#: ../data/currencies.xml.in.h:230 +#: ../data/currencies.xml.in.h:233 msgid "ar:GMD" msgstr "" -#: ../data/currencies.xml.in.h:231 +#: ../data/currencies.xml.in.h:234 msgid "Gambia" msgstr "" -#: ../data/currencies.xml.in.h:232 +#: ../data/currencies.xml.in.h:235 msgid "Georgian Lari" msgstr "Georgisk lari" -#: ../data/currencies.xml.in.h:233 +#: ../data/currencies.xml.in.h:236 msgid "ar:GEL,au:₾" msgstr "" -#: ../data/currencies.xml.in.h:234 +#: ../data/currencies.xml.in.h:237 msgid "Georgia" msgstr "Georgien" -#: ../data/currencies.xml.in.h:235 +#: ../data/currencies.xml.in.h:238 msgid "Ghanaian Cedi" msgstr "Ghanesisk cedi" -#: ../data/currencies.xml.in.h:236 +#: ../data/currencies.xml.in.h:239 msgid "ar:GHS,au:₵" msgstr "" -#: ../data/currencies.xml.in.h:237 +#: ../data/currencies.xml.in.h:240 msgid "Ghana" msgstr "" -#: ../data/currencies.xml.in.h:238 +#: ../data/currencies.xml.in.h:241 msgid "Gibraltar Pound" msgstr "Gibraltarpund" -#: ../data/currencies.xml.in.h:239 +#: ../data/currencies.xml.in.h:242 msgid "ar:GIP" msgstr "" -#: ../data/currencies.xml.in.h:240 +#: ../data/currencies.xml.in.h:243 msgid "Gibraltar" msgstr "" -#: ../data/currencies.xml.in.h:241 +#: ../data/currencies.xml.in.h:244 msgid "Guatemalan Quetzal" msgstr "Guatemalansk quetzal" -#: ../data/currencies.xml.in.h:242 +#: ../data/currencies.xml.in.h:245 msgid "ar:GTQ" msgstr "" -#: ../data/currencies.xml.in.h:243 +#: ../data/currencies.xml.in.h:246 msgid "Guatemala" msgstr "" -#: ../data/currencies.xml.in.h:244 +#: ../data/currencies.xml.in.h:247 msgid "Guernsey Pound" msgstr "Guernseypund" -#: ../data/currencies.xml.in.h:245 +#: ../data/currencies.xml.in.h:248 msgid "ar:GGP" msgstr "" -#: ../data/currencies.xml.in.h:246 +#: ../data/currencies.xml.in.h:249 msgid "Guernsey" msgstr "" -#: ../data/currencies.xml.in.h:247 +#: ../data/currencies.xml.in.h:250 msgid "Guinean Franc" msgstr "Guinesisk franc" -#: ../data/currencies.xml.in.h:248 +#: ../data/currencies.xml.in.h:251 msgid "ar:GNF" msgstr "" -#: ../data/currencies.xml.in.h:249 +#: ../data/currencies.xml.in.h:252 msgid "Guinea" msgstr "" -#: ../data/currencies.xml.in.h:250 +#: ../data/currencies.xml.in.h:253 msgid "Guyanese Dollar" msgstr "Guyansk dollar" -#: ../data/currencies.xml.in.h:251 +#: ../data/currencies.xml.in.h:254 msgid "ar:GYD" msgstr "" -#: ../data/currencies.xml.in.h:252 +#: ../data/currencies.xml.in.h:255 msgid "Guyana" msgstr "" -#: ../data/currencies.xml.in.h:253 +#: ../data/currencies.xml.in.h:256 msgid "Haitian Gourde" msgstr "Haitisk gourde" -#: ../data/currencies.xml.in.h:254 +#: ../data/currencies.xml.in.h:257 msgid "ar:HTG" msgstr "" -#: ../data/currencies.xml.in.h:255 +#: ../data/currencies.xml.in.h:258 msgid "Haiti" msgstr "" -#: ../data/currencies.xml.in.h:256 +#: ../data/currencies.xml.in.h:259 msgid "Honduran Lempira" msgstr "Honduransk lempira" -#: ../data/currencies.xml.in.h:257 +#: ../data/currencies.xml.in.h:260 msgid "ar:HNL" msgstr "" -#: ../data/currencies.xml.in.h:258 +#: ../data/currencies.xml.in.h:261 msgid "Honduras" msgstr "" -#: ../data/currencies.xml.in.h:259 +#: ../data/currencies.xml.in.h:262 msgid "Iranian Rial" msgstr "Iransk rial" -#: ../data/currencies.xml.in.h:260 +#: ../data/currencies.xml.in.h:263 msgid "ar:IRR,aiu:﷼" msgstr "" -#: ../data/currencies.xml.in.h:261 +#: ../data/currencies.xml.in.h:264 msgid "Iran" msgstr "" -#: ../data/currencies.xml.in.h:262 +#: ../data/currencies.xml.in.h:265 msgid "Iraqi Dinar" msgstr "Irakisk dinar" -#: ../data/currencies.xml.in.h:263 +#: ../data/currencies.xml.in.h:266 msgid "ar:IQD" msgstr "" -#: ../data/currencies.xml.in.h:264 +#: ../data/currencies.xml.in.h:267 msgid "Iraq" msgstr "" -#: ../data/currencies.xml.in.h:265 +#: ../data/currencies.xml.in.h:268 msgid "Jamaican Dollar" msgstr "Jamaicansk dollar" -#: ../data/currencies.xml.in.h:266 +#: ../data/currencies.xml.in.h:269 msgid "ar:JMD" msgstr "" -#: ../data/currencies.xml.in.h:267 +#: ../data/currencies.xml.in.h:270 msgid "Jamaica" msgstr "" -#: ../data/currencies.xml.in.h:268 +#: ../data/currencies.xml.in.h:271 msgid "Jordanian Dinar" msgstr "Jordansk dinar" -#: ../data/currencies.xml.in.h:269 +#: ../data/currencies.xml.in.h:272 msgid "ar:JOD" msgstr "" -#: ../data/currencies.xml.in.h:270 +#: ../data/currencies.xml.in.h:273 msgid "Jordan" msgstr "Jordanien" -#: ../data/currencies.xml.in.h:271 +#: ../data/currencies.xml.in.h:274 msgid "Kazakhstani Tenge" msgstr "Kazakstansk tenge" -#: ../data/currencies.xml.in.h:272 +#: ../data/currencies.xml.in.h:275 msgid "ar:KZT,au:₸" msgstr "" -#: ../data/currencies.xml.in.h:273 +#: ../data/currencies.xml.in.h:276 msgid "Kazakhstan" msgstr "Kazakstan" -#: ../data/currencies.xml.in.h:274 +#: ../data/currencies.xml.in.h:277 msgid "North Korean Won" msgstr "Nordkoreansk won" -#: ../data/currencies.xml.in.h:275 +#: ../data/currencies.xml.in.h:278 msgid "ar:KPW" msgstr "" -#: ../data/currencies.xml.in.h:276 +#: ../data/currencies.xml.in.h:279 msgid "North Korea" msgstr "Nordkorea" -#: ../data/currencies.xml.in.h:277 +#: ../data/currencies.xml.in.h:280 msgid "Kuwaiti Dinar" msgstr "Kuwaitisk dinar" -#: ../data/currencies.xml.in.h:278 +#: ../data/currencies.xml.in.h:281 msgid "ar:KWD" msgstr "" -#: ../data/currencies.xml.in.h:279 +#: ../data/currencies.xml.in.h:282 msgid "Kuwait" msgstr "" -#: ../data/currencies.xml.in.h:280 +#: ../data/currencies.xml.in.h:283 msgid "Kyrgyzstani Som" msgstr "Kirgizistansk som" -#: ../data/currencies.xml.in.h:281 +#: ../data/currencies.xml.in.h:284 msgid "ar:KGS,au:с" msgstr "" -#: ../data/currencies.xml.in.h:282 +#: ../data/currencies.xml.in.h:285 msgid "Kyrgyzstan" msgstr "Kirgizistan" -#: ../data/currencies.xml.in.h:283 +#: ../data/currencies.xml.in.h:286 msgid "Lao Kip" msgstr "Laotisk kip" -#: ../data/currencies.xml.in.h:284 +#: ../data/currencies.xml.in.h:287 msgid "ar:LAK,au:₭" msgstr "" -#: ../data/currencies.xml.in.h:285 +#: ../data/currencies.xml.in.h:288 msgid "Laos" msgstr "" -#: ../data/currencies.xml.in.h:286 +#: ../data/currencies.xml.in.h:289 msgid "Lebanese Pound" msgstr "Libanesiskt pund" -#: ../data/currencies.xml.in.h:287 +#: ../data/currencies.xml.in.h:290 msgid "ar:LBP" msgstr "" -#: ../data/currencies.xml.in.h:288 +#: ../data/currencies.xml.in.h:291 msgid "Lebanon" msgstr "Libanon" -#: ../data/currencies.xml.in.h:289 +#: ../data/currencies.xml.in.h:292 msgid "Lesotho Loti" msgstr "Lesothisk loti" -#: ../data/currencies.xml.in.h:290 +#: ../data/currencies.xml.in.h:293 msgid "ar:LSL" msgstr "" -#: ../data/currencies.xml.in.h:291 +#: ../data/currencies.xml.in.h:294 msgid "Lesotho" msgstr "" -#: ../data/currencies.xml.in.h:292 +#: ../data/currencies.xml.in.h:295 msgid "Liberian Dollar" msgstr "Liberiansk dollar" -#: ../data/currencies.xml.in.h:293 +#: ../data/currencies.xml.in.h:296 msgid "ar:LRD" msgstr "" -#: ../data/currencies.xml.in.h:294 +#: ../data/currencies.xml.in.h:297 msgid "Liberia" msgstr "" -#: ../data/currencies.xml.in.h:295 +#: ../data/currencies.xml.in.h:298 msgid "Libyan Dinar" msgstr "Libysk dinar" -#: ../data/currencies.xml.in.h:296 +#: ../data/currencies.xml.in.h:299 msgid "ar:LYD" msgstr "" -#: ../data/currencies.xml.in.h:297 +#: ../data/currencies.xml.in.h:300 msgid "Libya" msgstr "Libyen" -#: ../data/currencies.xml.in.h:298 +#: ../data/currencies.xml.in.h:301 msgid "Macanese Pataca" msgstr "Macaosk pataca" -#: ../data/currencies.xml.in.h:299 +#: ../data/currencies.xml.in.h:302 msgid "ar:MOP" msgstr "" -#: ../data/currencies.xml.in.h:300 +#: ../data/currencies.xml.in.h:303 msgid "Macau" msgstr "Macao" -#: ../data/currencies.xml.in.h:301 +#: ../data/currencies.xml.in.h:304 msgid "Macedonian Denar" msgstr "Makedonisk denar" -#: ../data/currencies.xml.in.h:302 +#: ../data/currencies.xml.in.h:305 msgid "ar:MKD" msgstr "" -#: ../data/currencies.xml.in.h:303 +#: ../data/currencies.xml.in.h:306 msgid "Macedonia" msgstr "Makedonien" -#: ../data/currencies.xml.in.h:304 +#: ../data/currencies.xml.in.h:307 msgid "Malagasy Ariary" msgstr "Madagaskisk ariary" -#: ../data/currencies.xml.in.h:305 +#: ../data/currencies.xml.in.h:308 msgid "ar:MGA" msgstr "" -#: ../data/currencies.xml.in.h:306 +#: ../data/currencies.xml.in.h:309 msgid "Madagascar" msgstr "Madagaskar" -#: ../data/currencies.xml.in.h:307 +#: ../data/currencies.xml.in.h:310 msgid "Malawian Kwacha" msgstr "Malawisk kwacha" -#: ../data/currencies.xml.in.h:308 +#: ../data/currencies.xml.in.h:311 msgid "ar:MWK" msgstr "" -#: ../data/currencies.xml.in.h:309 +#: ../data/currencies.xml.in.h:312 msgid "Malawi" msgstr "" -#: ../data/currencies.xml.in.h:310 +#: ../data/currencies.xml.in.h:313 msgid "Maldivian Rufiyaa" msgstr "Maldivisk rufiyaa" -#: ../data/currencies.xml.in.h:311 +#: ../data/currencies.xml.in.h:314 msgid "ar:MVR" msgstr "" -#: ../data/currencies.xml.in.h:312 +#: ../data/currencies.xml.in.h:315 msgid "Maldives" msgstr "Maldiverna" -#: ../data/currencies.xml.in.h:313 +#: ../data/currencies.xml.in.h:316 msgid "Mauritanian Ouguiya (obsolete)" msgstr "Mauretansk ouguiya (obsolet)" -#: ../data/currencies.xml.in.h:314 +#: ../data/currencies.xml.in.h:317 msgid "ar:MRO" msgstr "" -#: ../data/currencies.xml.in.h:315 +#: ../data/currencies.xml.in.h:318 msgid "Mauritian Rupee" msgstr "Mauritisk rupie" -#: ../data/currencies.xml.in.h:316 +#: ../data/currencies.xml.in.h:319 msgid "ar:MUR" msgstr "" -#: ../data/currencies.xml.in.h:317 +#: ../data/currencies.xml.in.h:320 msgid "Mauritius" msgstr "" -#: ../data/currencies.xml.in.h:318 +#: ../data/currencies.xml.in.h:321 msgid "Moldovan Leu" msgstr "Moldavisk leu" -#: ../data/currencies.xml.in.h:319 +#: ../data/currencies.xml.in.h:322 msgid "ar:MDL" msgstr "" -#: ../data/currencies.xml.in.h:320 +#: ../data/currencies.xml.in.h:323 msgid "Moldova" msgstr "Moldavien" -#: ../data/currencies.xml.in.h:321 +#: ../data/currencies.xml.in.h:324 msgid "Mongolian Tögrög" msgstr "Mongolsk tögrög" -#: ../data/currencies.xml.in.h:322 +#: ../data/currencies.xml.in.h:325 msgid "ar:MNT,au:₮" msgstr "" -#: ../data/currencies.xml.in.h:323 +#: ../data/currencies.xml.in.h:326 msgid "Mongolia" msgstr "Mongoliet" -#: ../data/currencies.xml.in.h:324 +#: ../data/currencies.xml.in.h:327 msgid "Moroccan Dirham" msgstr "Marockansk dirham" -#: ../data/currencies.xml.in.h:325 +#: ../data/currencies.xml.in.h:328 msgid "ar:MAD" msgstr "" -#: ../data/currencies.xml.in.h:326 +#: ../data/currencies.xml.in.h:329 msgid "Morocco" msgstr "Marocko" -#: ../data/currencies.xml.in.h:327 +#: ../data/currencies.xml.in.h:330 msgid "Mozambican Metical" msgstr "Moçambikansk metical" -#: ../data/currencies.xml.in.h:328 +#: ../data/currencies.xml.in.h:331 msgid "ar:MZN" msgstr "" -#: ../data/currencies.xml.in.h:329 +#: ../data/currencies.xml.in.h:332 msgid "Mozambique" msgstr "Moçambique" -#: ../data/currencies.xml.in.h:330 +#: ../data/currencies.xml.in.h:333 msgid "Myanmar (Burmese Kyat)" msgstr "Myanmarisk kyat" -#: ../data/currencies.xml.in.h:331 +#: ../data/currencies.xml.in.h:334 msgid "ar:MMK" msgstr "" -#: ../data/currencies.xml.in.h:332 +#: ../data/currencies.xml.in.h:335 msgid "Myanmar" msgstr "" -#: ../data/currencies.xml.in.h:333 +#: ../data/currencies.xml.in.h:336 msgid "Namibian Dollar" msgstr "Namibisk dollar" -#: ../data/currencies.xml.in.h:334 +#: ../data/currencies.xml.in.h:337 msgid "ar:NAD" msgstr "" -#: ../data/currencies.xml.in.h:335 +#: ../data/currencies.xml.in.h:338 msgid "Namibia" msgstr "Namibien" -#: ../data/currencies.xml.in.h:336 +#: ../data/currencies.xml.in.h:339 msgid "Nepalese Rupee" msgstr "Nepalesisk rupie" -#: ../data/currencies.xml.in.h:337 +#: ../data/currencies.xml.in.h:340 msgid "ar:NPR" msgstr "" -#: ../data/currencies.xml.in.h:338 +#: ../data/currencies.xml.in.h:341 msgid "Nepal" msgstr "" -#: ../data/currencies.xml.in.h:339 +#: ../data/currencies.xml.in.h:342 msgid "Nicaraguan Córdoba" msgstr "Nicaragiska córdoba" -#: ../data/currencies.xml.in.h:340 +#: ../data/currencies.xml.in.h:343 msgid "ar:NIO" msgstr "" -#: ../data/currencies.xml.in.h:341 +#: ../data/currencies.xml.in.h:344 msgid "Nicaragua" msgstr "" -#: ../data/currencies.xml.in.h:342 +#: ../data/currencies.xml.in.h:345 msgid "Nigerian Naira" msgstr "Nigeriansk naira" -#: ../data/currencies.xml.in.h:343 +#: ../data/currencies.xml.in.h:346 msgid "ar:NGN,au:₦" msgstr "" -#: ../data/currencies.xml.in.h:344 +#: ../data/currencies.xml.in.h:347 msgid "Nigeria" msgstr "" -#: ../data/currencies.xml.in.h:345 +#: ../data/currencies.xml.in.h:348 msgid "Omani Rial" msgstr "Omansk rial" -#: ../data/currencies.xml.in.h:346 +#: ../data/currencies.xml.in.h:349 msgid "ar:OMR" msgstr "" -#: ../data/currencies.xml.in.h:347 +#: ../data/currencies.xml.in.h:350 msgid "Oman" msgstr "" -#: ../data/currencies.xml.in.h:348 +#: ../data/currencies.xml.in.h:351 msgid "Pakistani Rupee" msgstr "Pakistansk rupie" -#: ../data/currencies.xml.in.h:349 +#: ../data/currencies.xml.in.h:352 msgid "ar:PKR" msgstr "" -#: ../data/currencies.xml.in.h:350 +#: ../data/currencies.xml.in.h:353 msgid "Pakistan" msgstr "" -#: ../data/currencies.xml.in.h:351 +#: ../data/currencies.xml.in.h:354 msgid "Panamaian Balboa" msgstr "Panamansk balboa" -#: ../data/currencies.xml.in.h:352 +#: ../data/currencies.xml.in.h:355 msgid "ar:PAB" msgstr "" -#: ../data/currencies.xml.in.h:353 +#: ../data/currencies.xml.in.h:356 msgid "Panama" msgstr "" -#: ../data/currencies.xml.in.h:354 +#: ../data/currencies.xml.in.h:357 msgid "Papua New Guinean Kina" msgstr "Papua Nya Guineansk kina" -#: ../data/currencies.xml.in.h:355 +#: ../data/currencies.xml.in.h:358 msgid "ar:PGK" msgstr "" -#: ../data/currencies.xml.in.h:356 +#: ../data/currencies.xml.in.h:359 msgid "Papua New Guinea" msgstr "Papua Nya Guinea" -#: ../data/currencies.xml.in.h:357 +#: ../data/currencies.xml.in.h:360 msgid "Paraguayan Guaraní" msgstr "Paraguaysk guarani" -#: ../data/currencies.xml.in.h:358 +#: ../data/currencies.xml.in.h:361 msgid "ar:PYG,au:₲" msgstr "" -#: ../data/currencies.xml.in.h:359 +#: ../data/currencies.xml.in.h:362 msgid "Paraguay" msgstr "" -#: ../data/currencies.xml.in.h:360 +#: ../data/currencies.xml.in.h:363 msgid "Peruvian Sol" msgstr "Peruviansk sol" -#: ../data/currencies.xml.in.h:361 +#: ../data/currencies.xml.in.h:364 msgid "ar:PEN" msgstr "" -#: ../data/currencies.xml.in.h:362 +#: ../data/currencies.xml.in.h:365 msgid "Peru" msgstr "" -#: ../data/currencies.xml.in.h:363 +#: ../data/currencies.xml.in.h:366 msgid "Qatari Riyal" msgstr "Qatarisk rial" -#: ../data/currencies.xml.in.h:364 +#: ../data/currencies.xml.in.h:367 msgid "ar:QAR" msgstr "" -#: ../data/currencies.xml.in.h:365 +#: ../data/currencies.xml.in.h:368 msgid "Qatar" msgstr "" -#: ../data/currencies.xml.in.h:366 +#: ../data/currencies.xml.in.h:369 msgid "Rwandan Franc" msgstr "Rwandisk franc" -#: ../data/currencies.xml.in.h:367 +#: ../data/currencies.xml.in.h:370 msgid "ar:RWF" msgstr "" -#: ../data/currencies.xml.in.h:368 +#: ../data/currencies.xml.in.h:371 msgid "Rwanda" msgstr "" -#: ../data/currencies.xml.in.h:369 +#: ../data/currencies.xml.in.h:372 msgid "São Tomé and Príncipe Dobra" msgstr "São Tomé och Príncipe-dobra" -#: ../data/currencies.xml.in.h:370 +#: ../data/currencies.xml.in.h:373 msgid "ar:STD" msgstr "" -#: ../data/currencies.xml.in.h:371 +#: ../data/currencies.xml.in.h:374 msgid "Sao Tome and Principe" msgstr "São Tomé och Príncipe" -#: ../data/currencies.xml.in.h:372 +#: ../data/currencies.xml.in.h:375 msgid "Saudi Riyal" msgstr "Saudiarabisk rial" -#: ../data/currencies.xml.in.h:373 +#: ../data/currencies.xml.in.h:376 msgid "ar:SAR" msgstr "" -#: ../data/currencies.xml.in.h:374 +#: ../data/currencies.xml.in.h:377 msgid "Saudi Arabia" msgstr "Saudiarabien" -#: ../data/currencies.xml.in.h:375 +#: ../data/currencies.xml.in.h:378 msgid "Serbian Dinar" msgstr "Serbisk dinar" -#: ../data/currencies.xml.in.h:376 +#: ../data/currencies.xml.in.h:379 msgid "ar:RSD" msgstr "" -#: ../data/currencies.xml.in.h:377 +#: ../data/currencies.xml.in.h:380 msgid "Serbia" msgstr "Serbien" -#: ../data/currencies.xml.in.h:378 +#: ../data/currencies.xml.in.h:381 msgid "Seychellois Rupee" msgstr "Seychellisk rupie" -#: ../data/currencies.xml.in.h:379 +#: ../data/currencies.xml.in.h:382 msgid "ar:SCR" msgstr "" -#: ../data/currencies.xml.in.h:380 +#: ../data/currencies.xml.in.h:383 msgid "Seychelles" msgstr "Seychellerna" -#: ../data/currencies.xml.in.h:381 +#: ../data/currencies.xml.in.h:384 msgid "Sierra Leonean Leone" msgstr "Sierra Leonsk leone" -#: ../data/currencies.xml.in.h:382 +#: ../data/currencies.xml.in.h:385 msgid "ar:SLL" msgstr "" -#: ../data/currencies.xml.in.h:383 +#: ../data/currencies.xml.in.h:386 msgid "Sierra Leone" msgstr "" -#: ../data/currencies.xml.in.h:384 +#: ../data/currencies.xml.in.h:387 msgid "Solomon Islands Dollar" msgstr "Salomondollar" -#: ../data/currencies.xml.in.h:385 +#: ../data/currencies.xml.in.h:388 msgid "ar:SBD" msgstr "" -#: ../data/currencies.xml.in.h:386 +#: ../data/currencies.xml.in.h:389 msgid "Solomon Islands" msgstr "Salomonöarna" -#: ../data/currencies.xml.in.h:387 +#: ../data/currencies.xml.in.h:390 msgid "Somali Shilling" msgstr "Somalisk schilling" -#: ../data/currencies.xml.in.h:388 +#: ../data/currencies.xml.in.h:391 msgid "ar:SOS" msgstr "" -#: ../data/currencies.xml.in.h:389 +#: ../data/currencies.xml.in.h:392 msgid "Somalia" msgstr "" -#: ../data/currencies.xml.in.h:390 +#: ../data/currencies.xml.in.h:393 msgid "Sri Lankan Rupee" msgstr "Lankesisk rupee" -#: ../data/currencies.xml.in.h:391 +#: ../data/currencies.xml.in.h:394 msgid "ar:LKR,au:௹" msgstr "" -#: ../data/currencies.xml.in.h:392 +#: ../data/currencies.xml.in.h:395 msgid "Sri Lanka" msgstr "" -#: ../data/currencies.xml.in.h:393 +#: ../data/currencies.xml.in.h:396 msgid "Sudanese Pound" msgstr "Sudanesiskt pund" -#: ../data/currencies.xml.in.h:394 +#: ../data/currencies.xml.in.h:397 msgid "ar:SDG" msgstr "" -#: ../data/currencies.xml.in.h:395 +#: ../data/currencies.xml.in.h:398 msgid "Sudan" msgstr "" -#: ../data/currencies.xml.in.h:396 +#: ../data/currencies.xml.in.h:399 msgid "Surinamese Dollar" msgstr "Surinamesisk dollar" -#: ../data/currencies.xml.in.h:397 +#: ../data/currencies.xml.in.h:400 msgid "ar:SRD" msgstr "" -#: ../data/currencies.xml.in.h:398 +#: ../data/currencies.xml.in.h:401 msgid "Suriname" msgstr "Surinam" -#: ../data/currencies.xml.in.h:399 +#: ../data/currencies.xml.in.h:402 msgid "Swazi Lilangeni" msgstr "Swaziland-lilangeni" -#: ../data/currencies.xml.in.h:400 +#: ../data/currencies.xml.in.h:403 msgid "ar:SZL" msgstr "" -#: ../data/currencies.xml.in.h:401 +#: ../data/currencies.xml.in.h:404 msgid "Swaziland" msgstr "" -#: ../data/currencies.xml.in.h:402 +#: ../data/currencies.xml.in.h:405 msgid "Syrian Pound" msgstr "Syriskt pund" -#: ../data/currencies.xml.in.h:403 +#: ../data/currencies.xml.in.h:406 msgid "ar:SYP" msgstr "" -#: ../data/currencies.xml.in.h:404 +#: ../data/currencies.xml.in.h:407 msgid "Syria" msgstr "Syrien" -#: ../data/currencies.xml.in.h:405 +#: ../data/currencies.xml.in.h:408 msgid "New Taiwan Dollar" msgstr "Taiwanesisk dollar" -#: ../data/currencies.xml.in.h:406 +#: ../data/currencies.xml.in.h:409 msgid "ar:TWD" msgstr "" -#: ../data/currencies.xml.in.h:407 +#: ../data/currencies.xml.in.h:410 msgid "Taiwan" msgstr "" -#: ../data/currencies.xml.in.h:408 +#: ../data/currencies.xml.in.h:411 msgid "Tajikistani Somoni" msgstr "Tajikisk somoni" -#: ../data/currencies.xml.in.h:409 +#: ../data/currencies.xml.in.h:412 msgid "ar:TJS" msgstr "" -#: ../data/currencies.xml.in.h:410 +#: ../data/currencies.xml.in.h:413 msgid "Tajikistan" msgstr "" -#: ../data/currencies.xml.in.h:411 +#: ../data/currencies.xml.in.h:414 msgid "Tanzanian Shilling" msgstr "Tanzanisk shilling" -#: ../data/currencies.xml.in.h:412 +#: ../data/currencies.xml.in.h:415 msgid "ar:TZS" msgstr "" -#: ../data/currencies.xml.in.h:413 +#: ../data/currencies.xml.in.h:416 msgid "Tanzania" msgstr "" -#: ../data/currencies.xml.in.h:414 +#: ../data/currencies.xml.in.h:417 msgid "Tongan Paʻanga" msgstr "Tongansk paʻanga" -#: ../data/currencies.xml.in.h:415 +#: ../data/currencies.xml.in.h:418 msgid "ar:TOP" msgstr "" -#: ../data/currencies.xml.in.h:416 +#: ../data/currencies.xml.in.h:419 msgid "Tonga" msgstr "" -#: ../data/currencies.xml.in.h:417 +#: ../data/currencies.xml.in.h:420 msgid "Trinidad and Tobago dollar" msgstr "Trinidaddollar" -#: ../data/currencies.xml.in.h:418 +#: ../data/currencies.xml.in.h:421 msgid "ar:TTD" msgstr "" -#: ../data/currencies.xml.in.h:419 +#: ../data/currencies.xml.in.h:422 msgid "Trinidad and Tobago" msgstr "Trinidad och Tobago" -#: ../data/currencies.xml.in.h:420 +#: ../data/currencies.xml.in.h:423 msgid "Tunisian Dinar" msgstr "Tunisisk dinar" -#: ../data/currencies.xml.in.h:421 +#: ../data/currencies.xml.in.h:424 msgid "ar:TND" msgstr "" -#: ../data/currencies.xml.in.h:422 +#: ../data/currencies.xml.in.h:425 msgid "Tunisia" msgstr "Tunisien" -#: ../data/currencies.xml.in.h:423 +#: ../data/currencies.xml.in.h:426 msgid "Turkmenistan Manat" msgstr "Turkmenistansk manat" -#: ../data/currencies.xml.in.h:424 +#: ../data/currencies.xml.in.h:427 msgid "ar:TMT" msgstr "" -#: ../data/currencies.xml.in.h:425 +#: ../data/currencies.xml.in.h:428 msgid "Turkmenistan" msgstr "" -#: ../data/currencies.xml.in.h:426 +#: ../data/currencies.xml.in.h:429 msgid "Ugandan Shilling" msgstr "Ugandisk shilling" -#: ../data/currencies.xml.in.h:427 +#: ../data/currencies.xml.in.h:430 msgid "ar:UGX" msgstr "" -#: ../data/currencies.xml.in.h:428 +#: ../data/currencies.xml.in.h:431 msgid "Uganda" msgstr "" -#: ../data/currencies.xml.in.h:429 +#: ../data/currencies.xml.in.h:432 msgid "Ukrainian Hryvnia" msgstr "Ukrainsk hryvnia" -#: ../data/currencies.xml.in.h:430 +#: ../data/currencies.xml.in.h:433 msgid "ar:UAH,au:₴" msgstr "" -#: ../data/currencies.xml.in.h:431 +#: ../data/currencies.xml.in.h:434 msgid "Ukraine" msgstr "Ukraina" -#: ../data/currencies.xml.in.h:432 +#: ../data/currencies.xml.in.h:435 msgid "United Arab Emirates Dirham" msgstr "Emiratisk dirham" -#: ../data/currencies.xml.in.h:433 +#: ../data/currencies.xml.in.h:436 msgid "ar:AED" msgstr "" -#: ../data/currencies.xml.in.h:434 +#: ../data/currencies.xml.in.h:437 msgid "United Arab Emirates" msgstr "Förenade Arabemiraten" -#: ../data/currencies.xml.in.h:435 +#: ../data/currencies.xml.in.h:438 msgid "Uruguayan Peso" msgstr "Uruguayansk peso" -#: ../data/currencies.xml.in.h:436 +#: ../data/currencies.xml.in.h:439 msgid "ar:UYU" msgstr "" -#: ../data/currencies.xml.in.h:437 +#: ../data/currencies.xml.in.h:440 msgid "Uruguay" msgstr "" -#: ../data/currencies.xml.in.h:438 +#: ../data/currencies.xml.in.h:441 msgid "Uzbekistan Soʻm" msgstr "Uzbekistansk som" -#: ../data/currencies.xml.in.h:439 +#: ../data/currencies.xml.in.h:442 msgid "ar:UZS" msgstr "" -#: ../data/currencies.xml.in.h:440 +#: ../data/currencies.xml.in.h:443 msgid "Uzbekistan" msgstr "" -#: ../data/currencies.xml.in.h:441 +#: ../data/currencies.xml.in.h:444 msgid "Vanuatu Vatu" msgstr "Vanuatisk vatu" -#: ../data/currencies.xml.in.h:442 +#: ../data/currencies.xml.in.h:445 msgid "ar:VUV" msgstr "" -#: ../data/currencies.xml.in.h:443 +#: ../data/currencies.xml.in.h:446 msgid "Vanuatu" msgstr "" -#: ../data/currencies.xml.in.h:444 +#: ../data/currencies.xml.in.h:447 msgid "Venezuelan Bolívar (obsolete)" msgstr "Venezuelansk bolívar (obsolet)" -#: ../data/currencies.xml.in.h:445 +#: ../data/currencies.xml.in.h:448 msgid "ar:VEF" msgstr "" -#: ../data/currencies.xml.in.h:446 +#: ../data/currencies.xml.in.h:449 msgid "Vietnamese Dồng" msgstr "Vietnamesisk dồng" -#: ../data/currencies.xml.in.h:447 +#: ../data/currencies.xml.in.h:450 msgid "ar:VND,au:₫" msgstr "" -#: ../data/currencies.xml.in.h:448 +#: ../data/currencies.xml.in.h:451 msgid "Vietnam" msgstr "" -#: ../data/currencies.xml.in.h:449 +#: ../data/currencies.xml.in.h:452 msgid "Yemeni Rial" msgstr "Jemenitisk rial" -#: ../data/currencies.xml.in.h:450 +#: ../data/currencies.xml.in.h:453 msgid "ar:YER" msgstr "" -#: ../data/currencies.xml.in.h:451 +#: ../data/currencies.xml.in.h:454 msgid "Yemen" msgstr "Jemen" -#: ../data/currencies.xml.in.h:452 +#: ../data/currencies.xml.in.h:455 msgid "Zambian Kwacha (obsolete)" msgstr "Zambisk kwacha (obsolet)" -#: ../data/currencies.xml.in.h:453 +#: ../data/currencies.xml.in.h:456 msgid "ar:ZMK" msgstr "" -#: ../data/currencies.xml.in.h:454 +#: ../data/currencies.xml.in.h:457 msgid "Euro Cent" msgstr "Eurocent" -#: ../data/currencies.xml.in.h:455 +#: ../data/currencies.xml.in.h:458 msgid "r:eurocent,p:eurocents" msgstr "eurocent" -#: ../data/currencies.xml.in.h:456 +#: ../data/currencies.xml.in.h:459 msgid "Cent (USD)" msgstr "Cent (USD)" -#: ../data/currencies.xml.in.h:457 +#: ../data/currencies.xml.in.h:460 msgid "au:¢,r:cent,p:cents" msgstr "au:¢,cent" -#: ../data/currencies.xml.in.h:458 +#: ../data/currencies.xml.in.h:461 msgid "Belgian Franc (obsolete)" msgstr "Belgisk franc (obsolet)" -#: ../data/currencies.xml.in.h:459 +#: ../data/currencies.xml.in.h:462 msgid "ar:BEF" msgstr "" -#: ../data/currencies.xml.in.h:460 +#: ../data/currencies.xml.in.h:463 msgid "Greek Drachma (obsolete)" msgstr "Grekisk drachma (obsolet)" -#: ../data/currencies.xml.in.h:461 +#: ../data/currencies.xml.in.h:464 msgid "ar:GRD,au:₯" msgstr "" -#: ../data/currencies.xml.in.h:462 +#: ../data/currencies.xml.in.h:465 msgid "French Franc (obsolete)" msgstr "Fransk franc (obsolet=" -#: ../data/currencies.xml.in.h:463 +#: ../data/currencies.xml.in.h:466 msgid "ar:FRF,au:₣" msgstr "" -#: ../data/currencies.xml.in.h:464 +#: ../data/currencies.xml.in.h:467 msgid "Italian Lira (obsolete)" msgstr "Italiensk lira (obsolet)" -#: ../data/currencies.xml.in.h:465 +#: ../data/currencies.xml.in.h:468 msgid "ar:ITL" msgstr "" -#: ../data/currencies.xml.in.h:466 +#: ../data/currencies.xml.in.h:469 msgid "Dutch Guilder (obsolete)" msgstr "Nederländsk gulden (obsolet)" -#: ../data/currencies.xml.in.h:467 +#: ../data/currencies.xml.in.h:470 msgid "ar:NLG" msgstr "" -#: ../data/currencies.xml.in.h:468 +#: ../data/currencies.xml.in.h:471 msgid "Portuguese Escudo (obsolete)" msgstr "Portugisisk escudo (obsolet)" -#: ../data/currencies.xml.in.h:469 +#: ../data/currencies.xml.in.h:472 msgid "ar:PTE" msgstr "" -#: ../data/currencies.xml.in.h:470 +#: ../data/currencies.xml.in.h:473 msgid "Deutsche Mark (obsolete)" msgstr "Tysk mark (obsolet)" -#: ../data/currencies.xml.in.h:471 +#: ../data/currencies.xml.in.h:474 msgid "ar:DEM" msgstr "" -#: ../data/currencies.xml.in.h:472 +#: ../data/currencies.xml.in.h:475 msgid "Spanish Peseta (obsolete)" msgstr "Spansk peseta (obsolet)" -#: ../data/currencies.xml.in.h:473 +#: ../data/currencies.xml.in.h:476 msgid "ar:ESP,au:₧" msgstr "" -#: ../data/currencies.xml.in.h:474 +#: ../data/currencies.xml.in.h:477 msgid "Irish Pound (obsolete)" msgstr "Irländskt pund (obsolet)" -#: ../data/currencies.xml.in.h:475 +#: ../data/currencies.xml.in.h:478 msgid "ar:IEP" msgstr "" -#: ../data/currencies.xml.in.h:476 +#: ../data/currencies.xml.in.h:479 msgid "Luxembourg Franc (obsolete)" msgstr "Luxemburgfranc (obsolet)" -#: ../data/currencies.xml.in.h:477 +#: ../data/currencies.xml.in.h:480 msgid "ar:LUF" msgstr "" -#: ../data/currencies.xml.in.h:478 +#: ../data/currencies.xml.in.h:481 msgid "Austrian Schilling (obsolete)" msgstr "Österrikisk schilling (obsolet)" -#: ../data/currencies.xml.in.h:479 +#: ../data/currencies.xml.in.h:482 msgid "ar:ATS" msgstr "" -#: ../data/currencies.xml.in.h:480 +#: ../data/currencies.xml.in.h:483 msgid "Finnish Markka (obsolete)" msgstr "Finsk mark (obsolet)" -#: ../data/currencies.xml.in.h:481 +#: ../data/currencies.xml.in.h:484 msgid "ar:FIM" msgstr "" -#: ../data/currencies.xml.in.h:482 +#: ../data/currencies.xml.in.h:485 msgid "Slovenian Tolar (obsolete)" msgstr "Slovensk tolar (obsolet)" -#: ../data/currencies.xml.in.h:483 +#: ../data/currencies.xml.in.h:486 msgid "ar:SIT" msgstr "" -#: ../data/currencies.xml.in.h:484 +#: ../data/currencies.xml.in.h:487 msgid "Cypriot Pound (obsolete)" msgstr "Cypriotiskt pund (obsolet)" -#: ../data/currencies.xml.in.h:485 +#: ../data/currencies.xml.in.h:488 msgid "ar:CYP" msgstr "" -#: ../data/currencies.xml.in.h:486 +#: ../data/currencies.xml.in.h:489 msgid "Estonian Kroon (obsolete)" msgstr "Estonisk kroon (obsolet)" -#: ../data/currencies.xml.in.h:487 +#: ../data/currencies.xml.in.h:490 msgid "ar:EEK" msgstr "" -#: ../data/currencies.xml.in.h:488 +#: ../data/currencies.xml.in.h:491 msgid "Slovak Koruna (obsolete)" msgstr "Slovakisk koruna (obsolet)" -#: ../data/currencies.xml.in.h:489 +#: ../data/currencies.xml.in.h:492 msgid "ar:SKK" msgstr "" -#: ../data/currencies.xml.in.h:490 +#: ../data/currencies.xml.in.h:493 msgid "Maltese Lira (obsolete)" msgstr "Maltesisk lira (obsolet)" -#: ../data/currencies.xml.in.h:491 +#: ../data/currencies.xml.in.h:494 msgid "ar:MTL" msgstr "" -#: ../data/currencies.xml.in.h:492 +#: ../data/currencies.xml.in.h:495 msgid "Latvian Lats (obsolete)" msgstr "Lettiska lats (obsolet)" -#: ../data/currencies.xml.in.h:493 +#: ../data/currencies.xml.in.h:496 msgid "ar:LVL" msgstr "" -#: ../data/currencies.xml.in.h:494 +#: ../data/currencies.xml.in.h:497 msgid "Lithuanian Litas (obsolete)" msgstr "Litauisk litas (obsolet)" -#: ../data/currencies.xml.in.h:495 +#: ../data/currencies.xml.in.h:498 msgid "ar:LTL" msgstr "" @@ -2053,7 +2065,7 @@ msgid "!datasets!r:number" msgstr "nummer" -#: ../data/datasets.xml.in.h:13 ../data/functions.xml.in.h:709 +#: ../data/datasets.xml.in.h:13 ../data/functions.xml.in.h:716 msgid "Name" msgstr "Namn" @@ -2081,7 +2093,7 @@ msgid "r:class" msgstr "klass" -#: ../data/datasets.xml.in.h:18 ../data/functions.xml.in.h:424 +#: ../data/datasets.xml.in.h:18 ../data/functions.xml.in.h:431 msgid "Weight" msgstr "Vikt" @@ -3650,86 +3662,102 @@ msgstr "" #: ../data/functions.xml.in.h:216 -msgid "Fibonacci Number" -msgstr "Fibonaccital" +msgid "Bernoulli Number/Polynomial" +msgstr "Bernoullital/-polynom" #: ../data/functions.xml.in.h:217 -msgid "r:fibonacci" +msgid "" +"Returns the nth Bernoulli number or polynomial (if the second argument is " +"non-zero)." msgstr "" +"Returnerar det n:te Bernoullitalet eller Bernoullipolynomet (om den andra " +"parametern inte är noll)." #: ../data/functions.xml.in.h:218 -msgid "Returns the n-th term of the Fibonacci sequence." -msgstr "Returnerar tal n i Fibonaccis talföljd." +msgid "r:bernoulli" +msgstr "" #: ../data/functions.xml.in.h:219 msgid "Index (n)" msgstr "Index (n)" #: ../data/functions.xml.in.h:220 +msgid "Fibonacci Number" +msgstr "Fibonaccital" + +#: ../data/functions.xml.in.h:221 +msgid "r:fibonacci" +msgstr "" + +#: ../data/functions.xml.in.h:222 +msgid "Returns the n-th term of the Fibonacci sequence." +msgstr "Returnerar tal n i Fibonaccis talföljd." + +#: ../data/functions.xml.in.h:223 msgid "Rounding" msgstr "Avrundning" -#: ../data/functions.xml.in.h:221 +#: ../data/functions.xml.in.h:224 msgid "Round" msgstr "Avrunda" -#: ../data/functions.xml.in.h:222 +#: ../data/functions.xml.in.h:225 msgid "r:round" msgstr "avrunda" -#: ../data/functions.xml.in.h:223 +#: ../data/functions.xml.in.h:226 msgid "Round Downwards" msgstr "Avrunda neråt" -#: ../data/functions.xml.in.h:224 +#: ../data/functions.xml.in.h:227 msgid "r:floor" msgstr "golv" -#: ../data/functions.xml.in.h:225 +#: ../data/functions.xml.in.h:228 msgid "Round Upwards" msgstr "Avrunda uppåt" -#: ../data/functions.xml.in.h:226 +#: ../data/functions.xml.in.h:229 msgid "r:ceil" msgstr "tak" -#: ../data/functions.xml.in.h:227 +#: ../data/functions.xml.in.h:230 msgid "Round Towards Zero" msgstr "Avrunda mot noll" -#: ../data/functions.xml.in.h:228 +#: ../data/functions.xml.in.h:231 msgid "r:trunc" msgstr "" -#: ../data/functions.xml.in.h:229 +#: ../data/functions.xml.in.h:232 msgid "Integer Part" msgstr "Heltalsdel" -#: ../data/functions.xml.in.h:230 +#: ../data/functions.xml.in.h:233 msgid "r:int" msgstr "" -#: ../data/functions.xml.in.h:231 +#: ../data/functions.xml.in.h:234 msgid "Fractional Part" msgstr "Bråktalsdel" -#: ../data/functions.xml.in.h:232 +#: ../data/functions.xml.in.h:235 msgid "r:frac" msgstr "" -#: ../data/functions.xml.in.h:233 +#: ../data/functions.xml.in.h:236 msgid "Number Bases" msgstr "Talbaser" -#: ../data/functions.xml.in.h:234 +#: ../data/functions.xml.in.h:237 msgid "Number Base" msgstr "Talbas" -#: ../data/functions.xml.in.h:235 +#: ../data/functions.xml.in.h:238 msgid "r:base" msgstr "bas" -#: ../data/functions.xml.in.h:236 +#: ../data/functions.xml.in.h:239 msgid "" "Returns a value from an expression using the specified number base (radix). " "For bases between -62 and 62 full mathematical expressions (including " @@ -3769,19 +3797,19 @@ "uppsättningen siffror väljs manuellt, omvandlas alltid det angivna uttrycket " "till ett enda nummer." -#: ../data/functions.xml.in.h:237 +#: ../data/functions.xml.in.h:240 msgid "Set of digits" msgstr "Uppsättning siffror" -#: ../data/functions.xml.in.h:238 +#: ../data/functions.xml.in.h:241 msgid "Binary" msgstr "Binär" -#: ../data/functions.xml.in.h:239 +#: ../data/functions.xml.in.h:242 msgid "r:bin" msgstr "" -#: ../data/functions.xml.in.h:240 +#: ../data/functions.xml.in.h:243 msgid "" "Returns a value from a binary expression. If two's complement is true, " "numbers beginning with '1' is interpreted as negative binary numbers using " @@ -3791,55 +3819,55 @@ "kommer tal som börjar med '1' att tolkas som negativt binärt tal som " "använder tvåkomplementsform." -#: ../data/functions.xml.in.h:241 +#: ../data/functions.xml.in.h:244 msgid "Binary number" msgstr "Binärt nummer" -#: ../data/functions.xml.in.h:242 +#: ../data/functions.xml.in.h:245 msgid "Two's complement" msgstr "Tvåkomplementsform" -#: ../data/functions.xml.in.h:243 +#: ../data/functions.xml.in.h:246 msgid "Octal" msgstr "Oktal" -#: ../data/functions.xml.in.h:244 +#: ../data/functions.xml.in.h:247 msgid "r:oct" msgstr "okt" -#: ../data/functions.xml.in.h:245 +#: ../data/functions.xml.in.h:248 msgid "Returns a value from an octal expression." msgstr "Returnerar ett värde från ett oktalt uttryck." -#: ../data/functions.xml.in.h:246 +#: ../data/functions.xml.in.h:249 msgid "Octal number" msgstr "Oktalt nummer" -#: ../data/functions.xml.in.h:247 +#: ../data/functions.xml.in.h:250 msgid "Decimal" msgstr "Decimaltal" -#: ../data/functions.xml.in.h:248 +#: ../data/functions.xml.in.h:251 msgid "r:dec" msgstr "" -#: ../data/functions.xml.in.h:249 +#: ../data/functions.xml.in.h:252 msgid "Returns a value from a decimal expression." msgstr "Returnerar ett värde från ett decimalt uttryck." -#: ../data/functions.xml.in.h:250 +#: ../data/functions.xml.in.h:253 msgid "Decimal number" msgstr "Decimalt nummer" -#: ../data/functions.xml.in.h:251 +#: ../data/functions.xml.in.h:254 msgid "Hexadecimal" msgstr "Hexadecimal" -#: ../data/functions.xml.in.h:252 +#: ../data/functions.xml.in.h:255 msgid "r:hex" msgstr "" -#: ../data/functions.xml.in.h:253 +#: ../data/functions.xml.in.h:256 msgid "" "Returns a value from a hexadecimal expression. If two's complement is true, " "numbers beginning with 8 or higher is interpreted as negative hexadecimal " @@ -3849,19 +3877,19 @@ "sant, kommer tal som börjar med 8 eller högre att tolkas som ett negativt " "hexadecimalt tal som använder tvåkomplementsform." -#: ../data/functions.xml.in.h:254 +#: ../data/functions.xml.in.h:257 msgid "Hexadecimal number" msgstr "Hexadecimalt nummer" -#: ../data/functions.xml.in.h:255 +#: ../data/functions.xml.in.h:258 msgid "Bijective base-26" msgstr "Bijektiv bas 26" -#: ../data/functions.xml.in.h:256 +#: ../data/functions.xml.in.h:259 msgid "r:bijective" msgstr "bijektiv" -#: ../data/functions.xml.in.h:257 +#: ../data/functions.xml.in.h:260 msgid "" "Returns a value from an expression in bijective base-26. Conversion in the " "opposite direction is also supported." @@ -3869,175 +3897,191 @@ "Returnerar ett värde från ett uttryck i bijektiv talbas 26. Omvandling i " "motsatt riktning stöds också." -#: ../data/functions.xml.in.h:258 +#: ../data/functions.xml.in.h:261 msgid "Bijective base-26 number" msgstr "Tal i bijektiv bas 26" -#: ../data/functions.xml.in.h:259 +#: ../data/functions.xml.in.h:262 msgid "Integers" msgstr "Heltal" -#: ../data/functions.xml.in.h:260 +#: ../data/functions.xml.in.h:263 msgid "Even" msgstr "Jämnt" -#: ../data/functions.xml.in.h:261 +#: ../data/functions.xml.in.h:264 msgid "r:even" msgstr "jämn" -#: ../data/functions.xml.in.h:262 +#: ../data/functions.xml.in.h:265 msgid "Odd" msgstr "Ojämnt" -#: ../data/functions.xml.in.h:263 +#: ../data/functions.xml.in.h:266 msgid "r:odd" msgstr "udda" -#: ../data/functions.xml.in.h:264 +#: ../data/functions.xml.in.h:267 msgid "Special Functions" msgstr "Speciella funktioner" -#: ../data/functions.xml.in.h:265 +#: ../data/functions.xml.in.h:268 msgid "Gamma Function" msgstr "Gammafunktion" -#: ../data/functions.xml.in.h:266 +#: ../data/functions.xml.in.h:269 msgid "r:gamma" msgstr "" -#: ../data/functions.xml.in.h:267 +#: ../data/functions.xml.in.h:270 msgid "Digamma Function" msgstr "Digammafunktion" -#: ../data/functions.xml.in.h:268 +#: ../data/functions.xml.in.h:271 msgid "r:digamma,psi" msgstr "" -#: ../data/functions.xml.in.h:269 +#: ../data/functions.xml.in.h:272 msgid "Beta Function" msgstr "Betafunktion" -#: ../data/functions.xml.in.h:270 +#: ../data/functions.xml.in.h:273 msgid "r:beta" msgstr "" -#: ../data/functions.xml.in.h:271 +#: ../data/functions.xml.in.h:274 msgid "Error Function" msgstr "Felfunktion" -#: ../data/functions.xml.in.h:272 +#: ../data/functions.xml.in.h:275 msgid "r:erf" msgstr "" -#: ../data/functions.xml.in.h:273 +#: ../data/functions.xml.in.h:276 msgid "Complementary Error Function" msgstr "Komplementära felfunktionen" -#: ../data/functions.xml.in.h:274 +#: ../data/functions.xml.in.h:277 msgid "r:erfc" msgstr "" -#: ../data/functions.xml.in.h:275 +#: ../data/functions.xml.in.h:278 +msgid "Imaginary Error Function" +msgstr "Imaginära felfunktionen" + +#: ../data/functions.xml.in.h:279 +msgid "r:erfi" +msgstr "" + +#: ../data/functions.xml.in.h:280 msgid "Polylogarithm" msgstr "Polylogaritm" -#: ../data/functions.xml.in.h:276 +#: ../data/functions.xml.in.h:281 msgid "rc:Li,polylog" msgstr "" -#: ../data/functions.xml.in.h:277 +#: ../data/functions.xml.in.h:282 msgid "Order" msgstr "Ordning" -#: ../data/functions.xml.in.h:278 +#: ../data/functions.xml.in.h:283 msgid "Argument" -msgstr "" +msgstr "Parameter" -#: ../data/functions.xml.in.h:279 +#: ../data/functions.xml.in.h:284 msgid "Airy Function" msgstr "Airyfunktion" -#: ../data/functions.xml.in.h:280 +#: ../data/functions.xml.in.h:285 msgid "r:airy" msgstr "" -#: ../data/functions.xml.in.h:281 +#: ../data/functions.xml.in.h:286 msgid "Bessel Function of the First Kind" msgstr "Besselfunktion av det första slaget" -#: ../data/functions.xml.in.h:282 +#: ../data/functions.xml.in.h:287 msgid "r:besselj" msgstr "" -#: ../data/functions.xml.in.h:283 +#: ../data/functions.xml.in.h:288 msgid "Bessel Function of the Second Kind" msgstr "Besselfunktion av det andra slaget" -#: ../data/functions.xml.in.h:284 +#: ../data/functions.xml.in.h:289 msgid "r:bessely" msgstr "" -#: ../data/functions.xml.in.h:285 +#: ../data/functions.xml.in.h:290 msgid "Riemann Zeta" msgstr "Riemanns Zeta" -#: ../data/functions.xml.in.h:286 +#: ../data/functions.xml.in.h:291 +msgid "Calculates Hurwitz zeta function if the second argument is not 1." +msgstr "Beräknar Hurwizs zetafunction om den andra parametern inte är 1." + +#: ../data/functions.xml.in.h:292 msgid "r:zeta" msgstr "" -#: ../data/functions.xml.in.h:287 +#: ../data/functions.xml.in.h:293 msgid "Integral point" msgstr "Integralpunkt" -#: ../data/functions.xml.in.h:288 +#: ../data/functions.xml.in.h:294 +msgid "Hurwitz zeta argument" +msgstr "Hurwitz zeta-parameter" + +#: ../data/functions.xml.in.h:295 msgid "Kronecker Delta" msgstr "Kroneckerdelta" -#: ../data/functions.xml.in.h:289 +#: ../data/functions.xml.in.h:296 msgid "r:kronecker" msgstr "" -#: ../data/functions.xml.in.h:290 +#: ../data/functions.xml.in.h:297 msgid "Returns 0 if i != j and 1 if i = j." msgstr "Returnerar 0 om i != j och 1 if i = j." -#: ../data/functions.xml.in.h:291 +#: ../data/functions.xml.in.h:298 msgid "Value 1 (i)" msgstr "Värde 1 (i)" -#: ../data/functions.xml.in.h:292 +#: ../data/functions.xml.in.h:299 msgid "Value 2 (j)" msgstr "Värde 2 (j)" -#: ../data/functions.xml.in.h:293 +#: ../data/functions.xml.in.h:300 msgid "Logit Transformation" msgstr "Logit transformation" -#: ../data/functions.xml.in.h:294 +#: ../data/functions.xml.in.h:301 msgid "r:logit" msgstr "" -#: ../data/functions.xml.in.h:295 +#: ../data/functions.xml.in.h:302 msgid "Sigmoid Function" msgstr "Sigmoidfunktion" -#: ../data/functions.xml.in.h:296 +#: ../data/functions.xml.in.h:303 msgid "r:sigmoid" msgstr "" -#: ../data/functions.xml.in.h:297 +#: ../data/functions.xml.in.h:304 msgid "Step Functions" msgstr "Språngfunktioner" -#: ../data/functions.xml.in.h:298 +#: ../data/functions.xml.in.h:305 msgid "Heaviside Step Function" msgstr "Heavisides stegfunktion" -#: ../data/functions.xml.in.h:299 +#: ../data/functions.xml.in.h:306 msgid "r:heaviside,au:θ" msgstr "" -#: ../data/functions.xml.in.h:300 +#: ../data/functions.xml.in.h:307 msgid "" "Discontinuous function also known as \"unit step function\". Returns 0 if x " "< 0, 1 if x > 0, and 1/2 if x = 0." @@ -4045,95 +4089,95 @@ "Stegfunktion även kallad \"enhetsstegfunktion\". Returnerar 0 om x < 0, 1 " "om x > 0, och 1/2 om x = 0." -#: ../data/functions.xml.in.h:301 +#: ../data/functions.xml.in.h:308 msgid "Dirac Delta Function" msgstr "Diracs deltafunktion" -#: ../data/functions.xml.in.h:302 +#: ../data/functions.xml.in.h:309 msgid "r:dirac,au:δ" msgstr "" -#: ../data/functions.xml.in.h:303 +#: ../data/functions.xml.in.h:310 msgid "Returns 0 if x is non-zero, and infinity if x is zero." msgstr "Returnerar 0 om x inte är noĺl, och oändlighet om x är noll." -#: ../data/functions.xml.in.h:304 +#: ../data/functions.xml.in.h:311 msgid "Ramp Function" msgstr "Rampfunktion" -#: ../data/functions.xml.in.h:305 +#: ../data/functions.xml.in.h:312 msgid "r:ramp" msgstr "" -#: ../data/functions.xml.in.h:306 +#: ../data/functions.xml.in.h:313 msgid "Rectangular Function" msgstr "Rektangulär funktion" -#: ../data/functions.xml.in.h:307 +#: ../data/functions.xml.in.h:314 msgid "r:rectangular" msgstr "rektangulär" -#: ../data/functions.xml.in.h:308 +#: ../data/functions.xml.in.h:315 msgid "Triangular Function" msgstr "Triangulär funktion" -#: ../data/functions.xml.in.h:309 +#: ../data/functions.xml.in.h:316 msgid "r:triangular" msgstr "triangulär" -#: ../data/functions.xml.in.h:310 +#: ../data/functions.xml.in.h:317 msgid "Complex Numbers" msgstr "Komplexa tal" -#: ../data/functions.xml.in.h:311 +#: ../data/functions.xml.in.h:318 msgid "Real Part" msgstr "Reell del" -#: ../data/functions.xml.in.h:312 +#: ../data/functions.xml.in.h:319 msgid "r:re,au:ℜ" msgstr "" -#: ../data/functions.xml.in.h:313 +#: ../data/functions.xml.in.h:320 msgid "Complex number" msgstr "Komplext nummer" -#: ../data/functions.xml.in.h:314 +#: ../data/functions.xml.in.h:321 msgid "Imaginary Part" msgstr "Imaginär del" -#: ../data/functions.xml.in.h:315 +#: ../data/functions.xml.in.h:322 msgid "r:im,au:ℑ" msgstr "" -#: ../data/functions.xml.in.h:316 +#: ../data/functions.xml.in.h:323 msgid "Principal Argument" msgstr "Principialargument" -#: ../data/functions.xml.in.h:317 +#: ../data/functions.xml.in.h:324 msgid "r:arg" msgstr "" -#: ../data/functions.xml.in.h:318 +#: ../data/functions.xml.in.h:325 msgid "Complex Conjugate" msgstr "Komplexkonjugat" -#: ../data/functions.xml.in.h:319 +#: ../data/functions.xml.in.h:326 msgid "r:conj" msgstr "" -#: ../data/functions.xml.in.h:320 +#: ../data/functions.xml.in.h:327 msgid "Exponents & Logarithms" msgstr "Exponenter & Logaritmer" -#: ../data/functions.xml.in.h:321 +#: ../data/functions.xml.in.h:328 msgid "Square Root" msgstr "Kvadratrot" -#: ../data/functions.xml.in.h:322 +#: ../data/functions.xml.in.h:329 msgid "au:√,r:sqrt" msgstr "" -#: ../data/functions.xml.in.h:323 +#: ../data/functions.xml.in.h:330 msgid "" "Returns the principal square root (for positive values the positive root is " "returned)." @@ -4141,27 +4185,27 @@ "Returnerar principalkvadratroten (för positiva värden returneras den " "positiva roten)." -#: ../data/functions.xml.in.h:324 +#: ../data/functions.xml.in.h:331 msgid "Cube Root" msgstr "Kubikrot" -#: ../data/functions.xml.in.h:325 +#: ../data/functions.xml.in.h:332 msgid "au:∛,r:cbrt" msgstr "" -#: ../data/functions.xml.in.h:326 +#: ../data/functions.xml.in.h:333 msgid "Returns the third real root." msgstr "Returnerar den tredje reella roten." -#: ../data/functions.xml.in.h:327 +#: ../data/functions.xml.in.h:334 msgid "Nth root" msgstr "N:te roten" -#: ../data/functions.xml.in.h:328 +#: ../data/functions.xml.in.h:335 msgid "r:root" msgstr "rot" -#: ../data/functions.xml.in.h:329 +#: ../data/functions.xml.in.h:336 msgid "" "Returns the real root. For negative values the degree must be odd. Complex " "values are not allowed." @@ -4169,51 +4213,51 @@ "Returnerar den reella roten. För negativa värden krävs en udda grad. " "Komplexa värden är inte tillåtna." -#: ../data/functions.xml.in.h:330 ../data/units.xml.in.h:65 +#: ../data/functions.xml.in.h:337 ../data/units.xml.in.h:65 msgid "Degree" msgstr "Grad" -#: ../data/functions.xml.in.h:331 +#: ../data/functions.xml.in.h:338 msgid "Square" msgstr "Kvadrat" -#: ../data/functions.xml.in.h:332 +#: ../data/functions.xml.in.h:339 msgid "r:sq" msgstr "" -#: ../data/functions.xml.in.h:333 +#: ../data/functions.xml.in.h:340 msgid "Exponential (e^x)" msgstr "Exponentialfunktion (e^x)" -#: ../data/functions.xml.in.h:334 +#: ../data/functions.xml.in.h:341 msgid "r:exp" msgstr "" -#: ../data/functions.xml.in.h:335 +#: ../data/functions.xml.in.h:342 msgid "Natural Logarithm" msgstr "Naturlig logaritm" -#: ../data/functions.xml.in.h:336 +#: ../data/functions.xml.in.h:343 msgid "r:ln" msgstr "" -#: ../data/functions.xml.in.h:337 +#: ../data/functions.xml.in.h:344 msgid "Base-N Logarithm" msgstr "Bas-N-logaritm" -#: ../data/functions.xml.in.h:338 +#: ../data/functions.xml.in.h:345 msgid "r:log" msgstr "" -#: ../data/functions.xml.in.h:339 +#: ../data/functions.xml.in.h:346 msgid "Lambert W Function (Omega Function, Product Log)" msgstr "Lamberts W-funktion (Omegafunktionen)" -#: ../data/functions.xml.in.h:340 +#: ../data/functions.xml.in.h:347 msgid "r:lambertw,productlog" msgstr "" -#: ../data/functions.xml.in.h:341 +#: ../data/functions.xml.in.h:348 msgid "" "Returns the inverse function for mx*e^x as ln() does for e^x. Only the " "principal branch and real valued results are currently supported." @@ -4222,191 +4266,191 @@ "Enbart principalgrenen och värden som ger reeala result stöds för " "närvarande. " -#: ../data/functions.xml.in.h:342 +#: ../data/functions.xml.in.h:349 msgid "Branch" msgstr "Gren" -#: ../data/functions.xml.in.h:343 +#: ../data/functions.xml.in.h:350 msgid "Complex Exponential (Cis)" msgstr "Komplex exponentialfunction (Cis)" -#: ../data/functions.xml.in.h:344 +#: ../data/functions.xml.in.h:351 msgid "r:cis" msgstr "" -#: ../data/functions.xml.in.h:345 +#: ../data/functions.xml.in.h:352 msgid "Base-2 Logarithm" msgstr "Bas-2-logaritm" -#: ../data/functions.xml.in.h:346 +#: ../data/functions.xml.in.h:353 msgid "rs:log2" msgstr "" -#: ../data/functions.xml.in.h:347 +#: ../data/functions.xml.in.h:354 msgid "Returns the base n logarithm." msgstr "Returnerar logaritmen för bas n." -#: ../data/functions.xml.in.h:348 +#: ../data/functions.xml.in.h:355 msgid "Base-10 Logarithm" msgstr "Bas-10-logaritm" -#: ../data/functions.xml.in.h:349 +#: ../data/functions.xml.in.h:356 msgid "rs:log10" msgstr "" -#: ../data/functions.xml.in.h:350 +#: ../data/functions.xml.in.h:357 msgid "2 raised to the power X" msgstr "2 upphöjt med X" -#: ../data/functions.xml.in.h:351 +#: ../data/functions.xml.in.h:358 msgid "rs:exp2" msgstr "" -#: ../data/functions.xml.in.h:352 +#: ../data/functions.xml.in.h:359 msgid "10 raised to the power X" msgstr "10 upphöjt med X" -#: ../data/functions.xml.in.h:353 +#: ../data/functions.xml.in.h:360 msgid "rs:exp10" msgstr "" -#: ../data/functions.xml.in.h:354 +#: ../data/functions.xml.in.h:361 msgid "X raised to the power Y" msgstr "X upphöjt med Y" -#: ../data/functions.xml.in.h:355 +#: ../data/functions.xml.in.h:362 msgid "r:pow" msgstr "upphöj" -#: ../data/functions.xml.in.h:356 +#: ../data/functions.xml.in.h:363 msgid "Square root (x * pi)" msgstr "Kvadratrot (x * pi)" -#: ../data/functions.xml.in.h:357 +#: ../data/functions.xml.in.h:364 msgid "r:sqrtpi" msgstr "" -#: ../data/functions.xml.in.h:358 +#: ../data/functions.xml.in.h:365 msgid "Returns the non-negative square root of x * pi" msgstr "Returnerar icke-negativa kvadratroten av x * pi" -#: ../data/functions.xml.in.h:359 +#: ../data/functions.xml.in.h:366 msgid "Non-negative value" msgstr "Icke-negativt nummer" -#: ../data/functions.xml.in.h:360 +#: ../data/functions.xml.in.h:367 msgid "Trigonometry" msgstr "Trigonometri" -#: ../data/functions.xml.in.h:361 +#: ../data/functions.xml.in.h:368 msgid "Sine" msgstr "Sinus" -#: ../data/functions.xml.in.h:362 +#: ../data/functions.xml.in.h:369 msgid "r:sin" msgstr "" -#: ../data/functions.xml.in.h:363 +#: ../data/functions.xml.in.h:370 msgid "Angle" msgstr "Vinkel" -#: ../data/functions.xml.in.h:364 +#: ../data/functions.xml.in.h:371 msgid "Cosine" msgstr "Cosinus" -#: ../data/functions.xml.in.h:365 +#: ../data/functions.xml.in.h:372 msgid "r:cos" msgstr "" -#: ../data/functions.xml.in.h:366 +#: ../data/functions.xml.in.h:373 msgid "Tangent" msgstr "Tangens" -#: ../data/functions.xml.in.h:367 +#: ../data/functions.xml.in.h:374 msgid "r:tan" msgstr "" -#: ../data/functions.xml.in.h:368 +#: ../data/functions.xml.in.h:375 msgid "Inverse Sine" msgstr "Invers sinus" -#: ../data/functions.xml.in.h:369 +#: ../data/functions.xml.in.h:376 msgid "r:asin" msgstr "" -#: ../data/functions.xml.in.h:370 +#: ../data/functions.xml.in.h:377 msgid "Inverse Cosine" msgstr "Invers cosinus" -#: ../data/functions.xml.in.h:371 +#: ../data/functions.xml.in.h:378 msgid "r:acos" msgstr "" -#: ../data/functions.xml.in.h:372 +#: ../data/functions.xml.in.h:379 msgid "Inverse Tangent" msgstr "Invers tangens" -#: ../data/functions.xml.in.h:373 +#: ../data/functions.xml.in.h:380 msgid "r:atan" msgstr "" -#: ../data/functions.xml.in.h:374 +#: ../data/functions.xml.in.h:381 msgid "Hyperbolic Sine" msgstr "Sinus hyperbolicus" -#: ../data/functions.xml.in.h:375 +#: ../data/functions.xml.in.h:382 msgid "r:sinh" msgstr "" -#: ../data/functions.xml.in.h:376 +#: ../data/functions.xml.in.h:383 msgid "Hyperbolic Cosine" msgstr "Cosinus hyperbolicus" -#: ../data/functions.xml.in.h:377 +#: ../data/functions.xml.in.h:384 msgid "r:cosh" msgstr "" -#: ../data/functions.xml.in.h:378 +#: ../data/functions.xml.in.h:385 msgid "Hyperbolic Tangent" msgstr "Tangens hyperbolicus" -#: ../data/functions.xml.in.h:379 +#: ../data/functions.xml.in.h:386 msgid "r:tanh" msgstr "" -#: ../data/functions.xml.in.h:380 +#: ../data/functions.xml.in.h:387 msgid "Inverse Hyperbolic Sine" msgstr "Invers sinus hyperbolicus" -#: ../data/functions.xml.in.h:381 +#: ../data/functions.xml.in.h:388 msgid "r:asinh" msgstr "" -#: ../data/functions.xml.in.h:382 +#: ../data/functions.xml.in.h:389 msgid "Inverse Hyperbolic Cosine" msgstr "Invers cosinus hyperbolicus" -#: ../data/functions.xml.in.h:383 +#: ../data/functions.xml.in.h:390 msgid "r:acosh" msgstr "" -#: ../data/functions.xml.in.h:384 +#: ../data/functions.xml.in.h:391 msgid "Inverse Hyperbolic Tangent" msgstr "Invers tangens hyperbolicus" -#: ../data/functions.xml.in.h:385 +#: ../data/functions.xml.in.h:392 msgid "r:atanh" msgstr "" -#: ../data/functions.xml.in.h:386 +#: ../data/functions.xml.in.h:393 msgid "Four-quadrant Inverse Tangent" msgstr "Fyra kvadranters invers tangens" -#: ../data/functions.xml.in.h:387 +#: ../data/functions.xml.in.h:394 msgid "r:atan2" msgstr "" -#: ../data/functions.xml.in.h:388 +#: ../data/functions.xml.in.h:395 msgid "" "Computes the principal value of the argument function applied to the complex " "number x+iy." @@ -4414,143 +4458,143 @@ "Beräknar principalvärdet för argumentfunktionen applicerad på det komplex " "talet x+iy." -#: ../data/functions.xml.in.h:389 +#: ../data/functions.xml.in.h:396 msgid "Y" msgstr "" -#: ../data/functions.xml.in.h:390 +#: ../data/functions.xml.in.h:397 msgid "X" msgstr "X" -#: ../data/functions.xml.in.h:391 +#: ../data/functions.xml.in.h:398 msgid "Cardinal Sine (Sinc Function)" msgstr "Sinc-funktionen" -#: ../data/functions.xml.in.h:392 +#: ../data/functions.xml.in.h:399 msgid "r:sinc" msgstr "" -#: ../data/functions.xml.in.h:393 +#: ../data/functions.xml.in.h:400 msgid "Radians to Default Angle Unit" msgstr "Radians till färvald vinkelenhet" -#: ../data/functions.xml.in.h:394 +#: ../data/functions.xml.in.h:401 msgid "r:radtodef" msgstr "" -#: ../data/functions.xml.in.h:395 +#: ../data/functions.xml.in.h:402 msgid "Radians" msgstr "Radianer" -#: ../data/functions.xml.in.h:396 +#: ../data/functions.xml.in.h:403 msgid "Secant" msgstr "Sekant" -#: ../data/functions.xml.in.h:397 +#: ../data/functions.xml.in.h:404 msgid "r:sec" msgstr "" -#: ../data/functions.xml.in.h:398 +#: ../data/functions.xml.in.h:405 msgid "Cosecant" msgstr "Cosekant" -#: ../data/functions.xml.in.h:399 +#: ../data/functions.xml.in.h:406 msgid "r:csc" msgstr "" -#: ../data/functions.xml.in.h:400 +#: ../data/functions.xml.in.h:407 msgid "Cotangent" msgstr "Cotangens" -#: ../data/functions.xml.in.h:401 +#: ../data/functions.xml.in.h:408 msgid "r:cot" msgstr "" -#: ../data/functions.xml.in.h:402 +#: ../data/functions.xml.in.h:409 msgid "Hyperbolic Secant" msgstr "Sekant hyperbolicus" -#: ../data/functions.xml.in.h:403 +#: ../data/functions.xml.in.h:410 msgid "r:sech" msgstr "" -#: ../data/functions.xml.in.h:404 +#: ../data/functions.xml.in.h:411 msgid "Hyperbolic Cosecant" msgstr "Cosekant hyperbolicus" -#: ../data/functions.xml.in.h:405 +#: ../data/functions.xml.in.h:412 msgid "r:csch" msgstr "" -#: ../data/functions.xml.in.h:406 +#: ../data/functions.xml.in.h:413 msgid "Hyperbolic Cotangent" msgstr "Cotangens hyperbolicus" -#: ../data/functions.xml.in.h:407 +#: ../data/functions.xml.in.h:414 msgid "r:coth" msgstr "" -#: ../data/functions.xml.in.h:408 +#: ../data/functions.xml.in.h:415 msgid "Inverse Secant" msgstr "Invers sekant" -#: ../data/functions.xml.in.h:409 +#: ../data/functions.xml.in.h:416 msgid "r:asec" msgstr "" -#: ../data/functions.xml.in.h:410 +#: ../data/functions.xml.in.h:417 msgid "Inverse Cosecant" msgstr "Invers cosekant" -#: ../data/functions.xml.in.h:411 +#: ../data/functions.xml.in.h:418 msgid "r:acsc" msgstr "" -#: ../data/functions.xml.in.h:412 +#: ../data/functions.xml.in.h:419 msgid "Inverse Cotangent" msgstr "Invers cotangens" -#: ../data/functions.xml.in.h:413 +#: ../data/functions.xml.in.h:420 msgid "r:acot" msgstr "" -#: ../data/functions.xml.in.h:414 +#: ../data/functions.xml.in.h:421 msgid "Inverse Hyperbolic Secant" msgstr "Invers sekant hyperbolicus" -#: ../data/functions.xml.in.h:415 +#: ../data/functions.xml.in.h:422 msgid "r:asech" msgstr "" -#: ../data/functions.xml.in.h:416 +#: ../data/functions.xml.in.h:423 msgid "Inverse Hyperbolic Cosecant" msgstr "Invers cosekant hyperbolicus" -#: ../data/functions.xml.in.h:417 +#: ../data/functions.xml.in.h:424 msgid "r:acsch" msgstr "" -#: ../data/functions.xml.in.h:418 +#: ../data/functions.xml.in.h:425 msgid "Inverse Hyperbolic Cotangent" msgstr "Invers cotangens hyperbolicus" -#: ../data/functions.xml.in.h:419 +#: ../data/functions.xml.in.h:426 msgid "r:acoth" msgstr "" -#: ../data/functions.xml.in.h:420 +#: ../data/functions.xml.in.h:427 msgid "Miscellaneous" msgstr "Diverse" -#: ../data/functions.xml.in.h:421 +#: ../data/functions.xml.in.h:428 msgid "Body Mass Index (BMI)" msgstr "" -#: ../data/functions.xml.in.h:422 +#: ../data/functions.xml.in.h:429 msgid "-r:bmi" msgstr "" -#: ../data/functions.xml.in.h:423 +#: ../data/functions.xml.in.h:430 msgid "" "Calculates the Body Mass Index. The resulting BMI-value is sometimes " "interpreted as follows (although varies with age, sex, etc.): " @@ -4563,19 +4607,19 @@ "25-30 Fetma > 30 Notera att du måste använda enheter för " "vikt (ex. 59kg) och längd (ex. 174cm)." -#: ../data/functions.xml.in.h:425 +#: ../data/functions.xml.in.h:432 msgid "Length" msgstr "Längd" -#: ../data/functions.xml.in.h:426 +#: ../data/functions.xml.in.h:433 msgid "RAID Space" msgstr "RAID-utrymme" -#: ../data/functions.xml.in.h:427 +#: ../data/functions.xml.in.h:434 msgid "r:raid" msgstr "" -#: ../data/functions.xml.in.h:428 +#: ../data/functions.xml.in.h:435 msgid "" "Calculates RAID array disk capacity usable for data storage. If the " "combination of number of disks and RAID level is invalid, zero is returned. " @@ -4588,47 +4632,47 @@ "0, 1, 2, 3, 4, 5, 6, 1+0/10, 0+1, 5+0/50, 6+0/60 och 1+6. Stripes anges " "enbart för nästlade RAID-nivåer (1+0 undantagen)." -#: ../data/functions.xml.in.h:429 +#: ../data/functions.xml.in.h:436 msgid "RAID level" msgstr "RAID-nivå" -#: ../data/functions.xml.in.h:430 +#: ../data/functions.xml.in.h:437 msgid "Capacity of each disk" msgstr "Storlek på varje disk" -#: ../data/functions.xml.in.h:431 +#: ../data/functions.xml.in.h:438 msgid "Number of disks" msgstr "Antal diskar" -#: ../data/functions.xml.in.h:432 +#: ../data/functions.xml.in.h:439 msgid "Stripes" msgstr "" -#: ../data/functions.xml.in.h:433 +#: ../data/functions.xml.in.h:440 msgid "Roman Number" msgstr "Romerskt tal" -#: ../data/functions.xml.in.h:434 +#: ../data/functions.xml.in.h:441 msgid "r:roman" msgstr "" -#: ../data/functions.xml.in.h:435 +#: ../data/functions.xml.in.h:442 msgid "Returns the value of a roman number." msgstr "Returnerar värdet för romerska siffror." -#: ../data/functions.xml.in.h:436 +#: ../data/functions.xml.in.h:443 msgid "Roman number" msgstr "Romerskt tal" -#: ../data/functions.xml.in.h:437 +#: ../data/functions.xml.in.h:444 msgid "Depth of Field" msgstr "Skärpedjup" -#: ../data/functions.xml.in.h:438 +#: ../data/functions.xml.in.h:445 msgid "r:dof" msgstr "" -#: ../data/functions.xml.in.h:439 +#: ../data/functions.xml.in.h:446 msgid "" "Returns the estimated distance between the nearest and the farthest objects " "that are in acceptably sharp focus in a photo. Enter focal length (e.g. 50 " @@ -4648,195 +4692,195 @@ "\"4/3\" (Fourt Thirds System), or 5='1\"' (Nikon 1, Sony RX10, Sony RX100) - " "för en diameter baserad på d/1500." -#: ../data/functions.xml.in.h:440 +#: ../data/functions.xml.in.h:447 msgid "Focal Length" msgstr "Brännvidd" -#: ../data/functions.xml.in.h:441 +#: ../data/functions.xml.in.h:448 msgid "F-stop (aperture)" msgstr "F-stop (bländarvärde)" -#: ../data/functions.xml.in.h:442 +#: ../data/functions.xml.in.h:449 msgid "Distance" msgstr "Avstånd" -#: ../data/functions.xml.in.h:443 +#: ../data/functions.xml.in.h:450 msgid "Circle of confusion or sensor size" msgstr "Oskärpecirkel eller sensorstorlek" -#: ../data/functions.xml.in.h:444 +#: ../data/functions.xml.in.h:451 msgid "American Wire Gauge Cross-Section Area" msgstr "American Wire Gauge (tvärsnittsarea)" -#: ../data/functions.xml.in.h:445 +#: ../data/functions.xml.in.h:452 msgid "r:awg" msgstr "" -#: ../data/functions.xml.in.h:446 +#: ../data/functions.xml.in.h:453 msgid "" "For gauges larger than 0000 (4/0), please use negative values (00=-1, " "000=-2, 0000=-3, 00000=-4, etc). For conversion to AWG, use an equation (e." "g. awg(x) = 20 mm^2)." msgstr "" -#: ../data/functions.xml.in.h:447 +#: ../data/functions.xml.in.h:454 msgid "American Wire Gauge Diameter" msgstr "American Wire Gauge (diameter)" -#: ../data/functions.xml.in.h:448 +#: ../data/functions.xml.in.h:455 msgid "r:awgd" msgstr "" -#: ../data/functions.xml.in.h:449 +#: ../data/functions.xml.in.h:456 msgid "" "For gauges larger than 0000 (4/0), please use negative values (00=-1, " "000=-2, 0000=-3, 00000=-4, etc). For conversion to AWG, use an equation (e." "g. awgd(x) = 5 mm)." msgstr "" -#: ../data/functions.xml.in.h:450 +#: ../data/functions.xml.in.h:457 msgid "Statistics" msgstr "Statistik" -#: ../data/functions.xml.in.h:451 +#: ../data/functions.xml.in.h:458 msgid "Descriptive Statistics" msgstr "Beskrivande statistik" -#: ../data/functions.xml.in.h:452 +#: ../data/functions.xml.in.h:459 msgid "Sum (total)" msgstr "Summa (total)" -#: ../data/functions.xml.in.h:453 +#: ../data/functions.xml.in.h:460 msgid "r:total" msgstr "totalt" -#: ../data/functions.xml.in.h:454 +#: ../data/functions.xml.in.h:461 msgid "Data" msgstr "Data" -#: ../data/functions.xml.in.h:455 +#: ../data/functions.xml.in.h:462 msgid "Percentile" msgstr "Percentil" -#: ../data/functions.xml.in.h:456 +#: ../data/functions.xml.in.h:463 msgid "r:percentile" msgstr "percentil" -#: ../data/functions.xml.in.h:458 +#: ../data/functions.xml.in.h:465 #, no-c-format msgid "Percentile (%)" msgstr "Percentil (%)" -#: ../data/functions.xml.in.h:459 +#: ../data/functions.xml.in.h:466 msgid "Quantile algorithm (as in R)" msgstr "Kvantilalgoritm (som i R)" -#: ../data/functions.xml.in.h:460 +#: ../data/functions.xml.in.h:467 msgid "r:min" msgstr "" -#: ../data/functions.xml.in.h:461 +#: ../data/functions.xml.in.h:468 msgid "Returns the lowest value." msgstr "Returnerar det lägsta värdet." -#: ../data/functions.xml.in.h:462 +#: ../data/functions.xml.in.h:469 msgid "r:max" msgstr "" -#: ../data/functions.xml.in.h:463 +#: ../data/functions.xml.in.h:470 msgid "Returns the highest value." msgstr "Returnerar det högsta värdet." -#: ../data/functions.xml.in.h:464 +#: ../data/functions.xml.in.h:471 msgid "Mode" msgstr "Typvärde" -#: ../data/functions.xml.in.h:465 +#: ../data/functions.xml.in.h:472 msgid "r:mode" msgstr "typvärde" -#: ../data/functions.xml.in.h:466 +#: ../data/functions.xml.in.h:473 msgid "Returns the most frequently occurring value." msgstr "Returnerar det mest förekommande värdet." -#: ../data/functions.xml.in.h:467 +#: ../data/functions.xml.in.h:474 msgid "Range" msgstr "Omfång" -#: ../data/functions.xml.in.h:468 +#: ../data/functions.xml.in.h:475 msgid "r:range" msgstr "omfång" -#: ../data/functions.xml.in.h:469 +#: ../data/functions.xml.in.h:476 msgid "Calculates the difference between the min and max value." msgstr "Beräknar skillnaden mellan min och max värdet." -#: ../data/functions.xml.in.h:470 +#: ../data/functions.xml.in.h:477 msgid "Median" msgstr "Median" -#: ../data/functions.xml.in.h:471 +#: ../data/functions.xml.in.h:478 msgid "r:median" msgstr "" -#: ../data/functions.xml.in.h:472 +#: ../data/functions.xml.in.h:479 msgid "Quartile" msgstr "Kvartil" -#: ../data/functions.xml.in.h:473 +#: ../data/functions.xml.in.h:480 msgid "r:quartile" msgstr "kvartil" -#: ../data/functions.xml.in.h:474 +#: ../data/functions.xml.in.h:481 msgid "Quantile Algorithm (as in R)" msgstr "Kvantilalgoritm (som i R)" -#: ../data/functions.xml.in.h:475 +#: ../data/functions.xml.in.h:482 msgid "Decile" msgstr "Decil" -#: ../data/functions.xml.in.h:476 +#: ../data/functions.xml.in.h:483 msgid "r:decile" msgstr "decil" -#: ../data/functions.xml.in.h:477 +#: ../data/functions.xml.in.h:484 msgid "Interquartile Range" msgstr "Kvartilavstånd" -#: ../data/functions.xml.in.h:478 +#: ../data/functions.xml.in.h:485 msgid "r:iqr" msgstr "" -#: ../data/functions.xml.in.h:479 +#: ../data/functions.xml.in.h:486 msgid "Calculates the difference between the first and third quartile." msgstr "Beräknar skillnaden mellan den första och tredje kvartilen." -#: ../data/functions.xml.in.h:480 +#: ../data/functions.xml.in.h:487 msgid "Number of Samples" msgstr "Antal" #. Number of samples -#: ../data/functions.xml.in.h:482 +#: ../data/functions.xml.in.h:489 msgid "r:number" msgstr "antal" -#: ../data/functions.xml.in.h:483 +#: ../data/functions.xml.in.h:490 msgid "Returns the number of samples." msgstr "Returnerar antalet prov." -#: ../data/functions.xml.in.h:484 +#: ../data/functions.xml.in.h:491 msgid "Random Numbers" msgstr "Slumptal" -#: ../data/functions.xml.in.h:485 +#: ../data/functions.xml.in.h:492 msgid "Random Number" msgstr "Slumptal" -#: ../data/functions.xml.in.h:486 +#: ../data/functions.xml.in.h:493 msgid "r:rand" msgstr "slumptal" -#: ../data/functions.xml.in.h:487 +#: ../data/functions.xml.in.h:494 msgid "" "Generates a pseudo-random number. Returns a real number between 0 and 1, if " "ceil is zero (default), or an integer between 1 and (including) ceil." @@ -4845,435 +4889,435 @@ "och 1, om taket är noll (förval), eller ett heltal mellan 1 och (inklusive) " "taket." -#: ../data/functions.xml.in.h:488 +#: ../data/functions.xml.in.h:495 msgid "Ceil" msgstr "Tak" -#: ../data/functions.xml.in.h:489 +#: ../data/functions.xml.in.h:496 msgid "Number of values" msgstr "Antal värden" -#: ../data/functions.xml.in.h:490 +#: ../data/functions.xml.in.h:497 msgid "Normally Distributed Random Number" msgstr "Normalfördelat slumptal" -#: ../data/functions.xml.in.h:491 +#: ../data/functions.xml.in.h:498 msgid "r:randnorm" msgstr "" -#: ../data/functions.xml.in.h:492 +#: ../data/functions.xml.in.h:499 msgid "Mean" msgstr "Medelvärde" -#: ../data/functions.xml.in.h:493 +#: ../data/functions.xml.in.h:500 msgid "Standard deviation" msgstr "Standardavvikelse" -#: ../data/functions.xml.in.h:494 +#: ../data/functions.xml.in.h:501 msgid "Poisson Distributed Random Number" msgstr "Poissonfördelat slumptal" -#: ../data/functions.xml.in.h:495 +#: ../data/functions.xml.in.h:502 msgid "r:randpoisson" msgstr "" -#: ../data/functions.xml.in.h:496 +#: ../data/functions.xml.in.h:503 msgid "Uniformly Distributed Random Number" msgstr "Enhetligt fördelat slumptal" -#: ../data/functions.xml.in.h:497 +#: ../data/functions.xml.in.h:504 msgid "r:randuniform" msgstr "" -#: ../data/functions.xml.in.h:498 +#: ../data/functions.xml.in.h:505 msgid "Random Number Between Limits" msgstr "Slumptal mellan gränser" -#: ../data/functions.xml.in.h:499 +#: ../data/functions.xml.in.h:506 msgid "r:randbetween" msgstr "" -#: ../data/functions.xml.in.h:500 +#: ../data/functions.xml.in.h:507 msgid "Returns an integer between (including) bottom and top." msgstr "Returnerar ett heltal mellan (inklusive) nedre och övre gräns" -#: ../data/functions.xml.in.h:501 +#: ../data/functions.xml.in.h:508 msgid "Bottom" msgstr "Nedre gräns" -#: ../data/functions.xml.in.h:502 +#: ../data/functions.xml.in.h:509 msgid "Top" msgstr "Övre gräns" -#: ../data/functions.xml.in.h:503 +#: ../data/functions.xml.in.h:510 msgid "Exponential Random Number" msgstr "Eponentialslumptal" -#: ../data/functions.xml.in.h:504 +#: ../data/functions.xml.in.h:511 msgid "r:randexp" msgstr "" -#: ../data/functions.xml.in.h:505 +#: ../data/functions.xml.in.h:512 msgid "Rate parameter" msgstr "Parameter" -#: ../data/functions.xml.in.h:506 +#: ../data/functions.xml.in.h:513 msgid "Rayleigh Distributed Random Number" msgstr "Rayleighfördelat slumptal" -#: ../data/functions.xml.in.h:507 +#: ../data/functions.xml.in.h:514 msgid "r:randrayleigh" msgstr "" -#: ../data/functions.xml.in.h:508 +#: ../data/functions.xml.in.h:515 msgid "Sigma" msgstr "Sigma" -#: ../data/functions.xml.in.h:509 +#: ../data/functions.xml.in.h:516 msgid "Means" msgstr "Medelvärde" -#: ../data/functions.xml.in.h:510 +#: ../data/functions.xml.in.h:517 msgid "r:mean,average,au:x̄" msgstr "medel,genomsnitt,au:x̄" -#: ../data/functions.xml.in.h:511 +#: ../data/functions.xml.in.h:518 msgid "Harmonic Mean" msgstr "Harmoniskt medelvärde" -#: ../data/functions.xml.in.h:512 +#: ../data/functions.xml.in.h:519 msgid "r:harmmean" msgstr "harmmedel" -#: ../data/functions.xml.in.h:513 +#: ../data/functions.xml.in.h:520 msgid "Geometric Mean" msgstr "Geometriskt medelvärde" -#: ../data/functions.xml.in.h:514 +#: ../data/functions.xml.in.h:521 msgid "r:geomean" msgstr "geomedel" -#: ../data/functions.xml.in.h:515 +#: ../data/functions.xml.in.h:522 msgid "Trimmed Mean" msgstr "Trimmat medelvärde" -#: ../data/functions.xml.in.h:516 +#: ../data/functions.xml.in.h:523 msgid "r:trimmean" msgstr "" -#: ../data/functions.xml.in.h:517 +#: ../data/functions.xml.in.h:524 msgid "Trimmed percentage (at each end)" msgstr "Trimmad procent (i båda ändarna)" -#: ../data/functions.xml.in.h:518 +#: ../data/functions.xml.in.h:525 msgid "Winsorized Mean" msgstr "Winsor-medelvärde" -#: ../data/functions.xml.in.h:519 +#: ../data/functions.xml.in.h:526 msgid "r:winsormean" msgstr "" -#: ../data/functions.xml.in.h:520 +#: ../data/functions.xml.in.h:527 msgid "Winsorized percentage (at each end)" msgstr "Winsorprocent (i båda ändarna)" -#: ../data/functions.xml.in.h:521 +#: ../data/functions.xml.in.h:528 msgid "Weighted Mean" msgstr "Viktat medelvärde" -#: ../data/functions.xml.in.h:522 +#: ../data/functions.xml.in.h:529 msgid "r:weighmean" msgstr "" -#: ../data/functions.xml.in.h:523 +#: ../data/functions.xml.in.h:530 msgid "Weights" msgstr "Vikter" -#: ../data/functions.xml.in.h:524 +#: ../data/functions.xml.in.h:531 msgid "Quadratic Mean (RMS)" msgstr "Kvadratiskt medelvärde" -#: ../data/functions.xml.in.h:525 +#: ../data/functions.xml.in.h:532 msgid "r:rms" msgstr "" -#: ../data/functions.xml.in.h:526 +#: ../data/functions.xml.in.h:533 msgid "Moments" msgstr "Moment" -#: ../data/functions.xml.in.h:527 +#: ../data/functions.xml.in.h:534 msgid "Standard Deviation (entire population)" msgstr "Standardavvikelse (komplett population)" -#: ../data/functions.xml.in.h:528 +#: ../data/functions.xml.in.h:535 msgid "r:stdevp" msgstr "" -#: ../data/functions.xml.in.h:529 +#: ../data/functions.xml.in.h:536 msgid "Standard Deviation (random sampling)" msgstr "Standardavvikelse (slumpmässigt urval)" -#: ../data/functions.xml.in.h:530 +#: ../data/functions.xml.in.h:537 msgid "r:stdev" msgstr "standardavvikelse" -#: ../data/functions.xml.in.h:531 +#: ../data/functions.xml.in.h:538 msgid "Variance (entire population)" msgstr "Varians (komplett population)" -#: ../data/functions.xml.in.h:532 +#: ../data/functions.xml.in.h:539 msgid "r:varp" msgstr "" -#: ../data/functions.xml.in.h:533 +#: ../data/functions.xml.in.h:540 msgid "Variance (random sampling)" msgstr "Varians (slumpmässigt urval)" -#: ../data/functions.xml.in.h:534 +#: ../data/functions.xml.in.h:541 msgid "r:var" msgstr "" -#: ../data/functions.xml.in.h:535 +#: ../data/functions.xml.in.h:542 msgid "Standard Error" msgstr "Standardfel" -#: ../data/functions.xml.in.h:536 +#: ../data/functions.xml.in.h:543 msgid "r:stderr" msgstr "standardfel" -#: ../data/functions.xml.in.h:537 +#: ../data/functions.xml.in.h:544 msgid "Mean Deviation" msgstr "Medelavvikelse" -#: ../data/functions.xml.in.h:538 +#: ../data/functions.xml.in.h:545 msgid "r:meandev" msgstr "medelavvikelse" -#: ../data/functions.xml.in.h:539 +#: ../data/functions.xml.in.h:546 msgid "Covariance" msgstr "Kovarians" -#: ../data/functions.xml.in.h:540 +#: ../data/functions.xml.in.h:547 msgid "r:cov,r:covar" msgstr "" -#: ../data/functions.xml.in.h:541 +#: ../data/functions.xml.in.h:548 msgid "Data 1" msgstr "Data 1" -#: ../data/functions.xml.in.h:542 +#: ../data/functions.xml.in.h:549 msgid "Data 2" msgstr "Data 2" -#: ../data/functions.xml.in.h:543 +#: ../data/functions.xml.in.h:550 msgid "Pooled Variance" msgstr "Gemensam varians" -#: ../data/functions.xml.in.h:544 +#: ../data/functions.xml.in.h:551 msgid "r:poolvar" msgstr "" -#: ../data/functions.xml.in.h:545 +#: ../data/functions.xml.in.h:552 msgid "Regression" msgstr "Regression" -#: ../data/functions.xml.in.h:546 +#: ../data/functions.xml.in.h:553 msgid "Statistical Correlation" msgstr "Statistisk korrelation" -#: ../data/functions.xml.in.h:547 +#: ../data/functions.xml.in.h:554 msgid "r:cor" msgstr "" -#: ../data/functions.xml.in.h:548 +#: ../data/functions.xml.in.h:555 msgid "Pearson's Correlation Coefficient" msgstr "Pearsons korrelationskoefficient" -#: ../data/functions.xml.in.h:549 +#: ../data/functions.xml.in.h:556 msgid "r:pearson,r:correl" msgstr "korrelation" -#: ../data/functions.xml.in.h:550 +#: ../data/functions.xml.in.h:557 msgid "Spearman's Rho" msgstr "Spearmans Rho" -#: ../data/functions.xml.in.h:551 +#: ../data/functions.xml.in.h:558 msgid "r:spearman" msgstr "" -#: ../data/functions.xml.in.h:552 +#: ../data/functions.xml.in.h:559 msgid "Statistical Tests" msgstr "Statistika tester" -#: ../data/functions.xml.in.h:553 +#: ../data/functions.xml.in.h:560 msgid "Unpaired T-Test" msgstr "T-test" -#: ../data/functions.xml.in.h:554 +#: ../data/functions.xml.in.h:561 msgid "r:ttest" msgstr "" -#: ../data/functions.xml.in.h:555 +#: ../data/functions.xml.in.h:562 msgid "Paired T-Test" msgstr "Parvist t-test" -#: ../data/functions.xml.in.h:556 +#: ../data/functions.xml.in.h:563 msgid "r:pttest" msgstr "" -#: ../data/functions.xml.in.h:557 +#: ../data/functions.xml.in.h:564 msgid "Distribution" msgstr "Distribution" -#: ../data/functions.xml.in.h:558 +#: ../data/functions.xml.in.h:565 msgid "Binomial Distribution" msgstr "Binomialfördelning" -#: ../data/functions.xml.in.h:559 +#: ../data/functions.xml.in.h:566 msgid "r:binomdist" msgstr "" -#: ../data/functions.xml.in.h:560 +#: ../data/functions.xml.in.h:567 msgid "" "Returns the probability mass or cumulative distribution function of the " "binomial distribution." msgstr "" -#: ../data/functions.xml.in.h:561 +#: ../data/functions.xml.in.h:568 msgid "Number of successes" msgstr "Antal lyckade" -#: ../data/functions.xml.in.h:562 +#: ../data/functions.xml.in.h:569 msgid "Number of trials" msgstr "Antal försök" -#: ../data/functions.xml.in.h:563 +#: ../data/functions.xml.in.h:570 msgid "Probability" msgstr "Sannolikhet" -#: ../data/functions.xml.in.h:564 +#: ../data/functions.xml.in.h:571 msgid "Cumulative" msgstr "Kumulativ" -#: ../data/functions.xml.in.h:565 +#: ../data/functions.xml.in.h:572 msgid "Exponential Distribution" msgstr "Exponentialfördelning" -#: ../data/functions.xml.in.h:566 +#: ../data/functions.xml.in.h:573 msgid "r:expondist" msgstr "" -#: ../data/functions.xml.in.h:567 +#: ../data/functions.xml.in.h:574 msgid "" "Returns the probability density or cumulative distribution function of the " "exponential distribution." msgstr "" -#: ../data/functions.xml.in.h:568 +#: ../data/functions.xml.in.h:575 msgid "Logistic Distribution" msgstr "Logistisk fördelning" -#: ../data/functions.xml.in.h:569 +#: ../data/functions.xml.in.h:576 msgid "r:logistic" msgstr "" -#: ../data/functions.xml.in.h:570 +#: ../data/functions.xml.in.h:577 msgid "" "Returns the probability density p(x) at x for a logistic distribution with " "scale parameter. (from Gnumeric)" msgstr "" -#: ../data/functions.xml.in.h:571 +#: ../data/functions.xml.in.h:578 msgid "Scale" msgstr "Skalparameter" -#: ../data/functions.xml.in.h:572 +#: ../data/functions.xml.in.h:579 msgid "Normal Distribution" msgstr "Normalfördelning" -#: ../data/functions.xml.in.h:573 +#: ../data/functions.xml.in.h:580 msgid "r:normdist" msgstr "" -#: ../data/functions.xml.in.h:574 +#: ../data/functions.xml.in.h:581 msgid "" "Returns the probability density or cumulative distribution function of a " "normal distribution." msgstr "" -#: ../data/functions.xml.in.h:575 +#: ../data/functions.xml.in.h:582 msgid "Pareto Distribution" msgstr "Paretofördelning" -#: ../data/functions.xml.in.h:576 +#: ../data/functions.xml.in.h:583 msgid "r:pareto" msgstr "" -#: ../data/functions.xml.in.h:577 +#: ../data/functions.xml.in.h:584 msgid "" "Returns the probability density p(x) at x for a Pareto distribution with " "exponent and scale. (from Gnumeric)" msgstr "" -#: ../data/functions.xml.in.h:578 +#: ../data/functions.xml.in.h:585 msgid "Poisson Distribution" msgstr "Poissonfördelning" -#: ../data/functions.xml.in.h:579 +#: ../data/functions.xml.in.h:586 msgid "r:poisson" msgstr "" -#: ../data/functions.xml.in.h:580 +#: ../data/functions.xml.in.h:587 msgid "" "Returns the probability mass or cumulative distribution of the Poisson " "distribution." msgstr "" -#: ../data/functions.xml.in.h:581 +#: ../data/functions.xml.in.h:588 msgid "Number of events (x)" msgstr "Antal element (x)" -#: ../data/functions.xml.in.h:582 +#: ../data/functions.xml.in.h:589 msgid "Rayleigh Distribution" msgstr "Rayleighfördelning" -#: ../data/functions.xml.in.h:583 +#: ../data/functions.xml.in.h:590 msgid "r:rayleigh" msgstr "" -#: ../data/functions.xml.in.h:584 +#: ../data/functions.xml.in.h:591 msgid "" "Returns the probability density p(x) at x for a Rayleigh distribution with " "scale parameter sigma. (from Gnumeric)" msgstr "" -#: ../data/functions.xml.in.h:585 +#: ../data/functions.xml.in.h:592 msgid "Rayleigh Tail Distribution" msgstr "Rayleighsvansfördelning" -#: ../data/functions.xml.in.h:586 +#: ../data/functions.xml.in.h:593 msgid "r:rayleightail" msgstr "" -#: ../data/functions.xml.in.h:587 +#: ../data/functions.xml.in.h:594 msgid "" "Returns the probability density p(x) at x for a Rayleigh tail distribution " "with scale parameter sigma and a lower limit. (from Gnumeric)" msgstr "" -#: ../data/functions.xml.in.h:588 ../data/variables.xml.in.h:204 +#: ../data/functions.xml.in.h:595 ../data/variables.xml.in.h:204 msgid "Date & Time" msgstr "Datum & Tid" -#: ../data/functions.xml.in.h:589 +#: ../data/functions.xml.in.h:596 msgid "Construct Date" msgstr "Skapa datum" -#: ../data/functions.xml.in.h:590 +#: ../data/functions.xml.in.h:597 msgid "r:date" msgstr "datum" -#: ../data/functions.xml.in.h:591 +#: ../data/functions.xml.in.h:598 msgid "" "Returns a date. Available calendars gregorian (1), hebrew (2), islamic (3), " "persian (4), indian (5), chinese (6), julian (7), milankovic (8), coptic " @@ -5287,51 +5331,51 @@ "använder en epok som börjar 2697 f.Kr. och kinesiska skottmånader indikeras " "genom att addera 12 till månadens nummer (t.ex. skottmånad 4 = 16)." -#: ../data/functions.xml.in.h:592 +#: ../data/functions.xml.in.h:599 msgid "Year" msgstr "År" -#: ../data/functions.xml.in.h:593 ../data/units.xml.in.h:153 +#: ../data/functions.xml.in.h:600 ../data/units.xml.in.h:153 msgid "Month" msgstr "Månad" -#: ../data/functions.xml.in.h:594 ../data/units.xml.in.h:145 +#: ../data/functions.xml.in.h:601 ../data/units.xml.in.h:145 msgid "Day" msgstr "Dag" -#: ../data/functions.xml.in.h:595 +#: ../data/functions.xml.in.h:602 msgid "Calendar" msgstr "Kalender" -#: ../data/functions.xml.in.h:596 +#: ../data/functions.xml.in.h:603 msgid "Construct Date and Time" msgstr "Skapa datum och tid" -#: ../data/functions.xml.in.h:597 +#: ../data/functions.xml.in.h:604 msgid "r:datetime" msgstr "" -#: ../data/functions.xml.in.h:598 ../data/units.xml.in.h:143 +#: ../data/functions.xml.in.h:605 ../data/units.xml.in.h:143 msgid "Hour" msgstr "Timme" -#: ../data/functions.xml.in.h:599 ../data/units.xml.in.h:141 +#: ../data/functions.xml.in.h:606 ../data/units.xml.in.h:141 msgid "Minute" msgstr "Minut" -#: ../data/functions.xml.in.h:600 ../data/units.xml.in.h:139 +#: ../data/functions.xml.in.h:607 ../data/units.xml.in.h:139 msgid "Second" msgstr "Sekund" -#: ../data/functions.xml.in.h:601 +#: ../data/functions.xml.in.h:608 msgid "Days between two dates" msgstr "Antal dagar mellan två datum" -#: ../data/functions.xml.in.h:602 +#: ../data/functions.xml.in.h:609 msgid "r:days" msgstr "dagar" -#: ../data/functions.xml.in.h:603 +#: ../data/functions.xml.in.h:610 msgid "" "Returns the number of days between two dates. Basis is the type of " "day counting you want to use: 0: US 30/360, 1: real days (default), 2: real " @@ -5341,31 +5385,31 @@ "vara: 0: Amerikanskt 30/360 (förvald), 1: verkliga dagar, 2: verkliga " "dagar/360, 3: verkliga dagar/365, eller 4: Europeiskt 30/360" -#: ../data/functions.xml.in.h:604 +#: ../data/functions.xml.in.h:611 msgid "First date" msgstr "Första datumet" -#: ../data/functions.xml.in.h:605 +#: ../data/functions.xml.in.h:612 msgid "Second date" msgstr "Andra datumet" -#: ../data/functions.xml.in.h:606 +#: ../data/functions.xml.in.h:613 msgid "Day counting basis" msgstr "Dagsräkningssystem" -#: ../data/functions.xml.in.h:607 +#: ../data/functions.xml.in.h:614 msgid "Financial function mode" msgstr "Läge för financiella funktioner" -#: ../data/functions.xml.in.h:608 +#: ../data/functions.xml.in.h:615 msgid "Years between two dates" msgstr "Antal år mellan två datum" -#: ../data/functions.xml.in.h:609 +#: ../data/functions.xml.in.h:616 msgid "r:yearfrac" msgstr "" -#: ../data/functions.xml.in.h:610 +#: ../data/functions.xml.in.h:617 msgid "" "Returns the number of years (fractional) between two dates. Basis " "is the type of day counting you want to use: 0: US 30/360, 1: real days " @@ -5376,91 +5420,91 @@ "(förvald), 2: verkliga dagar/360, 3: verkliga dagar/365, eller 4: Europeiskt " "30/360" -#: ../data/functions.xml.in.h:611 +#: ../data/functions.xml.in.h:618 msgid "Week of Year" msgstr "Vecka på året" -#: ../data/functions.xml.in.h:612 +#: ../data/functions.xml.in.h:619 msgid "r:week" msgstr "vecka" -#: ../data/functions.xml.in.h:613 +#: ../data/functions.xml.in.h:620 msgid "Date" msgstr "Datum" -#: ../data/functions.xml.in.h:614 +#: ../data/functions.xml.in.h:621 msgid "Week begins on Sunday" msgstr "Veckor börjar på söndag" -#: ../data/functions.xml.in.h:615 +#: ../data/functions.xml.in.h:622 msgid "Day of Week" msgstr "Veckodag" -#: ../data/functions.xml.in.h:616 +#: ../data/functions.xml.in.h:623 msgid "r:weekday" msgstr "veckodag" -#: ../data/functions.xml.in.h:617 +#: ../data/functions.xml.in.h:624 msgid "r:month" msgstr "månad" -#: ../data/functions.xml.in.h:618 +#: ../data/functions.xml.in.h:625 msgid "Day of Month" msgstr "Månadsdag" -#: ../data/functions.xml.in.h:619 +#: ../data/functions.xml.in.h:626 msgid "r:day" msgstr "dag" -#: ../data/functions.xml.in.h:620 +#: ../data/functions.xml.in.h:627 msgid "r:year" msgstr "år" -#: ../data/functions.xml.in.h:621 +#: ../data/functions.xml.in.h:628 msgid "Day of Year" msgstr "Dag på året" -#: ../data/functions.xml.in.h:622 +#: ../data/functions.xml.in.h:629 msgid "r:yearday" msgstr "årsdag" -#: ../data/functions.xml.in.h:623 +#: ../data/functions.xml.in.h:630 msgid "Current Time" msgstr "Nuvarande tid" -#: ../data/functions.xml.in.h:624 +#: ../data/functions.xml.in.h:631 msgid "r:time" msgstr "tid" -#: ../data/functions.xml.in.h:625 +#: ../data/functions.xml.in.h:632 msgid "Time Value" msgstr "Tidsvärde" -#: ../data/functions.xml.in.h:626 +#: ../data/functions.xml.in.h:633 msgid "r:timevalue" msgstr "tidsvärde" -#: ../data/functions.xml.in.h:627 +#: ../data/functions.xml.in.h:634 msgid "Returns the time part, in fractional hours, of a date and time value." msgstr "Returnerar tidsdelen, i timmar, för ett datum och tid-värde." -#: ../data/functions.xml.in.h:628 +#: ../data/functions.xml.in.h:635 msgid "Date to Unix Timestamp" msgstr "Datum till Unixtid" -#: ../data/functions.xml.in.h:629 +#: ../data/functions.xml.in.h:636 msgid "r:timestamp" msgstr "" -#: ../data/functions.xml.in.h:630 +#: ../data/functions.xml.in.h:637 msgid "Unix Timestamp to Date" msgstr "Unixtid till datum" -#: ../data/functions.xml.in.h:631 +#: ../data/functions.xml.in.h:638 msgid "r:stamptodate,unix2date" msgstr "" -#: ../data/functions.xml.in.h:632 +#: ../data/functions.xml.in.h:639 msgid "" "Returns the local date and time represented by the specified Unix timestamp " "(seconds, excluding leap seconds, since 1970-01-01). Supports time units." @@ -5469,55 +5513,55 @@ "Unixtiden (sekunderar, exklusive skottsekunders, sedan 1970-01-01). " "Tidsenheter stöds." -#: ../data/functions.xml.in.h:633 +#: ../data/functions.xml.in.h:640 msgid "Timestamp" msgstr "Unixtid" -#: ../data/functions.xml.in.h:634 +#: ../data/functions.xml.in.h:641 msgid "Add Days" msgstr "Addera dagar" -#: ../data/functions.xml.in.h:635 +#: ../data/functions.xml.in.h:642 msgid "r:addDays" msgstr "adderaDagar" -#: ../data/functions.xml.in.h:636 +#: ../data/functions.xml.in.h:643 msgid "Days" msgstr "Dagar" -#: ../data/functions.xml.in.h:637 +#: ../data/functions.xml.in.h:644 msgid "Add Months" msgstr "Addera månader" -#: ../data/functions.xml.in.h:638 +#: ../data/functions.xml.in.h:645 msgid "r:addMonths" msgstr "adderaMånader" -#: ../data/functions.xml.in.h:639 +#: ../data/functions.xml.in.h:646 msgid "Months" msgstr "Månader" -#: ../data/functions.xml.in.h:640 +#: ../data/functions.xml.in.h:647 msgid "Add Years" msgstr "Addera år" -#: ../data/functions.xml.in.h:641 +#: ../data/functions.xml.in.h:648 msgid "r:addYears" msgstr "adderaÅr" -#: ../data/functions.xml.in.h:642 +#: ../data/functions.xml.in.h:649 msgid "Years" msgstr "Antal år" -#: ../data/functions.xml.in.h:643 +#: ../data/functions.xml.in.h:650 msgid "Add Time" msgstr "Addera tid" -#: ../data/functions.xml.in.h:644 +#: ../data/functions.xml.in.h:651 msgid "r:addTime" msgstr "adderaTid" -#: ../data/functions.xml.in.h:645 +#: ../data/functions.xml.in.h:652 msgid "" "Adds a time value to a date. The value can be positive or negative, but must " "use a unit based on seconds (such as day and year). Fractions of days are " @@ -5527,19 +5571,19 @@ "negativt, men måste använda en enhet baserad på sekunder (såsom dag och år). " "Delar av dagar avrundas mot noll." -#: ../data/functions.xml.in.h:646 ../data/units.xml.in.h:138 +#: ../data/functions.xml.in.h:653 ../data/units.xml.in.h:138 msgid "Time" msgstr "Tid" -#: ../data/functions.xml.in.h:647 +#: ../data/functions.xml.in.h:654 msgid "Lunar Phase" msgstr "Månfas" -#: ../data/functions.xml.in.h:648 +#: ../data/functions.xml.in.h:655 msgid "r:lunarphase" msgstr "månfas" -#: ../data/functions.xml.in.h:649 +#: ../data/functions.xml.in.h:656 msgid "" "Returns the lunar phase, as a number between 0 and 1, for the specified " "date. 0 represents new moon, 0.5 full moon, and 0.25 and 0.75 quarter moons." @@ -5547,15 +5591,15 @@ "Returnerar månfasen, som ett nummer mellan 0 och 1, för det angivna datumet. " "0 representerar nymåne, 0,5 fullmånar, och 0,25 samt 0,75 kvartsmånar." -#: ../data/functions.xml.in.h:650 +#: ../data/functions.xml.in.h:657 msgid "Find Lunar Phase" msgstr "Hitta månfas" -#: ../data/functions.xml.in.h:651 +#: ../data/functions.xml.in.h:658 msgid "r:nextlunarphase" msgstr "nästamånfas" -#: ../data/functions.xml.in.h:652 +#: ../data/functions.xml.in.h:659 msgid "" "Returns the date when the specified lunar phase occurs. The function " "searches forward beginning at the specified date. The lunar phase are " @@ -5566,43 +5610,43 @@ "med början på angivet datum. Månfasen anges som ett nummer mellan 0 och 1, " "där 0 representerar nymåne, 0,5 fullmånar, och 0,25 samt 0,75 kvartsmånar." -#: ../data/functions.xml.in.h:653 +#: ../data/functions.xml.in.h:660 msgid "Start Date" msgstr "Startdatum" -#: ../data/functions.xml.in.h:654 ../data/variables.xml.in.h:197 +#: ../data/functions.xml.in.h:661 ../data/variables.xml.in.h:197 msgid "Utilities" msgstr "Verktyg" -#: ../data/functions.xml.in.h:655 +#: ../data/functions.xml.in.h:662 msgid "Plot Functions and Vectors" msgstr "Rita funktioner och vektorer" -#: ../data/functions.xml.in.h:656 +#: ../data/functions.xml.in.h:663 msgid "r:plot" msgstr "" -#: ../data/functions.xml.in.h:657 +#: ../data/functions.xml.in.h:664 msgid "Expression or vector" msgstr "Uttryck eller vektor" -#: ../data/functions.xml.in.h:658 +#: ../data/functions.xml.in.h:665 msgid "Minimum x value" msgstr "Minsta x-värde" -#: ../data/functions.xml.in.h:659 +#: ../data/functions.xml.in.h:666 msgid "Maximum x value" msgstr "Högsta x-värde" -#: ../data/functions.xml.in.h:660 +#: ../data/functions.xml.in.h:667 msgid "Number of samples / Step size" msgstr "Antal värden / stegstorlek" -#: ../data/functions.xml.in.h:661 +#: ../data/functions.xml.in.h:668 msgid "X variable" msgstr "X-variabel" -#: ../data/functions.xml.in.h:662 +#: ../data/functions.xml.in.h:669 msgid "" "Plots one or more expressions or vectors. Use a vector for the first " "argument to plot multiple series. Only the first argument is used for vector " @@ -5614,63 +5658,63 @@ "första parametern används för vektorserier. Det är även möjligt att rita en " "matrix där varje rad utgör parvisa x och y värden." -#: ../data/functions.xml.in.h:663 +#: ../data/functions.xml.in.h:670 msgid "Unicode Value" msgstr "Unicode-värde" -#: ../data/functions.xml.in.h:664 +#: ../data/functions.xml.in.h:671 msgid "r:code" msgstr "kod" -#: ../data/functions.xml.in.h:665 +#: ../data/functions.xml.in.h:672 msgid "Character" msgstr "Tecken" -#: ../data/functions.xml.in.h:666 +#: ../data/functions.xml.in.h:673 msgid "Unicode Character" msgstr "Unicode-tecken" -#: ../data/functions.xml.in.h:667 +#: ../data/functions.xml.in.h:674 msgid "r:char" msgstr "tecken" -#: ../data/functions.xml.in.h:668 +#: ../data/functions.xml.in.h:675 msgid "Length of string" msgstr "Textsträngslängd" -#: ../data/functions.xml.in.h:669 +#: ../data/functions.xml.in.h:676 msgid "r:len" msgstr "längd" -#: ../data/functions.xml.in.h:670 +#: ../data/functions.xml.in.h:677 msgid "Text" msgstr "Text" -#: ../data/functions.xml.in.h:671 +#: ../data/functions.xml.in.h:678 msgid "Concatenate Strings" msgstr "Sammanfoga textsträngar" -#: ../data/functions.xml.in.h:672 +#: ../data/functions.xml.in.h:679 msgid "r:concatenate" msgstr "sammanfoga" -#: ../data/functions.xml.in.h:673 +#: ../data/functions.xml.in.h:680 msgid "Text string 1" msgstr "Textsträng 1" -#: ../data/functions.xml.in.h:674 +#: ../data/functions.xml.in.h:681 msgid "Text string 2" msgstr "Textsträng 2" -#: ../data/functions.xml.in.h:675 +#: ../data/functions.xml.in.h:682 msgid "Replace" msgstr "Ersätt" -#: ../data/functions.xml.in.h:676 +#: ../data/functions.xml.in.h:683 msgid "r:replace" msgstr "ersätt" -#: ../data/functions.xml.in.h:677 +#: ../data/functions.xml.in.h:684 msgid "" "Replaces a certain value in an expression with a new value. The expression " "is calculated before the replacement if the fourth argument is true." @@ -5678,31 +5722,31 @@ "Ersätt ett visst värde i ett uttryck med ett nytt värde. Uttrycket beräknas " "innan ersättandet om den parametern är satt till sant." -#: ../data/functions.xml.in.h:678 +#: ../data/functions.xml.in.h:685 msgid "Expression" msgstr "Uttryck" -#: ../data/functions.xml.in.h:679 +#: ../data/functions.xml.in.h:686 msgid "Original value" msgstr "Ursprungligt värde" -#: ../data/functions.xml.in.h:680 +#: ../data/functions.xml.in.h:687 msgid "New value" msgstr "Nytt värde" -#: ../data/functions.xml.in.h:681 +#: ../data/functions.xml.in.h:688 msgid "Precalculate expression" msgstr "Beräkna uttrycket först" -#: ../data/functions.xml.in.h:682 +#: ../data/functions.xml.in.h:689 msgid "Strip Units" msgstr "Ta bort enheter" -#: ../data/functions.xml.in.h:683 +#: ../data/functions.xml.in.h:690 msgid "r:nounit,strip_units" msgstr "" -#: ../data/functions.xml.in.h:684 +#: ../data/functions.xml.in.h:691 msgid "" "Removes all units from an expression. The expression is calculated before " "the removal." @@ -5710,303 +5754,303 @@ "Tar bort alla enheter från ett uttryck. Uttrycket beräknas innan " "borttagandet." -#: ../data/functions.xml.in.h:685 +#: ../data/functions.xml.in.h:692 msgid "Process Vector Elements" msgstr "Modifiera vektorelement" -#: ../data/functions.xml.in.h:686 +#: ../data/functions.xml.in.h:693 msgid "r:process" msgstr "" -#: ../data/functions.xml.in.h:687 +#: ../data/functions.xml.in.h:694 msgid "Element variable" msgstr "Elementvariabel" -#: ../data/functions.xml.in.h:688 +#: ../data/functions.xml.in.h:695 msgid "Index variable" msgstr "Indexvariabel" -#: ../data/functions.xml.in.h:689 +#: ../data/functions.xml.in.h:696 msgid "Vector variable" msgstr "Vektorvariabel" -#: ../data/functions.xml.in.h:690 +#: ../data/functions.xml.in.h:697 msgid "Process Matrix Elements" msgstr "Modifiera matriselement" -#: ../data/functions.xml.in.h:691 +#: ../data/functions.xml.in.h:698 msgid "r:processm" msgstr "" -#: ../data/functions.xml.in.h:692 +#: ../data/functions.xml.in.h:699 msgid "Row variable" msgstr "Radvariabel" -#: ../data/functions.xml.in.h:693 +#: ../data/functions.xml.in.h:700 msgid "Column variable" msgstr "Kolumnvariabel" -#: ../data/functions.xml.in.h:694 +#: ../data/functions.xml.in.h:701 msgid "Matrix variable" msgstr "Matrisvariabel" -#: ../data/functions.xml.in.h:695 +#: ../data/functions.xml.in.h:702 msgid "Custom Sum of Elements" msgstr "Anpassad elementsumma" -#: ../data/functions.xml.in.h:696 +#: ../data/functions.xml.in.h:703 msgid "r:csum" msgstr "" -#: ../data/functions.xml.in.h:697 +#: ../data/functions.xml.in.h:704 msgid "First element" msgstr "Första elementet" -#: ../data/functions.xml.in.h:698 +#: ../data/functions.xml.in.h:705 msgid "Last element" msgstr "Sista elementet" -#: ../data/functions.xml.in.h:699 +#: ../data/functions.xml.in.h:706 msgid "Initial value" msgstr "Initialt värde" -#: ../data/functions.xml.in.h:700 +#: ../data/functions.xml.in.h:707 msgid "Value variable" msgstr "Värdevariabel" -#: ../data/functions.xml.in.h:701 +#: ../data/functions.xml.in.h:708 msgid "Select Vector Elements" msgstr "Utvälj vektorelement" -#: ../data/functions.xml.in.h:702 +#: ../data/functions.xml.in.h:709 msgid "r:select" msgstr "" -#: ../data/functions.xml.in.h:703 +#: ../data/functions.xml.in.h:710 msgid "Condition" msgstr "Förutsättning" -#: ../data/functions.xml.in.h:704 +#: ../data/functions.xml.in.h:711 msgid "Select first match" msgstr "Välj första matchande element" -#: ../data/functions.xml.in.h:705 +#: ../data/functions.xml.in.h:712 msgid "r:function" msgstr "funktion" -#: ../data/functions.xml.in.h:706 +#: ../data/functions.xml.in.h:713 msgid "Arguments" msgstr "Parametrar" -#: ../data/functions.xml.in.h:707 +#: ../data/functions.xml.in.h:714 msgid "Title" msgstr "Titel" -#: ../data/functions.xml.in.h:708 +#: ../data/functions.xml.in.h:715 msgid "r:title" msgstr "titel" -#: ../data/functions.xml.in.h:710 +#: ../data/functions.xml.in.h:717 msgid "Display Error" msgstr "Visa felmeddelande" -#: ../data/functions.xml.in.h:711 +#: ../data/functions.xml.in.h:718 msgid "r:error" msgstr "fel" -#: ../data/functions.xml.in.h:712 +#: ../data/functions.xml.in.h:719 msgid "Message" msgstr "Meddelande" -#: ../data/functions.xml.in.h:713 +#: ../data/functions.xml.in.h:720 msgid "Display Warning" msgstr "Visa varning" -#: ../data/functions.xml.in.h:714 +#: ../data/functions.xml.in.h:721 msgid "r:warning" msgstr "varning" -#: ../data/functions.xml.in.h:715 +#: ../data/functions.xml.in.h:722 msgid "Display Message" msgstr "Visa meddelande" -#: ../data/functions.xml.in.h:716 +#: ../data/functions.xml.in.h:723 msgid "r:message" msgstr "meddelande" -#: ../data/functions.xml.in.h:717 +#: ../data/functions.xml.in.h:724 msgid "Save as Variable" msgstr "Spara som variabel" -#: ../data/functions.xml.in.h:718 +#: ../data/functions.xml.in.h:725 msgid "r:save" msgstr "spara" -#: ../data/functions.xml.in.h:719 +#: ../data/functions.xml.in.h:726 msgid "Category" msgstr "Kategori" -#: ../data/functions.xml.in.h:720 +#: ../data/functions.xml.in.h:727 msgid "RPN Stack Register" msgstr "RPN-stackregister" -#: ../data/functions.xml.in.h:721 +#: ../data/functions.xml.in.h:728 msgid "r:register" msgstr "" -#: ../data/functions.xml.in.h:722 +#: ../data/functions.xml.in.h:729 msgid "Returns the value of a RPN stack register." msgstr "Returnerar värdet för ett register på RPN-stacken." -#: ../data/functions.xml.in.h:723 +#: ../data/functions.xml.in.h:730 msgid "Index" msgstr "Index" -#: ../data/functions.xml.in.h:724 +#: ../data/functions.xml.in.h:731 msgid "RPN Stack Vector" msgstr "RPN-stackvektor" -#: ../data/functions.xml.in.h:725 +#: ../data/functions.xml.in.h:732 msgid "r:stack" msgstr "" -#: ../data/functions.xml.in.h:726 +#: ../data/functions.xml.in.h:733 msgid "Returns the RPN stack as a vector." msgstr "Returnerar RPN-stacken som en vektor." -#: ../data/functions.xml.in.h:727 +#: ../data/functions.xml.in.h:734 msgid "Is Number" msgstr "Är nummer" -#: ../data/functions.xml.in.h:728 +#: ../data/functions.xml.in.h:735 msgid "r:isNumber" msgstr "ärNummer" -#: ../data/functions.xml.in.h:729 +#: ../data/functions.xml.in.h:736 msgid "Is Real" msgstr "Är reellt" -#: ../data/functions.xml.in.h:730 +#: ../data/functions.xml.in.h:737 msgid "r:isReal" msgstr "ärReellt" -#: ../data/functions.xml.in.h:731 +#: ../data/functions.xml.in.h:738 msgid "Is Rational" msgstr "Är rationellt" -#: ../data/functions.xml.in.h:732 +#: ../data/functions.xml.in.h:739 msgid "r:isRational" msgstr "ärRationellt" -#: ../data/functions.xml.in.h:733 +#: ../data/functions.xml.in.h:740 msgid "Is Integer" msgstr "Är heltal" -#: ../data/functions.xml.in.h:734 +#: ../data/functions.xml.in.h:741 msgid "r:isInteger" msgstr "ärHeltal" -#: ../data/functions.xml.in.h:735 +#: ../data/functions.xml.in.h:742 msgid "Represents Number" msgstr "Representar nummer" -#: ../data/functions.xml.in.h:736 +#: ../data/functions.xml.in.h:743 msgid "r:representsNumber" msgstr "representerarNummer" -#: ../data/functions.xml.in.h:737 +#: ../data/functions.xml.in.h:744 msgid "Represents Real" msgstr "Representerar reellt tal" -#: ../data/functions.xml.in.h:738 +#: ../data/functions.xml.in.h:745 msgid "r:representsReal" msgstr "representerarReelt" -#: ../data/functions.xml.in.h:739 +#: ../data/functions.xml.in.h:746 msgid "Represents Rational" msgstr "Representerar rationellt tal" -#: ../data/functions.xml.in.h:740 +#: ../data/functions.xml.in.h:747 msgid "r:representsRational" msgstr "representerarRationellt" -#: ../data/functions.xml.in.h:741 +#: ../data/functions.xml.in.h:748 msgid "Represents Integer" msgstr "Representerar ett heltal" -#: ../data/functions.xml.in.h:742 +#: ../data/functions.xml.in.h:749 msgid "r:representsInteger" msgstr "representarHeltal" -#: ../data/functions.xml.in.h:743 +#: ../data/functions.xml.in.h:750 msgid "Interval" msgstr "Intervall" -#: ../data/functions.xml.in.h:744 +#: ../data/functions.xml.in.h:751 msgid "r:interval" msgstr "intervall" -#: ../data/functions.xml.in.h:745 +#: ../data/functions.xml.in.h:752 msgid "Lower endpoint" msgstr "Undre gräns" -#: ../data/functions.xml.in.h:746 +#: ../data/functions.xml.in.h:753 msgid "Upper endpoint" msgstr "Övre gräns" -#: ../data/functions.xml.in.h:747 +#: ../data/functions.xml.in.h:754 msgid "Uncertainty" msgstr "Fel (osäkerhet)" -#: ../data/functions.xml.in.h:748 +#: ../data/functions.xml.in.h:755 msgid "r:uncertainty" msgstr "" -#: ../data/functions.xml.in.h:749 +#: ../data/functions.xml.in.h:756 msgid "Uncertainty is relative" msgstr "Felet är relativt" -#: ../data/functions.xml.in.h:750 +#: ../data/functions.xml.in.h:757 msgid "Logical" msgstr "Logik" -#: ../data/functions.xml.in.h:751 +#: ../data/functions.xml.in.h:758 msgid "For...Do" msgstr "För...utför" -#: ../data/functions.xml.in.h:752 +#: ../data/functions.xml.in.h:759 msgid "r:for" msgstr "för" -#: ../data/functions.xml.in.h:753 +#: ../data/functions.xml.in.h:760 msgid "Initial value of counter" msgstr "Initialt värde för räknare" -#: ../data/functions.xml.in.h:754 +#: ../data/functions.xml.in.h:761 msgid "Counter variable" msgstr "Räknarvariabel" -#: ../data/functions.xml.in.h:755 +#: ../data/functions.xml.in.h:762 msgid "For condition" msgstr "Medans-villkor" -#: ../data/functions.xml.in.h:756 +#: ../data/functions.xml.in.h:763 msgid "Counter update function" msgstr "Funktion för uppdatering av räknare" -#: ../data/functions.xml.in.h:757 +#: ../data/functions.xml.in.h:764 msgid "Do function" msgstr "Utför-funktion" -#: ../data/functions.xml.in.h:758 +#: ../data/functions.xml.in.h:765 msgid "If...Then...Else" msgstr "Om...då...annars" -#: ../data/functions.xml.in.h:759 +#: ../data/functions.xml.in.h:766 msgid "r:if" msgstr "om" -#: ../data/functions.xml.in.h:760 +#: ../data/functions.xml.in.h:767 msgid "" "Tests a condition and returns a value depending on the result. Vectors can " "be used for argument 1 and 2, instead of nested functions." @@ -6014,47 +6058,47 @@ "Testar ett villkor och returnerar ett värde beroende av result. Vektorer kan " "anges för parameter 1 och 2, för att undvika nästlade funktioner." -#: ../data/functions.xml.in.h:761 +#: ../data/functions.xml.in.h:768 msgid "Expression if condition is met" msgstr "Uttryck om villkoret uppfylls" -#: ../data/functions.xml.in.h:762 +#: ../data/functions.xml.in.h:769 msgid "Expression if condition is NOT met" msgstr "Uttryck om villkoret INTE uppfylls" -#: ../data/functions.xml.in.h:763 +#: ../data/functions.xml.in.h:770 msgid "Assume false if not true" msgstr "Antag falskt om ej sant" -#: ../data/functions.xml.in.h:764 +#: ../data/functions.xml.in.h:771 msgid "Bitwise Exclusive OR" msgstr "Bitvist exklusivt OR" -#: ../data/functions.xml.in.h:765 +#: ../data/functions.xml.in.h:772 msgid "r:xor" msgstr "" -#: ../data/functions.xml.in.h:766 +#: ../data/functions.xml.in.h:773 msgid "Value 1" msgstr "Värde 1" -#: ../data/functions.xml.in.h:767 +#: ../data/functions.xml.in.h:774 msgid "Value 2" msgstr "Värde 2" -#: ../data/functions.xml.in.h:768 +#: ../data/functions.xml.in.h:775 msgid "Logical Exclusive OR" msgstr "Logiskt exklusivt OR" -#: ../data/functions.xml.in.h:769 +#: ../data/functions.xml.in.h:776 msgid "r:lxor" msgstr "" -#: ../data/functions.xml.in.h:770 +#: ../data/functions.xml.in.h:777 msgid "Bitwise Shift" msgstr "Bitvist skift" -#: ../data/functions.xml.in.h:771 +#: ../data/functions.xml.in.h:778 msgid "" "Applies logical or arithmetic bitwise shift to an integer. The second " "argument specifies the number of steps that each binary bit is shifted to " @@ -6064,23 +6108,23 @@ "parametern anger antalet steg som varje binär bit flyttas åt vänster (använd " "negativa värden för högerskift)." -#: ../data/functions.xml.in.h:772 +#: ../data/functions.xml.in.h:779 msgid "r:shift" msgstr "" -#: ../data/functions.xml.in.h:773 +#: ../data/functions.xml.in.h:780 msgid "Steps" msgstr "Steg" -#: ../data/functions.xml.in.h:774 +#: ../data/functions.xml.in.h:781 msgid "Arithmetic shift using two's complement" msgstr "Aritmetiskt skift med tvåkomplement" -#: ../data/functions.xml.in.h:775 +#: ../data/functions.xml.in.h:782 msgid "Bitwise Complement (Not)" msgstr "Bitvivst komplement (Icke)" -#: ../data/functions.xml.in.h:776 +#: ../data/functions.xml.in.h:783 msgid "" "Applies bitwise NOT to an integer of specified bit width and signedness (use " "1 for signed and 0 for unsigned). If bit width is zero, the smallest " @@ -6090,23 +6134,23 @@ "som signed (1) eller unsigned (0). Om bitvidd är noll, används det minsta " "nödvändiga antalet bitar (av 8, 16, 32, 64, 128, ...)." -#: ../data/functions.xml.in.h:777 +#: ../data/functions.xml.in.h:784 msgid "r:bitcmp" msgstr "" -#: ../data/functions.xml.in.h:778 +#: ../data/functions.xml.in.h:785 msgid "Bit Width" msgstr "Bitbredd" -#: ../data/functions.xml.in.h:779 +#: ../data/functions.xml.in.h:786 msgid "Signed Integer" msgstr "Signed integer" -#: ../data/functions.xml.in.h:780 +#: ../data/functions.xml.in.h:787 msgid "Bit Rotation" msgstr "Bitrotation" -#: ../data/functions.xml.in.h:781 +#: ../data/functions.xml.in.h:788 msgid "" "Applies circular bitwise shift to an integer of specified bit width and " "signedness (use 1 for signed and 0 for unsigned). The second argument " @@ -6120,23 +6164,23 @@ "för högerskift). Om bitvidd är noll, används det minsta nödvändiga antalet " "bitar (av 8, 16, 32, 64, 128, ...)." -#: ../data/functions.xml.in.h:782 +#: ../data/functions.xml.in.h:789 msgid "r:bitrot" msgstr "" -#: ../data/functions.xml.in.h:783 +#: ../data/functions.xml.in.h:790 msgid "Algebra" msgstr "Algebra" -#: ../data/functions.xml.in.h:784 +#: ../data/functions.xml.in.h:791 msgid "Summation" msgstr "Summa" -#: ../data/functions.xml.in.h:785 +#: ../data/functions.xml.in.h:792 msgid "au:Σ,r:sum" msgstr "au:Σ,summa" -#: ../data/functions.xml.in.h:786 +#: ../data/functions.xml.in.h:793 msgid "" "Corresponds to the summation symbol. Adds terms for each x ranging from the " "lower to the upper limit." @@ -6144,27 +6188,27 @@ "Motsvarar summasymbolen. Adderar termer för varje x från den undre till den " "övre gränsen." -#: ../data/functions.xml.in.h:787 +#: ../data/functions.xml.in.h:794 msgid "Term expression" msgstr "Termuttryck" -#: ../data/functions.xml.in.h:788 +#: ../data/functions.xml.in.h:795 msgid "Lower limit (i)" msgstr "Undre gräns (i)" -#: ../data/functions.xml.in.h:789 +#: ../data/functions.xml.in.h:796 msgid "Upper limit (n)" msgstr "Övre gräns (n)" -#: ../data/functions.xml.in.h:790 +#: ../data/functions.xml.in.h:797 msgid "Product of a sequence" msgstr "Produkt av en serie" -#: ../data/functions.xml.in.h:791 +#: ../data/functions.xml.in.h:798 msgid "au:Π,r:product" msgstr "au:Π,produkt" -#: ../data/functions.xml.in.h:792 +#: ../data/functions.xml.in.h:799 msgid "" "Corresponds to the product symbol. Multiplies factors for each x ranging " "from the lower to the upper limit." @@ -6172,77 +6216,77 @@ "Motsvarar produktsymbolen. Multiplicerar faktorer för varje x från den undre " "till den övre gränsen." -#: ../data/functions.xml.in.h:793 +#: ../data/functions.xml.in.h:800 msgid "Factor expression" msgstr "Faktoruttryck" -#: ../data/functions.xml.in.h:794 +#: ../data/functions.xml.in.h:801 msgid "Solve for multiple variables" msgstr "Lös för flera variabler" -#: ../data/functions.xml.in.h:795 +#: ../data/functions.xml.in.h:802 msgid "r:multisolve" msgstr "" -#: ../data/functions.xml.in.h:796 +#: ../data/functions.xml.in.h:803 msgid "Equation vector" msgstr "Ekvationsvektor" -#: ../data/functions.xml.in.h:797 +#: ../data/functions.xml.in.h:804 msgid "Variable vector" msgstr "Variabelvektor" -#: ../data/functions.xml.in.h:798 +#: ../data/functions.xml.in.h:805 msgid "Solve equation" msgstr "Lös ekvation" -#: ../data/functions.xml.in.h:799 +#: ../data/functions.xml.in.h:806 msgid "r:solve" msgstr "lös" -#: ../data/functions.xml.in.h:800 +#: ../data/functions.xml.in.h:807 msgid "Equation" msgstr "Ekvation" -#: ../data/functions.xml.in.h:801 +#: ../data/functions.xml.in.h:808 msgid "With respect to" msgstr "Med avseende på" -#: ../data/functions.xml.in.h:802 +#: ../data/functions.xml.in.h:809 msgid "Solve differential equation" msgstr "Lös differentialekvation" -#: ../data/functions.xml.in.h:803 +#: ../data/functions.xml.in.h:810 msgid "r:dsolve" msgstr "" -#: ../data/functions.xml.in.h:804 +#: ../data/functions.xml.in.h:811 msgid "Initial condition: function value (y)" msgstr "Initialt villkor: funktionsvärde (y)" -#: ../data/functions.xml.in.h:805 +#: ../data/functions.xml.in.h:812 msgid "Initial condition: argument value (x)" msgstr "Initialt villkor: parametervärde (x)" -#: ../data/functions.xml.in.h:806 +#: ../data/functions.xml.in.h:813 msgid "" "Solves a differential equation and returns the value of y(x). The derivative " "in the equation should be in the format diff(y, x). Only first-order " "differential equations are currently supported." msgstr "" "Löser en differentialekvation och returnerar värdet på y(x). Derivatan i " -"ekvation måste vara i formatet diff(y; x). Enbart första ordningens " +"ekvation måste vara i formatet diff(y; x). Enbart första ordningens " "differentialekvationer stöds för nuvarande." -#: ../data/functions.xml.in.h:807 +#: ../data/functions.xml.in.h:814 msgid "Solve for two variables" msgstr "Lös för två variabler" -#: ../data/functions.xml.in.h:808 +#: ../data/functions.xml.in.h:815 msgid "r:solve2" msgstr "lös2" -#: ../data/functions.xml.in.h:809 +#: ../data/functions.xml.in.h:816 msgid "" "Solves two equations with two unknown variables. Returns the value of the " "first variable." @@ -6250,118 +6294,118 @@ "Lös två ekvationer med två okända variabler. Returnerar värdet på den första " "variabeln." -#: ../data/functions.xml.in.h:810 +#: ../data/functions.xml.in.h:817 msgid "Equation 1" msgstr "Ekvation 1" -#: ../data/functions.xml.in.h:811 +#: ../data/functions.xml.in.h:818 msgid "Equation 2" msgstr "Ekvation 2" -#: ../data/functions.xml.in.h:812 +#: ../data/functions.xml.in.h:819 msgid "Variable 1" msgstr "Variabel 1" -#: ../data/functions.xml.in.h:813 +#: ../data/functions.xml.in.h:820 msgid "Variable 2" msgstr "Variabel 2" -#: ../data/functions.xml.in.h:814 +#: ../data/functions.xml.in.h:821 msgid "Find Linear Function" msgstr "Finn linjär funktion" -#: ../data/functions.xml.in.h:815 +#: ../data/functions.xml.in.h:822 msgid "r:linearfunction" msgstr "linjär_funktion" -#: ../data/functions.xml.in.h:816 +#: ../data/functions.xml.in.h:823 msgid "" "Finds the linear function for the straight line between two distinct points." msgstr "" "Finner den linjära funktionen för den räta linjen mellan två distinkta " "punkter." -#: ../data/functions.xml.in.h:817 +#: ../data/functions.xml.in.h:824 msgid "x1" msgstr "" -#: ../data/functions.xml.in.h:818 +#: ../data/functions.xml.in.h:825 msgid "y1" msgstr "" -#: ../data/functions.xml.in.h:819 +#: ../data/functions.xml.in.h:826 msgid "x2" msgstr "" -#: ../data/functions.xml.in.h:820 +#: ../data/functions.xml.in.h:827 msgid "y2" msgstr "" -#: ../data/functions.xml.in.h:821 +#: ../data/functions.xml.in.h:828 msgid "Calculus" msgstr "Calculus" -#: ../data/functions.xml.in.h:822 +#: ../data/functions.xml.in.h:829 msgid "Differentiate" msgstr "Derivera" -#: ../data/functions.xml.in.h:823 +#: ../data/functions.xml.in.h:830 msgid "r:diff,derivative" msgstr "diff,derivata,derivera" -#: ../data/functions.xml.in.h:824 +#: ../data/functions.xml.in.h:831 msgid "Variable value" msgstr "Variabelvärde" -#: ../data/functions.xml.in.h:825 +#: ../data/functions.xml.in.h:832 msgid "Integrate" msgstr "Integrera" -#: ../data/functions.xml.in.h:826 +#: ../data/functions.xml.in.h:833 msgid "r:integrate,integral,au:∫" msgstr "integrera,integral,au:∫" -#: ../data/functions.xml.in.h:827 +#: ../data/functions.xml.in.h:834 msgid "Variable of integration" msgstr "Variabel för integration" -#: ../data/functions.xml.in.h:828 +#: ../data/functions.xml.in.h:835 msgid "Force numerical integration" msgstr "Tvinga numerisk integrering" -#: ../data/functions.xml.in.h:829 +#: ../data/functions.xml.in.h:836 msgid "Romberg Integration" msgstr "Romberg-integrering" -#: ../data/functions.xml.in.h:830 +#: ../data/functions.xml.in.h:837 msgid "r:romberg" msgstr "" -#: ../data/functions.xml.in.h:831 +#: ../data/functions.xml.in.h:838 msgid "Min iterations" msgstr "Min iterationer" -#: ../data/functions.xml.in.h:832 +#: ../data/functions.xml.in.h:839 msgid "Max iterations" msgstr "Max iterationer" -#: ../data/functions.xml.in.h:833 +#: ../data/functions.xml.in.h:840 msgid "Monte Carlo Integration" msgstr "Monte Carlo-integrering" -#: ../data/functions.xml.in.h:834 +#: ../data/functions.xml.in.h:841 msgid "r:montecarlo" msgstr "" -#: ../data/functions.xml.in.h:835 +#: ../data/functions.xml.in.h:842 msgid "Number of samples" msgstr "Antal värden" -#: ../data/functions.xml.in.h:836 +#: ../data/functions.xml.in.h:843 msgid "Limit" msgstr "Gränsvärde" -#: ../data/functions.xml.in.h:837 +#: ../data/functions.xml.in.h:844 msgid "" "Returns the two-sided limit of the function if direction is zero, limit from " "left (below) if direction is -1, or limit from right (above) if direction is " @@ -6371,371 +6415,395 @@ "gränsvärdet från vänster (underifrån) om riktning är -1 eller gränsvärdet " "från höger (ovanifrån) om riktning är +1." -#: ../data/functions.xml.in.h:838 +#: ../data/functions.xml.in.h:845 msgid "r:limit" msgstr "" -#: ../data/functions.xml.in.h:839 +#: ../data/functions.xml.in.h:846 msgid "Value to approach" msgstr "Värde att närma" -#: ../data/functions.xml.in.h:840 +#: ../data/functions.xml.in.h:847 msgid "Direction" msgstr "Riktning" -#: ../data/functions.xml.in.h:841 +#: ../data/functions.xml.in.h:848 msgid "Extreme Values" msgstr "Extremvärden" -#: ../data/functions.xml.in.h:842 +#: ../data/functions.xml.in.h:849 msgid "r:extremum" msgstr "" -#: ../data/functions.xml.in.h:843 +#: ../data/functions.xml.in.h:850 msgid "Named Integrals" msgstr "Namngivna integraler" -#: ../data/functions.xml.in.h:844 +#: ../data/functions.xml.in.h:851 msgid "Logarithmic Integral" msgstr "Logaritmisk integral" -#: ../data/functions.xml.in.h:845 +#: ../data/functions.xml.in.h:852 msgid "rc:li,logint" msgstr "" -#: ../data/functions.xml.in.h:846 +#: ../data/functions.xml.in.h:853 msgid "The integral of 1/ln(x)." msgstr "Integralen av 1/ln(x)." -#: ../data/functions.xml.in.h:847 +#: ../data/functions.xml.in.h:854 msgid "Exponential Integral" msgstr "Exponentiell integral" -#: ../data/functions.xml.in.h:848 +#: ../data/functions.xml.in.h:855 msgid "rc:Ei,expint" msgstr "" -#: ../data/functions.xml.in.h:849 +#: ../data/functions.xml.in.h:856 msgid "The integral of e^x/x." msgstr "Integralen av e^x/x." -#: ../data/functions.xml.in.h:850 +#: ../data/functions.xml.in.h:857 msgid "Sine Integral" msgstr "Sineintegral" -#: ../data/functions.xml.in.h:851 +#: ../data/functions.xml.in.h:858 msgid "rc:Si,sinint" msgstr "" -#: ../data/functions.xml.in.h:852 +#: ../data/functions.xml.in.h:859 msgid "The integral of sin(x)/x." msgstr "Integralen av sin(x)/x" -#: ../data/functions.xml.in.h:853 +#: ../data/functions.xml.in.h:860 msgid "Cosine Integral" msgstr "Cosineintegral" -#: ../data/functions.xml.in.h:854 +#: ../data/functions.xml.in.h:861 msgid "rc:Ci,cosint" msgstr "" -#: ../data/functions.xml.in.h:855 +#: ../data/functions.xml.in.h:862 msgid "The integral of cos(x)/x." msgstr "Integralen av cos(x)/x." -#: ../data/functions.xml.in.h:856 +#: ../data/functions.xml.in.h:863 msgid "Hyperbolic Sine Integral" msgstr "Sinus hyperbolicus-integral" -#: ../data/functions.xml.in.h:857 +#: ../data/functions.xml.in.h:864 msgid "rc:Shi,sinhint" msgstr "" -#: ../data/functions.xml.in.h:858 +#: ../data/functions.xml.in.h:865 msgid "The integral of sinh(x)/x." msgstr "Integralen av sinh(x)/x." -#: ../data/functions.xml.in.h:859 +#: ../data/functions.xml.in.h:866 msgid "Hyperbolic Cosine Integral" msgstr "Cosinus hyperbolicus-integral" -#: ../data/functions.xml.in.h:860 +#: ../data/functions.xml.in.h:867 msgid "rc:Chi,coshint" msgstr "" -#: ../data/functions.xml.in.h:861 +#: ../data/functions.xml.in.h:868 msgid "The integral of cosh(x)/x." msgstr "Integralen av cosh(x)/x." -#: ../data/functions.xml.in.h:862 +#: ../data/functions.xml.in.h:869 +msgid "Fresnel Integral S" +msgstr "Fresnels integral S" + +#: ../data/functions.xml.in.h:870 +msgid "r:fresnels" +msgstr "" + +#: ../data/functions.xml.in.h:871 +msgid "The integral of sin(pi*x^2/2)." +msgstr "Integralen av sin(pi*x^2/2)." + +#: ../data/functions.xml.in.h:872 +msgid "Fresnel Integral C" +msgstr "Fresnels integral C" + +#: ../data/functions.xml.in.h:873 +msgid "r:fresnelc" +msgstr "" + +#: ../data/functions.xml.in.h:874 +msgid "The integral of cos(pi*x^2/2)." +msgstr "Integralen av cos(pi*x^2/2)." + +#: ../data/functions.xml.in.h:875 msgid "Upper Incomplete Gamma Function" msgstr "Övre ofullständig gammafunktion" -#: ../data/functions.xml.in.h:863 +#: ../data/functions.xml.in.h:876 msgid "r:igamma" msgstr "" -#: ../data/functions.xml.in.h:864 +#: ../data/functions.xml.in.h:877 msgid "Lower Incomplete Gamma Function" msgstr "Undre ofullständig gammafunktion" -#: ../data/functions.xml.in.h:865 +#: ../data/functions.xml.in.h:878 msgid "r:gammainc" msgstr "" -#: ../data/functions.xml.in.h:866 +#: ../data/functions.xml.in.h:879 msgid "Geometry" msgstr "Geometri" -#: ../data/functions.xml.in.h:867 +#: ../data/functions.xml.in.h:880 msgid "Triangle" msgstr "Triangel" -#: ../data/functions.xml.in.h:868 +#: ../data/functions.xml.in.h:881 msgid "Hypotenuse" msgstr "Hypotenusa" -#: ../data/functions.xml.in.h:869 +#: ../data/functions.xml.in.h:882 msgid "r:hypot" msgstr "" -#: ../data/functions.xml.in.h:870 +#: ../data/functions.xml.in.h:883 msgid "Side A" msgstr "Sida A" -#: ../data/functions.xml.in.h:871 +#: ../data/functions.xml.in.h:884 msgid "Side B" msgstr "Sida B" -#: ../data/functions.xml.in.h:872 +#: ../data/functions.xml.in.h:885 msgid "Triangle Area" msgstr "Triangelarea" -#: ../data/functions.xml.in.h:873 +#: ../data/functions.xml.in.h:886 msgid "r:triangle" msgstr "triangel" -#: ../data/functions.xml.in.h:874 +#: ../data/functions.xml.in.h:887 msgid "Height" msgstr "Höjd" -#: ../data/functions.xml.in.h:875 +#: ../data/functions.xml.in.h:888 msgid "Triangle Perimeter" msgstr "Rektangelomkrets" -#: ../data/functions.xml.in.h:876 +#: ../data/functions.xml.in.h:889 msgid "r:triangle_perimeter" msgstr "triangelomkrets" -#: ../data/functions.xml.in.h:877 +#: ../data/functions.xml.in.h:890 msgid "Side C" msgstr "Sida C" -#: ../data/functions.xml.in.h:878 +#: ../data/functions.xml.in.h:891 msgid "Circle" msgstr "Cirkel" -#: ../data/functions.xml.in.h:879 +#: ../data/functions.xml.in.h:892 msgid "Circle Area" msgstr "Cirkelarea" -#: ../data/functions.xml.in.h:880 +#: ../data/functions.xml.in.h:893 msgid "r:circle" msgstr "cirkel" -#: ../data/functions.xml.in.h:881 +#: ../data/functions.xml.in.h:894 msgid "Calculates the area of a circle using the radius" msgstr "Beräknar arean för en cirkel." -#: ../data/functions.xml.in.h:882 +#: ../data/functions.xml.in.h:895 msgid "Radius" msgstr "Radie" -#: ../data/functions.xml.in.h:883 +#: ../data/functions.xml.in.h:896 msgid "Circle Circumference" msgstr "Cirkelomkrets" -#: ../data/functions.xml.in.h:884 +#: ../data/functions.xml.in.h:897 msgid "r:circumference" msgstr "omkrets" -#: ../data/functions.xml.in.h:885 +#: ../data/functions.xml.in.h:898 msgid "Cylinder" msgstr "Cylinder" -#: ../data/functions.xml.in.h:886 +#: ../data/functions.xml.in.h:899 msgid "Cylinder Volume" msgstr "Cylindervolym" -#: ../data/functions.xml.in.h:887 +#: ../data/functions.xml.in.h:900 msgid "r:cylinder" msgstr "" -#: ../data/functions.xml.in.h:888 +#: ../data/functions.xml.in.h:901 msgid "Surface Area of Cylinder" msgstr "Ytarea för en cylinder" -#: ../data/functions.xml.in.h:889 +#: ../data/functions.xml.in.h:902 msgid "r:cylinder_sa" msgstr "cylinderyta" -#: ../data/functions.xml.in.h:890 +#: ../data/functions.xml.in.h:903 msgid "Cone" msgstr "Kon" -#: ../data/functions.xml.in.h:891 +#: ../data/functions.xml.in.h:904 msgid "Cone Volume" msgstr "Konvolym" -#: ../data/functions.xml.in.h:892 +#: ../data/functions.xml.in.h:905 msgid "r:cone" msgstr "kon" -#: ../data/functions.xml.in.h:893 +#: ../data/functions.xml.in.h:906 msgid "Surface Area of Cone" msgstr "Ytarea för en kon" -#: ../data/functions.xml.in.h:894 +#: ../data/functions.xml.in.h:907 msgid "r:cone_sa" msgstr "konyta" -#: ../data/functions.xml.in.h:895 +#: ../data/functions.xml.in.h:908 msgid "Sphere" msgstr "Sfär" -#: ../data/functions.xml.in.h:896 +#: ../data/functions.xml.in.h:909 msgid "Sphere Volume" msgstr "Sfärvolym" -#: ../data/functions.xml.in.h:897 +#: ../data/functions.xml.in.h:910 msgid "r:sphere" msgstr "sfär" -#: ../data/functions.xml.in.h:898 +#: ../data/functions.xml.in.h:911 msgid "Surface Area of Sphere" msgstr "Ytarea för en sfär" -#: ../data/functions.xml.in.h:899 +#: ../data/functions.xml.in.h:912 msgid "r:sphere_sa" msgstr "sfäryta" -#: ../data/functions.xml.in.h:900 +#: ../data/functions.xml.in.h:913 msgid "Square Area" msgstr "Kvadratarea" -#: ../data/functions.xml.in.h:901 +#: ../data/functions.xml.in.h:914 msgid "r:square" msgstr "kvadrat" -#: ../data/functions.xml.in.h:902 +#: ../data/functions.xml.in.h:915 msgid "Length of side" msgstr "Sidans längd" -#: ../data/functions.xml.in.h:903 +#: ../data/functions.xml.in.h:916 msgid "Square Perimeter" msgstr "Kvadratomkrets" -#: ../data/functions.xml.in.h:904 +#: ../data/functions.xml.in.h:917 msgid "r:square_perimeter" msgstr "kvadratomkrets" -#: ../data/functions.xml.in.h:905 +#: ../data/functions.xml.in.h:918 msgid "Cube" msgstr "Kub" -#: ../data/functions.xml.in.h:906 +#: ../data/functions.xml.in.h:919 msgid "Cube Volume" msgstr "Kubvolym" -#: ../data/functions.xml.in.h:907 +#: ../data/functions.xml.in.h:920 msgid "r:cube" msgstr "kub" -#: ../data/functions.xml.in.h:908 +#: ../data/functions.xml.in.h:921 msgid "Surface Area of Cube" msgstr "Ytarea för en kub" -#: ../data/functions.xml.in.h:909 +#: ../data/functions.xml.in.h:922 msgid "r:cube_sa" msgstr "kubyta" -#: ../data/functions.xml.in.h:910 +#: ../data/functions.xml.in.h:923 msgid "Rectangle" msgstr "Rektangel" -#: ../data/functions.xml.in.h:911 +#: ../data/functions.xml.in.h:924 msgid "Rectangle Area" msgstr "Rektangelarea" -#: ../data/functions.xml.in.h:912 +#: ../data/functions.xml.in.h:925 msgid "r:rect" msgstr "rektangel" -#: ../data/functions.xml.in.h:913 +#: ../data/functions.xml.in.h:926 msgid "Width" msgstr "Bredd" -#: ../data/functions.xml.in.h:914 +#: ../data/functions.xml.in.h:927 msgid "Rectangle Perimeter" msgstr "Rektangelomkrets" -#: ../data/functions.xml.in.h:915 +#: ../data/functions.xml.in.h:928 msgid "r:rect_perimeter" msgstr "rektangelomkrets" -#: ../data/functions.xml.in.h:916 +#: ../data/functions.xml.in.h:929 msgid "Prism" msgstr "Prism" -#: ../data/functions.xml.in.h:917 +#: ../data/functions.xml.in.h:930 msgid "Volume of Rectangular Prism" msgstr "Volym för en rektangulär prism" -#: ../data/functions.xml.in.h:918 +#: ../data/functions.xml.in.h:931 msgid "r:rectprism" msgstr "rektangelprism" -#: ../data/functions.xml.in.h:919 +#: ../data/functions.xml.in.h:932 msgid "Calculates the volume of a prism with rectangular base." msgstr "Beräknar volymen för en prisma med rektangulär bas." -#: ../data/functions.xml.in.h:920 +#: ../data/functions.xml.in.h:933 msgid "Surface Area of Rectangular Prism" msgstr "Ytarea för en rektangulär prism" -#: ../data/functions.xml.in.h:921 +#: ../data/functions.xml.in.h:934 msgid "r:rectprism_sa" msgstr "rektangelprismyta" -#: ../data/functions.xml.in.h:922 +#: ../data/functions.xml.in.h:935 msgid "Calculates the surface area of a prism with rectangular base." msgstr "Beräknar ytarean för en prisma med rektangulär bas." -#: ../data/functions.xml.in.h:923 +#: ../data/functions.xml.in.h:936 msgid "Volume of Triangular Prism" msgstr "Volym för en triangulär prism" -#: ../data/functions.xml.in.h:924 +#: ../data/functions.xml.in.h:937 msgid "r:triangleprism" msgstr "triangelprism" -#: ../data/functions.xml.in.h:925 +#: ../data/functions.xml.in.h:938 msgid "Calculates the volume of a prism with triangular base." msgstr "Beräknar volymen för en prisma med triangulär bas." -#: ../data/functions.xml.in.h:926 +#: ../data/functions.xml.in.h:939 msgid "Pyramid" msgstr "Pyramid" -#: ../data/functions.xml.in.h:927 +#: ../data/functions.xml.in.h:940 msgid "Pyramid Volume" msgstr "Pyramidvolym" -#: ../data/functions.xml.in.h:928 +#: ../data/functions.xml.in.h:941 msgid "r:pyramid" msgstr "" -#: ../data/functions.xml.in.h:929 +#: ../data/functions.xml.in.h:942 msgid "" "Calculates the volume of a 3-dimensional shape standing on a rectangular " "base and terminating in a point at the top." @@ -6743,75 +6811,75 @@ "Beräknar volymen för en 3-dimensionell form som står på en rektangulär bas " "och som slutar en punkt på toppen." -#: ../data/functions.xml.in.h:930 +#: ../data/functions.xml.in.h:943 msgid "Length of base" msgstr "Basens längd" -#: ../data/functions.xml.in.h:931 +#: ../data/functions.xml.in.h:944 msgid "Width of base" msgstr "Basens bredd" -#: ../data/functions.xml.in.h:932 +#: ../data/functions.xml.in.h:945 msgid "Volume of Regular Tetrahedron" msgstr "Volym för en liksidig tetrahedron" -#: ../data/functions.xml.in.h:933 +#: ../data/functions.xml.in.h:946 msgid "r:tetrahedron" msgstr "" -#: ../data/functions.xml.in.h:934 +#: ../data/functions.xml.in.h:947 msgid "Surface Area of Regular Tetrahedron" msgstr "Ytarea för en liksidig tetrahedron" -#: ../data/functions.xml.in.h:935 +#: ../data/functions.xml.in.h:948 msgid "r:tetrahedron_sa" msgstr "tetrahedronyta" -#: ../data/functions.xml.in.h:936 +#: ../data/functions.xml.in.h:949 msgid "Height of Regular Tetrahedron" msgstr "Höjden på en liksidig tetrahedron" -#: ../data/functions.xml.in.h:937 +#: ../data/functions.xml.in.h:950 msgid "r:tetrahedron_height" msgstr "tetrahedronhöjd" -#: ../data/functions.xml.in.h:938 +#: ../data/functions.xml.in.h:951 msgid "Volume of Square Pyramid" msgstr "Volym för en kvadratisk pyramid" -#: ../data/functions.xml.in.h:939 +#: ../data/functions.xml.in.h:952 msgid "r:sqpyramid" msgstr "kvpyramid" -#: ../data/functions.xml.in.h:940 +#: ../data/functions.xml.in.h:953 msgid "Surface Area of Square Pyramid" msgstr "Ytarea för en kvadratisk pyramid" -#: ../data/functions.xml.in.h:941 +#: ../data/functions.xml.in.h:954 msgid "r:sqpyramid_sa" msgstr "kvpyramidyta" -#: ../data/functions.xml.in.h:942 +#: ../data/functions.xml.in.h:955 msgid "Height of Square Pyramid" msgstr "Höjden på en kvadratisk pyramid" -#: ../data/functions.xml.in.h:943 +#: ../data/functions.xml.in.h:956 msgid "r:sqpyramid_height" msgstr "kvpyramidhöjd" -#: ../data/functions.xml.in.h:944 +#: ../data/functions.xml.in.h:957 msgid "Parallelogram" msgstr "Parallelogram" -#: ../data/functions.xml.in.h:945 +#: ../data/functions.xml.in.h:958 msgid "Parallelogram Area" msgstr "Parallelogramarea" -#: ../data/functions.xml.in.h:946 +#: ../data/functions.xml.in.h:959 msgid "r:parallelogram" msgstr "parallellogram" -#: ../data/functions.xml.in.h:947 +#: ../data/functions.xml.in.h:960 msgid "" "Calculates the area of a four-sided figure whose opposite sides are both " "parallel and equal in length." @@ -6819,15 +6887,15 @@ "Beräknar arean för en fyrsidig figur vars motstående sidor är parallella och " "är lika långa." -#: ../data/functions.xml.in.h:948 +#: ../data/functions.xml.in.h:961 msgid "Parallelogram Perimeter" msgstr "Parallelogramomkrets" -#: ../data/functions.xml.in.h:949 +#: ../data/functions.xml.in.h:962 msgid "r:parallelogram_perimeter" msgstr "parallellogramomkrets" -#: ../data/functions.xml.in.h:950 +#: ../data/functions.xml.in.h:963 msgid "" "Calculates the perimeter of a four-sided figure whose opposite sides are " "both parallel and equal in length." @@ -6835,39 +6903,39 @@ "Beräknar omkretsen för en fyrsidig figur vars motstående sidor är både " "parallella och lika långa." -#: ../data/functions.xml.in.h:951 +#: ../data/functions.xml.in.h:964 msgid "Trapezoid" msgstr "Trapetsoid" -#: ../data/functions.xml.in.h:952 +#: ../data/functions.xml.in.h:965 msgid "Trapezoid Area" msgstr "Trapetsoidarea" -#: ../data/functions.xml.in.h:953 +#: ../data/functions.xml.in.h:966 msgid "r:trapezoid" msgstr "trapetsoid" -#: ../data/functions.xml.in.h:954 +#: ../data/functions.xml.in.h:967 msgid "Calculates the area of a four-sided figure with two parallel sides." msgstr "Beräknar arean för en fyrsidig figur med två parallella sidor." -#: ../data/functions.xml.in.h:955 +#: ../data/functions.xml.in.h:968 msgid "Economics" msgstr "Ekonomi" -#: ../data/functions.xml.in.h:956 +#: ../data/functions.xml.in.h:969 msgid "Microeconomics" msgstr "Mikroekonomi" -#: ../data/functions.xml.in.h:957 +#: ../data/functions.xml.in.h:970 msgid "Elasticity" msgstr "Elasticitet" -#: ../data/functions.xml.in.h:958 +#: ../data/functions.xml.in.h:971 msgid "r:elasticity" msgstr "elasticitet" -#: ../data/functions.xml.in.h:959 +#: ../data/functions.xml.in.h:972 msgid "" "Calculates the demand elasticity. Also works for supply elasticity, income " "elasticity, cross-price elasticity, etc. Just replace demand with supply, or " @@ -6881,27 +6949,27 @@ "efterfrågeelasticiteten när priset är 3 för functionen \"Q = 100 - x^2\" där " "x är den förvalda prisvariabeln." -#: ../data/functions.xml.in.h:960 +#: ../data/functions.xml.in.h:973 msgid "Demand function" msgstr "Efterfrågefunktion" -#: ../data/functions.xml.in.h:961 +#: ../data/functions.xml.in.h:974 msgid "Price" msgstr "Pris" -#: ../data/functions.xml.in.h:962 +#: ../data/functions.xml.in.h:975 msgid "Price variable" msgstr "Prisvariabel" -#: ../data/functions.xml.in.h:963 +#: ../data/functions.xml.in.h:976 msgid "Sum-of-Years Digits Depreciation" msgstr "Årlig avskrivningssumma" -#: ../data/functions.xml.in.h:964 +#: ../data/functions.xml.in.h:977 msgid "r:syd" msgstr "" -#: ../data/functions.xml.in.h:965 +#: ../data/functions.xml.in.h:978 msgid "" "Calculates the sum-of-years digits depreciation for an asset based on its " "cost, salvage value, anticipated life, and a particular period. This method " @@ -6916,31 +6984,31 @@ "Den avskrivbara kostnaden är den faktiskta kostnaden minus slutvärdet. " "Livslängden är den period (anges ofta i år) som värdeminskningen pågår." -#: ../data/functions.xml.in.h:966 +#: ../data/functions.xml.in.h:979 msgid "Cost" msgstr "Kostnad" -#: ../data/functions.xml.in.h:967 +#: ../data/functions.xml.in.h:980 msgid "Salvage value" msgstr "Slutvärde" -#: ../data/functions.xml.in.h:968 +#: ../data/functions.xml.in.h:981 msgid "Life" msgstr "Livslängd" -#: ../data/functions.xml.in.h:969 +#: ../data/functions.xml.in.h:982 msgid "Period" msgstr "Period" -#: ../data/functions.xml.in.h:970 +#: ../data/functions.xml.in.h:983 msgid "Straight Line Depreciation" msgstr "Linjär avskrivning" -#: ../data/functions.xml.in.h:971 +#: ../data/functions.xml.in.h:984 msgid "r:sln" msgstr "" -#: ../data/functions.xml.in.h:972 +#: ../data/functions.xml.in.h:985 msgid "" "Determines the straight line depreciation of an asset for a single period." " Cost is the amount you paid for the asset. Salvage is the value of " @@ -6949,164 +7017,164 @@ "asset." msgstr "" -#: ../data/functions.xml.in.h:973 +#: ../data/functions.xml.in.h:986 msgid "Present Value" msgstr "Nuvärde" -#: ../data/functions.xml.in.h:974 +#: ../data/functions.xml.in.h:987 msgid "r:pv" msgstr "" -#: ../data/functions.xml.in.h:975 +#: ../data/functions.xml.in.h:988 msgid "" "Returns the present value of an investment. If type = 1 then the " "payment is made at the beginning of the period, If type = 0 (or omitted) it " "is made at the end of each period." msgstr "" -#: ../data/functions.xml.in.h:976 +#: ../data/functions.xml.in.h:989 msgid "Interest rate" msgstr "Räntesats" -#: ../data/functions.xml.in.h:977 +#: ../data/functions.xml.in.h:990 msgid "Number of periods" msgstr "Antal perioder" -#: ../data/functions.xml.in.h:978 +#: ../data/functions.xml.in.h:991 msgid "Payment made each period" msgstr "Periodisk avbetalning " -#: ../data/functions.xml.in.h:979 +#: ../data/functions.xml.in.h:992 msgid "Future value" msgstr "Framtida värde" -#: ../data/functions.xml.in.h:980 +#: ../data/functions.xml.in.h:993 msgid "Type" msgstr "Typ" -#: ../data/functions.xml.in.h:981 +#: ../data/functions.xml.in.h:994 msgid "Nominal Interest Rate" msgstr "Nominell räntesats" -#: ../data/functions.xml.in.h:982 +#: ../data/functions.xml.in.h:995 msgid "r:nominal" msgstr "" -#: ../data/functions.xml.in.h:983 +#: ../data/functions.xml.in.h:996 msgid "" "Calculates the nominal interest rate from a given effective interest rate " "compounded at given intervals." msgstr "Beräknar den nominella räntesatsen från en given effektiv ränta." -#: ../data/functions.xml.in.h:984 +#: ../data/functions.xml.in.h:997 msgid "Effective interest rate" msgstr "Effektiv räntesats" -#: ../data/functions.xml.in.h:985 +#: ../data/functions.xml.in.h:998 msgid "Periods" msgstr "Antal perioder" -#: ../data/functions.xml.in.h:986 +#: ../data/functions.xml.in.h:999 msgid "Zero Coupon" msgstr "Nollkupong" -#: ../data/functions.xml.in.h:987 +#: ../data/functions.xml.in.h:1000 msgid "r:zero_coupon" msgstr "" -#: ../data/functions.xml.in.h:988 +#: ../data/functions.xml.in.h:1001 msgid "Calculates the value of a zero-coupon (pure discount) bond." msgstr "" -#: ../data/functions.xml.in.h:989 +#: ../data/functions.xml.in.h:1002 msgid "Face value" msgstr "Nominellt värde" -#: ../data/functions.xml.in.h:990 +#: ../data/functions.xml.in.h:1003 msgid "Treasury Bill Yield" msgstr "Avkastningen för statsskuldväxel" -#: ../data/functions.xml.in.h:991 +#: ../data/functions.xml.in.h:1004 msgid "r:tbillyield" msgstr "" -#: ../data/functions.xml.in.h:992 +#: ../data/functions.xml.in.h:1005 msgid "Returns the yield for a treasury bill." msgstr "" -#: ../data/functions.xml.in.h:993 +#: ../data/functions.xml.in.h:1006 msgid "Settlement date" msgstr "Avräkningsdatum" -#: ../data/functions.xml.in.h:994 +#: ../data/functions.xml.in.h:1007 msgid "Maturity date" msgstr "Mognadsdatum" -#: ../data/functions.xml.in.h:995 +#: ../data/functions.xml.in.h:1008 msgid "Price per $100 face value" msgstr "Pris per 100 kr nominellt värde" -#: ../data/functions.xml.in.h:996 +#: ../data/functions.xml.in.h:1009 msgid "Treasury Bill Price" msgstr "Värde för statsskuldväxel" -#: ../data/functions.xml.in.h:997 +#: ../data/functions.xml.in.h:1010 msgid "r:tbillprice" msgstr "" -#: ../data/functions.xml.in.h:998 +#: ../data/functions.xml.in.h:1011 msgid "Returns the price per $100 value for a treasury bill." msgstr "" -#: ../data/functions.xml.in.h:999 +#: ../data/functions.xml.in.h:1012 msgid "Discount rate" msgstr "Diskonto" -#: ../data/functions.xml.in.h:1000 +#: ../data/functions.xml.in.h:1013 msgid "Treasury Bill Equivalent" msgstr "Statsskultväxelavkastning motsvarande obligation" -#: ../data/functions.xml.in.h:1001 +#: ../data/functions.xml.in.h:1014 msgid "r:tbilleq" msgstr "" -#: ../data/functions.xml.in.h:1002 +#: ../data/functions.xml.in.h:1015 msgid "Returns the bond equivalent for a treasury bill." msgstr "" -#: ../data/functions.xml.in.h:1003 +#: ../data/functions.xml.in.h:1016 msgid "Interest paid on a given period of an investment (ISPMT)" msgstr "Ränta betalad under specifik betalningsperiod (ISPMT)" -#: ../data/functions.xml.in.h:1004 +#: ../data/functions.xml.in.h:1017 msgid "r:ispmt" msgstr "" -#: ../data/functions.xml.in.h:1005 +#: ../data/functions.xml.in.h:1018 msgid "Calculates the interest paid on a given period of an investment." msgstr "Beräknar den betalda räntan för en viss period av en investering." -#: ../data/functions.xml.in.h:1006 +#: ../data/functions.xml.in.h:1019 msgid "Periodic interest rate" msgstr "Periodisk räntesats" -#: ../data/functions.xml.in.h:1007 +#: ../data/functions.xml.in.h:1020 msgid "Amortizement period" msgstr "Amorteringsperiod" -#: ../data/functions.xml.in.h:1008 +#: ../data/functions.xml.in.h:1021 msgid "Present value" msgstr "Nuvärde" -#: ../data/functions.xml.in.h:1009 +#: ../data/functions.xml.in.h:1022 msgid "Payment for a loan" msgstr "Betalning för ett lån" -#: ../data/functions.xml.in.h:1010 +#: ../data/functions.xml.in.h:1023 msgid "r:pmt" msgstr "" -#: ../data/functions.xml.in.h:1011 +#: ../data/functions.xml.in.h:1024 msgid "" "Returns the amount of payment (negative) each period for a loan based on a " "constant interest rate and constant payments (each payment is equal amount)." @@ -7127,19 +7195,19 @@ "dela årsräntan med 12 och ange det totala antalet månader (12 gånger antalet " "år) i fältet för period." -#: ../data/functions.xml.in.h:1012 +#: ../data/functions.xml.in.h:1025 msgid "Rate" msgstr "Räntesats" -#: ../data/functions.xml.in.h:1013 +#: ../data/functions.xml.in.h:1026 msgid "Periods of an investment" msgstr "Perioder för en investering" -#: ../data/functions.xml.in.h:1014 +#: ../data/functions.xml.in.h:1027 msgid "r:nper" msgstr "" -#: ../data/functions.xml.in.h:1015 +#: ../data/functions.xml.in.h:1028 msgid "" "Calculates number of periods of an investment based on periodic constant " "payments and a constant interest rate. Type defines the due date. 1 " @@ -7151,15 +7219,15 @@ "för betalning i början av perioden och 0 (förvald) för betalning i slutet av " "perioden." -#: ../data/functions.xml.in.h:1016 +#: ../data/functions.xml.in.h:1029 msgid "Periods for investment to attain desired value" msgstr "Perioder för investering att uppnå önskat värde" -#: ../data/functions.xml.in.h:1017 +#: ../data/functions.xml.in.h:1030 msgid "r:g_duration" msgstr "" -#: ../data/functions.xml.in.h:1018 +#: ../data/functions.xml.in.h:1031 msgid "" "Returns the number of periods needed for an investment to attain a desired " "value." @@ -7167,15 +7235,15 @@ "Returnerar antalet perioder som krävs för en investering att uppnå ett " "önskat värde." -#: ../data/functions.xml.in.h:1019 +#: ../data/functions.xml.in.h:1032 msgid "Payment of an annuity going towards principal (PPMT)" msgstr "Betalning för livränta som går mot kapital (PPMT)" -#: ../data/functions.xml.in.h:1020 +#: ../data/functions.xml.in.h:1033 msgid "r:ppmt" msgstr "" -#: ../data/functions.xml.in.h:1021 +#: ../data/functions.xml.in.h:1034 msgid "" "Calculates the amount of a payment of an annuity going towards principal." " Type defines the due date. 1 for payment at the beginning of a " @@ -7185,35 +7253,35 @@ "Typ anger när betalningarna sker. 1 för betalning i början av perioden och 0 " "(förvald) för betalning i slutet av perioden." -#: ../data/functions.xml.in.h:1022 +#: ../data/functions.xml.in.h:1035 msgid "Desired future value" msgstr "Önskat framtida värde" -#: ../data/functions.xml.in.h:1023 +#: ../data/functions.xml.in.h:1036 msgid "Effective Interest Rate" msgstr "Effektiv räntesats" -#: ../data/functions.xml.in.h:1024 +#: ../data/functions.xml.in.h:1037 msgid "r:effect" msgstr "" -#: ../data/functions.xml.in.h:1025 +#: ../data/functions.xml.in.h:1038 msgid "Calculates the effective interest for a given nominal rate." msgstr "Beräknar den effektiva räntan från en given nominell räntesats." -#: ../data/functions.xml.in.h:1026 +#: ../data/functions.xml.in.h:1039 msgid "Nominal interest rate" msgstr "Nominell räntesats" -#: ../data/functions.xml.in.h:1027 +#: ../data/functions.xml.in.h:1040 msgid "Future Value" msgstr "Framtida värde" -#: ../data/functions.xml.in.h:1028 +#: ../data/functions.xml.in.h:1041 msgid "r:fv" msgstr "" -#: ../data/functions.xml.in.h:1029 +#: ../data/functions.xml.in.h:1042 msgid "" "Computes the future value of an investment. This is based on periodic, " "constant payments and a constant interest rate. If type = 1 then " @@ -7225,51 +7293,51 @@ "för betalning i början av perioden och 0 (förvald) för betalning i slutet av " "perioden." -#: ../data/functions.xml.in.h:1030 +#: ../data/functions.xml.in.h:1043 msgid "Return on continuously compounded interest" msgstr "Avkastning på fortlöpande sammansatt ränta" -#: ../data/functions.xml.in.h:1031 +#: ../data/functions.xml.in.h:1044 msgid "r:continuous" msgstr "" -#: ../data/functions.xml.in.h:1032 +#: ../data/functions.xml.in.h:1045 msgid "" "Calculates the return on continuously compounded interest, given the " "principal, nominal rate and time in years." msgstr "" -#: ../data/functions.xml.in.h:1033 +#: ../data/functions.xml.in.h:1046 msgid "Principal" msgstr "" -#: ../data/functions.xml.in.h:1034 +#: ../data/functions.xml.in.h:1047 msgid "Compound" msgstr "Sammansatt" -#: ../data/functions.xml.in.h:1035 +#: ../data/functions.xml.in.h:1048 msgid "r:compound" msgstr "" -#: ../data/functions.xml.in.h:1036 +#: ../data/functions.xml.in.h:1049 msgid "" "Returns the value of an investment, given the principal, nominal interest " "rate, compounding frequency and time." msgstr "" -#: ../data/functions.xml.in.h:1037 +#: ../data/functions.xml.in.h:1050 msgid "Periods per year" msgstr "Perioder per år" -#: ../data/functions.xml.in.h:1038 +#: ../data/functions.xml.in.h:1051 msgid "Payment of an annuity going towards interest (IPMT)" msgstr "Betalning för livränta som går mot ränta (IPMT)" -#: ../data/functions.xml.in.h:1039 +#: ../data/functions.xml.in.h:1052 msgid "r:ipmt" msgstr "" -#: ../data/functions.xml.in.h:1040 +#: ../data/functions.xml.in.h:1053 msgid "" "Calculates the amount of a payment of an annuity going towards interest. " " Type defines the due date. 1 for payment at the beginning of a period " @@ -7279,77 +7347,77 @@ "Typ anger när betalningarna sker. 1 för betalning i början av perioden och 0 " "(förvald) för betalning i slutet av perioden." -#: ../data/functions.xml.in.h:1041 +#: ../data/functions.xml.in.h:1054 msgid "Interest rate for a fully invested security" msgstr "Räntesats för betalt värdepapper" -#: ../data/functions.xml.in.h:1042 +#: ../data/functions.xml.in.h:1055 msgid "r:intrate" msgstr "" -#: ../data/functions.xml.in.h:1043 +#: ../data/functions.xml.in.h:1056 msgid "" "Returns the interest rate for a fully invested security. Basis is " "the type of day counting you want to use: 0: US 30/360 (default), 1: real " "days, 2: real days/360, 3: real days/365 or 4: European 30/360." msgstr "" -#: ../data/functions.xml.in.h:1044 +#: ../data/functions.xml.in.h:1057 msgid "Investment" msgstr "Investering" -#: ../data/functions.xml.in.h:1045 +#: ../data/functions.xml.in.h:1058 msgid "Redemption" msgstr "Utlösande summa" -#: ../data/functions.xml.in.h:1046 +#: ../data/functions.xml.in.h:1059 msgid "Dollar Fraction" msgstr "Kronor till bråktal" -#: ../data/functions.xml.in.h:1047 +#: ../data/functions.xml.in.h:1060 msgid "r:dollarfr" msgstr "" -#: ../data/functions.xml.in.h:1048 +#: ../data/functions.xml.in.h:1061 msgid "" "Converts a decimal dollar price into a dollar price expressed as a fraction." msgstr "" -#: ../data/functions.xml.in.h:1049 +#: ../data/functions.xml.in.h:1062 msgid "Decimal dollar" msgstr "Bråktal till kronor" -#: ../data/functions.xml.in.h:1050 +#: ../data/functions.xml.in.h:1063 msgid "Denominator of fraction" msgstr "Bråktalets nämnare " -#: ../data/functions.xml.in.h:1051 +#: ../data/functions.xml.in.h:1064 msgid "Dollar Decimal" msgstr "Decimaltal" -#: ../data/functions.xml.in.h:1052 +#: ../data/functions.xml.in.h:1065 msgid "r:dollarde" msgstr "" -#: ../data/functions.xml.in.h:1053 +#: ../data/functions.xml.in.h:1066 msgid "" "Converts a dollar price expressed as a fraction into a dollar price " "expressed as a decimal number." msgstr "" -#: ../data/functions.xml.in.h:1054 +#: ../data/functions.xml.in.h:1067 msgid "Fractional dollar" msgstr "Bråktal" -#: ../data/functions.xml.in.h:1055 +#: ../data/functions.xml.in.h:1068 msgid "Amount received at maturity for a security bond" msgstr "Erhållet belopp för en säkerhet vid mognad" -#: ../data/functions.xml.in.h:1056 +#: ../data/functions.xml.in.h:1069 msgid "r:received" msgstr "" -#: ../data/functions.xml.in.h:1057 +#: ../data/functions.xml.in.h:1070 msgid "" "Returns the amount received at the maturity date for an invested security." " Basis is the type of day counting you want to use: 0: US 30/360 " @@ -7357,30 +7425,30 @@ "30/360. The settlement date must be before maturity date." msgstr "" -#: ../data/functions.xml.in.h:1058 +#: ../data/functions.xml.in.h:1071 msgid "Discount rate for a security" msgstr "Reduceringshastighet för säkerhet" -#: ../data/functions.xml.in.h:1059 +#: ../data/functions.xml.in.h:1072 msgid "r:disc" msgstr "" -#: ../data/functions.xml.in.h:1060 +#: ../data/functions.xml.in.h:1073 msgid "" "Returns the discount rate for a security. Basis is the type of day " "counting you want to use: 0: US 30/360 (default), 1: real days, 2: real " "days/360, 3: real days/365 or 4: European 30/360." msgstr "" -#: ../data/functions.xml.in.h:1061 +#: ../data/functions.xml.in.h:1074 msgid "Accrued interest of security paying at maturity" msgstr "Ränta för en säkerhet från start till mognad" -#: ../data/functions.xml.in.h:1062 +#: ../data/functions.xml.in.h:1075 msgid "r:accrintm" msgstr "" -#: ../data/functions.xml.in.h:1063 +#: ../data/functions.xml.in.h:1076 msgid "" "Returns the accrued interest for a security which pays interest at maturity " "date. Basis is the type of day counting you want to use: 0: US " @@ -7388,27 +7456,27 @@ "European 30/360." msgstr "" -#: ../data/functions.xml.in.h:1064 +#: ../data/functions.xml.in.h:1077 msgid "Issue date" msgstr "Startdatum" -#: ../data/functions.xml.in.h:1065 +#: ../data/functions.xml.in.h:1078 msgid "Annual rate of security" msgstr "Årlig hastighet" -#: ../data/functions.xml.in.h:1066 +#: ../data/functions.xml.in.h:1079 msgid "Par value" msgstr "Nominellt värde" -#: ../data/functions.xml.in.h:1067 +#: ../data/functions.xml.in.h:1080 msgid "Accrued interest of security with periodic interest payments" msgstr "Ränta för en säkerhet med periodisk ränta" -#: ../data/functions.xml.in.h:1068 +#: ../data/functions.xml.in.h:1081 msgid "r:accrint" msgstr "" -#: ../data/functions.xml.in.h:1069 +#: ../data/functions.xml.in.h:1082 msgid "" "Returns accrued interest for a security which pays periodic interest. " " Allowed frequencies are 1 - annual, 2 - semi-annual or 4 - quarterly. " @@ -7416,23 +7484,23 @@ "1: real days, 2: real days/360, 3: real days/365 or 4: European 30/360." msgstr "" -#: ../data/functions.xml.in.h:1070 +#: ../data/functions.xml.in.h:1083 msgid "First interest" msgstr "Första ränteinbetalning" -#: ../data/functions.xml.in.h:1071 +#: ../data/functions.xml.in.h:1084 msgid "Frequency" msgstr "Frekvens" -#: ../data/functions.xml.in.h:1072 +#: ../data/functions.xml.in.h:1085 msgid "Number of coupons to be paid" msgstr "Antal förfallande kuponger" -#: ../data/functions.xml.in.h:1073 +#: ../data/functions.xml.in.h:1086 msgid "r:coupnum" msgstr "" -#: ../data/functions.xml.in.h:1074 +#: ../data/functions.xml.in.h:1087 msgid "" "Returns the number of coupons to be paid between the settlement and the " "maturity. Basis is the type of day counting you want to use: 0: US " @@ -7440,15 +7508,15 @@ "European 30/360." msgstr "" -#: ../data/functions.xml.in.h:1075 +#: ../data/functions.xml.in.h:1088 msgid "Price per $100 face value of a discounted security" msgstr "Pris per 100 kr nominellt värde för diskonterat värdepapper" -#: ../data/functions.xml.in.h:1076 +#: ../data/functions.xml.in.h:1089 msgid "r:pricedisc" msgstr "" -#: ../data/functions.xml.in.h:1077 +#: ../data/functions.xml.in.h:1090 msgid "" "Calculates and returns the price per $100 face value of a discounted " "security. The security does not pay interest at maturity. Basis is " @@ -7460,19 +7528,19 @@ "vara: 0: Amerikanskt 30/360 (förvald), 1: verkliga dagar, 2: verkliga " "dagar/360, 3: verkliga dagar/365, eller 4: Europeiskt 30/360" -#: ../data/functions.xml.in.h:1078 +#: ../data/functions.xml.in.h:1091 msgid "Discount" msgstr "Diskonto" -#: ../data/functions.xml.in.h:1079 +#: ../data/functions.xml.in.h:1092 msgid "Price per $100 face value of a security" msgstr "Pris per 100 kr nominellt värde för säkerhet" -#: ../data/functions.xml.in.h:1080 +#: ../data/functions.xml.in.h:1093 msgid "r:pricemat" msgstr "" -#: ../data/functions.xml.in.h:1081 +#: ../data/functions.xml.in.h:1094 msgid "" "Calculates and returns the price per $100 face value of a security. The " "security pays interest at maturity. Basis is the type of day " @@ -7484,31 +7552,31 @@ "Amerikanskt 30/360 (förvald), 1: verkliga dagar, 2: verkliga dagar/360, 3: " "verkliga dagar/365, eller 4: Europeiskt 30/360" -#: ../data/functions.xml.in.h:1082 +#: ../data/functions.xml.in.h:1095 msgid "Annual yield" msgstr "Årlig avkastning" -#: ../data/functions.xml.in.h:1083 +#: ../data/functions.xml.in.h:1096 msgid "Level-Coupon Bond" msgstr "Jämn kupongobligation" -#: ../data/functions.xml.in.h:1084 +#: ../data/functions.xml.in.h:1097 msgid "r:level_coupon" msgstr "" -#: ../data/functions.xml.in.h:1085 +#: ../data/functions.xml.in.h:1098 msgid "Calculates the value of a level-coupon bond." msgstr "" -#: ../data/functions.xml.in.h:1086 +#: ../data/functions.xml.in.h:1099 msgid "Coupon rate" msgstr "Kupongränta" -#: ../data/functions.xml.in.h:1087 +#: ../data/functions.xml.in.h:1100 msgid "Coupons per year" msgstr "Antal kuponger per år" -#: ../data/functions.xml.in.h:1088 +#: ../data/functions.xml.in.h:1101 msgid "Market interest rate" msgstr "Marknadsränta" @@ -10798,12 +10866,6 @@ #~ msgid "Supergolden Ratio" #~ msgstr "Supergyllene snittet" -#~ msgid "Belarusian Ruble" -#~ msgstr "Vitrysk rubel" - -#~ msgid "Belarus" -#~ msgstr "Vitryssland" - #~ msgid "Zambian Kwacha" #~ msgstr "Zambisk kwacha" diff -Nru libqalculate-3.6.0/po-defs/zh_CN.po libqalculate-3.7.0/po-defs/zh_CN.po --- libqalculate-3.6.0/po-defs/zh_CN.po 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/po-defs/zh_CN.po 2020-01-21 22:54:40.000000000 +0000 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: zh_CN\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-25 10:28+0100\n" +"POT-Creation-Date: 2020-01-12 11:29+0100\n" "PO-Revision-Date: 2007-08-04 23:40+0800\n" "Last-Translator: Roy Qu \n" "Language-Team: Simplified Chinese\n" @@ -636,1510 +636,1524 @@ msgstr "" #: ../data/currencies.xml.in.h:147 +#, fuzzy +msgid "Belarusian Ruble" +msgstr "俄罗斯卢布" + +#: ../data/currencies.xml.in.h:148 +msgid "ar:BYN" +msgstr "" + +#: ../data/currencies.xml.in.h:149 +#, fuzzy +msgid "Belarus" +msgstr "俄罗斯卢布" + +#: ../data/currencies.xml.in.h:150 msgid "Belarusian Ruble p. (obsolete)" msgstr "" -#: ../data/currencies.xml.in.h:148 +#: ../data/currencies.xml.in.h:151 msgid "ar:BYR" msgstr "" -#: ../data/currencies.xml.in.h:149 +#: ../data/currencies.xml.in.h:152 #, fuzzy msgid "Belize Dollar" msgstr "新加坡元" -#: ../data/currencies.xml.in.h:150 +#: ../data/currencies.xml.in.h:153 msgid "ar:BZD" msgstr "" -#: ../data/currencies.xml.in.h:151 +#: ../data/currencies.xml.in.h:154 msgid "Belize" msgstr "" -#: ../data/currencies.xml.in.h:152 +#: ../data/currencies.xml.in.h:155 #, fuzzy msgid "West African CFA Franc" msgstr "南非兰特" -#: ../data/currencies.xml.in.h:153 +#: ../data/currencies.xml.in.h:156 msgid "ar:XOF,a:CFA" msgstr "" -#: ../data/currencies.xml.in.h:154 +#: ../data/currencies.xml.in.h:157 msgid "" "Benin, Burkina Faso, Guinea-Bissau, Ivory Coast, Mali, Niger, Senegal, Togo" msgstr "" -#: ../data/currencies.xml.in.h:155 +#: ../data/currencies.xml.in.h:158 #, fuzzy msgid "Bermudian Dollar" msgstr "加拿大元" -#: ../data/currencies.xml.in.h:156 +#: ../data/currencies.xml.in.h:159 msgid "ar:BMD" msgstr "" -#: ../data/currencies.xml.in.h:157 +#: ../data/currencies.xml.in.h:160 msgid "Bermuda" msgstr "" -#: ../data/currencies.xml.in.h:158 +#: ../data/currencies.xml.in.h:161 msgid "Bolivian Boliviano Bs" msgstr "" -#: ../data/currencies.xml.in.h:159 +#: ../data/currencies.xml.in.h:162 msgid "ar:BOB" msgstr "" -#: ../data/currencies.xml.in.h:160 +#: ../data/currencies.xml.in.h:163 msgid "Bolivia" msgstr "" -#: ../data/currencies.xml.in.h:161 +#: ../data/currencies.xml.in.h:164 msgid "Bosnia and Herzegovina Convertible Mark" msgstr "" -#: ../data/currencies.xml.in.h:162 +#: ../data/currencies.xml.in.h:165 msgid "ar:BAM" msgstr "" -#: ../data/currencies.xml.in.h:163 +#: ../data/currencies.xml.in.h:166 msgid "Bosnia and Herzegovina" msgstr "" -#: ../data/currencies.xml.in.h:164 +#: ../data/currencies.xml.in.h:167 msgid "Botswana Pula" msgstr "" -#: ../data/currencies.xml.in.h:165 +#: ../data/currencies.xml.in.h:168 msgid "ar:BWP" msgstr "" -#: ../data/currencies.xml.in.h:166 +#: ../data/currencies.xml.in.h:169 msgid "Botswana" msgstr "" -#: ../data/currencies.xml.in.h:167 +#: ../data/currencies.xml.in.h:170 #, fuzzy msgid "Brunei Dollar" msgstr "加拿大元" -#: ../data/currencies.xml.in.h:168 +#: ../data/currencies.xml.in.h:171 msgid "ar:BND" msgstr "" -#: ../data/currencies.xml.in.h:169 +#: ../data/currencies.xml.in.h:172 msgid "Brunei" msgstr "" -#: ../data/currencies.xml.in.h:170 +#: ../data/currencies.xml.in.h:173 #, fuzzy msgid "Burundian Franc" msgstr "比利时法郎" -#: ../data/currencies.xml.in.h:171 +#: ../data/currencies.xml.in.h:174 msgid "ar:BIF" msgstr "" -#: ../data/currencies.xml.in.h:172 +#: ../data/currencies.xml.in.h:175 msgid "Burundi" msgstr "" -#: ../data/currencies.xml.in.h:173 +#: ../data/currencies.xml.in.h:176 msgid "Cambodian Riel" msgstr "" -#: ../data/currencies.xml.in.h:174 +#: ../data/currencies.xml.in.h:177 #, fuzzy msgid "ar:KHR,aiu:៛" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:175 +#: ../data/currencies.xml.in.h:178 msgid "Cambodia" msgstr "" -#: ../data/currencies.xml.in.h:176 +#: ../data/currencies.xml.in.h:179 msgid "Central African CFA Franc" msgstr "" -#: ../data/currencies.xml.in.h:177 +#: ../data/currencies.xml.in.h:180 msgid "ar:XAF,a:FCFA" msgstr "" -#: ../data/currencies.xml.in.h:178 +#: ../data/currencies.xml.in.h:181 msgid "" "Cameroon, Central African Republic, Chad, Republic of the Congo, Equatorial " "Guinea, Gabon" msgstr "" -#: ../data/currencies.xml.in.h:179 +#: ../data/currencies.xml.in.h:182 msgid "Cape Verdean Escudo" msgstr "" -#: ../data/currencies.xml.in.h:180 +#: ../data/currencies.xml.in.h:183 msgid "ar:CVE" msgstr "" -#: ../data/currencies.xml.in.h:181 +#: ../data/currencies.xml.in.h:184 msgid "Cape Verde" msgstr "" -#: ../data/currencies.xml.in.h:182 +#: ../data/currencies.xml.in.h:185 #, fuzzy msgid "Cayman Islands Dollar" msgstr "加拿大元" -#: ../data/currencies.xml.in.h:183 +#: ../data/currencies.xml.in.h:186 #, fuzzy msgid "ar:KYD" msgstr "ar:KRW" -#: ../data/currencies.xml.in.h:184 +#: ../data/currencies.xml.in.h:187 msgid "Cayman Islands" msgstr "" -#: ../data/currencies.xml.in.h:185 +#: ../data/currencies.xml.in.h:188 msgid "Chilean Peso" msgstr "" -#: ../data/currencies.xml.in.h:186 +#: ../data/currencies.xml.in.h:189 msgid "ar:CLP" msgstr "" -#: ../data/currencies.xml.in.h:187 +#: ../data/currencies.xml.in.h:190 msgid "Chile" msgstr "" -#: ../data/currencies.xml.in.h:188 +#: ../data/currencies.xml.in.h:191 #, fuzzy msgid "Colombian Peso" msgstr "组合" -#: ../data/currencies.xml.in.h:189 +#: ../data/currencies.xml.in.h:192 msgid "ar:COP" msgstr "" -#: ../data/currencies.xml.in.h:190 +#: ../data/currencies.xml.in.h:193 #, fuzzy msgid "Colombia" msgstr "库仑" -#: ../data/currencies.xml.in.h:191 +#: ../data/currencies.xml.in.h:194 #, fuzzy msgid "Comorian Franc" msgstr "比利时法郎" -#: ../data/currencies.xml.in.h:192 +#: ../data/currencies.xml.in.h:195 #, fuzzy msgid "ar:KMF" msgstr "ar:KRW" -#: ../data/currencies.xml.in.h:193 +#: ../data/currencies.xml.in.h:196 msgid "Comoros" msgstr "" -#: ../data/currencies.xml.in.h:194 +#: ../data/currencies.xml.in.h:197 msgid "Democratic Republic of the Congo (Congolese Franc)" msgstr "" -#: ../data/currencies.xml.in.h:195 +#: ../data/currencies.xml.in.h:198 msgid "ar:CDF" msgstr "" -#: ../data/currencies.xml.in.h:196 +#: ../data/currencies.xml.in.h:199 msgid "Democratic Republic of the Congo" msgstr "" -#: ../data/currencies.xml.in.h:197 +#: ../data/currencies.xml.in.h:200 msgid "Costa Rican colón" msgstr "" -#: ../data/currencies.xml.in.h:198 +#: ../data/currencies.xml.in.h:201 msgid "ar:CRC" msgstr "" -#: ../data/currencies.xml.in.h:199 +#: ../data/currencies.xml.in.h:202 msgid "Costa Rica" msgstr "" -#: ../data/currencies.xml.in.h:200 +#: ../data/currencies.xml.in.h:203 msgid "Cuban Peso" msgstr "" -#: ../data/currencies.xml.in.h:201 +#: ../data/currencies.xml.in.h:204 msgid "ar:CUP" msgstr "" -#: ../data/currencies.xml.in.h:202 +#: ../data/currencies.xml.in.h:205 msgid "Cuba" msgstr "" -#: ../data/currencies.xml.in.h:203 +#: ../data/currencies.xml.in.h:206 #, fuzzy msgid "Djiboutian Franc" msgstr "比利时法郎" -#: ../data/currencies.xml.in.h:204 +#: ../data/currencies.xml.in.h:207 #, fuzzy msgid "ar:DJF" msgstr "a:DEM,马克" -#: ../data/currencies.xml.in.h:205 +#: ../data/currencies.xml.in.h:208 msgid "Djibouti" msgstr "" -#: ../data/currencies.xml.in.h:206 +#: ../data/currencies.xml.in.h:209 msgid "Dominican Peso" msgstr "" -#: ../data/currencies.xml.in.h:207 +#: ../data/currencies.xml.in.h:210 #, fuzzy msgid "ar:DOP" msgstr "a:DEM,马克" -#: ../data/currencies.xml.in.h:208 +#: ../data/currencies.xml.in.h:211 msgid "Dominican Republic" msgstr "" -#: ../data/currencies.xml.in.h:209 +#: ../data/currencies.xml.in.h:212 #, fuzzy msgid "Egyptian Pound" msgstr "塞浦路斯镑" -#: ../data/currencies.xml.in.h:210 +#: ../data/currencies.xml.in.h:213 #, fuzzy msgid "ar:EGP" msgstr "ar:EEK" -#: ../data/currencies.xml.in.h:211 +#: ../data/currencies.xml.in.h:214 msgid "Egypt" msgstr "" -#: ../data/currencies.xml.in.h:212 +#: ../data/currencies.xml.in.h:215 msgid "El Salvadoran Colon (obsolete)" msgstr "" -#: ../data/currencies.xml.in.h:213 +#: ../data/currencies.xml.in.h:216 #, fuzzy msgid "ar:SVC" msgstr "tolar,ar:SIT" -#: ../data/currencies.xml.in.h:214 +#: ../data/currencies.xml.in.h:217 msgid "Eritrean Nafka" msgstr "" -#: ../data/currencies.xml.in.h:215 +#: ../data/currencies.xml.in.h:218 #, fuzzy msgid "ar:ERN" msgstr "ar:EEK" -#: ../data/currencies.xml.in.h:216 +#: ../data/currencies.xml.in.h:219 msgid "Eritrea" msgstr "" -#: ../data/currencies.xml.in.h:217 +#: ../data/currencies.xml.in.h:220 msgid "Ethiopian Birr" msgstr "" -#: ../data/currencies.xml.in.h:218 +#: ../data/currencies.xml.in.h:221 #, fuzzy msgid "ar:ETB" msgstr "ar:EEK" -#: ../data/currencies.xml.in.h:219 +#: ../data/currencies.xml.in.h:222 msgid "Ethiopia" msgstr "" -#: ../data/currencies.xml.in.h:220 +#: ../data/currencies.xml.in.h:223 msgid "Falkland Islands Pound" msgstr "" -#: ../data/currencies.xml.in.h:221 +#: ../data/currencies.xml.in.h:224 msgid "ar:FKP" msgstr "" -#: ../data/currencies.xml.in.h:222 +#: ../data/currencies.xml.in.h:225 msgid "Falkland Islands" msgstr "" -#: ../data/currencies.xml.in.h:223 +#: ../data/currencies.xml.in.h:226 #, fuzzy msgid "Fijian Dollar" msgstr "加拿大元" -#: ../data/currencies.xml.in.h:224 +#: ../data/currencies.xml.in.h:227 msgid "ar:FJD" msgstr "" -#: ../data/currencies.xml.in.h:225 +#: ../data/currencies.xml.in.h:228 msgid "Fiji" msgstr "" -#: ../data/currencies.xml.in.h:226 +#: ../data/currencies.xml.in.h:229 msgid "CFP franc" msgstr "" -#: ../data/currencies.xml.in.h:227 +#: ../data/currencies.xml.in.h:230 msgid "ar:XPF" msgstr "" -#: ../data/currencies.xml.in.h:228 +#: ../data/currencies.xml.in.h:231 msgid "French Polynesia, New Caledonia, Wallis and Futuna" msgstr "" -#: ../data/currencies.xml.in.h:229 +#: ../data/currencies.xml.in.h:232 #, fuzzy msgid "Gambian Dalasi" msgstr "加拿大元" -#: ../data/currencies.xml.in.h:230 +#: ../data/currencies.xml.in.h:233 #, fuzzy msgid "ar:GMD" msgstr "ar:GRD" -#: ../data/currencies.xml.in.h:231 +#: ../data/currencies.xml.in.h:234 msgid "Gambia" msgstr "" -#: ../data/currencies.xml.in.h:232 +#: ../data/currencies.xml.in.h:235 msgid "Georgian Lari" msgstr "" -#: ../data/currencies.xml.in.h:233 +#: ../data/currencies.xml.in.h:236 #, fuzzy msgid "ar:GEL,au:₾" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:234 +#: ../data/currencies.xml.in.h:237 msgid "Georgia" msgstr "" -#: ../data/currencies.xml.in.h:235 +#: ../data/currencies.xml.in.h:238 msgid "Ghanaian Cedi" msgstr "" -#: ../data/currencies.xml.in.h:236 +#: ../data/currencies.xml.in.h:239 #, fuzzy msgid "ar:GHS,au:₵" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:237 +#: ../data/currencies.xml.in.h:240 msgid "Ghana" msgstr "" -#: ../data/currencies.xml.in.h:238 +#: ../data/currencies.xml.in.h:241 msgid "Gibraltar Pound" msgstr "" -#: ../data/currencies.xml.in.h:239 +#: ../data/currencies.xml.in.h:242 #, fuzzy msgid "ar:GIP" msgstr "ar:GRD" -#: ../data/currencies.xml.in.h:240 +#: ../data/currencies.xml.in.h:243 msgid "Gibraltar" msgstr "" -#: ../data/currencies.xml.in.h:241 +#: ../data/currencies.xml.in.h:244 msgid "Guatemalan Quetzal" msgstr "" -#: ../data/currencies.xml.in.h:242 +#: ../data/currencies.xml.in.h:245 #, fuzzy msgid "ar:GTQ" msgstr "ar:GRD" -#: ../data/currencies.xml.in.h:243 +#: ../data/currencies.xml.in.h:246 msgid "Guatemala" msgstr "" -#: ../data/currencies.xml.in.h:244 +#: ../data/currencies.xml.in.h:247 #, fuzzy msgid "Guernsey Pound" msgstr "爱尔兰镑" -#: ../data/currencies.xml.in.h:245 +#: ../data/currencies.xml.in.h:248 #, fuzzy msgid "ar:GGP" msgstr "ar:GRD" -#: ../data/currencies.xml.in.h:246 +#: ../data/currencies.xml.in.h:249 msgid "Guernsey" msgstr "" -#: ../data/currencies.xml.in.h:247 +#: ../data/currencies.xml.in.h:250 #, fuzzy msgid "Guinean Franc" msgstr "比利时法郎" -#: ../data/currencies.xml.in.h:248 +#: ../data/currencies.xml.in.h:251 #, fuzzy msgid "ar:GNF" msgstr "ar:GRD" -#: ../data/currencies.xml.in.h:249 +#: ../data/currencies.xml.in.h:252 msgid "Guinea" msgstr "" -#: ../data/currencies.xml.in.h:250 +#: ../data/currencies.xml.in.h:253 #, fuzzy msgid "Guyanese Dollar" msgstr "澳大利亚元" -#: ../data/currencies.xml.in.h:251 +#: ../data/currencies.xml.in.h:254 #, fuzzy msgid "ar:GYD" msgstr "ar:GRD" -#: ../data/currencies.xml.in.h:252 +#: ../data/currencies.xml.in.h:255 msgid "Guyana" msgstr "" -#: ../data/currencies.xml.in.h:253 +#: ../data/currencies.xml.in.h:256 msgid "Haitian Gourde" msgstr "" -#: ../data/currencies.xml.in.h:254 +#: ../data/currencies.xml.in.h:257 msgid "ar:HTG" msgstr "" -#: ../data/currencies.xml.in.h:255 +#: ../data/currencies.xml.in.h:258 msgid "Haiti" msgstr "" -#: ../data/currencies.xml.in.h:256 +#: ../data/currencies.xml.in.h:259 msgid "Honduran Lempira" msgstr "" -#: ../data/currencies.xml.in.h:257 +#: ../data/currencies.xml.in.h:260 msgid "ar:HNL" msgstr "" -#: ../data/currencies.xml.in.h:258 +#: ../data/currencies.xml.in.h:261 msgid "Honduras" msgstr "" -#: ../data/currencies.xml.in.h:259 +#: ../data/currencies.xml.in.h:262 #, fuzzy msgid "Iranian Rial" msgstr "意大利里拉" -#: ../data/currencies.xml.in.h:260 +#: ../data/currencies.xml.in.h:263 #, fuzzy msgid "ar:IRR,aiu:﷼" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:261 +#: ../data/currencies.xml.in.h:264 msgid "Iran" msgstr "" -#: ../data/currencies.xml.in.h:262 +#: ../data/currencies.xml.in.h:265 msgid "Iraqi Dinar" msgstr "" -#: ../data/currencies.xml.in.h:263 +#: ../data/currencies.xml.in.h:266 msgid "ar:IQD" msgstr "" -#: ../data/currencies.xml.in.h:264 +#: ../data/currencies.xml.in.h:267 msgid "Iraq" msgstr "" -#: ../data/currencies.xml.in.h:265 +#: ../data/currencies.xml.in.h:268 #, fuzzy msgid "Jamaican Dollar" msgstr "加拿大元" -#: ../data/currencies.xml.in.h:266 +#: ../data/currencies.xml.in.h:269 msgid "ar:JMD" msgstr "" -#: ../data/currencies.xml.in.h:267 +#: ../data/currencies.xml.in.h:270 msgid "Jamaica" msgstr "" -#: ../data/currencies.xml.in.h:268 +#: ../data/currencies.xml.in.h:271 msgid "Jordanian Dinar" msgstr "" -#: ../data/currencies.xml.in.h:269 +#: ../data/currencies.xml.in.h:272 msgid "ar:JOD" msgstr "" -#: ../data/currencies.xml.in.h:270 +#: ../data/currencies.xml.in.h:273 msgid "Jordan" msgstr "" -#: ../data/currencies.xml.in.h:271 +#: ../data/currencies.xml.in.h:274 msgid "Kazakhstani Tenge" msgstr "" -#: ../data/currencies.xml.in.h:272 +#: ../data/currencies.xml.in.h:275 #, fuzzy msgid "ar:KZT,au:₸" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:273 +#: ../data/currencies.xml.in.h:276 msgid "Kazakhstan" msgstr "" -#: ../data/currencies.xml.in.h:274 +#: ../data/currencies.xml.in.h:277 #, fuzzy msgid "North Korean Won" msgstr "韩元" -#: ../data/currencies.xml.in.h:275 +#: ../data/currencies.xml.in.h:278 #, fuzzy msgid "ar:KPW" msgstr "ar:KRW" -#: ../data/currencies.xml.in.h:276 +#: ../data/currencies.xml.in.h:279 #, fuzzy msgid "North Korea" msgstr "韩元" -#: ../data/currencies.xml.in.h:277 +#: ../data/currencies.xml.in.h:280 msgid "Kuwaiti Dinar" msgstr "" -#: ../data/currencies.xml.in.h:278 +#: ../data/currencies.xml.in.h:281 #, fuzzy msgid "ar:KWD" msgstr "ar:KRW" -#: ../data/currencies.xml.in.h:279 +#: ../data/currencies.xml.in.h:282 msgid "Kuwait" msgstr "" -#: ../data/currencies.xml.in.h:280 +#: ../data/currencies.xml.in.h:283 msgid "Kyrgyzstani Som" msgstr "" -#: ../data/currencies.xml.in.h:281 +#: ../data/currencies.xml.in.h:284 #, fuzzy msgid "ar:KGS,au:с" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:282 +#: ../data/currencies.xml.in.h:285 msgid "Kyrgyzstan" msgstr "" -#: ../data/currencies.xml.in.h:283 +#: ../data/currencies.xml.in.h:286 msgid "Lao Kip" msgstr "" -#: ../data/currencies.xml.in.h:284 +#: ../data/currencies.xml.in.h:287 #, fuzzy msgid "ar:LAK,au:₭" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:285 +#: ../data/currencies.xml.in.h:288 msgid "Laos" msgstr "" -#: ../data/currencies.xml.in.h:286 +#: ../data/currencies.xml.in.h:289 msgid "Lebanese Pound" msgstr "" -#: ../data/currencies.xml.in.h:287 +#: ../data/currencies.xml.in.h:290 msgid "ar:LBP" msgstr "" -#: ../data/currencies.xml.in.h:288 +#: ../data/currencies.xml.in.h:291 msgid "Lebanon" msgstr "" -#: ../data/currencies.xml.in.h:289 +#: ../data/currencies.xml.in.h:292 msgid "Lesotho Loti" msgstr "" -#: ../data/currencies.xml.in.h:290 +#: ../data/currencies.xml.in.h:293 msgid "ar:LSL" msgstr "" -#: ../data/currencies.xml.in.h:291 +#: ../data/currencies.xml.in.h:294 msgid "Lesotho" msgstr "" -#: ../data/currencies.xml.in.h:292 +#: ../data/currencies.xml.in.h:295 #, fuzzy msgid "Liberian Dollar" msgstr "澳大利亚元" -#: ../data/currencies.xml.in.h:293 +#: ../data/currencies.xml.in.h:296 msgid "ar:LRD" msgstr "" -#: ../data/currencies.xml.in.h:294 +#: ../data/currencies.xml.in.h:297 msgid "Liberia" msgstr "" -#: ../data/currencies.xml.in.h:295 +#: ../data/currencies.xml.in.h:298 msgid "Libyan Dinar" msgstr "" -#: ../data/currencies.xml.in.h:296 +#: ../data/currencies.xml.in.h:299 msgid "ar:LYD" msgstr "" -#: ../data/currencies.xml.in.h:297 +#: ../data/currencies.xml.in.h:300 msgid "Libya" msgstr "" -#: ../data/currencies.xml.in.h:298 +#: ../data/currencies.xml.in.h:301 msgid "Macanese Pataca" msgstr "" -#: ../data/currencies.xml.in.h:299 +#: ../data/currencies.xml.in.h:302 msgid "ar:MOP" msgstr "" -#: ../data/currencies.xml.in.h:300 +#: ../data/currencies.xml.in.h:303 msgid "Macau" msgstr "" -#: ../data/currencies.xml.in.h:301 +#: ../data/currencies.xml.in.h:304 msgid "Macedonian Denar" msgstr "" -#: ../data/currencies.xml.in.h:302 +#: ../data/currencies.xml.in.h:305 msgid "ar:MKD" msgstr "" -#: ../data/currencies.xml.in.h:303 +#: ../data/currencies.xml.in.h:306 msgid "Macedonia" msgstr "" -#: ../data/currencies.xml.in.h:304 +#: ../data/currencies.xml.in.h:307 msgid "Malagasy Ariary" msgstr "" -#: ../data/currencies.xml.in.h:305 +#: ../data/currencies.xml.in.h:308 msgid "ar:MGA" msgstr "" -#: ../data/currencies.xml.in.h:306 +#: ../data/currencies.xml.in.h:309 msgid "Madagascar" msgstr "" -#: ../data/currencies.xml.in.h:307 +#: ../data/currencies.xml.in.h:310 msgid "Malawian Kwacha" msgstr "" -#: ../data/currencies.xml.in.h:308 +#: ../data/currencies.xml.in.h:311 msgid "ar:MWK" msgstr "" -#: ../data/currencies.xml.in.h:309 +#: ../data/currencies.xml.in.h:312 msgid "Malawi" msgstr "" -#: ../data/currencies.xml.in.h:310 +#: ../data/currencies.xml.in.h:313 msgid "Maldivian Rufiyaa" msgstr "" -#: ../data/currencies.xml.in.h:311 +#: ../data/currencies.xml.in.h:314 msgid "ar:MVR" msgstr "" -#: ../data/currencies.xml.in.h:312 +#: ../data/currencies.xml.in.h:315 msgid "Maldives" msgstr "" -#: ../data/currencies.xml.in.h:313 +#: ../data/currencies.xml.in.h:316 msgid "Mauritanian Ouguiya (obsolete)" msgstr "" -#: ../data/currencies.xml.in.h:314 +#: ../data/currencies.xml.in.h:317 msgid "ar:MRO" msgstr "" -#: ../data/currencies.xml.in.h:315 +#: ../data/currencies.xml.in.h:318 msgid "Mauritian Rupee" msgstr "" -#: ../data/currencies.xml.in.h:316 +#: ../data/currencies.xml.in.h:319 msgid "ar:MUR" msgstr "" -#: ../data/currencies.xml.in.h:317 +#: ../data/currencies.xml.in.h:320 msgid "Mauritius" msgstr "" -#: ../data/currencies.xml.in.h:318 +#: ../data/currencies.xml.in.h:321 msgid "Moldovan Leu" msgstr "" -#: ../data/currencies.xml.in.h:319 +#: ../data/currencies.xml.in.h:322 msgid "ar:MDL" msgstr "" -#: ../data/currencies.xml.in.h:320 +#: ../data/currencies.xml.in.h:323 msgid "Moldova" msgstr "" -#: ../data/currencies.xml.in.h:321 +#: ../data/currencies.xml.in.h:324 msgid "Mongolian Tögrög" msgstr "" -#: ../data/currencies.xml.in.h:322 +#: ../data/currencies.xml.in.h:325 #, fuzzy msgid "ar:MNT,au:₮" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:323 +#: ../data/currencies.xml.in.h:326 msgid "Mongolia" msgstr "" -#: ../data/currencies.xml.in.h:324 +#: ../data/currencies.xml.in.h:327 msgid "Moroccan Dirham" msgstr "" -#: ../data/currencies.xml.in.h:325 +#: ../data/currencies.xml.in.h:328 msgid "ar:MAD" msgstr "" -#: ../data/currencies.xml.in.h:326 +#: ../data/currencies.xml.in.h:329 msgid "Morocco" msgstr "" -#: ../data/currencies.xml.in.h:327 +#: ../data/currencies.xml.in.h:330 msgid "Mozambican Metical" msgstr "" -#: ../data/currencies.xml.in.h:328 +#: ../data/currencies.xml.in.h:331 msgid "ar:MZN" msgstr "" -#: ../data/currencies.xml.in.h:329 +#: ../data/currencies.xml.in.h:332 msgid "Mozambique" msgstr "" -#: ../data/currencies.xml.in.h:330 +#: ../data/currencies.xml.in.h:333 msgid "Myanmar (Burmese Kyat)" msgstr "" -#: ../data/currencies.xml.in.h:331 +#: ../data/currencies.xml.in.h:334 msgid "ar:MMK" msgstr "" -#: ../data/currencies.xml.in.h:332 +#: ../data/currencies.xml.in.h:335 msgid "Myanmar" msgstr "" -#: ../data/currencies.xml.in.h:333 +#: ../data/currencies.xml.in.h:336 #, fuzzy msgid "Namibian Dollar" msgstr "加拿大元" -#: ../data/currencies.xml.in.h:334 +#: ../data/currencies.xml.in.h:337 msgid "ar:NAD" msgstr "" -#: ../data/currencies.xml.in.h:335 +#: ../data/currencies.xml.in.h:338 msgid "Namibia" msgstr "" -#: ../data/currencies.xml.in.h:336 +#: ../data/currencies.xml.in.h:339 msgid "Nepalese Rupee" msgstr "" -#: ../data/currencies.xml.in.h:337 +#: ../data/currencies.xml.in.h:340 msgid "ar:NPR" msgstr "" -#: ../data/currencies.xml.in.h:338 +#: ../data/currencies.xml.in.h:341 msgid "Nepal" msgstr "" -#: ../data/currencies.xml.in.h:339 +#: ../data/currencies.xml.in.h:342 msgid "Nicaraguan Córdoba" msgstr "" -#: ../data/currencies.xml.in.h:340 +#: ../data/currencies.xml.in.h:343 msgid "ar:NIO" msgstr "" -#: ../data/currencies.xml.in.h:341 +#: ../data/currencies.xml.in.h:344 msgid "Nicaragua" msgstr "" -#: ../data/currencies.xml.in.h:342 +#: ../data/currencies.xml.in.h:345 msgid "Nigerian Naira" msgstr "" -#: ../data/currencies.xml.in.h:343 +#: ../data/currencies.xml.in.h:346 #, fuzzy msgid "ar:NGN,au:₦" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:344 +#: ../data/currencies.xml.in.h:347 msgid "Nigeria" msgstr "" -#: ../data/currencies.xml.in.h:345 +#: ../data/currencies.xml.in.h:348 msgid "Omani Rial" msgstr "" -#: ../data/currencies.xml.in.h:346 +#: ../data/currencies.xml.in.h:349 msgid "ar:OMR" msgstr "" -#: ../data/currencies.xml.in.h:347 +#: ../data/currencies.xml.in.h:350 msgid "Oman" msgstr "" -#: ../data/currencies.xml.in.h:348 +#: ../data/currencies.xml.in.h:351 msgid "Pakistani Rupee" msgstr "" -#: ../data/currencies.xml.in.h:349 +#: ../data/currencies.xml.in.h:352 #, fuzzy msgid "ar:PKR" msgstr "ar:PHP" -#: ../data/currencies.xml.in.h:350 +#: ../data/currencies.xml.in.h:353 #, fuzzy msgid "Pakistan" msgstr "普朗克常数" -#: ../data/currencies.xml.in.h:351 +#: ../data/currencies.xml.in.h:354 msgid "Panamaian Balboa" msgstr "" -#: ../data/currencies.xml.in.h:352 +#: ../data/currencies.xml.in.h:355 #, fuzzy msgid "ar:PAB" msgstr "ar:PHP" -#: ../data/currencies.xml.in.h:353 +#: ../data/currencies.xml.in.h:356 msgid "Panama" msgstr "" -#: ../data/currencies.xml.in.h:354 +#: ../data/currencies.xml.in.h:357 msgid "Papua New Guinean Kina" msgstr "" -#: ../data/currencies.xml.in.h:355 +#: ../data/currencies.xml.in.h:358 #, fuzzy msgid "ar:PGK" msgstr "ar:PHP" -#: ../data/currencies.xml.in.h:356 +#: ../data/currencies.xml.in.h:359 msgid "Papua New Guinea" msgstr "" -#: ../data/currencies.xml.in.h:357 +#: ../data/currencies.xml.in.h:360 msgid "Paraguayan Guaraní" msgstr "" -#: ../data/currencies.xml.in.h:358 +#: ../data/currencies.xml.in.h:361 #, fuzzy msgid "ar:PYG,au:₲" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:359 +#: ../data/currencies.xml.in.h:362 msgid "Paraguay" msgstr "" -#: ../data/currencies.xml.in.h:360 +#: ../data/currencies.xml.in.h:363 msgid "Peruvian Sol" msgstr "" -#: ../data/currencies.xml.in.h:361 +#: ../data/currencies.xml.in.h:364 #, fuzzy msgid "ar:PEN" msgstr "ar:PHP" -#: ../data/currencies.xml.in.h:362 +#: ../data/currencies.xml.in.h:365 msgid "Peru" msgstr "" -#: ../data/currencies.xml.in.h:363 +#: ../data/currencies.xml.in.h:366 msgid "Qatari Riyal" msgstr "" -#: ../data/currencies.xml.in.h:364 +#: ../data/currencies.xml.in.h:367 msgid "ar:QAR" msgstr "" -#: ../data/currencies.xml.in.h:365 +#: ../data/currencies.xml.in.h:368 msgid "Qatar" msgstr "" -#: ../data/currencies.xml.in.h:366 +#: ../data/currencies.xml.in.h:369 #, fuzzy msgid "Rwandan Franc" msgstr "比利时法郎" -#: ../data/currencies.xml.in.h:367 +#: ../data/currencies.xml.in.h:370 msgid "ar:RWF" msgstr "" -#: ../data/currencies.xml.in.h:368 +#: ../data/currencies.xml.in.h:371 msgid "Rwanda" msgstr "" -#: ../data/currencies.xml.in.h:369 +#: ../data/currencies.xml.in.h:372 msgid "São Tomé and Príncipe Dobra" msgstr "" -#: ../data/currencies.xml.in.h:370 +#: ../data/currencies.xml.in.h:373 #, fuzzy msgid "ar:STD" msgstr "tolar,ar:SIT" -#: ../data/currencies.xml.in.h:371 +#: ../data/currencies.xml.in.h:374 msgid "Sao Tome and Principe" msgstr "" -#: ../data/currencies.xml.in.h:372 +#: ../data/currencies.xml.in.h:375 msgid "Saudi Riyal" msgstr "" -#: ../data/currencies.xml.in.h:373 +#: ../data/currencies.xml.in.h:376 #, fuzzy msgid "ar:SAR" msgstr "tolar,ar:SIT" -#: ../data/currencies.xml.in.h:374 +#: ../data/currencies.xml.in.h:377 msgid "Saudi Arabia" msgstr "" -#: ../data/currencies.xml.in.h:375 +#: ../data/currencies.xml.in.h:378 msgid "Serbian Dinar" msgstr "" -#: ../data/currencies.xml.in.h:376 +#: ../data/currencies.xml.in.h:379 msgid "ar:RSD" msgstr "" -#: ../data/currencies.xml.in.h:377 +#: ../data/currencies.xml.in.h:380 #, fuzzy msgid "Serbia" msgstr "铽" -#: ../data/currencies.xml.in.h:378 +#: ../data/currencies.xml.in.h:381 msgid "Seychellois Rupee" msgstr "" -#: ../data/currencies.xml.in.h:379 +#: ../data/currencies.xml.in.h:382 #, fuzzy msgid "ar:SCR" msgstr "tolar,ar:SIT" -#: ../data/currencies.xml.in.h:380 +#: ../data/currencies.xml.in.h:383 msgid "Seychelles" msgstr "" -#: ../data/currencies.xml.in.h:381 +#: ../data/currencies.xml.in.h:384 msgid "Sierra Leonean Leone" msgstr "" -#: ../data/currencies.xml.in.h:382 +#: ../data/currencies.xml.in.h:385 #, fuzzy msgid "ar:SLL" msgstr "tolar,ar:SIT" -#: ../data/currencies.xml.in.h:383 +#: ../data/currencies.xml.in.h:386 msgid "Sierra Leone" msgstr "" -#: ../data/currencies.xml.in.h:384 +#: ../data/currencies.xml.in.h:387 msgid "Solomon Islands Dollar" msgstr "" -#: ../data/currencies.xml.in.h:385 +#: ../data/currencies.xml.in.h:388 #, fuzzy msgid "ar:SBD" msgstr "tolar,ar:SIT" -#: ../data/currencies.xml.in.h:386 +#: ../data/currencies.xml.in.h:389 msgid "Solomon Islands" msgstr "" -#: ../data/currencies.xml.in.h:387 +#: ../data/currencies.xml.in.h:390 #, fuzzy msgid "Somali Shilling" msgstr "奥地利先令" -#: ../data/currencies.xml.in.h:388 +#: ../data/currencies.xml.in.h:391 #, fuzzy msgid "ar:SOS" msgstr "tolar,ar:SIT" -#: ../data/currencies.xml.in.h:389 +#: ../data/currencies.xml.in.h:392 msgid "Somalia" msgstr "" -#: ../data/currencies.xml.in.h:390 +#: ../data/currencies.xml.in.h:393 msgid "Sri Lankan Rupee" msgstr "" -#: ../data/currencies.xml.in.h:391 +#: ../data/currencies.xml.in.h:394 #, fuzzy msgid "ar:LKR,au:௹" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:392 +#: ../data/currencies.xml.in.h:395 msgid "Sri Lanka" msgstr "" -#: ../data/currencies.xml.in.h:393 +#: ../data/currencies.xml.in.h:396 msgid "Sudanese Pound" msgstr "" -#: ../data/currencies.xml.in.h:394 +#: ../data/currencies.xml.in.h:397 #, fuzzy msgid "ar:SDG" msgstr "tolar,ar:SIT" -#: ../data/currencies.xml.in.h:395 +#: ../data/currencies.xml.in.h:398 msgid "Sudan" msgstr "" -#: ../data/currencies.xml.in.h:396 +#: ../data/currencies.xml.in.h:399 #, fuzzy msgid "Surinamese Dollar" msgstr "新加坡元" -#: ../data/currencies.xml.in.h:397 +#: ../data/currencies.xml.in.h:400 #, fuzzy msgid "ar:SRD" msgstr "tolar,ar:SIT" -#: ../data/currencies.xml.in.h:398 +#: ../data/currencies.xml.in.h:401 #, fuzzy msgid "Suriname" msgstr "文件名" -#: ../data/currencies.xml.in.h:399 +#: ../data/currencies.xml.in.h:402 msgid "Swazi Lilangeni" msgstr "" -#: ../data/currencies.xml.in.h:400 +#: ../data/currencies.xml.in.h:403 #, fuzzy msgid "ar:SZL" msgstr "tolar,ar:SIT" -#: ../data/currencies.xml.in.h:401 +#: ../data/currencies.xml.in.h:404 msgid "Swaziland" msgstr "" -#: ../data/currencies.xml.in.h:402 +#: ../data/currencies.xml.in.h:405 #, fuzzy msgid "Syrian Pound" msgstr "塞浦路斯镑" -#: ../data/currencies.xml.in.h:403 +#: ../data/currencies.xml.in.h:406 #, fuzzy msgid "ar:SYP" msgstr "tolar,ar:SIT" -#: ../data/currencies.xml.in.h:404 +#: ../data/currencies.xml.in.h:407 msgid "Syria" msgstr "" -#: ../data/currencies.xml.in.h:405 +#: ../data/currencies.xml.in.h:408 #, fuzzy msgid "New Taiwan Dollar" msgstr "新西兰元" -#: ../data/currencies.xml.in.h:406 +#: ../data/currencies.xml.in.h:409 #, fuzzy msgid "ar:TWD" msgstr "ar:TRY" -#: ../data/currencies.xml.in.h:407 +#: ../data/currencies.xml.in.h:410 msgid "Taiwan" msgstr "" -#: ../data/currencies.xml.in.h:408 +#: ../data/currencies.xml.in.h:411 msgid "Tajikistani Somoni" msgstr "" -#: ../data/currencies.xml.in.h:409 +#: ../data/currencies.xml.in.h:412 #, fuzzy msgid "ar:TJS" msgstr "ar:TRY" -#: ../data/currencies.xml.in.h:410 +#: ../data/currencies.xml.in.h:413 msgid "Tajikistan" msgstr "" -#: ../data/currencies.xml.in.h:411 +#: ../data/currencies.xml.in.h:414 #, fuzzy msgid "Tanzanian Shilling" msgstr "奥地利先令" -#: ../data/currencies.xml.in.h:412 +#: ../data/currencies.xml.in.h:415 #, fuzzy msgid "ar:TZS" msgstr "ar:TRY" -#: ../data/currencies.xml.in.h:413 +#: ../data/currencies.xml.in.h:416 msgid "Tanzania" msgstr "" -#: ../data/currencies.xml.in.h:414 +#: ../data/currencies.xml.in.h:417 msgid "Tongan Paʻanga" msgstr "" -#: ../data/currencies.xml.in.h:415 +#: ../data/currencies.xml.in.h:418 #, fuzzy msgid "ar:TOP" msgstr "ar:TRY" -#: ../data/currencies.xml.in.h:416 +#: ../data/currencies.xml.in.h:419 msgid "Tonga" msgstr "" -#: ../data/currencies.xml.in.h:417 +#: ../data/currencies.xml.in.h:420 msgid "Trinidad and Tobago dollar" msgstr "" -#: ../data/currencies.xml.in.h:418 +#: ../data/currencies.xml.in.h:421 #, fuzzy msgid "ar:TTD" msgstr "ar:TRY" -#: ../data/currencies.xml.in.h:419 +#: ../data/currencies.xml.in.h:422 msgid "Trinidad and Tobago" msgstr "" -#: ../data/currencies.xml.in.h:420 +#: ../data/currencies.xml.in.h:423 msgid "Tunisian Dinar" msgstr "" -#: ../data/currencies.xml.in.h:421 +#: ../data/currencies.xml.in.h:424 #, fuzzy msgid "ar:TND" msgstr "ar:TRY" -#: ../data/currencies.xml.in.h:422 +#: ../data/currencies.xml.in.h:425 msgid "Tunisia" msgstr "" -#: ../data/currencies.xml.in.h:423 +#: ../data/currencies.xml.in.h:426 msgid "Turkmenistan Manat" msgstr "" -#: ../data/currencies.xml.in.h:424 +#: ../data/currencies.xml.in.h:427 #, fuzzy msgid "ar:TMT" msgstr "ar:TRY" -#: ../data/currencies.xml.in.h:425 +#: ../data/currencies.xml.in.h:428 msgid "Turkmenistan" msgstr "" -#: ../data/currencies.xml.in.h:426 +#: ../data/currencies.xml.in.h:429 #, fuzzy msgid "Ugandan Shilling" msgstr "奥地利先令" -#: ../data/currencies.xml.in.h:427 +#: ../data/currencies.xml.in.h:430 msgid "ar:UGX" msgstr "" -#: ../data/currencies.xml.in.h:428 +#: ../data/currencies.xml.in.h:431 msgid "Uganda" msgstr "" -#: ../data/currencies.xml.in.h:429 +#: ../data/currencies.xml.in.h:432 msgid "Ukrainian Hryvnia" msgstr "" -#: ../data/currencies.xml.in.h:430 +#: ../data/currencies.xml.in.h:433 #, fuzzy msgid "ar:UAH,au:₴" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:431 +#: ../data/currencies.xml.in.h:434 #, fuzzy msgid "Ukraine" msgstr "格令" -#: ../data/currencies.xml.in.h:432 +#: ../data/currencies.xml.in.h:435 msgid "United Arab Emirates Dirham" msgstr "" -#: ../data/currencies.xml.in.h:433 +#: ../data/currencies.xml.in.h:436 msgid "ar:AED" msgstr "" -#: ../data/currencies.xml.in.h:434 +#: ../data/currencies.xml.in.h:437 msgid "United Arab Emirates" msgstr "" -#: ../data/currencies.xml.in.h:435 +#: ../data/currencies.xml.in.h:438 msgid "Uruguayan Peso" msgstr "" -#: ../data/currencies.xml.in.h:436 +#: ../data/currencies.xml.in.h:439 msgid "ar:UYU" msgstr "" -#: ../data/currencies.xml.in.h:437 +#: ../data/currencies.xml.in.h:440 msgid "Uruguay" msgstr "" -#: ../data/currencies.xml.in.h:438 +#: ../data/currencies.xml.in.h:441 msgid "Uzbekistan Soʻm" msgstr "" -#: ../data/currencies.xml.in.h:439 +#: ../data/currencies.xml.in.h:442 msgid "ar:UZS" msgstr "" -#: ../data/currencies.xml.in.h:440 +#: ../data/currencies.xml.in.h:443 msgid "Uzbekistan" msgstr "" -#: ../data/currencies.xml.in.h:441 +#: ../data/currencies.xml.in.h:444 msgid "Vanuatu Vatu" msgstr "" -#: ../data/currencies.xml.in.h:442 +#: ../data/currencies.xml.in.h:445 msgid "ar:VUV" msgstr "" -#: ../data/currencies.xml.in.h:443 +#: ../data/currencies.xml.in.h:446 msgid "Vanuatu" msgstr "" -#: ../data/currencies.xml.in.h:444 +#: ../data/currencies.xml.in.h:447 #, fuzzy msgid "Venezuelan Bolívar (obsolete)" msgstr "斯洛文尼亚Tolar" -#: ../data/currencies.xml.in.h:445 +#: ../data/currencies.xml.in.h:448 msgid "ar:VEF" msgstr "" -#: ../data/currencies.xml.in.h:446 +#: ../data/currencies.xml.in.h:449 msgid "Vietnamese Dồng" msgstr "" -#: ../data/currencies.xml.in.h:447 +#: ../data/currencies.xml.in.h:450 #, fuzzy msgid "ar:VND,au:₫" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:448 +#: ../data/currencies.xml.in.h:451 msgid "Vietnam" msgstr "" -#: ../data/currencies.xml.in.h:449 +#: ../data/currencies.xml.in.h:452 msgid "Yemeni Rial" msgstr "" -#: ../data/currencies.xml.in.h:450 +#: ../data/currencies.xml.in.h:453 msgid "ar:YER" msgstr "" -#: ../data/currencies.xml.in.h:451 +#: ../data/currencies.xml.in.h:454 #, fuzzy msgid "Yemen" msgstr "一个元素" -#: ../data/currencies.xml.in.h:452 +#: ../data/currencies.xml.in.h:455 msgid "Zambian Kwacha (obsolete)" msgstr "" -#: ../data/currencies.xml.in.h:453 +#: ../data/currencies.xml.in.h:456 msgid "ar:ZMK" msgstr "" -#: ../data/currencies.xml.in.h:454 +#: ../data/currencies.xml.in.h:457 msgid "Euro Cent" msgstr "欧元分" -#: ../data/currencies.xml.in.h:455 +#: ../data/currencies.xml.in.h:458 msgid "r:eurocent,p:eurocents" msgstr "r:欧元分" -#: ../data/currencies.xml.in.h:456 +#: ../data/currencies.xml.in.h:459 msgid "Cent (USD)" msgstr "美分" -#: ../data/currencies.xml.in.h:457 +#: ../data/currencies.xml.in.h:460 msgid "au:¢,r:cent,p:cents" msgstr "au:¢,r:美分" -#: ../data/currencies.xml.in.h:458 +#: ../data/currencies.xml.in.h:461 #, fuzzy msgid "Belgian Franc (obsolete)" msgstr "比利时法郎" -#: ../data/currencies.xml.in.h:459 +#: ../data/currencies.xml.in.h:462 msgid "ar:BEF" msgstr "" -#: ../data/currencies.xml.in.h:460 +#: ../data/currencies.xml.in.h:463 #, fuzzy msgid "Greek Drachma (obsolete)" msgstr "希腊德拉马克" -#: ../data/currencies.xml.in.h:461 +#: ../data/currencies.xml.in.h:464 #, fuzzy msgid "ar:GRD,au:₯" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:462 +#: ../data/currencies.xml.in.h:465 #, fuzzy msgid "French Franc (obsolete)" msgstr "法国法郎" -#: ../data/currencies.xml.in.h:463 +#: ../data/currencies.xml.in.h:466 #, fuzzy msgid "ar:FRF,au:₣" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:464 +#: ../data/currencies.xml.in.h:467 #, fuzzy msgid "Italian Lira (obsolete)" msgstr "意大利里拉" -#: ../data/currencies.xml.in.h:465 +#: ../data/currencies.xml.in.h:468 msgid "ar:ITL" msgstr "" -#: ../data/currencies.xml.in.h:466 +#: ../data/currencies.xml.in.h:469 #, fuzzy msgid "Dutch Guilder (obsolete)" msgstr "荷兰盾" -#: ../data/currencies.xml.in.h:467 +#: ../data/currencies.xml.in.h:470 msgid "ar:NLG" msgstr "" -#: ../data/currencies.xml.in.h:468 +#: ../data/currencies.xml.in.h:471 #, fuzzy msgid "Portuguese Escudo (obsolete)" msgstr "葡萄牙埃斯库多" -#: ../data/currencies.xml.in.h:469 +#: ../data/currencies.xml.in.h:472 #, fuzzy msgid "ar:PTE" msgstr "ar:PHP" -#: ../data/currencies.xml.in.h:470 +#: ../data/currencies.xml.in.h:473 msgid "Deutsche Mark (obsolete)" msgstr "" -#: ../data/currencies.xml.in.h:471 +#: ../data/currencies.xml.in.h:474 #, fuzzy msgid "ar:DEM" msgstr "a:DEM,马克" -#: ../data/currencies.xml.in.h:472 +#: ../data/currencies.xml.in.h:475 #, fuzzy msgid "Spanish Peseta (obsolete)" msgstr "西班牙比塞塔" -#: ../data/currencies.xml.in.h:473 +#: ../data/currencies.xml.in.h:476 #, fuzzy msgid "ar:ESP,au:₧" msgstr "ar:GBP,au:£" -#: ../data/currencies.xml.in.h:474 +#: ../data/currencies.xml.in.h:477 #, fuzzy msgid "Irish Pound (obsolete)" msgstr "爱尔兰镑" -#: ../data/currencies.xml.in.h:475 +#: ../data/currencies.xml.in.h:478 msgid "ar:IEP" msgstr "" -#: ../data/currencies.xml.in.h:476 +#: ../data/currencies.xml.in.h:479 #, fuzzy msgid "Luxembourg Franc (obsolete)" msgstr "卢森堡法郎" -#: ../data/currencies.xml.in.h:477 +#: ../data/currencies.xml.in.h:480 msgid "ar:LUF" msgstr "" -#: ../data/currencies.xml.in.h:478 +#: ../data/currencies.xml.in.h:481 #, fuzzy msgid "Austrian Schilling (obsolete)" msgstr "奥地利先令" -#: ../data/currencies.xml.in.h:479 +#: ../data/currencies.xml.in.h:482 msgid "ar:ATS" msgstr "" -#: ../data/currencies.xml.in.h:480 +#: ../data/currencies.xml.in.h:483 #, fuzzy msgid "Finnish Markka (obsolete)" msgstr "芬兰马克" -#: ../data/currencies.xml.in.h:481 +#: ../data/currencies.xml.in.h:484 msgid "ar:FIM" msgstr "" -#: ../data/currencies.xml.in.h:482 +#: ../data/currencies.xml.in.h:485 #, fuzzy msgid "Slovenian Tolar (obsolete)" msgstr "斯洛文尼亚Tolar" -#: ../data/currencies.xml.in.h:483 +#: ../data/currencies.xml.in.h:486 #, fuzzy msgid "ar:SIT" msgstr "tolar,ar:SIT" -#: ../data/currencies.xml.in.h:484 +#: ../data/currencies.xml.in.h:487 #, fuzzy msgid "Cypriot Pound (obsolete)" msgstr "塞浦路斯镑" -#: ../data/currencies.xml.in.h:485 +#: ../data/currencies.xml.in.h:488 msgid "ar:CYP" msgstr "" -#: ../data/currencies.xml.in.h:486 +#: ../data/currencies.xml.in.h:489 #, fuzzy msgid "Estonian Kroon (obsolete)" msgstr "爱沙尼亚克鲁恩" -#: ../data/currencies.xml.in.h:487 +#: ../data/currencies.xml.in.h:490 msgid "ar:EEK" msgstr "ar:EEK" -#: ../data/currencies.xml.in.h:488 +#: ../data/currencies.xml.in.h:491 #, fuzzy msgid "Slovak Koruna (obsolete)" msgstr "斯洛伐克Koruna" -#: ../data/currencies.xml.in.h:489 +#: ../data/currencies.xml.in.h:492 msgid "ar:SKK" msgstr "" -#: ../data/currencies.xml.in.h:490 +#: ../data/currencies.xml.in.h:493 #, fuzzy msgid "Maltese Lira (obsolete)" msgstr "马耳他里拉" -#: ../data/currencies.xml.in.h:491 +#: ../data/currencies.xml.in.h:494 msgid "ar:MTL" msgstr "" -#: ../data/currencies.xml.in.h:492 +#: ../data/currencies.xml.in.h:495 #, fuzzy msgid "Latvian Lats (obsolete)" msgstr "拉脱维亚 Lats" -#: ../data/currencies.xml.in.h:493 +#: ../data/currencies.xml.in.h:496 msgid "ar:LVL" msgstr "" -#: ../data/currencies.xml.in.h:494 +#: ../data/currencies.xml.in.h:497 #, fuzzy msgid "Lithuanian Litas (obsolete)" msgstr "立陶宛Litas" -#: ../data/currencies.xml.in.h:495 +#: ../data/currencies.xml.in.h:498 msgid "ar:LTL" msgstr "" @@ -2179,7 +2193,7 @@ msgid "!datasets!r:number" msgstr "编号" -#: ../data/datasets.xml.in.h:13 ../data/functions.xml.in.h:709 +#: ../data/datasets.xml.in.h:13 ../data/functions.xml.in.h:716 msgid "Name" msgstr "名称" @@ -2207,7 +2221,7 @@ msgid "r:class" msgstr "" -#: ../data/datasets.xml.in.h:18 ../data/functions.xml.in.h:424 +#: ../data/datasets.xml.in.h:18 ../data/functions.xml.in.h:431 msgid "Weight" msgstr "重量" @@ -3755,15 +3769,17 @@ msgstr "" #: ../data/functions.xml.in.h:216 -msgid "Fibonacci Number" -msgstr "斐波纳契系数" +msgid "Bernoulli Number/Polynomial" +msgstr "" #: ../data/functions.xml.in.h:217 -msgid "r:fibonacci" +msgid "" +"Returns the nth Bernoulli number or polynomial (if the second argument is " +"non-zero)." msgstr "" #: ../data/functions.xml.in.h:218 -msgid "Returns the n-th term of the Fibonacci sequence." +msgid "r:bernoulli" msgstr "" #: ../data/functions.xml.in.h:219 @@ -3771,70 +3787,82 @@ msgstr "下标(n)" #: ../data/functions.xml.in.h:220 +msgid "Fibonacci Number" +msgstr "斐波纳契系数" + +#: ../data/functions.xml.in.h:221 +msgid "r:fibonacci" +msgstr "" + +#: ../data/functions.xml.in.h:222 +msgid "Returns the n-th term of the Fibonacci sequence." +msgstr "" + +#: ../data/functions.xml.in.h:223 msgid "Rounding" msgstr "取整" -#: ../data/functions.xml.in.h:221 +#: ../data/functions.xml.in.h:224 msgid "Round" msgstr "取整" -#: ../data/functions.xml.in.h:222 +#: ../data/functions.xml.in.h:225 msgid "r:round" msgstr "" -#: ../data/functions.xml.in.h:223 +#: ../data/functions.xml.in.h:226 msgid "Round Downwards" msgstr "向下取整" -#: ../data/functions.xml.in.h:224 +#: ../data/functions.xml.in.h:227 msgid "r:floor" msgstr "" -#: ../data/functions.xml.in.h:225 +#: ../data/functions.xml.in.h:228 msgid "Round Upwards" msgstr "向上取整" -#: ../data/functions.xml.in.h:226 +#: ../data/functions.xml.in.h:229 msgid "r:ceil" msgstr "" -#: ../data/functions.xml.in.h:227 +#: ../data/functions.xml.in.h:230 msgid "Round Towards Zero" msgstr "向零取整" -#: ../data/functions.xml.in.h:228 +#: ../data/functions.xml.in.h:231 msgid "r:trunc" msgstr "" -#: ../data/functions.xml.in.h:229 +#: ../data/functions.xml.in.h:232 msgid "Integer Part" msgstr "提取整数部分" -#: ../data/functions.xml.in.h:230 +#: ../data/functions.xml.in.h:233 msgid "r:int" msgstr "" -#: ../data/functions.xml.in.h:231 +#: ../data/functions.xml.in.h:234 msgid "Fractional Part" msgstr "提取分数部分" -#: ../data/functions.xml.in.h:232 +#: ../data/functions.xml.in.h:235 msgid "r:frac" msgstr "" -#: ../data/functions.xml.in.h:233 +#: ../data/functions.xml.in.h:236 msgid "Number Bases" msgstr "数字进制" -#: ../data/functions.xml.in.h:234 +#: ../data/functions.xml.in.h:237 msgid "Number Base" msgstr "数字进制" -#: ../data/functions.xml.in.h:235 +#: ../data/functions.xml.in.h:238 msgid "r:base" msgstr "" -#: ../data/functions.xml.in.h:236 +#: ../data/functions.xml.in.h:239 msgid "" "Returns a value from an expression using the specified number base (radix). " "For bases between -62 and 62 full mathematical expressions (including " @@ -3855,271 +3883,287 @@ "selected, the specified expression is always converted to a single number." msgstr "" -#: ../data/functions.xml.in.h:237 +#: ../data/functions.xml.in.h:240 msgid "Set of digits" msgstr "" -#: ../data/functions.xml.in.h:238 +#: ../data/functions.xml.in.h:241 msgid "Binary" msgstr "二进制" -#: ../data/functions.xml.in.h:239 +#: ../data/functions.xml.in.h:242 msgid "r:bin" msgstr "" -#: ../data/functions.xml.in.h:240 +#: ../data/functions.xml.in.h:243 msgid "" "Returns a value from a binary expression. If two's complement is true, " "numbers beginning with '1' is interpreted as negative binary numbers using " "two's complement." msgstr "" -#: ../data/functions.xml.in.h:241 +#: ../data/functions.xml.in.h:244 msgid "Binary number" msgstr "二进制数" -#: ../data/functions.xml.in.h:242 +#: ../data/functions.xml.in.h:245 msgid "Two's complement" msgstr "" -#: ../data/functions.xml.in.h:243 +#: ../data/functions.xml.in.h:246 msgid "Octal" msgstr "八进制" -#: ../data/functions.xml.in.h:244 +#: ../data/functions.xml.in.h:247 msgid "r:oct" msgstr "" -#: ../data/functions.xml.in.h:245 +#: ../data/functions.xml.in.h:248 #, fuzzy msgid "Returns a value from an octal expression." msgstr "返回一个十六进制数字表示的数值" -#: ../data/functions.xml.in.h:246 +#: ../data/functions.xml.in.h:249 msgid "Octal number" msgstr "八进制数" -#: ../data/functions.xml.in.h:247 +#: ../data/functions.xml.in.h:250 msgid "Decimal" msgstr "十进制" -#: ../data/functions.xml.in.h:248 +#: ../data/functions.xml.in.h:251 msgid "r:dec" msgstr "" -#: ../data/functions.xml.in.h:249 +#: ../data/functions.xml.in.h:252 #, fuzzy msgid "Returns a value from a decimal expression." msgstr "返回一个十六进制数字表示的数值" -#: ../data/functions.xml.in.h:250 +#: ../data/functions.xml.in.h:253 msgid "Decimal number" msgstr "十进制数" -#: ../data/functions.xml.in.h:251 +#: ../data/functions.xml.in.h:254 msgid "Hexadecimal" msgstr "十六进制" -#: ../data/functions.xml.in.h:252 +#: ../data/functions.xml.in.h:255 msgid "r:hex" msgstr "" -#: ../data/functions.xml.in.h:253 +#: ../data/functions.xml.in.h:256 msgid "" "Returns a value from a hexadecimal expression. If two's complement is true, " "numbers beginning with 8 or higher is interpreted as negative hexadecimal " "numbers using two's complement." msgstr "" -#: ../data/functions.xml.in.h:254 +#: ../data/functions.xml.in.h:257 msgid "Hexadecimal number" msgstr "十六进制数" -#: ../data/functions.xml.in.h:255 +#: ../data/functions.xml.in.h:258 msgid "Bijective base-26" msgstr "" -#: ../data/functions.xml.in.h:256 +#: ../data/functions.xml.in.h:259 msgid "r:bijective" msgstr "" -#: ../data/functions.xml.in.h:257 +#: ../data/functions.xml.in.h:260 #, fuzzy msgid "" "Returns a value from an expression in bijective base-26. Conversion in the " "opposite direction is also supported." msgstr "返回一个指定进制(2-36之间)数字的值" -#: ../data/functions.xml.in.h:258 +#: ../data/functions.xml.in.h:261 msgid "Bijective base-26 number" msgstr "" -#: ../data/functions.xml.in.h:259 +#: ../data/functions.xml.in.h:262 msgid "Integers" msgstr "整数" -#: ../data/functions.xml.in.h:260 +#: ../data/functions.xml.in.h:263 msgid "Even" msgstr "偶" -#: ../data/functions.xml.in.h:261 +#: ../data/functions.xml.in.h:264 msgid "r:even" msgstr "" -#: ../data/functions.xml.in.h:262 +#: ../data/functions.xml.in.h:265 msgid "Odd" msgstr "奇" -#: ../data/functions.xml.in.h:263 +#: ../data/functions.xml.in.h:266 msgid "r:odd" msgstr "" -#: ../data/functions.xml.in.h:264 +#: ../data/functions.xml.in.h:267 msgid "Special Functions" msgstr "特殊函数" -#: ../data/functions.xml.in.h:265 +#: ../data/functions.xml.in.h:268 msgid "Gamma Function" msgstr "γ函数" -#: ../data/functions.xml.in.h:266 +#: ../data/functions.xml.in.h:269 msgid "r:gamma" msgstr "" -#: ../data/functions.xml.in.h:267 +#: ../data/functions.xml.in.h:270 msgid "Digamma Function" msgstr "双伽玛函数" -#: ../data/functions.xml.in.h:268 +#: ../data/functions.xml.in.h:271 msgid "r:digamma,psi" msgstr "" -#: ../data/functions.xml.in.h:269 +#: ../data/functions.xml.in.h:272 msgid "Beta Function" msgstr "β函数" -#: ../data/functions.xml.in.h:270 +#: ../data/functions.xml.in.h:273 msgid "r:beta" msgstr "" -#: ../data/functions.xml.in.h:271 +#: ../data/functions.xml.in.h:274 msgid "Error Function" msgstr "误差函数" -#: ../data/functions.xml.in.h:272 +#: ../data/functions.xml.in.h:275 msgid "r:erf" msgstr "" -#: ../data/functions.xml.in.h:273 +#: ../data/functions.xml.in.h:276 msgid "Complementary Error Function" msgstr "互补错误功能" -#: ../data/functions.xml.in.h:274 +#: ../data/functions.xml.in.h:277 msgid "r:erfc" msgstr "" -#: ../data/functions.xml.in.h:275 +#: ../data/functions.xml.in.h:278 +msgid "Imaginary Error Function" +msgstr "虚误差函数" + +#: ../data/functions.xml.in.h:279 +msgid "r:erfi" +msgstr "" + +#: ../data/functions.xml.in.h:280 msgid "Polylogarithm" msgstr "多重对数函数" -#: ../data/functions.xml.in.h:276 +#: ../data/functions.xml.in.h:281 msgid "rc:Li,polylog" msgstr "" -#: ../data/functions.xml.in.h:277 +#: ../data/functions.xml.in.h:282 msgid "Order" msgstr "次数" -#: ../data/functions.xml.in.h:278 +#: ../data/functions.xml.in.h:283 #, fuzzy msgid "Argument" msgstr "自变量" -#: ../data/functions.xml.in.h:279 +#: ../data/functions.xml.in.h:284 msgid "Airy Function" msgstr "艾里函数" -#: ../data/functions.xml.in.h:280 +#: ../data/functions.xml.in.h:285 msgid "r:airy" msgstr "" -#: ../data/functions.xml.in.h:281 +#: ../data/functions.xml.in.h:286 msgid "Bessel Function of the First Kind" msgstr "第一类贝塞尔函数" -#: ../data/functions.xml.in.h:282 +#: ../data/functions.xml.in.h:287 msgid "r:besselj" msgstr "" -#: ../data/functions.xml.in.h:283 +#: ../data/functions.xml.in.h:288 msgid "Bessel Function of the Second Kind" msgstr "第二类贝塞尔函数" -#: ../data/functions.xml.in.h:284 +#: ../data/functions.xml.in.h:289 msgid "r:bessely" msgstr "" -#: ../data/functions.xml.in.h:285 +#: ../data/functions.xml.in.h:290 msgid "Riemann Zeta" msgstr "Riemann Zeta" -#: ../data/functions.xml.in.h:286 +#: ../data/functions.xml.in.h:291 +msgid "Calculates Hurwitz zeta function if the second argument is not 1." +msgstr "" + +#: ../data/functions.xml.in.h:292 msgid "r:zeta" msgstr "" -#: ../data/functions.xml.in.h:287 +#: ../data/functions.xml.in.h:293 msgid "Integral point" msgstr "积分点" -#: ../data/functions.xml.in.h:288 +#: ../data/functions.xml.in.h:294 +msgid "Hurwitz zeta argument" +msgstr "" + +#: ../data/functions.xml.in.h:295 msgid "Kronecker Delta" msgstr "Kronecker Delta" -#: ../data/functions.xml.in.h:289 +#: ../data/functions.xml.in.h:296 msgid "r:kronecker" msgstr "" -#: ../data/functions.xml.in.h:290 +#: ../data/functions.xml.in.h:297 msgid "Returns 0 if i != j and 1 if i = j." msgstr "如果i不等于j,返回0;如果i等于j,返回1。" -#: ../data/functions.xml.in.h:291 +#: ../data/functions.xml.in.h:298 msgid "Value 1 (i)" msgstr "值1(i)" -#: ../data/functions.xml.in.h:292 +#: ../data/functions.xml.in.h:299 msgid "Value 2 (j)" msgstr "值2(i)" -#: ../data/functions.xml.in.h:293 +#: ../data/functions.xml.in.h:300 msgid "Logit Transformation" msgstr "Logit变换" -#: ../data/functions.xml.in.h:294 +#: ../data/functions.xml.in.h:301 msgid "r:logit" msgstr "" -#: ../data/functions.xml.in.h:295 +#: ../data/functions.xml.in.h:302 msgid "Sigmoid Function" msgstr "sigmoid函数" -#: ../data/functions.xml.in.h:296 +#: ../data/functions.xml.in.h:303 msgid "r:sigmoid" msgstr "" -#: ../data/functions.xml.in.h:297 +#: ../data/functions.xml.in.h:304 msgid "Step Functions" msgstr "阶梯函数" -#: ../data/functions.xml.in.h:298 +#: ../data/functions.xml.in.h:305 msgid "Heaviside Step Function" msgstr "Heaviside阶梯函数" -#: ../data/functions.xml.in.h:299 +#: ../data/functions.xml.in.h:306 msgid "r:heaviside,au:θ" msgstr "" -#: ../data/functions.xml.in.h:300 +#: ../data/functions.xml.in.h:307 msgid "" "Discontinuous function also known as \"unit step function\". Returns 0 if x " "< 0, 1 if x > 0, and 1/2 if x = 0." @@ -4127,507 +4171,507 @@ "间断函数也被称作是\" 单位阶跃函数\"。当 x < 0时值为0, x > 0时值为1, x " "= 0时则为1/2。" -#: ../data/functions.xml.in.h:301 +#: ../data/functions.xml.in.h:308 msgid "Dirac Delta Function" msgstr "狄拉克δ函数" -#: ../data/functions.xml.in.h:302 +#: ../data/functions.xml.in.h:309 msgid "r:dirac,au:δ" msgstr "" -#: ../data/functions.xml.in.h:303 +#: ../data/functions.xml.in.h:310 msgid "Returns 0 if x is non-zero, and infinity if x is zero." msgstr "" -#: ../data/functions.xml.in.h:304 +#: ../data/functions.xml.in.h:311 msgid "Ramp Function" msgstr " 斜坡函数" -#: ../data/functions.xml.in.h:305 +#: ../data/functions.xml.in.h:312 msgid "r:ramp" msgstr "" -#: ../data/functions.xml.in.h:306 +#: ../data/functions.xml.in.h:313 msgid "Rectangular Function" msgstr "矩阵函数" -#: ../data/functions.xml.in.h:307 +#: ../data/functions.xml.in.h:314 msgid "r:rectangular" msgstr "" -#: ../data/functions.xml.in.h:308 +#: ../data/functions.xml.in.h:315 msgid "Triangular Function" msgstr "三角函数" -#: ../data/functions.xml.in.h:309 +#: ../data/functions.xml.in.h:316 msgid "r:triangular" msgstr "" -#: ../data/functions.xml.in.h:310 +#: ../data/functions.xml.in.h:317 msgid "Complex Numbers" msgstr "复数" -#: ../data/functions.xml.in.h:311 +#: ../data/functions.xml.in.h:318 msgid "Real Part" msgstr "实部" -#: ../data/functions.xml.in.h:312 +#: ../data/functions.xml.in.h:319 #, fuzzy msgid "r:re,au:ℜ" msgstr "ar:GBP,au:£" -#: ../data/functions.xml.in.h:313 +#: ../data/functions.xml.in.h:320 msgid "Complex number" msgstr "复数" -#: ../data/functions.xml.in.h:314 +#: ../data/functions.xml.in.h:321 msgid "Imaginary Part" msgstr "虚部" -#: ../data/functions.xml.in.h:315 +#: ../data/functions.xml.in.h:322 #, fuzzy msgid "r:im,au:ℑ" msgstr "ar:GBP,au:£" -#: ../data/functions.xml.in.h:316 +#: ../data/functions.xml.in.h:323 msgid "Principal Argument" msgstr "幅角" -#: ../data/functions.xml.in.h:317 +#: ../data/functions.xml.in.h:324 msgid "r:arg" msgstr "" -#: ../data/functions.xml.in.h:318 +#: ../data/functions.xml.in.h:325 msgid "Complex Conjugate" msgstr "共轭复数" -#: ../data/functions.xml.in.h:319 +#: ../data/functions.xml.in.h:326 msgid "r:conj" msgstr "" -#: ../data/functions.xml.in.h:320 +#: ../data/functions.xml.in.h:327 msgid "Exponents & Logarithms" msgstr "指数与对数" -#: ../data/functions.xml.in.h:321 +#: ../data/functions.xml.in.h:328 msgid "Square Root" msgstr "平方根" -#: ../data/functions.xml.in.h:322 +#: ../data/functions.xml.in.h:329 msgid "au:√,r:sqrt" msgstr "" -#: ../data/functions.xml.in.h:323 +#: ../data/functions.xml.in.h:330 msgid "" "Returns the principal square root (for positive values the positive root is " "returned)." msgstr "" -#: ../data/functions.xml.in.h:324 +#: ../data/functions.xml.in.h:331 msgid "Cube Root" msgstr "立方根" -#: ../data/functions.xml.in.h:325 +#: ../data/functions.xml.in.h:332 msgid "au:∛,r:cbrt" msgstr "" -#: ../data/functions.xml.in.h:326 +#: ../data/functions.xml.in.h:333 #, fuzzy msgid "Returns the third real root." msgstr "返回最大值。" -#: ../data/functions.xml.in.h:327 +#: ../data/functions.xml.in.h:334 msgid "Nth root" msgstr "N次方根" -#: ../data/functions.xml.in.h:328 +#: ../data/functions.xml.in.h:335 msgid "r:root" msgstr "" -#: ../data/functions.xml.in.h:329 +#: ../data/functions.xml.in.h:336 msgid "" "Returns the real root. For negative values the degree must be odd. Complex " "values are not allowed." msgstr "" -#: ../data/functions.xml.in.h:330 ../data/units.xml.in.h:65 +#: ../data/functions.xml.in.h:337 ../data/units.xml.in.h:65 msgid "Degree" msgstr "度" -#: ../data/functions.xml.in.h:331 +#: ../data/functions.xml.in.h:338 msgid "Square" msgstr "正方形" -#: ../data/functions.xml.in.h:332 +#: ../data/functions.xml.in.h:339 msgid "r:sq" msgstr "" -#: ../data/functions.xml.in.h:333 +#: ../data/functions.xml.in.h:340 msgid "Exponential (e^x)" msgstr "e的乘方" -#: ../data/functions.xml.in.h:334 +#: ../data/functions.xml.in.h:341 msgid "r:exp" msgstr "" -#: ../data/functions.xml.in.h:335 +#: ../data/functions.xml.in.h:342 msgid "Natural Logarithm" msgstr "自然对数" -#: ../data/functions.xml.in.h:336 +#: ../data/functions.xml.in.h:343 msgid "r:ln" msgstr "" -#: ../data/functions.xml.in.h:337 +#: ../data/functions.xml.in.h:344 msgid "Base-N Logarithm" msgstr "以n为底的对数" -#: ../data/functions.xml.in.h:338 +#: ../data/functions.xml.in.h:345 msgid "r:log" msgstr "" -#: ../data/functions.xml.in.h:339 +#: ../data/functions.xml.in.h:346 msgid "Lambert W Function (Omega Function, Product Log)" msgstr "Lambert W函数(ω函数, Product Log)" -#: ../data/functions.xml.in.h:340 +#: ../data/functions.xml.in.h:347 msgid "r:lambertw,productlog" msgstr "r:lambertw,productlog" -#: ../data/functions.xml.in.h:341 +#: ../data/functions.xml.in.h:348 #, fuzzy msgid "" "Returns the inverse function for mx*e^x as ln() does for e^x. Only the " "principal branch and real valued results are currently supported." msgstr "返回函数mx*e^x的逆函数。" -#: ../data/functions.xml.in.h:342 +#: ../data/functions.xml.in.h:349 msgid "Branch" msgstr "" -#: ../data/functions.xml.in.h:343 +#: ../data/functions.xml.in.h:350 msgid "Complex Exponential (Cis)" msgstr "复指数(Cis)" -#: ../data/functions.xml.in.h:344 +#: ../data/functions.xml.in.h:351 msgid "r:cis" msgstr "" -#: ../data/functions.xml.in.h:345 +#: ../data/functions.xml.in.h:352 msgid "Base-2 Logarithm" msgstr "以2为底的对数" -#: ../data/functions.xml.in.h:346 +#: ../data/functions.xml.in.h:353 msgid "rs:log2" msgstr "" -#: ../data/functions.xml.in.h:347 +#: ../data/functions.xml.in.h:354 msgid "Returns the base n logarithm." msgstr "返回以n为底的对数。" -#: ../data/functions.xml.in.h:348 +#: ../data/functions.xml.in.h:355 msgid "Base-10 Logarithm" msgstr "以10为底的对数" -#: ../data/functions.xml.in.h:349 +#: ../data/functions.xml.in.h:356 msgid "rs:log10" msgstr "" -#: ../data/functions.xml.in.h:350 +#: ../data/functions.xml.in.h:357 msgid "2 raised to the power X" msgstr "2的乘方" -#: ../data/functions.xml.in.h:351 +#: ../data/functions.xml.in.h:358 msgid "rs:exp2" msgstr "" -#: ../data/functions.xml.in.h:352 +#: ../data/functions.xml.in.h:359 msgid "10 raised to the power X" msgstr "10的乘方" -#: ../data/functions.xml.in.h:353 +#: ../data/functions.xml.in.h:360 msgid "rs:exp10" msgstr "" -#: ../data/functions.xml.in.h:354 +#: ../data/functions.xml.in.h:361 msgid "X raised to the power Y" msgstr "X的Y次方" -#: ../data/functions.xml.in.h:355 +#: ../data/functions.xml.in.h:362 msgid "r:pow" msgstr "" -#: ../data/functions.xml.in.h:356 +#: ../data/functions.xml.in.h:363 msgid "Square root (x * pi)" msgstr "平方根(x*π)" -#: ../data/functions.xml.in.h:357 +#: ../data/functions.xml.in.h:364 msgid "r:sqrtpi" msgstr "" -#: ../data/functions.xml.in.h:358 +#: ../data/functions.xml.in.h:365 msgid "Returns the non-negative square root of x * pi" msgstr "返回xπ的非负平方根" -#: ../data/functions.xml.in.h:359 +#: ../data/functions.xml.in.h:366 msgid "Non-negative value" msgstr "非负值" -#: ../data/functions.xml.in.h:360 +#: ../data/functions.xml.in.h:367 msgid "Trigonometry" msgstr "三角学" -#: ../data/functions.xml.in.h:361 +#: ../data/functions.xml.in.h:368 msgid "Sine" msgstr "正弦" -#: ../data/functions.xml.in.h:362 +#: ../data/functions.xml.in.h:369 msgid "r:sin" msgstr "" -#: ../data/functions.xml.in.h:363 +#: ../data/functions.xml.in.h:370 msgid "Angle" msgstr "角度" -#: ../data/functions.xml.in.h:364 +#: ../data/functions.xml.in.h:371 msgid "Cosine" msgstr "余弦" -#: ../data/functions.xml.in.h:365 +#: ../data/functions.xml.in.h:372 msgid "r:cos" msgstr "" -#: ../data/functions.xml.in.h:366 +#: ../data/functions.xml.in.h:373 msgid "Tangent" msgstr "正切" -#: ../data/functions.xml.in.h:367 +#: ../data/functions.xml.in.h:374 msgid "r:tan" msgstr "" -#: ../data/functions.xml.in.h:368 +#: ../data/functions.xml.in.h:375 msgid "Inverse Sine" msgstr "反正弦" -#: ../data/functions.xml.in.h:369 +#: ../data/functions.xml.in.h:376 msgid "r:asin" msgstr "" -#: ../data/functions.xml.in.h:370 +#: ../data/functions.xml.in.h:377 msgid "Inverse Cosine" msgstr "反余弦" -#: ../data/functions.xml.in.h:371 +#: ../data/functions.xml.in.h:378 msgid "r:acos" msgstr "" -#: ../data/functions.xml.in.h:372 +#: ../data/functions.xml.in.h:379 msgid "Inverse Tangent" msgstr "反正切" -#: ../data/functions.xml.in.h:373 +#: ../data/functions.xml.in.h:380 msgid "r:atan" msgstr "" -#: ../data/functions.xml.in.h:374 +#: ../data/functions.xml.in.h:381 msgid "Hyperbolic Sine" msgstr "双曲正弦" -#: ../data/functions.xml.in.h:375 +#: ../data/functions.xml.in.h:382 msgid "r:sinh" msgstr "" -#: ../data/functions.xml.in.h:376 +#: ../data/functions.xml.in.h:383 msgid "Hyperbolic Cosine" msgstr "双曲余弦" -#: ../data/functions.xml.in.h:377 +#: ../data/functions.xml.in.h:384 msgid "r:cosh" msgstr "" -#: ../data/functions.xml.in.h:378 +#: ../data/functions.xml.in.h:385 msgid "Hyperbolic Tangent" msgstr "双曲正割" -#: ../data/functions.xml.in.h:379 +#: ../data/functions.xml.in.h:386 msgid "r:tanh" msgstr "" -#: ../data/functions.xml.in.h:380 +#: ../data/functions.xml.in.h:387 msgid "Inverse Hyperbolic Sine" msgstr "反双曲正弦" -#: ../data/functions.xml.in.h:381 +#: ../data/functions.xml.in.h:388 msgid "r:asinh" msgstr "" -#: ../data/functions.xml.in.h:382 +#: ../data/functions.xml.in.h:389 msgid "Inverse Hyperbolic Cosine" msgstr "反双曲余弦" -#: ../data/functions.xml.in.h:383 +#: ../data/functions.xml.in.h:390 msgid "r:acosh" msgstr "" -#: ../data/functions.xml.in.h:384 +#: ../data/functions.xml.in.h:391 msgid "Inverse Hyperbolic Tangent" msgstr "反双曲正切" -#: ../data/functions.xml.in.h:385 +#: ../data/functions.xml.in.h:392 msgid "r:atanh" msgstr "" -#: ../data/functions.xml.in.h:386 +#: ../data/functions.xml.in.h:393 msgid "Four-quadrant Inverse Tangent" msgstr "Atan2" -#: ../data/functions.xml.in.h:387 +#: ../data/functions.xml.in.h:394 msgid "r:atan2" msgstr "" -#: ../data/functions.xml.in.h:388 +#: ../data/functions.xml.in.h:395 msgid "" "Computes the principal value of the argument function applied to the complex " "number x+iy." msgstr "" -#: ../data/functions.xml.in.h:389 +#: ../data/functions.xml.in.h:396 msgid "Y" msgstr "" -#: ../data/functions.xml.in.h:390 +#: ../data/functions.xml.in.h:397 msgid "X" msgstr "X" -#: ../data/functions.xml.in.h:391 +#: ../data/functions.xml.in.h:398 msgid "Cardinal Sine (Sinc Function)" msgstr "Sinc函数" -#: ../data/functions.xml.in.h:392 +#: ../data/functions.xml.in.h:399 msgid "r:sinc" msgstr "" -#: ../data/functions.xml.in.h:393 +#: ../data/functions.xml.in.h:400 msgid "Radians to Default Angle Unit" msgstr "将弧度转换到缺省角度单位" -#: ../data/functions.xml.in.h:394 +#: ../data/functions.xml.in.h:401 msgid "r:radtodef" msgstr "" -#: ../data/functions.xml.in.h:395 +#: ../data/functions.xml.in.h:402 msgid "Radians" msgstr "弧度" -#: ../data/functions.xml.in.h:396 +#: ../data/functions.xml.in.h:403 msgid "Secant" msgstr "正割" -#: ../data/functions.xml.in.h:397 +#: ../data/functions.xml.in.h:404 msgid "r:sec" msgstr "" -#: ../data/functions.xml.in.h:398 +#: ../data/functions.xml.in.h:405 msgid "Cosecant" msgstr "余割" -#: ../data/functions.xml.in.h:399 +#: ../data/functions.xml.in.h:406 msgid "r:csc" msgstr "" -#: ../data/functions.xml.in.h:400 +#: ../data/functions.xml.in.h:407 msgid "Cotangent" msgstr "余切" -#: ../data/functions.xml.in.h:401 +#: ../data/functions.xml.in.h:408 msgid "r:cot" msgstr "" -#: ../data/functions.xml.in.h:402 +#: ../data/functions.xml.in.h:409 msgid "Hyperbolic Secant" msgstr "双曲正切" -#: ../data/functions.xml.in.h:403 +#: ../data/functions.xml.in.h:410 msgid "r:sech" msgstr "" -#: ../data/functions.xml.in.h:404 +#: ../data/functions.xml.in.h:411 msgid "Hyperbolic Cosecant" msgstr "双曲余割" -#: ../data/functions.xml.in.h:405 +#: ../data/functions.xml.in.h:412 msgid "r:csch" msgstr "" -#: ../data/functions.xml.in.h:406 +#: ../data/functions.xml.in.h:413 msgid "Hyperbolic Cotangent" msgstr "双曲余切" -#: ../data/functions.xml.in.h:407 +#: ../data/functions.xml.in.h:414 msgid "r:coth" msgstr "" -#: ../data/functions.xml.in.h:408 +#: ../data/functions.xml.in.h:415 msgid "Inverse Secant" msgstr "反正割" -#: ../data/functions.xml.in.h:409 +#: ../data/functions.xml.in.h:416 msgid "r:asec" msgstr "" -#: ../data/functions.xml.in.h:410 +#: ../data/functions.xml.in.h:417 msgid "Inverse Cosecant" msgstr "反余割" -#: ../data/functions.xml.in.h:411 +#: ../data/functions.xml.in.h:418 msgid "r:acsc" msgstr "" -#: ../data/functions.xml.in.h:412 +#: ../data/functions.xml.in.h:419 msgid "Inverse Cotangent" msgstr "反余切" -#: ../data/functions.xml.in.h:413 +#: ../data/functions.xml.in.h:420 msgid "r:acot" msgstr "" -#: ../data/functions.xml.in.h:414 +#: ../data/functions.xml.in.h:421 msgid "Inverse Hyperbolic Secant" msgstr "反双曲正割" -#: ../data/functions.xml.in.h:415 +#: ../data/functions.xml.in.h:422 msgid "r:asech" msgstr "" -#: ../data/functions.xml.in.h:416 +#: ../data/functions.xml.in.h:423 msgid "Inverse Hyperbolic Cosecant" msgstr "反双曲余割" -#: ../data/functions.xml.in.h:417 +#: ../data/functions.xml.in.h:424 msgid "r:acsch" msgstr "" -#: ../data/functions.xml.in.h:418 +#: ../data/functions.xml.in.h:425 msgid "Inverse Hyperbolic Cotangent" msgstr "反双曲余切" -#: ../data/functions.xml.in.h:419 +#: ../data/functions.xml.in.h:426 msgid "r:acoth" msgstr "" -#: ../data/functions.xml.in.h:420 +#: ../data/functions.xml.in.h:427 msgid "Miscellaneous" msgstr "杂项" -#: ../data/functions.xml.in.h:421 +#: ../data/functions.xml.in.h:428 msgid "Body Mass Index (BMI)" msgstr "体质指数(BMI)" -#: ../data/functions.xml.in.h:422 +#: ../data/functions.xml.in.h:429 msgid "-r:bmi" msgstr "" -#: ../data/functions.xml.in.h:423 +#: ../data/functions.xml.in.h:430 msgid "" "Calculates the Body Mass Index. The resulting BMI-value is sometimes " "interpreted as follows (although varies with age, sex, etc.): " @@ -4639,19 +4683,19 @@ " 体重过轻 < 18.5 体重正常 18.5-25 体重过重 25-30 肥胖 " "> 30 注意您必须使用 重量和长度单位(如,59kg和174cm)。" -#: ../data/functions.xml.in.h:425 +#: ../data/functions.xml.in.h:432 msgid "Length" msgstr "长度" -#: ../data/functions.xml.in.h:426 +#: ../data/functions.xml.in.h:433 msgid "RAID Space" msgstr "" -#: ../data/functions.xml.in.h:427 +#: ../data/functions.xml.in.h:434 msgid "r:raid" msgstr "" -#: ../data/functions.xml.in.h:428 +#: ../data/functions.xml.in.h:435 msgid "" "Calculates RAID array disk capacity usable for data storage. If the " "combination of number of disks and RAID level is invalid, zero is returned. " @@ -4660,50 +4704,50 @@ "1+0)." msgstr "" -#: ../data/functions.xml.in.h:429 +#: ../data/functions.xml.in.h:436 msgid "RAID level" msgstr "" -#: ../data/functions.xml.in.h:430 +#: ../data/functions.xml.in.h:437 msgid "Capacity of each disk" msgstr "" -#: ../data/functions.xml.in.h:431 +#: ../data/functions.xml.in.h:438 #, fuzzy msgid "Number of disks" msgstr "期数" -#: ../data/functions.xml.in.h:432 +#: ../data/functions.xml.in.h:439 #, fuzzy msgid "Stripes" msgstr "剥离单位" -#: ../data/functions.xml.in.h:433 +#: ../data/functions.xml.in.h:440 msgid "Roman Number" msgstr "罗马数字" -#: ../data/functions.xml.in.h:434 +#: ../data/functions.xml.in.h:441 msgid "r:roman" msgstr "" -#: ../data/functions.xml.in.h:435 +#: ../data/functions.xml.in.h:442 msgid "Returns the value of a roman number." msgstr "返回罗马数字表示的值。" -#: ../data/functions.xml.in.h:436 +#: ../data/functions.xml.in.h:443 msgid "Roman number" msgstr "罗马数字" -#: ../data/functions.xml.in.h:437 +#: ../data/functions.xml.in.h:444 #, fuzzy msgid "Depth of Field" msgstr "边长" -#: ../data/functions.xml.in.h:438 +#: ../data/functions.xml.in.h:445 msgid "r:dof" msgstr "" -#: ../data/functions.xml.in.h:439 +#: ../data/functions.xml.in.h:446 msgid "" "Returns the estimated distance between the nearest and the farthest objects " "that are in acceptably sharp focus in a photo. Enter focal length (e.g. 50 " @@ -4715,197 +4759,197 @@ "on d/1500." msgstr "" -#: ../data/functions.xml.in.h:440 +#: ../data/functions.xml.in.h:447 #, fuzzy msgid "Focal Length" msgstr "长度" -#: ../data/functions.xml.in.h:441 +#: ../data/functions.xml.in.h:448 msgid "F-stop (aperture)" msgstr "" -#: ../data/functions.xml.in.h:442 +#: ../data/functions.xml.in.h:449 #, fuzzy msgid "Distance" msgstr "物质" -#: ../data/functions.xml.in.h:443 +#: ../data/functions.xml.in.h:450 msgid "Circle of confusion or sensor size" msgstr "" -#: ../data/functions.xml.in.h:444 +#: ../data/functions.xml.in.h:451 msgid "American Wire Gauge Cross-Section Area" msgstr "" -#: ../data/functions.xml.in.h:445 +#: ../data/functions.xml.in.h:452 msgid "r:awg" msgstr "" -#: ../data/functions.xml.in.h:446 +#: ../data/functions.xml.in.h:453 msgid "" "For gauges larger than 0000 (4/0), please use negative values (00=-1, " "000=-2, 0000=-3, 00000=-4, etc). For conversion to AWG, use an equation (e." "g. awg(x) = 20 mm^2)." msgstr "" -#: ../data/functions.xml.in.h:447 +#: ../data/functions.xml.in.h:454 msgid "American Wire Gauge Diameter" msgstr "" -#: ../data/functions.xml.in.h:448 +#: ../data/functions.xml.in.h:455 msgid "r:awgd" msgstr "" -#: ../data/functions.xml.in.h:449 +#: ../data/functions.xml.in.h:456 msgid "" "For gauges larger than 0000 (4/0), please use negative values (00=-1, " "000=-2, 0000=-3, 00000=-4, etc). For conversion to AWG, use an equation (e." "g. awgd(x) = 5 mm)." msgstr "" -#: ../data/functions.xml.in.h:450 +#: ../data/functions.xml.in.h:457 msgid "Statistics" msgstr "统计" -#: ../data/functions.xml.in.h:451 +#: ../data/functions.xml.in.h:458 msgid "Descriptive Statistics" msgstr "描述性统计" -#: ../data/functions.xml.in.h:452 +#: ../data/functions.xml.in.h:459 msgid "Sum (total)" msgstr "总和" -#: ../data/functions.xml.in.h:453 +#: ../data/functions.xml.in.h:460 msgid "r:total" msgstr "" -#: ../data/functions.xml.in.h:454 +#: ../data/functions.xml.in.h:461 msgid "Data" msgstr "数据" -#: ../data/functions.xml.in.h:455 +#: ../data/functions.xml.in.h:462 msgid "Percentile" msgstr "百分位数" -#: ../data/functions.xml.in.h:456 +#: ../data/functions.xml.in.h:463 msgid "r:percentile" msgstr "" -#: ../data/functions.xml.in.h:458 +#: ../data/functions.xml.in.h:465 #, no-c-format msgid "Percentile (%)" msgstr "百分位数(%)" -#: ../data/functions.xml.in.h:459 +#: ../data/functions.xml.in.h:466 msgid "Quantile algorithm (as in R)" msgstr "" -#: ../data/functions.xml.in.h:460 +#: ../data/functions.xml.in.h:467 msgid "r:min" msgstr "" -#: ../data/functions.xml.in.h:461 +#: ../data/functions.xml.in.h:468 msgid "Returns the lowest value." msgstr "返回最小值。" -#: ../data/functions.xml.in.h:462 +#: ../data/functions.xml.in.h:469 msgid "r:max" msgstr "" -#: ../data/functions.xml.in.h:463 +#: ../data/functions.xml.in.h:470 msgid "Returns the highest value." msgstr "返回最大值。" -#: ../data/functions.xml.in.h:464 +#: ../data/functions.xml.in.h:471 msgid "Mode" msgstr "模式" -#: ../data/functions.xml.in.h:465 +#: ../data/functions.xml.in.h:472 msgid "r:mode" msgstr "" -#: ../data/functions.xml.in.h:466 +#: ../data/functions.xml.in.h:473 msgid "Returns the most frequently occurring value." msgstr "返回最常出现的值。" -#: ../data/functions.xml.in.h:467 +#: ../data/functions.xml.in.h:474 msgid "Range" msgstr "范围" -#: ../data/functions.xml.in.h:468 +#: ../data/functions.xml.in.h:475 msgid "r:range" msgstr "" -#: ../data/functions.xml.in.h:469 +#: ../data/functions.xml.in.h:476 msgid "Calculates the difference between the min and max value." msgstr "计算最大和最小值之间的差。" -#: ../data/functions.xml.in.h:470 +#: ../data/functions.xml.in.h:477 msgid "Median" msgstr "中位数" -#: ../data/functions.xml.in.h:471 +#: ../data/functions.xml.in.h:478 msgid "r:median" msgstr "" -#: ../data/functions.xml.in.h:472 +#: ../data/functions.xml.in.h:479 msgid "Quartile" msgstr "四分位数" -#: ../data/functions.xml.in.h:473 +#: ../data/functions.xml.in.h:480 msgid "r:quartile" msgstr "" -#: ../data/functions.xml.in.h:474 +#: ../data/functions.xml.in.h:481 msgid "Quantile Algorithm (as in R)" msgstr "" -#: ../data/functions.xml.in.h:475 +#: ../data/functions.xml.in.h:482 msgid "Decile" msgstr "十分位数" -#: ../data/functions.xml.in.h:476 +#: ../data/functions.xml.in.h:483 msgid "r:decile" msgstr "" -#: ../data/functions.xml.in.h:477 +#: ../data/functions.xml.in.h:484 msgid "Interquartile Range" msgstr "四分位距" -#: ../data/functions.xml.in.h:478 +#: ../data/functions.xml.in.h:485 msgid "r:iqr" msgstr "" -#: ../data/functions.xml.in.h:479 +#: ../data/functions.xml.in.h:486 msgid "Calculates the difference between the first and third quartile." msgstr "计算第一和第三四分位数之间的差。" -#: ../data/functions.xml.in.h:480 +#: ../data/functions.xml.in.h:487 msgid "Number of Samples" msgstr "样本数量" #. Number of samples -#: ../data/functions.xml.in.h:482 +#: ../data/functions.xml.in.h:489 msgid "r:number" msgstr "" -#: ../data/functions.xml.in.h:483 +#: ../data/functions.xml.in.h:490 msgid "Returns the number of samples." msgstr "返回样本数量。" -#: ../data/functions.xml.in.h:484 +#: ../data/functions.xml.in.h:491 msgid "Random Numbers" msgstr "随机数" -#: ../data/functions.xml.in.h:485 +#: ../data/functions.xml.in.h:492 msgid "Random Number" msgstr "随机数" -#: ../data/functions.xml.in.h:486 +#: ../data/functions.xml.in.h:493 msgid "r:rand" msgstr "" -#: ../data/functions.xml.in.h:487 +#: ../data/functions.xml.in.h:494 msgid "" "Generates a pseudo-random number. Returns a real number between 0 and 1, if " "ceil is zero (default), or an integer between 1 and (including) ceil." @@ -4913,430 +4957,430 @@ "产生一个伪随机数。如果顶部值为0(缺省值),返回一个在0与1之间的实数;否则返回一" "个 在1与顶部值之间(包含顶部值)的整数。" -#: ../data/functions.xml.in.h:488 +#: ../data/functions.xml.in.h:495 msgid "Ceil" msgstr "顶部值" -#: ../data/functions.xml.in.h:489 +#: ../data/functions.xml.in.h:496 #, fuzzy msgid "Number of values" msgstr "样本数量" -#: ../data/functions.xml.in.h:490 +#: ../data/functions.xml.in.h:497 msgid "Normally Distributed Random Number" msgstr "" -#: ../data/functions.xml.in.h:491 +#: ../data/functions.xml.in.h:498 msgid "r:randnorm" msgstr "" -#: ../data/functions.xml.in.h:492 +#: ../data/functions.xml.in.h:499 msgid "Mean" msgstr "平均" -#: ../data/functions.xml.in.h:493 +#: ../data/functions.xml.in.h:500 #, fuzzy msgid "Standard deviation" msgstr "均差" -#: ../data/functions.xml.in.h:494 +#: ../data/functions.xml.in.h:501 #, fuzzy msgid "Poisson Distributed Random Number" msgstr "Logistic分布" -#: ../data/functions.xml.in.h:495 +#: ../data/functions.xml.in.h:502 msgid "r:randpoisson" msgstr "" -#: ../data/functions.xml.in.h:496 +#: ../data/functions.xml.in.h:503 msgid "Uniformly Distributed Random Number" msgstr "" -#: ../data/functions.xml.in.h:497 +#: ../data/functions.xml.in.h:504 msgid "r:randuniform" msgstr "" -#: ../data/functions.xml.in.h:498 +#: ../data/functions.xml.in.h:505 msgid "Random Number Between Limits" msgstr "在某一范围内的随机数" -#: ../data/functions.xml.in.h:499 +#: ../data/functions.xml.in.h:506 msgid "r:randbetween" msgstr "" -#: ../data/functions.xml.in.h:500 +#: ../data/functions.xml.in.h:507 msgid "Returns an integer between (including) bottom and top." msgstr "返回在顶部和底部之间(含底部)的一个整数。" -#: ../data/functions.xml.in.h:501 +#: ../data/functions.xml.in.h:508 msgid "Bottom" msgstr "底部" -#: ../data/functions.xml.in.h:502 +#: ../data/functions.xml.in.h:509 msgid "Top" msgstr "顶部" -#: ../data/functions.xml.in.h:503 +#: ../data/functions.xml.in.h:510 #, fuzzy msgid "Exponential Random Number" msgstr "随机数" -#: ../data/functions.xml.in.h:504 +#: ../data/functions.xml.in.h:511 msgid "r:randexp" msgstr "" -#: ../data/functions.xml.in.h:505 +#: ../data/functions.xml.in.h:512 #, fuzzy msgid "Rate parameter" msgstr "米每米" -#: ../data/functions.xml.in.h:506 +#: ../data/functions.xml.in.h:513 #, fuzzy msgid "Rayleigh Distributed Random Number" msgstr "Logistic分布" -#: ../data/functions.xml.in.h:507 +#: ../data/functions.xml.in.h:514 msgid "r:randrayleigh" msgstr "" -#: ../data/functions.xml.in.h:508 +#: ../data/functions.xml.in.h:515 msgid "Sigma" msgstr "Sigma" -#: ../data/functions.xml.in.h:509 +#: ../data/functions.xml.in.h:516 msgid "Means" msgstr "平均" -#: ../data/functions.xml.in.h:510 +#: ../data/functions.xml.in.h:517 msgid "r:mean,average,au:x̄" msgstr "" -#: ../data/functions.xml.in.h:511 +#: ../data/functions.xml.in.h:518 msgid "Harmonic Mean" msgstr "调和平均" -#: ../data/functions.xml.in.h:512 +#: ../data/functions.xml.in.h:519 msgid "r:harmmean" msgstr "" -#: ../data/functions.xml.in.h:513 +#: ../data/functions.xml.in.h:520 msgid "Geometric Mean" msgstr "几何平均" -#: ../data/functions.xml.in.h:514 +#: ../data/functions.xml.in.h:521 msgid "r:geomean" msgstr "" -#: ../data/functions.xml.in.h:515 +#: ../data/functions.xml.in.h:522 msgid "Trimmed Mean" msgstr "截尾均值" -#: ../data/functions.xml.in.h:516 +#: ../data/functions.xml.in.h:523 msgid "r:trimmean" msgstr "" -#: ../data/functions.xml.in.h:517 +#: ../data/functions.xml.in.h:524 msgid "Trimmed percentage (at each end)" msgstr "截尾百分比(在每一端)" -#: ../data/functions.xml.in.h:518 +#: ../data/functions.xml.in.h:525 msgid "Winsorized Mean" msgstr "Winsorized平均" -#: ../data/functions.xml.in.h:519 +#: ../data/functions.xml.in.h:526 msgid "r:winsormean" msgstr "" -#: ../data/functions.xml.in.h:520 +#: ../data/functions.xml.in.h:527 msgid "Winsorized percentage (at each end)" msgstr "Winsorized百分比(在每一端)" -#: ../data/functions.xml.in.h:521 +#: ../data/functions.xml.in.h:528 msgid "Weighted Mean" msgstr "加权平均" -#: ../data/functions.xml.in.h:522 +#: ../data/functions.xml.in.h:529 msgid "r:weighmean" msgstr "" -#: ../data/functions.xml.in.h:523 +#: ../data/functions.xml.in.h:530 msgid "Weights" msgstr "权重" -#: ../data/functions.xml.in.h:524 +#: ../data/functions.xml.in.h:531 msgid "Quadratic Mean (RMS)" msgstr "均方(RMS)" -#: ../data/functions.xml.in.h:525 +#: ../data/functions.xml.in.h:532 msgid "r:rms" msgstr "" -#: ../data/functions.xml.in.h:526 +#: ../data/functions.xml.in.h:533 msgid "Moments" msgstr "统计矩" -#: ../data/functions.xml.in.h:527 +#: ../data/functions.xml.in.h:534 msgid "Standard Deviation (entire population)" msgstr "标准差(总体)" -#: ../data/functions.xml.in.h:528 +#: ../data/functions.xml.in.h:535 msgid "r:stdevp" msgstr "" -#: ../data/functions.xml.in.h:529 +#: ../data/functions.xml.in.h:536 msgid "Standard Deviation (random sampling)" msgstr "标准差(随机采样)" -#: ../data/functions.xml.in.h:530 +#: ../data/functions.xml.in.h:537 msgid "r:stdev" msgstr "" -#: ../data/functions.xml.in.h:531 +#: ../data/functions.xml.in.h:538 msgid "Variance (entire population)" msgstr "方差(总体)" -#: ../data/functions.xml.in.h:532 +#: ../data/functions.xml.in.h:539 msgid "r:varp" msgstr "" -#: ../data/functions.xml.in.h:533 +#: ../data/functions.xml.in.h:540 msgid "Variance (random sampling)" msgstr "方差(随机样本)" -#: ../data/functions.xml.in.h:534 +#: ../data/functions.xml.in.h:541 msgid "r:var" msgstr "" -#: ../data/functions.xml.in.h:535 +#: ../data/functions.xml.in.h:542 msgid "Standard Error" msgstr "标准误差" -#: ../data/functions.xml.in.h:536 +#: ../data/functions.xml.in.h:543 msgid "r:stderr" msgstr "" -#: ../data/functions.xml.in.h:537 +#: ../data/functions.xml.in.h:544 msgid "Mean Deviation" msgstr "均差" -#: ../data/functions.xml.in.h:538 +#: ../data/functions.xml.in.h:545 msgid "r:meandev" msgstr "" -#: ../data/functions.xml.in.h:539 +#: ../data/functions.xml.in.h:546 msgid "Covariance" msgstr "协方差" -#: ../data/functions.xml.in.h:540 +#: ../data/functions.xml.in.h:547 msgid "r:cov,r:covar" msgstr "" -#: ../data/functions.xml.in.h:541 +#: ../data/functions.xml.in.h:548 msgid "Data 1" msgstr "数据1" -#: ../data/functions.xml.in.h:542 +#: ../data/functions.xml.in.h:549 msgid "Data 2" msgstr "数据2" -#: ../data/functions.xml.in.h:543 +#: ../data/functions.xml.in.h:550 msgid "Pooled Variance" msgstr "合并方差" -#: ../data/functions.xml.in.h:544 +#: ../data/functions.xml.in.h:551 msgid "r:poolvar" msgstr "" -#: ../data/functions.xml.in.h:545 +#: ../data/functions.xml.in.h:552 msgid "Regression" msgstr "回归分析" -#: ../data/functions.xml.in.h:546 +#: ../data/functions.xml.in.h:553 msgid "Statistical Correlation" msgstr "统计相关" -#: ../data/functions.xml.in.h:547 +#: ../data/functions.xml.in.h:554 msgid "r:cor" msgstr "" -#: ../data/functions.xml.in.h:548 +#: ../data/functions.xml.in.h:555 msgid "Pearson's Correlation Coefficient" msgstr "个人相关系数" -#: ../data/functions.xml.in.h:549 +#: ../data/functions.xml.in.h:556 msgid "r:pearson,r:correl" msgstr "" -#: ../data/functions.xml.in.h:550 +#: ../data/functions.xml.in.h:557 msgid "Spearman's Rho" msgstr "" -#: ../data/functions.xml.in.h:551 +#: ../data/functions.xml.in.h:558 msgid "r:spearman" msgstr "" -#: ../data/functions.xml.in.h:552 +#: ../data/functions.xml.in.h:559 msgid "Statistical Tests" msgstr "统计测试" -#: ../data/functions.xml.in.h:553 +#: ../data/functions.xml.in.h:560 msgid "Unpaired T-Test" msgstr "非配对T测试" -#: ../data/functions.xml.in.h:554 +#: ../data/functions.xml.in.h:561 msgid "r:ttest" msgstr "" -#: ../data/functions.xml.in.h:555 +#: ../data/functions.xml.in.h:562 msgid "Paired T-Test" msgstr "配对t检验" -#: ../data/functions.xml.in.h:556 +#: ../data/functions.xml.in.h:563 msgid "r:pttest" msgstr "" -#: ../data/functions.xml.in.h:557 +#: ../data/functions.xml.in.h:564 msgid "Distribution" msgstr "分布" -#: ../data/functions.xml.in.h:558 +#: ../data/functions.xml.in.h:565 msgid "Binomial Distribution" msgstr "二項分佈" -#: ../data/functions.xml.in.h:559 +#: ../data/functions.xml.in.h:566 msgid "r:binomdist" msgstr "" -#: ../data/functions.xml.in.h:560 +#: ../data/functions.xml.in.h:567 msgid "" "Returns the probability mass or cumulative distribution function of the " "binomial distribution." msgstr "" -#: ../data/functions.xml.in.h:561 +#: ../data/functions.xml.in.h:568 #, fuzzy msgid "Number of successes" msgstr "期数" -#: ../data/functions.xml.in.h:562 +#: ../data/functions.xml.in.h:569 #, fuzzy msgid "Number of trials" msgstr "样本数量" -#: ../data/functions.xml.in.h:563 +#: ../data/functions.xml.in.h:570 #, fuzzy msgid "Probability" msgstr "磁导率" -#: ../data/functions.xml.in.h:564 +#: ../data/functions.xml.in.h:571 msgid "Cumulative" msgstr "" -#: ../data/functions.xml.in.h:565 +#: ../data/functions.xml.in.h:572 msgid "Exponential Distribution" msgstr "指数分布" -#: ../data/functions.xml.in.h:566 +#: ../data/functions.xml.in.h:573 msgid "r:expondist" msgstr "" -#: ../data/functions.xml.in.h:567 +#: ../data/functions.xml.in.h:574 #, fuzzy msgid "" "Returns the probability density or cumulative distribution function of the " "exponential distribution." msgstr "根据指定的指数和规模返回Pareto分布在x点的密度概率p(x)。(用Gnumeric)" -#: ../data/functions.xml.in.h:568 +#: ../data/functions.xml.in.h:575 msgid "Logistic Distribution" msgstr "Logistic分布" -#: ../data/functions.xml.in.h:569 +#: ../data/functions.xml.in.h:576 msgid "r:logistic" msgstr "" -#: ../data/functions.xml.in.h:570 +#: ../data/functions.xml.in.h:577 msgid "" "Returns the probability density p(x) at x for a logistic distribution with " "scale parameter. (from Gnumeric)" msgstr "根据指定的规模返回logistic分布在x点的密度概率p(x)。(用Gnumeric)" -#: ../data/functions.xml.in.h:571 +#: ../data/functions.xml.in.h:578 msgid "Scale" msgstr "规模" -#: ../data/functions.xml.in.h:572 +#: ../data/functions.xml.in.h:579 msgid "Normal Distribution" msgstr "正态分布" -#: ../data/functions.xml.in.h:573 +#: ../data/functions.xml.in.h:580 msgid "r:normdist" msgstr "" -#: ../data/functions.xml.in.h:574 +#: ../data/functions.xml.in.h:581 #, fuzzy msgid "" "Returns the probability density or cumulative distribution function of a " "normal distribution." msgstr "根据指定的指数和规模返回Pareto分布在x点的密度概率p(x)。(用Gnumeric)" -#: ../data/functions.xml.in.h:575 +#: ../data/functions.xml.in.h:582 msgid "Pareto Distribution" msgstr "帕累托分布" -#: ../data/functions.xml.in.h:576 +#: ../data/functions.xml.in.h:583 msgid "r:pareto" msgstr "" -#: ../data/functions.xml.in.h:577 +#: ../data/functions.xml.in.h:584 msgid "" "Returns the probability density p(x) at x for a Pareto distribution with " "exponent and scale. (from Gnumeric)" msgstr "根据指定的指数和规模返回Pareto分布在x点的密度概率p(x)。(用Gnumeric)" -#: ../data/functions.xml.in.h:578 +#: ../data/functions.xml.in.h:585 msgid "Poisson Distribution" msgstr "泊松分佈" -#: ../data/functions.xml.in.h:579 +#: ../data/functions.xml.in.h:586 msgid "r:poisson" msgstr "" -#: ../data/functions.xml.in.h:580 +#: ../data/functions.xml.in.h:587 msgid "" "Returns the probability mass or cumulative distribution of the Poisson " "distribution." msgstr "" -#: ../data/functions.xml.in.h:581 +#: ../data/functions.xml.in.h:588 #, fuzzy msgid "Number of events (x)" msgstr "元素个数" -#: ../data/functions.xml.in.h:582 +#: ../data/functions.xml.in.h:589 msgid "Rayleigh Distribution" msgstr "瑞利分布" -#: ../data/functions.xml.in.h:583 +#: ../data/functions.xml.in.h:590 msgid "r:rayleigh" msgstr "" -#: ../data/functions.xml.in.h:584 +#: ../data/functions.xml.in.h:591 msgid "" "Returns the probability density p(x) at x for a Rayleigh distribution with " "scale parameter sigma. (from Gnumeric)" msgstr "" "根据指定的规模参数Sigma返回Rayleigh分布在x点的密度概率p(x)。(用Gnumeric)" -#: ../data/functions.xml.in.h:585 +#: ../data/functions.xml.in.h:592 msgid "Rayleigh Tail Distribution" msgstr "瑞利尾分布" -#: ../data/functions.xml.in.h:586 +#: ../data/functions.xml.in.h:593 msgid "r:rayleightail" msgstr "" -#: ../data/functions.xml.in.h:587 +#: ../data/functions.xml.in.h:594 msgid "" "Returns the probability density p(x) at x for a Rayleigh tail distribution " "with scale parameter sigma and a lower limit. (from Gnumeric)" @@ -5344,21 +5388,21 @@ "根据指定的规模参数Sigma和下限返回Rayleigh尾分布在x点的密度概率p(x)。(用" "Gnumeric)" -#: ../data/functions.xml.in.h:588 ../data/variables.xml.in.h:204 +#: ../data/functions.xml.in.h:595 ../data/variables.xml.in.h:204 msgid "Date & Time" msgstr "日期与时间" -#: ../data/functions.xml.in.h:589 +#: ../data/functions.xml.in.h:596 #, fuzzy msgid "Construct Date" msgstr "构造矩阵" -#: ../data/functions.xml.in.h:590 +#: ../data/functions.xml.in.h:597 #, fuzzy msgid "r:date" msgstr "第一个日期" -#: ../data/functions.xml.in.h:591 +#: ../data/functions.xml.in.h:598 msgid "" "Returns a date. Available calendars gregorian (1), hebrew (2), islamic (3), " "persian (4), indian (5), chinese (6), julian (7), milankovic (8), coptic " @@ -5367,53 +5411,53 @@ "(e.g. leap month 4 = 16)." msgstr "" -#: ../data/functions.xml.in.h:592 +#: ../data/functions.xml.in.h:599 msgid "Year" msgstr "年" -#: ../data/functions.xml.in.h:593 ../data/units.xml.in.h:153 +#: ../data/functions.xml.in.h:600 ../data/units.xml.in.h:153 msgid "Month" msgstr "月份" -#: ../data/functions.xml.in.h:594 ../data/units.xml.in.h:145 +#: ../data/functions.xml.in.h:601 ../data/units.xml.in.h:145 msgid "Day" msgstr "日" -#: ../data/functions.xml.in.h:595 +#: ../data/functions.xml.in.h:602 msgid "Calendar" msgstr "" -#: ../data/functions.xml.in.h:596 +#: ../data/functions.xml.in.h:603 #, fuzzy msgid "Construct Date and Time" msgstr "构造矩阵" -#: ../data/functions.xml.in.h:597 +#: ../data/functions.xml.in.h:604 #, fuzzy msgid "r:datetime" msgstr "第一个日期" -#: ../data/functions.xml.in.h:598 ../data/units.xml.in.h:143 +#: ../data/functions.xml.in.h:605 ../data/units.xml.in.h:143 msgid "Hour" msgstr "小时" -#: ../data/functions.xml.in.h:599 ../data/units.xml.in.h:141 +#: ../data/functions.xml.in.h:606 ../data/units.xml.in.h:141 msgid "Minute" msgstr "分" -#: ../data/functions.xml.in.h:600 ../data/units.xml.in.h:139 +#: ../data/functions.xml.in.h:607 ../data/units.xml.in.h:139 msgid "Second" msgstr "秒" -#: ../data/functions.xml.in.h:601 +#: ../data/functions.xml.in.h:608 msgid "Days between two dates" msgstr "两个日期之间的天数" -#: ../data/functions.xml.in.h:602 +#: ../data/functions.xml.in.h:609 msgid "r:days" msgstr "" -#: ../data/functions.xml.in.h:603 +#: ../data/functions.xml.in.h:610 msgid "" "Returns the number of days between two dates. Basis is the type of " "day counting you want to use: 0: US 30/360, 1: real days (default), 2: real " @@ -5423,31 +5467,31 @@ "30/360 (缺省值), 1: 真实天数, 2: 真实天数/360, 3: 真实天数/365 or 4: 欧式 " "30/360。" -#: ../data/functions.xml.in.h:604 +#: ../data/functions.xml.in.h:611 msgid "First date" msgstr "第一个日期" -#: ../data/functions.xml.in.h:605 +#: ../data/functions.xml.in.h:612 msgid "Second date" msgstr "第二个日期" -#: ../data/functions.xml.in.h:606 +#: ../data/functions.xml.in.h:613 msgid "Day counting basis" msgstr "天数计算基准" -#: ../data/functions.xml.in.h:607 +#: ../data/functions.xml.in.h:614 msgid "Financial function mode" msgstr "金融函数模式" -#: ../data/functions.xml.in.h:608 +#: ../data/functions.xml.in.h:615 msgid "Years between two dates" msgstr "两个日期之间相隔的年数" -#: ../data/functions.xml.in.h:609 +#: ../data/functions.xml.in.h:616 msgid "r:yearfrac" msgstr "" -#: ../data/functions.xml.in.h:610 +#: ../data/functions.xml.in.h:617 msgid "" "Returns the number of years (fractional) between two dates. Basis " "is the type of day counting you want to use: 0: US 30/360, 1: real days " @@ -5457,147 +5501,147 @@ "0: 美式 30/360 (缺省值), 1: 真实天数, 2: 真实天数/360, 3: 真实天数/365 or " "4: 欧式 30/360。" -#: ../data/functions.xml.in.h:611 +#: ../data/functions.xml.in.h:618 msgid "Week of Year" msgstr "一年中的第几周" -#: ../data/functions.xml.in.h:612 +#: ../data/functions.xml.in.h:619 msgid "r:week" msgstr "" -#: ../data/functions.xml.in.h:613 +#: ../data/functions.xml.in.h:620 msgid "Date" msgstr "日期" -#: ../data/functions.xml.in.h:614 +#: ../data/functions.xml.in.h:621 msgid "Week begins on Sunday" msgstr "每周从星期天开始" -#: ../data/functions.xml.in.h:615 +#: ../data/functions.xml.in.h:622 msgid "Day of Week" msgstr "星期中的第几天" -#: ../data/functions.xml.in.h:616 +#: ../data/functions.xml.in.h:623 msgid "r:weekday" msgstr "" -#: ../data/functions.xml.in.h:617 +#: ../data/functions.xml.in.h:624 msgid "r:month" msgstr "" -#: ../data/functions.xml.in.h:618 +#: ../data/functions.xml.in.h:625 msgid "Day of Month" msgstr "月份中的第几天" -#: ../data/functions.xml.in.h:619 +#: ../data/functions.xml.in.h:626 msgid "r:day" msgstr "" -#: ../data/functions.xml.in.h:620 +#: ../data/functions.xml.in.h:627 msgid "r:year" msgstr "" -#: ../data/functions.xml.in.h:621 +#: ../data/functions.xml.in.h:628 msgid "Day of Year" msgstr "一年中的第几天" -#: ../data/functions.xml.in.h:622 +#: ../data/functions.xml.in.h:629 msgid "r:yearday" msgstr "" -#: ../data/functions.xml.in.h:623 +#: ../data/functions.xml.in.h:630 msgid "Current Time" msgstr "当前时间" -#: ../data/functions.xml.in.h:624 +#: ../data/functions.xml.in.h:631 msgid "r:time" msgstr "" -#: ../data/functions.xml.in.h:625 +#: ../data/functions.xml.in.h:632 #, fuzzy msgid "Time Value" msgstr "极限值" -#: ../data/functions.xml.in.h:626 +#: ../data/functions.xml.in.h:633 #, fuzzy msgid "r:timevalue" msgstr "未来值" -#: ../data/functions.xml.in.h:627 +#: ../data/functions.xml.in.h:634 msgid "Returns the time part, in fractional hours, of a date and time value." msgstr "" -#: ../data/functions.xml.in.h:628 +#: ../data/functions.xml.in.h:635 msgid "Date to Unix Timestamp" msgstr "将时间转换为Unix时间戳" -#: ../data/functions.xml.in.h:629 +#: ../data/functions.xml.in.h:636 msgid "r:timestamp" msgstr "" -#: ../data/functions.xml.in.h:630 +#: ../data/functions.xml.in.h:637 msgid "Unix Timestamp to Date" msgstr "Unix时间戳转换为日期" -#: ../data/functions.xml.in.h:631 +#: ../data/functions.xml.in.h:638 msgid "r:stamptodate,unix2date" msgstr "" -#: ../data/functions.xml.in.h:632 +#: ../data/functions.xml.in.h:639 msgid "" "Returns the local date and time represented by the specified Unix timestamp " "(seconds, excluding leap seconds, since 1970-01-01). Supports time units." msgstr "" -#: ../data/functions.xml.in.h:633 +#: ../data/functions.xml.in.h:640 msgid "Timestamp" msgstr "时间戳" -#: ../data/functions.xml.in.h:634 +#: ../data/functions.xml.in.h:641 msgid "Add Days" msgstr "加日" -#: ../data/functions.xml.in.h:635 +#: ../data/functions.xml.in.h:642 msgid "r:addDays" msgstr "" -#: ../data/functions.xml.in.h:636 +#: ../data/functions.xml.in.h:643 msgid "Days" msgstr "日" -#: ../data/functions.xml.in.h:637 +#: ../data/functions.xml.in.h:644 msgid "Add Months" msgstr "加月份" -#: ../data/functions.xml.in.h:638 +#: ../data/functions.xml.in.h:645 msgid "r:addMonths" msgstr "" -#: ../data/functions.xml.in.h:639 +#: ../data/functions.xml.in.h:646 msgid "Months" msgstr "月份" -#: ../data/functions.xml.in.h:640 +#: ../data/functions.xml.in.h:647 msgid "Add Years" msgstr "加年" -#: ../data/functions.xml.in.h:641 +#: ../data/functions.xml.in.h:648 msgid "r:addYears" msgstr "" -#: ../data/functions.xml.in.h:642 +#: ../data/functions.xml.in.h:649 msgid "Years" msgstr "年" -#: ../data/functions.xml.in.h:643 +#: ../data/functions.xml.in.h:650 msgid "Add Time" msgstr "加时间" -#: ../data/functions.xml.in.h:644 +#: ../data/functions.xml.in.h:651 msgid "r:addTime" msgstr "" -#: ../data/functions.xml.in.h:645 +#: ../data/functions.xml.in.h:652 msgid "" "Adds a time value to a date. The value can be positive or negative, but must " "use a unit based on seconds (such as day and year). Fractions of days are " @@ -5606,33 +5650,33 @@ "将一个时间间隔值加到日期中。该值可正可负,但其单位必须基于秒(如日或者年)。日" "期的分数部分会被截取掉。" -#: ../data/functions.xml.in.h:646 ../data/units.xml.in.h:138 +#: ../data/functions.xml.in.h:653 ../data/units.xml.in.h:138 msgid "Time" msgstr "时间" -#: ../data/functions.xml.in.h:647 +#: ../data/functions.xml.in.h:654 msgid "Lunar Phase" msgstr "" -#: ../data/functions.xml.in.h:648 +#: ../data/functions.xml.in.h:655 msgid "r:lunarphase" msgstr "" -#: ../data/functions.xml.in.h:649 +#: ../data/functions.xml.in.h:656 msgid "" "Returns the lunar phase, as a number between 0 and 1, for the specified " "date. 0 represents new moon, 0.5 full moon, and 0.25 and 0.75 quarter moons." msgstr "" -#: ../data/functions.xml.in.h:650 +#: ../data/functions.xml.in.h:657 msgid "Find Lunar Phase" msgstr "" -#: ../data/functions.xml.in.h:651 +#: ../data/functions.xml.in.h:658 msgid "r:nextlunarphase" msgstr "" -#: ../data/functions.xml.in.h:652 +#: ../data/functions.xml.in.h:659 msgid "" "Returns the date when the specified lunar phase occurs. The function " "searches forward beginning at the specified date. The lunar phase are " @@ -5640,47 +5684,47 @@ "moon, and 0.25 and 0.75 quarter moons." msgstr "" -#: ../data/functions.xml.in.h:653 +#: ../data/functions.xml.in.h:660 #, fuzzy msgid "Start Date" msgstr "构造矩阵" -#: ../data/functions.xml.in.h:654 ../data/variables.xml.in.h:197 +#: ../data/functions.xml.in.h:661 ../data/variables.xml.in.h:197 msgid "Utilities" msgstr "工具" -#: ../data/functions.xml.in.h:655 +#: ../data/functions.xml.in.h:662 msgid "Plot Functions and Vectors" msgstr "" -#: ../data/functions.xml.in.h:656 +#: ../data/functions.xml.in.h:663 msgid "r:plot" msgstr "" -#: ../data/functions.xml.in.h:657 +#: ../data/functions.xml.in.h:664 #, fuzzy msgid "Expression or vector" msgstr "矩阵或向量" -#: ../data/functions.xml.in.h:658 +#: ../data/functions.xml.in.h:665 msgid "Minimum x value" msgstr "" -#: ../data/functions.xml.in.h:659 +#: ../data/functions.xml.in.h:666 #, fuzzy msgid "Maximum x value" msgstr "矩阵变量" -#: ../data/functions.xml.in.h:660 +#: ../data/functions.xml.in.h:667 msgid "Number of samples / Step size" msgstr "样本数量/步长" -#: ../data/functions.xml.in.h:661 +#: ../data/functions.xml.in.h:668 #, fuzzy msgid "X variable" msgstr "行变量" -#: ../data/functions.xml.in.h:662 +#: ../data/functions.xml.in.h:669 msgid "" "Plots one or more expressions or vectors. Use a vector for the first " "argument to plot multiple series. Only the first argument is used for vector " @@ -5688,65 +5732,65 @@ "and y values." msgstr "" -#: ../data/functions.xml.in.h:663 +#: ../data/functions.xml.in.h:670 #, fuzzy msgid "Unicode Value" msgstr "极限值" -#: ../data/functions.xml.in.h:664 +#: ../data/functions.xml.in.h:671 msgid "r:code" msgstr "" -#: ../data/functions.xml.in.h:665 +#: ../data/functions.xml.in.h:672 msgid "Character" msgstr "字符" -#: ../data/functions.xml.in.h:666 +#: ../data/functions.xml.in.h:673 #, fuzzy msgid "Unicode Character" msgstr "字符" -#: ../data/functions.xml.in.h:667 +#: ../data/functions.xml.in.h:674 msgid "r:char" msgstr "" -#: ../data/functions.xml.in.h:668 +#: ../data/functions.xml.in.h:675 msgid "Length of string" msgstr "字符串长度" -#: ../data/functions.xml.in.h:669 +#: ../data/functions.xml.in.h:676 msgid "r:len" msgstr "" -#: ../data/functions.xml.in.h:670 +#: ../data/functions.xml.in.h:677 msgid "Text" msgstr "文字" -#: ../data/functions.xml.in.h:671 +#: ../data/functions.xml.in.h:678 msgid "Concatenate Strings" msgstr "连接字符串" -#: ../data/functions.xml.in.h:672 +#: ../data/functions.xml.in.h:679 msgid "r:concatenate" msgstr "" -#: ../data/functions.xml.in.h:673 +#: ../data/functions.xml.in.h:680 msgid "Text string 1" msgstr "文字1" -#: ../data/functions.xml.in.h:674 +#: ../data/functions.xml.in.h:681 msgid "Text string 2" msgstr "文字2" -#: ../data/functions.xml.in.h:675 +#: ../data/functions.xml.in.h:682 msgid "Replace" msgstr "替换" -#: ../data/functions.xml.in.h:676 +#: ../data/functions.xml.in.h:683 msgid "r:replace" msgstr "" -#: ../data/functions.xml.in.h:677 +#: ../data/functions.xml.in.h:684 msgid "" "Replaces a certain value in an expression with a new value. The expression " "is calculated before the replacement if the fourth argument is true." @@ -5754,433 +5798,433 @@ "使用新值替换表达式中的特定值。如果第四个参数是真,则在替换前首先对表达式 进行" "计算。" -#: ../data/functions.xml.in.h:678 +#: ../data/functions.xml.in.h:685 msgid "Expression" msgstr "表达式" -#: ../data/functions.xml.in.h:679 +#: ../data/functions.xml.in.h:686 msgid "Original value" msgstr "原始值" -#: ../data/functions.xml.in.h:680 +#: ../data/functions.xml.in.h:687 msgid "New value" msgstr "新值" -#: ../data/functions.xml.in.h:681 +#: ../data/functions.xml.in.h:688 msgid "Precalculate expression" msgstr "预先计算表达式" -#: ../data/functions.xml.in.h:682 +#: ../data/functions.xml.in.h:689 msgid "Strip Units" msgstr "剥离单位" -#: ../data/functions.xml.in.h:683 +#: ../data/functions.xml.in.h:690 msgid "r:nounit,strip_units" msgstr "" -#: ../data/functions.xml.in.h:684 +#: ../data/functions.xml.in.h:691 msgid "" "Removes all units from an expression. The expression is calculated before " "the removal." msgstr "从表达式中删除全部单位。在删除之前会先对表达式进行计算。" -#: ../data/functions.xml.in.h:685 +#: ../data/functions.xml.in.h:692 msgid "Process Vector Elements" msgstr "处理向量元素" -#: ../data/functions.xml.in.h:686 +#: ../data/functions.xml.in.h:693 msgid "r:process" msgstr "" -#: ../data/functions.xml.in.h:687 +#: ../data/functions.xml.in.h:694 msgid "Element variable" msgstr "元素变量" -#: ../data/functions.xml.in.h:688 +#: ../data/functions.xml.in.h:695 msgid "Index variable" msgstr "下标变量" -#: ../data/functions.xml.in.h:689 +#: ../data/functions.xml.in.h:696 msgid "Vector variable" msgstr "向量变量" -#: ../data/functions.xml.in.h:690 +#: ../data/functions.xml.in.h:697 msgid "Process Matrix Elements" msgstr "处理矩阵元素" -#: ../data/functions.xml.in.h:691 +#: ../data/functions.xml.in.h:698 msgid "r:processm" msgstr "" -#: ../data/functions.xml.in.h:692 +#: ../data/functions.xml.in.h:699 msgid "Row variable" msgstr "行变量" -#: ../data/functions.xml.in.h:693 +#: ../data/functions.xml.in.h:700 msgid "Column variable" msgstr "列标量" -#: ../data/functions.xml.in.h:694 +#: ../data/functions.xml.in.h:701 msgid "Matrix variable" msgstr "矩阵变量" -#: ../data/functions.xml.in.h:695 +#: ../data/functions.xml.in.h:702 msgid "Custom Sum of Elements" msgstr "元素的自定义和" -#: ../data/functions.xml.in.h:696 +#: ../data/functions.xml.in.h:703 msgid "r:csum" msgstr "" -#: ../data/functions.xml.in.h:697 +#: ../data/functions.xml.in.h:704 msgid "First element" msgstr "最后一个元素" -#: ../data/functions.xml.in.h:698 +#: ../data/functions.xml.in.h:705 msgid "Last element" msgstr "最后一个元素" -#: ../data/functions.xml.in.h:699 +#: ../data/functions.xml.in.h:706 msgid "Initial value" msgstr "初始值" -#: ../data/functions.xml.in.h:700 +#: ../data/functions.xml.in.h:707 msgid "Value variable" msgstr "值变量" -#: ../data/functions.xml.in.h:701 +#: ../data/functions.xml.in.h:708 msgid "Select Vector Elements" msgstr "选择矩阵元素" -#: ../data/functions.xml.in.h:702 +#: ../data/functions.xml.in.h:709 msgid "r:select" msgstr "" -#: ../data/functions.xml.in.h:703 +#: ../data/functions.xml.in.h:710 msgid "Condition" msgstr "条件" -#: ../data/functions.xml.in.h:704 +#: ../data/functions.xml.in.h:711 msgid "Select first match" msgstr "选择第一个匹配项" -#: ../data/functions.xml.in.h:705 +#: ../data/functions.xml.in.h:712 msgid "r:function" msgstr "" -#: ../data/functions.xml.in.h:706 +#: ../data/functions.xml.in.h:713 msgid "Arguments" msgstr "自变量" -#: ../data/functions.xml.in.h:707 +#: ../data/functions.xml.in.h:714 msgid "Title" msgstr "标题" -#: ../data/functions.xml.in.h:708 +#: ../data/functions.xml.in.h:715 msgid "r:title" msgstr "" -#: ../data/functions.xml.in.h:710 +#: ../data/functions.xml.in.h:717 msgid "Display Error" msgstr "显示错误" -#: ../data/functions.xml.in.h:711 +#: ../data/functions.xml.in.h:718 msgid "r:error" msgstr "" -#: ../data/functions.xml.in.h:712 +#: ../data/functions.xml.in.h:719 msgid "Message" msgstr "信息" -#: ../data/functions.xml.in.h:713 +#: ../data/functions.xml.in.h:720 msgid "Display Warning" msgstr "显示警告" -#: ../data/functions.xml.in.h:714 +#: ../data/functions.xml.in.h:721 msgid "r:warning" msgstr "" -#: ../data/functions.xml.in.h:715 +#: ../data/functions.xml.in.h:722 msgid "Display Message" msgstr "显示信息" -#: ../data/functions.xml.in.h:716 +#: ../data/functions.xml.in.h:723 msgid "r:message" msgstr "" -#: ../data/functions.xml.in.h:717 +#: ../data/functions.xml.in.h:724 msgid "Save as Variable" msgstr "作为变量保存" -#: ../data/functions.xml.in.h:718 +#: ../data/functions.xml.in.h:725 msgid "r:save" msgstr "" -#: ../data/functions.xml.in.h:719 +#: ../data/functions.xml.in.h:726 msgid "Category" msgstr "类别" -#: ../data/functions.xml.in.h:720 +#: ../data/functions.xml.in.h:727 msgid "RPN Stack Register" msgstr "RPN栈寄存器" -#: ../data/functions.xml.in.h:721 +#: ../data/functions.xml.in.h:728 msgid "r:register" msgstr "" -#: ../data/functions.xml.in.h:722 +#: ../data/functions.xml.in.h:729 msgid "Returns the value of a RPN stack register." msgstr "返回RPN栈寄存器的值。" -#: ../data/functions.xml.in.h:723 +#: ../data/functions.xml.in.h:730 msgid "Index" msgstr "下标" -#: ../data/functions.xml.in.h:724 +#: ../data/functions.xml.in.h:731 msgid "RPN Stack Vector" msgstr "RPN栈向量" -#: ../data/functions.xml.in.h:725 +#: ../data/functions.xml.in.h:732 msgid "r:stack" msgstr "" -#: ../data/functions.xml.in.h:726 +#: ../data/functions.xml.in.h:733 msgid "Returns the RPN stack as a vector." msgstr "将RPN栈作为向量返回。" -#: ../data/functions.xml.in.h:727 +#: ../data/functions.xml.in.h:734 msgid "Is Number" msgstr "是数字" -#: ../data/functions.xml.in.h:728 +#: ../data/functions.xml.in.h:735 msgid "r:isNumber" msgstr "" -#: ../data/functions.xml.in.h:729 +#: ../data/functions.xml.in.h:736 msgid "Is Real" msgstr "是实数" -#: ../data/functions.xml.in.h:730 +#: ../data/functions.xml.in.h:737 msgid "r:isReal" msgstr "" -#: ../data/functions.xml.in.h:731 +#: ../data/functions.xml.in.h:738 msgid "Is Rational" msgstr "是有理数" -#: ../data/functions.xml.in.h:732 +#: ../data/functions.xml.in.h:739 msgid "r:isRational" msgstr "" -#: ../data/functions.xml.in.h:733 +#: ../data/functions.xml.in.h:740 msgid "Is Integer" msgstr "是整数" -#: ../data/functions.xml.in.h:734 +#: ../data/functions.xml.in.h:741 msgid "r:isInteger" msgstr "" -#: ../data/functions.xml.in.h:735 +#: ../data/functions.xml.in.h:742 msgid "Represents Number" msgstr "代表数字" -#: ../data/functions.xml.in.h:736 +#: ../data/functions.xml.in.h:743 msgid "r:representsNumber" msgstr "" -#: ../data/functions.xml.in.h:737 +#: ../data/functions.xml.in.h:744 msgid "Represents Real" msgstr "代表实数" -#: ../data/functions.xml.in.h:738 +#: ../data/functions.xml.in.h:745 msgid "r:representsReal" msgstr "" -#: ../data/functions.xml.in.h:739 +#: ../data/functions.xml.in.h:746 msgid "Represents Rational" msgstr "代表有理数" -#: ../data/functions.xml.in.h:740 +#: ../data/functions.xml.in.h:747 msgid "r:representsRational" msgstr "" -#: ../data/functions.xml.in.h:741 +#: ../data/functions.xml.in.h:748 msgid "Represents Integer" msgstr "代表整数" -#: ../data/functions.xml.in.h:742 +#: ../data/functions.xml.in.h:749 msgid "r:representsInteger" msgstr "" -#: ../data/functions.xml.in.h:743 +#: ../data/functions.xml.in.h:750 #, fuzzy msgid "Interval" msgstr "积分" -#: ../data/functions.xml.in.h:744 +#: ../data/functions.xml.in.h:751 #, fuzzy msgid "r:interval" msgstr "积分" -#: ../data/functions.xml.in.h:745 +#: ../data/functions.xml.in.h:752 #, fuzzy msgid "Lower endpoint" msgstr "下限" -#: ../data/functions.xml.in.h:746 +#: ../data/functions.xml.in.h:753 #, fuzzy msgid "Upper endpoint" msgstr "上限" -#: ../data/functions.xml.in.h:747 +#: ../data/functions.xml.in.h:754 msgid "Uncertainty" msgstr "" -#: ../data/functions.xml.in.h:748 +#: ../data/functions.xml.in.h:755 msgid "r:uncertainty" msgstr "" -#: ../data/functions.xml.in.h:749 +#: ../data/functions.xml.in.h:756 msgid "Uncertainty is relative" msgstr "" -#: ../data/functions.xml.in.h:750 +#: ../data/functions.xml.in.h:757 msgid "Logical" msgstr "逻辑" -#: ../data/functions.xml.in.h:751 +#: ../data/functions.xml.in.h:758 msgid "For...Do" msgstr "For...Do" -#: ../data/functions.xml.in.h:752 +#: ../data/functions.xml.in.h:759 msgid "r:for" msgstr "" -#: ../data/functions.xml.in.h:753 +#: ../data/functions.xml.in.h:760 msgid "Initial value of counter" msgstr "计数器初始值" -#: ../data/functions.xml.in.h:754 +#: ../data/functions.xml.in.h:761 msgid "Counter variable" msgstr "计数器变量" -#: ../data/functions.xml.in.h:755 +#: ../data/functions.xml.in.h:762 msgid "For condition" msgstr "For条件" -#: ../data/functions.xml.in.h:756 +#: ../data/functions.xml.in.h:763 msgid "Counter update function" msgstr "计数器更新函数" -#: ../data/functions.xml.in.h:757 +#: ../data/functions.xml.in.h:764 msgid "Do function" msgstr "Do函数" -#: ../data/functions.xml.in.h:758 +#: ../data/functions.xml.in.h:765 msgid "If...Then...Else" msgstr "If...Then...Else" -#: ../data/functions.xml.in.h:759 +#: ../data/functions.xml.in.h:766 msgid "r:if" msgstr "" -#: ../data/functions.xml.in.h:760 +#: ../data/functions.xml.in.h:767 #, fuzzy msgid "" "Tests a condition and returns a value depending on the result. Vectors can " "be used for argument 1 and 2, instead of nested functions." msgstr "对一个条件进行测试,并根据测试结果返回一个值。" -#: ../data/functions.xml.in.h:761 +#: ../data/functions.xml.in.h:768 msgid "Expression if condition is met" msgstr "条件满足时的表达式" -#: ../data/functions.xml.in.h:762 +#: ../data/functions.xml.in.h:769 msgid "Expression if condition is NOT met" msgstr "条件不满足时的表达式" -#: ../data/functions.xml.in.h:763 +#: ../data/functions.xml.in.h:770 msgid "Assume false if not true" msgstr "" -#: ../data/functions.xml.in.h:764 +#: ../data/functions.xml.in.h:771 msgid "Bitwise Exclusive OR" msgstr "按位排斥OR" -#: ../data/functions.xml.in.h:765 +#: ../data/functions.xml.in.h:772 msgid "r:xor" msgstr "" -#: ../data/functions.xml.in.h:766 +#: ../data/functions.xml.in.h:773 msgid "Value 1" msgstr "值1" -#: ../data/functions.xml.in.h:767 +#: ../data/functions.xml.in.h:774 msgid "Value 2" msgstr "值2" -#: ../data/functions.xml.in.h:768 +#: ../data/functions.xml.in.h:775 msgid "Logical Exclusive OR" msgstr "逻辑排斥OR" -#: ../data/functions.xml.in.h:769 +#: ../data/functions.xml.in.h:776 msgid "r:lxor" msgstr "" -#: ../data/functions.xml.in.h:770 +#: ../data/functions.xml.in.h:777 msgid "Bitwise Shift" msgstr "按位移位" -#: ../data/functions.xml.in.h:771 +#: ../data/functions.xml.in.h:778 msgid "" "Applies logical or arithmetic bitwise shift to an integer. The second " "argument specifies the number of steps that each binary bit is shifted to " "the left (use negative values for right shift)." msgstr "" -#: ../data/functions.xml.in.h:772 +#: ../data/functions.xml.in.h:779 msgid "r:shift" msgstr "" -#: ../data/functions.xml.in.h:773 +#: ../data/functions.xml.in.h:780 msgid "Steps" msgstr "" -#: ../data/functions.xml.in.h:774 +#: ../data/functions.xml.in.h:781 msgid "Arithmetic shift using two's complement" msgstr "" -#: ../data/functions.xml.in.h:775 +#: ../data/functions.xml.in.h:782 msgid "Bitwise Complement (Not)" msgstr "" -#: ../data/functions.xml.in.h:776 +#: ../data/functions.xml.in.h:783 msgid "" "Applies bitwise NOT to an integer of specified bit width and signedness (use " "1 for signed and 0 for unsigned). If bit width is zero, the smallest " "necessary number of bits (of 8, 16, 32, 64, 128, ...) will be used." msgstr "" -#: ../data/functions.xml.in.h:777 +#: ../data/functions.xml.in.h:784 msgid "r:bitcmp" msgstr "" -#: ../data/functions.xml.in.h:778 +#: ../data/functions.xml.in.h:785 #, fuzzy msgid "Bit Width" msgstr "宽度" -#: ../data/functions.xml.in.h:779 +#: ../data/functions.xml.in.h:786 #, fuzzy msgid "Signed Integer" msgstr "积分" -#: ../data/functions.xml.in.h:780 +#: ../data/functions.xml.in.h:787 #, fuzzy msgid "Bit Rotation" msgstr "是有理数" -#: ../data/functions.xml.in.h:781 +#: ../data/functions.xml.in.h:788 msgid "" "Applies circular bitwise shift to an integer of specified bit width and " "signedness (use 1 for signed and 0 for unsigned). The second argument " @@ -6189,755 +6233,781 @@ "necessary number of bits (of 8, 16, 32, 64, 128, ...) will be used." msgstr "" -#: ../data/functions.xml.in.h:782 +#: ../data/functions.xml.in.h:789 msgid "r:bitrot" msgstr "" -#: ../data/functions.xml.in.h:783 +#: ../data/functions.xml.in.h:790 msgid "Algebra" msgstr "代数" -#: ../data/functions.xml.in.h:784 +#: ../data/functions.xml.in.h:791 msgid "Summation" msgstr "求和符号" -#: ../data/functions.xml.in.h:785 +#: ../data/functions.xml.in.h:792 msgid "au:Σ,r:sum" msgstr "" -#: ../data/functions.xml.in.h:786 +#: ../data/functions.xml.in.h:793 #, fuzzy msgid "" "Corresponds to the summation symbol. Adds terms for each x ranging from the " "lower to the upper limit." msgstr "相当于求和符号Σ。将从上限到下限的每项x相加。" -#: ../data/functions.xml.in.h:787 +#: ../data/functions.xml.in.h:794 msgid "Term expression" msgstr "项表达式" -#: ../data/functions.xml.in.h:788 +#: ../data/functions.xml.in.h:795 msgid "Lower limit (i)" msgstr "下限(i)" -#: ../data/functions.xml.in.h:789 +#: ../data/functions.xml.in.h:796 msgid "Upper limit (n)" msgstr "上限(n)" -#: ../data/functions.xml.in.h:790 +#: ../data/functions.xml.in.h:797 msgid "Product of a sequence" msgstr "积" -#: ../data/functions.xml.in.h:791 +#: ../data/functions.xml.in.h:798 msgid "au:Π,r:product" msgstr "" -#: ../data/functions.xml.in.h:792 +#: ../data/functions.xml.in.h:799 msgid "" "Corresponds to the product symbol. Multiplies factors for each x ranging " "from the lower to the upper limit." msgstr "相当于连乘符号Π。将从上限到下限的每项x相乘。" -#: ../data/functions.xml.in.h:793 +#: ../data/functions.xml.in.h:800 msgid "Factor expression" msgstr "因子表达式" -#: ../data/functions.xml.in.h:794 +#: ../data/functions.xml.in.h:801 msgid "Solve for multiple variables" msgstr "多变量求解" -#: ../data/functions.xml.in.h:795 +#: ../data/functions.xml.in.h:802 msgid "r:multisolve" msgstr "r:multisolve" -#: ../data/functions.xml.in.h:796 +#: ../data/functions.xml.in.h:803 msgid "Equation vector" msgstr "方程向量" -#: ../data/functions.xml.in.h:797 +#: ../data/functions.xml.in.h:804 msgid "Variable vector" msgstr "变量向量" -#: ../data/functions.xml.in.h:798 +#: ../data/functions.xml.in.h:805 msgid "Solve equation" msgstr "方程求解" -#: ../data/functions.xml.in.h:799 +#: ../data/functions.xml.in.h:806 msgid "r:solve" msgstr "" -#: ../data/functions.xml.in.h:800 +#: ../data/functions.xml.in.h:807 msgid "Equation" msgstr "方程" -#: ../data/functions.xml.in.h:801 +#: ../data/functions.xml.in.h:808 msgid "With respect to" msgstr "关于" -#: ../data/functions.xml.in.h:802 +#: ../data/functions.xml.in.h:809 #, fuzzy msgid "Solve differential equation" msgstr "方程求解" -#: ../data/functions.xml.in.h:803 +#: ../data/functions.xml.in.h:810 #, fuzzy msgid "r:dsolve" msgstr "r:multisolve" -#: ../data/functions.xml.in.h:804 +#: ../data/functions.xml.in.h:811 msgid "Initial condition: function value (y)" msgstr "" -#: ../data/functions.xml.in.h:805 +#: ../data/functions.xml.in.h:812 msgid "Initial condition: argument value (x)" msgstr "" -#: ../data/functions.xml.in.h:806 +#: ../data/functions.xml.in.h:813 msgid "" "Solves a differential equation and returns the value of y(x). The derivative " "in the equation should be in the format diff(y, x). Only first-order " "differential equations are currently supported." msgstr "" -#: ../data/functions.xml.in.h:807 +#: ../data/functions.xml.in.h:814 msgid "Solve for two variables" msgstr "双变量求解" -#: ../data/functions.xml.in.h:808 +#: ../data/functions.xml.in.h:815 msgid "r:solve2" msgstr "" -#: ../data/functions.xml.in.h:809 +#: ../data/functions.xml.in.h:816 msgid "" "Solves two equations with two unknown variables. Returns the value of the " "first variable." msgstr "解由两个未知数和两个方程组成方程组。返回第一个变量的值。" -#: ../data/functions.xml.in.h:810 +#: ../data/functions.xml.in.h:817 msgid "Equation 1" msgstr "方程1" -#: ../data/functions.xml.in.h:811 +#: ../data/functions.xml.in.h:818 msgid "Equation 2" msgstr "方程" -#: ../data/functions.xml.in.h:812 +#: ../data/functions.xml.in.h:819 msgid "Variable 1" msgstr "变量1" -#: ../data/functions.xml.in.h:813 +#: ../data/functions.xml.in.h:820 msgid "Variable 2" msgstr "变量2" -#: ../data/functions.xml.in.h:814 +#: ../data/functions.xml.in.h:821 msgid "Find Linear Function" msgstr "寻找线性函数" -#: ../data/functions.xml.in.h:815 +#: ../data/functions.xml.in.h:822 msgid "r:linearfunction" msgstr "" -#: ../data/functions.xml.in.h:816 +#: ../data/functions.xml.in.h:823 msgid "" "Finds the linear function for the straight line between two distinct points." msgstr "寻找过两点直线段的线性函数" -#: ../data/functions.xml.in.h:817 +#: ../data/functions.xml.in.h:824 msgid "x1" msgstr "" -#: ../data/functions.xml.in.h:818 +#: ../data/functions.xml.in.h:825 msgid "y1" msgstr "" -#: ../data/functions.xml.in.h:819 +#: ../data/functions.xml.in.h:826 msgid "x2" msgstr "" -#: ../data/functions.xml.in.h:820 +#: ../data/functions.xml.in.h:827 msgid "y2" msgstr "" -#: ../data/functions.xml.in.h:821 +#: ../data/functions.xml.in.h:828 msgid "Calculus" msgstr "微积分" -#: ../data/functions.xml.in.h:822 +#: ../data/functions.xml.in.h:829 msgid "Differentiate" msgstr "百分位数" -#: ../data/functions.xml.in.h:823 +#: ../data/functions.xml.in.h:830 msgid "r:diff,derivative" msgstr "diff,导数" -#: ../data/functions.xml.in.h:824 +#: ../data/functions.xml.in.h:831 #, fuzzy msgid "Variable value" msgstr "变量向量" -#: ../data/functions.xml.in.h:825 +#: ../data/functions.xml.in.h:832 msgid "Integrate" msgstr "积分" -#: ../data/functions.xml.in.h:826 +#: ../data/functions.xml.in.h:833 msgid "r:integrate,integral,au:∫" msgstr "积分,au:∫" -#: ../data/functions.xml.in.h:827 +#: ../data/functions.xml.in.h:834 msgid "Variable of integration" msgstr "积分变量" -#: ../data/functions.xml.in.h:828 +#: ../data/functions.xml.in.h:835 #, fuzzy msgid "Force numerical integration" msgstr "积分变量" -#: ../data/functions.xml.in.h:829 +#: ../data/functions.xml.in.h:836 #, fuzzy msgid "Romberg Integration" msgstr "积分变量" -#: ../data/functions.xml.in.h:830 +#: ../data/functions.xml.in.h:837 msgid "r:romberg" msgstr "" -#: ../data/functions.xml.in.h:831 +#: ../data/functions.xml.in.h:838 #, fuzzy msgid "Min iterations" msgstr "均差" -#: ../data/functions.xml.in.h:832 +#: ../data/functions.xml.in.h:839 #, fuzzy msgid "Max iterations" msgstr "质量分数" -#: ../data/functions.xml.in.h:833 +#: ../data/functions.xml.in.h:840 #, fuzzy msgid "Monte Carlo Integration" msgstr "积分变量" -#: ../data/functions.xml.in.h:834 +#: ../data/functions.xml.in.h:841 msgid "r:montecarlo" msgstr "" -#: ../data/functions.xml.in.h:835 +#: ../data/functions.xml.in.h:842 #, fuzzy msgid "Number of samples" msgstr "样本数量" -#: ../data/functions.xml.in.h:836 +#: ../data/functions.xml.in.h:843 #, fuzzy msgid "Limit" msgstr "下限" -#: ../data/functions.xml.in.h:837 +#: ../data/functions.xml.in.h:844 msgid "" "Returns the two-sided limit of the function if direction is zero, limit from " "left (below) if direction is -1, or limit from right (above) if direction is " "+1." msgstr "" -#: ../data/functions.xml.in.h:838 +#: ../data/functions.xml.in.h:845 #, fuzzy msgid "r:limit" msgstr "下限" -#: ../data/functions.xml.in.h:839 +#: ../data/functions.xml.in.h:846 msgid "Value to approach" msgstr "" -#: ../data/functions.xml.in.h:840 +#: ../data/functions.xml.in.h:847 #, fuzzy msgid "Direction" msgstr "持续时间" -#: ../data/functions.xml.in.h:841 +#: ../data/functions.xml.in.h:848 msgid "Extreme Values" msgstr "极限值" -#: ../data/functions.xml.in.h:842 +#: ../data/functions.xml.in.h:849 msgid "r:extremum" msgstr "" -#: ../data/functions.xml.in.h:843 +#: ../data/functions.xml.in.h:850 #, fuzzy msgid "Named Integrals" msgstr "整数" -#: ../data/functions.xml.in.h:844 +#: ../data/functions.xml.in.h:851 msgid "Logarithmic Integral" msgstr "" -#: ../data/functions.xml.in.h:845 +#: ../data/functions.xml.in.h:852 msgid "rc:li,logint" msgstr "" -#: ../data/functions.xml.in.h:846 +#: ../data/functions.xml.in.h:853 msgid "The integral of 1/ln(x)." msgstr "" -#: ../data/functions.xml.in.h:847 +#: ../data/functions.xml.in.h:854 #, fuzzy msgid "Exponential Integral" msgstr "e的乘方" -#: ../data/functions.xml.in.h:848 +#: ../data/functions.xml.in.h:855 msgid "rc:Ei,expint" msgstr "" -#: ../data/functions.xml.in.h:849 +#: ../data/functions.xml.in.h:856 msgid "The integral of e^x/x." msgstr "" -#: ../data/functions.xml.in.h:850 +#: ../data/functions.xml.in.h:857 #, fuzzy msgid "Sine Integral" msgstr "积分" -#: ../data/functions.xml.in.h:851 +#: ../data/functions.xml.in.h:858 msgid "rc:Si,sinint" msgstr "" -#: ../data/functions.xml.in.h:852 +#: ../data/functions.xml.in.h:859 msgid "The integral of sin(x)/x." msgstr "" -#: ../data/functions.xml.in.h:853 +#: ../data/functions.xml.in.h:860 #, fuzzy msgid "Cosine Integral" msgstr "是整数" -#: ../data/functions.xml.in.h:854 +#: ../data/functions.xml.in.h:861 msgid "rc:Ci,cosint" msgstr "" -#: ../data/functions.xml.in.h:855 +#: ../data/functions.xml.in.h:862 msgid "The integral of cos(x)/x." msgstr "" -#: ../data/functions.xml.in.h:856 +#: ../data/functions.xml.in.h:863 #, fuzzy msgid "Hyperbolic Sine Integral" msgstr "双曲正弦" -#: ../data/functions.xml.in.h:857 +#: ../data/functions.xml.in.h:864 msgid "rc:Shi,sinhint" msgstr "" -#: ../data/functions.xml.in.h:858 +#: ../data/functions.xml.in.h:865 msgid "The integral of sinh(x)/x." msgstr "" -#: ../data/functions.xml.in.h:859 +#: ../data/functions.xml.in.h:866 #, fuzzy msgid "Hyperbolic Cosine Integral" msgstr "双曲余弦" -#: ../data/functions.xml.in.h:860 +#: ../data/functions.xml.in.h:867 msgid "rc:Chi,coshint" msgstr "" -#: ../data/functions.xml.in.h:861 +#: ../data/functions.xml.in.h:868 msgid "The integral of cosh(x)/x." msgstr "" -#: ../data/functions.xml.in.h:862 +#: ../data/functions.xml.in.h:869 +#, fuzzy +msgid "Fresnel Integral S" +msgstr "是整数" + +#: ../data/functions.xml.in.h:870 +msgid "r:fresnels" +msgstr "" + +#: ../data/functions.xml.in.h:871 +msgid "The integral of sin(pi*x^2/2)." +msgstr "" + +#: ../data/functions.xml.in.h:872 +#, fuzzy +msgid "Fresnel Integral C" +msgstr "是整数" + +#: ../data/functions.xml.in.h:873 +msgid "r:fresnelc" +msgstr "" + +#: ../data/functions.xml.in.h:874 +msgid "The integral of cos(pi*x^2/2)." +msgstr "" + +#: ../data/functions.xml.in.h:875 #, fuzzy msgid "Upper Incomplete Gamma Function" msgstr "γ函数" -#: ../data/functions.xml.in.h:863 +#: ../data/functions.xml.in.h:876 msgid "r:igamma" msgstr "" -#: ../data/functions.xml.in.h:864 +#: ../data/functions.xml.in.h:877 #, fuzzy msgid "Lower Incomplete Gamma Function" msgstr "γ函数" -#: ../data/functions.xml.in.h:865 +#: ../data/functions.xml.in.h:878 msgid "r:gammainc" msgstr "" -#: ../data/functions.xml.in.h:866 +#: ../data/functions.xml.in.h:879 msgid "Geometry" msgstr "几何" -#: ../data/functions.xml.in.h:867 +#: ../data/functions.xml.in.h:880 msgid "Triangle" msgstr "三角形" -#: ../data/functions.xml.in.h:868 +#: ../data/functions.xml.in.h:881 msgid "Hypotenuse" msgstr "斜边" -#: ../data/functions.xml.in.h:869 +#: ../data/functions.xml.in.h:882 msgid "r:hypot" msgstr "" -#: ../data/functions.xml.in.h:870 +#: ../data/functions.xml.in.h:883 msgid "Side A" msgstr "边A" -#: ../data/functions.xml.in.h:871 +#: ../data/functions.xml.in.h:884 msgid "Side B" msgstr "边B" -#: ../data/functions.xml.in.h:872 +#: ../data/functions.xml.in.h:885 msgid "Triangle Area" msgstr "三角形面积" -#: ../data/functions.xml.in.h:873 +#: ../data/functions.xml.in.h:886 msgid "r:triangle" msgstr "" -#: ../data/functions.xml.in.h:874 +#: ../data/functions.xml.in.h:887 msgid "Height" msgstr "高度" -#: ../data/functions.xml.in.h:875 +#: ../data/functions.xml.in.h:888 msgid "Triangle Perimeter" msgstr "(直角)三角形周长" -#: ../data/functions.xml.in.h:876 +#: ../data/functions.xml.in.h:889 msgid "r:triangle_perimeter" msgstr "" -#: ../data/functions.xml.in.h:877 +#: ../data/functions.xml.in.h:890 msgid "Side C" msgstr "边C" -#: ../data/functions.xml.in.h:878 +#: ../data/functions.xml.in.h:891 msgid "Circle" msgstr "圆形" -#: ../data/functions.xml.in.h:879 +#: ../data/functions.xml.in.h:892 msgid "Circle Area" msgstr "圆面积" -#: ../data/functions.xml.in.h:880 +#: ../data/functions.xml.in.h:893 msgid "r:circle" msgstr "" -#: ../data/functions.xml.in.h:881 +#: ../data/functions.xml.in.h:894 msgid "Calculates the area of a circle using the radius" msgstr "使用半径计算圆面积" -#: ../data/functions.xml.in.h:882 +#: ../data/functions.xml.in.h:895 msgid "Radius" msgstr "半径" -#: ../data/functions.xml.in.h:883 +#: ../data/functions.xml.in.h:896 msgid "Circle Circumference" msgstr "圆周长" -#: ../data/functions.xml.in.h:884 +#: ../data/functions.xml.in.h:897 msgid "r:circumference" msgstr "" -#: ../data/functions.xml.in.h:885 +#: ../data/functions.xml.in.h:898 msgid "Cylinder" msgstr "圆柱" -#: ../data/functions.xml.in.h:886 +#: ../data/functions.xml.in.h:899 msgid "Cylinder Volume" msgstr "圆柱体积" -#: ../data/functions.xml.in.h:887 +#: ../data/functions.xml.in.h:900 msgid "r:cylinder" msgstr "" -#: ../data/functions.xml.in.h:888 +#: ../data/functions.xml.in.h:901 msgid "Surface Area of Cylinder" msgstr "圆柱体表面积" -#: ../data/functions.xml.in.h:889 +#: ../data/functions.xml.in.h:902 msgid "r:cylinder_sa" msgstr "" -#: ../data/functions.xml.in.h:890 +#: ../data/functions.xml.in.h:903 msgid "Cone" msgstr "圆锥" -#: ../data/functions.xml.in.h:891 +#: ../data/functions.xml.in.h:904 msgid "Cone Volume" msgstr "圆锥体积" -#: ../data/functions.xml.in.h:892 +#: ../data/functions.xml.in.h:905 msgid "r:cone" msgstr "" -#: ../data/functions.xml.in.h:893 +#: ../data/functions.xml.in.h:906 msgid "Surface Area of Cone" msgstr "圆锥表面积" -#: ../data/functions.xml.in.h:894 +#: ../data/functions.xml.in.h:907 msgid "r:cone_sa" msgstr "" -#: ../data/functions.xml.in.h:895 +#: ../data/functions.xml.in.h:908 msgid "Sphere" msgstr "球体" -#: ../data/functions.xml.in.h:896 +#: ../data/functions.xml.in.h:909 msgid "Sphere Volume" msgstr "球体积" -#: ../data/functions.xml.in.h:897 +#: ../data/functions.xml.in.h:910 msgid "r:sphere" msgstr "" -#: ../data/functions.xml.in.h:898 +#: ../data/functions.xml.in.h:911 msgid "Surface Area of Sphere" msgstr "球体表面积" -#: ../data/functions.xml.in.h:899 +#: ../data/functions.xml.in.h:912 msgid "r:sphere_sa" msgstr "" -#: ../data/functions.xml.in.h:900 +#: ../data/functions.xml.in.h:913 msgid "Square Area" msgstr "正方形面积" -#: ../data/functions.xml.in.h:901 +#: ../data/functions.xml.in.h:914 msgid "r:square" msgstr "" -#: ../data/functions.xml.in.h:902 +#: ../data/functions.xml.in.h:915 msgid "Length of side" msgstr "边长" -#: ../data/functions.xml.in.h:903 +#: ../data/functions.xml.in.h:916 msgid "Square Perimeter" msgstr "正方形周长" -#: ../data/functions.xml.in.h:904 +#: ../data/functions.xml.in.h:917 msgid "r:square_perimeter" msgstr "" -#: ../data/functions.xml.in.h:905 +#: ../data/functions.xml.in.h:918 msgid "Cube" msgstr "立方体" -#: ../data/functions.xml.in.h:906 +#: ../data/functions.xml.in.h:919 msgid "Cube Volume" msgstr "立方体体积" -#: ../data/functions.xml.in.h:907 +#: ../data/functions.xml.in.h:920 msgid "r:cube" msgstr "" -#: ../data/functions.xml.in.h:908 +#: ../data/functions.xml.in.h:921 msgid "Surface Area of Cube" msgstr "立方体表面积" -#: ../data/functions.xml.in.h:909 +#: ../data/functions.xml.in.h:922 msgid "r:cube_sa" msgstr "" -#: ../data/functions.xml.in.h:910 +#: ../data/functions.xml.in.h:923 msgid "Rectangle" msgstr "矩形" -#: ../data/functions.xml.in.h:911 +#: ../data/functions.xml.in.h:924 msgid "Rectangle Area" msgstr "矩形面积" -#: ../data/functions.xml.in.h:912 +#: ../data/functions.xml.in.h:925 msgid "r:rect" msgstr "" -#: ../data/functions.xml.in.h:913 +#: ../data/functions.xml.in.h:926 msgid "Width" msgstr "宽度" -#: ../data/functions.xml.in.h:914 +#: ../data/functions.xml.in.h:927 msgid "Rectangle Perimeter" msgstr "矩形周长" -#: ../data/functions.xml.in.h:915 +#: ../data/functions.xml.in.h:928 msgid "r:rect_perimeter" msgstr "" -#: ../data/functions.xml.in.h:916 +#: ../data/functions.xml.in.h:929 msgid "Prism" msgstr "棱柱" -#: ../data/functions.xml.in.h:917 +#: ../data/functions.xml.in.h:930 msgid "Volume of Rectangular Prism" msgstr "矩形棱柱体积" -#: ../data/functions.xml.in.h:918 +#: ../data/functions.xml.in.h:931 msgid "r:rectprism" msgstr "" -#: ../data/functions.xml.in.h:919 +#: ../data/functions.xml.in.h:932 msgid "Calculates the volume of a prism with rectangular base." msgstr "计算矩形棱柱的体积。" -#: ../data/functions.xml.in.h:920 +#: ../data/functions.xml.in.h:933 msgid "Surface Area of Rectangular Prism" msgstr " 矩形棱柱表面积" -#: ../data/functions.xml.in.h:921 +#: ../data/functions.xml.in.h:934 msgid "r:rectprism_sa" msgstr "" -#: ../data/functions.xml.in.h:922 +#: ../data/functions.xml.in.h:935 msgid "Calculates the surface area of a prism with rectangular base." msgstr "计算矩形棱柱的表面积" -#: ../data/functions.xml.in.h:923 +#: ../data/functions.xml.in.h:936 msgid "Volume of Triangular Prism" msgstr "三角棱柱体积" -#: ../data/functions.xml.in.h:924 +#: ../data/functions.xml.in.h:937 msgid "r:triangleprism" msgstr "" -#: ../data/functions.xml.in.h:925 +#: ../data/functions.xml.in.h:938 msgid "Calculates the volume of a prism with triangular base." msgstr "计算三角棱柱的体积。" -#: ../data/functions.xml.in.h:926 +#: ../data/functions.xml.in.h:939 msgid "Pyramid" msgstr "锥体" -#: ../data/functions.xml.in.h:927 +#: ../data/functions.xml.in.h:940 msgid "Pyramid Volume" msgstr "锥体体积" -#: ../data/functions.xml.in.h:928 +#: ../data/functions.xml.in.h:941 msgid "r:pyramid" msgstr "" -#: ../data/functions.xml.in.h:929 +#: ../data/functions.xml.in.h:942 msgid "" "Calculates the volume of a 3-dimensional shape standing on a rectangular " "base and terminating in a point at the top." msgstr "计算矩形锥体的体积。" -#: ../data/functions.xml.in.h:930 +#: ../data/functions.xml.in.h:943 msgid "Length of base" msgstr "底面长度" -#: ../data/functions.xml.in.h:931 +#: ../data/functions.xml.in.h:944 msgid "Width of base" msgstr "底面宽度" -#: ../data/functions.xml.in.h:932 +#: ../data/functions.xml.in.h:945 msgid "Volume of Regular Tetrahedron" msgstr "正四面体体积" -#: ../data/functions.xml.in.h:933 +#: ../data/functions.xml.in.h:946 msgid "r:tetrahedron" msgstr "" -#: ../data/functions.xml.in.h:934 +#: ../data/functions.xml.in.h:947 msgid "Surface Area of Regular Tetrahedron" msgstr "正四面体表面积" -#: ../data/functions.xml.in.h:935 +#: ../data/functions.xml.in.h:948 msgid "r:tetrahedron_sa" msgstr "" -#: ../data/functions.xml.in.h:936 +#: ../data/functions.xml.in.h:949 msgid "Height of Regular Tetrahedron" msgstr "正四面体的高度" -#: ../data/functions.xml.in.h:937 +#: ../data/functions.xml.in.h:950 msgid "r:tetrahedron_height" msgstr "" -#: ../data/functions.xml.in.h:938 +#: ../data/functions.xml.in.h:951 msgid "Volume of Square Pyramid" msgstr "方锥体体积" -#: ../data/functions.xml.in.h:939 +#: ../data/functions.xml.in.h:952 msgid "r:sqpyramid" msgstr "" -#: ../data/functions.xml.in.h:940 +#: ../data/functions.xml.in.h:953 msgid "Surface Area of Square Pyramid" msgstr "方锥体表面积" -#: ../data/functions.xml.in.h:941 +#: ../data/functions.xml.in.h:954 msgid "r:sqpyramid_sa" msgstr "" -#: ../data/functions.xml.in.h:942 +#: ../data/functions.xml.in.h:955 msgid "Height of Square Pyramid" msgstr "方角锥的高度" -#: ../data/functions.xml.in.h:943 +#: ../data/functions.xml.in.h:956 msgid "r:sqpyramid_height" msgstr "" -#: ../data/functions.xml.in.h:944 +#: ../data/functions.xml.in.h:957 msgid "Parallelogram" msgstr "平行四边形" -#: ../data/functions.xml.in.h:945 +#: ../data/functions.xml.in.h:958 msgid "Parallelogram Area" msgstr "平行四边形面积" -#: ../data/functions.xml.in.h:946 +#: ../data/functions.xml.in.h:959 msgid "r:parallelogram" msgstr "" -#: ../data/functions.xml.in.h:947 +#: ../data/functions.xml.in.h:960 msgid "" "Calculates the area of a four-sided figure whose opposite sides are both " "parallel and equal in length." msgstr "计算平行四边形的面积。" -#: ../data/functions.xml.in.h:948 +#: ../data/functions.xml.in.h:961 msgid "Parallelogram Perimeter" msgstr "平行四边形周长" -#: ../data/functions.xml.in.h:949 +#: ../data/functions.xml.in.h:962 msgid "r:parallelogram_perimeter" msgstr "" -#: ../data/functions.xml.in.h:950 +#: ../data/functions.xml.in.h:963 msgid "" "Calculates the perimeter of a four-sided figure whose opposite sides are " "both parallel and equal in length." msgstr "计算平行四边形的周长。" -#: ../data/functions.xml.in.h:951 +#: ../data/functions.xml.in.h:964 msgid "Trapezoid" msgstr "梯形" -#: ../data/functions.xml.in.h:952 +#: ../data/functions.xml.in.h:965 msgid "Trapezoid Area" msgstr "梯形面积" -#: ../data/functions.xml.in.h:953 +#: ../data/functions.xml.in.h:966 msgid "r:trapezoid" msgstr "" -#: ../data/functions.xml.in.h:954 +#: ../data/functions.xml.in.h:967 msgid "Calculates the area of a four-sided figure with two parallel sides." msgstr "计算梯形的面积。" -#: ../data/functions.xml.in.h:955 +#: ../data/functions.xml.in.h:968 msgid "Economics" msgstr "经济学" -#: ../data/functions.xml.in.h:956 +#: ../data/functions.xml.in.h:969 msgid "Microeconomics" msgstr "微观经济学" -#: ../data/functions.xml.in.h:957 +#: ../data/functions.xml.in.h:970 msgid "Elasticity" msgstr "弹性" -#: ../data/functions.xml.in.h:958 +#: ../data/functions.xml.in.h:971 msgid "r:elasticity" msgstr "" -#: ../data/functions.xml.in.h:959 +#: ../data/functions.xml.in.h:972 msgid "" "Calculates the demand elasticity. Also works for supply elasticity, income " "elasticity, cross-price elasticity, etc. Just replace demand with supply, or " @@ -6949,27 +7019,27 @@ "性、交叉价格弹性等。 例如,表达式elasticity(100-x^2, 3)计算x为价格" "变量的函数\"Q = 100 - x^2\",当价格为3时的 需求弹性。" -#: ../data/functions.xml.in.h:960 +#: ../data/functions.xml.in.h:973 msgid "Demand function" msgstr "需求函数" -#: ../data/functions.xml.in.h:961 +#: ../data/functions.xml.in.h:974 msgid "Price" msgstr "价格" -#: ../data/functions.xml.in.h:962 +#: ../data/functions.xml.in.h:975 msgid "Price variable" msgstr "价格变量" -#: ../data/functions.xml.in.h:963 +#: ../data/functions.xml.in.h:976 msgid "Sum-of-Years Digits Depreciation" msgstr "年数总和折旧" -#: ../data/functions.xml.in.h:964 +#: ../data/functions.xml.in.h:977 msgid "r:syd" msgstr "" -#: ../data/functions.xml.in.h:965 +#: ../data/functions.xml.in.h:978 msgid "" "Calculates the sum-of-years digits depreciation for an asset based on its " "cost, salvage value, anticipated life, and a particular period. This method " @@ -6982,31 +7052,31 @@ "方法加速折旧率,因此在早期的折旧支出比晚期要多。\"折旧成本\"是实际的成本 减去" "残值。\"寿命\"是指该资产折旧的周期数目(通常单位为年)。" -#: ../data/functions.xml.in.h:966 +#: ../data/functions.xml.in.h:979 msgid "Cost" msgstr "成本" -#: ../data/functions.xml.in.h:967 +#: ../data/functions.xml.in.h:980 msgid "Salvage value" msgstr "残值" -#: ../data/functions.xml.in.h:968 +#: ../data/functions.xml.in.h:981 msgid "Life" msgstr "" -#: ../data/functions.xml.in.h:969 +#: ../data/functions.xml.in.h:982 msgid "Period" msgstr "周期" -#: ../data/functions.xml.in.h:970 +#: ../data/functions.xml.in.h:983 msgid "Straight Line Depreciation" msgstr "直线折旧" -#: ../data/functions.xml.in.h:971 +#: ../data/functions.xml.in.h:984 msgid "r:sln" msgstr "" -#: ../data/functions.xml.in.h:972 +#: ../data/functions.xml.in.h:985 msgid "" "Determines the straight line depreciation of an asset for a single period." " Cost is the amount you paid for the asset. Salvage is the value of " @@ -7018,15 +7088,15 @@ "产的花销。\"残值\"是此资产在周期 结束时的价值。\"寿命\"是指该资产折旧的周期数" "目。SLN将资产的价值 均摊到它的寿命上。" -#: ../data/functions.xml.in.h:973 +#: ../data/functions.xml.in.h:986 msgid "Present Value" msgstr "现值" -#: ../data/functions.xml.in.h:974 +#: ../data/functions.xml.in.h:987 msgid "r:pv" msgstr "" -#: ../data/functions.xml.in.h:975 +#: ../data/functions.xml.in.h:988 msgid "" "Returns the present value of an investment. If type = 1 then the " "payment is made at the beginning of the period, If type = 0 (or omitted) it " @@ -7035,149 +7105,149 @@ "返回一项投资的现值。 \"类型\" 定义了到期日期。\"1\"代表在每个周期的" "开头支付; \"0\"(缺省值)代表在每个周期末尾支付。" -#: ../data/functions.xml.in.h:976 +#: ../data/functions.xml.in.h:989 msgid "Interest rate" msgstr "利率" -#: ../data/functions.xml.in.h:977 +#: ../data/functions.xml.in.h:990 msgid "Number of periods" msgstr "期数" -#: ../data/functions.xml.in.h:978 +#: ../data/functions.xml.in.h:991 msgid "Payment made each period" msgstr "每期支付" -#: ../data/functions.xml.in.h:979 +#: ../data/functions.xml.in.h:992 msgid "Future value" msgstr "未来值" -#: ../data/functions.xml.in.h:980 +#: ../data/functions.xml.in.h:993 msgid "Type" msgstr "类型" -#: ../data/functions.xml.in.h:981 +#: ../data/functions.xml.in.h:994 msgid "Nominal Interest Rate" msgstr "名义利率" -#: ../data/functions.xml.in.h:982 +#: ../data/functions.xml.in.h:995 msgid "r:nominal" msgstr "" -#: ../data/functions.xml.in.h:983 +#: ../data/functions.xml.in.h:996 msgid "" "Calculates the nominal interest rate from a given effective interest rate " "compounded at given intervals." msgstr "根据在给定时间段内复合的给定有效利率计算名义利率。" -#: ../data/functions.xml.in.h:984 +#: ../data/functions.xml.in.h:997 msgid "Effective interest rate" msgstr "有效利率" -#: ../data/functions.xml.in.h:985 +#: ../data/functions.xml.in.h:998 msgid "Periods" msgstr "周期" -#: ../data/functions.xml.in.h:986 +#: ../data/functions.xml.in.h:999 msgid "Zero Coupon" msgstr "零息" -#: ../data/functions.xml.in.h:987 +#: ../data/functions.xml.in.h:1000 msgid "r:zero_coupon" msgstr "" -#: ../data/functions.xml.in.h:988 +#: ../data/functions.xml.in.h:1001 msgid "Calculates the value of a zero-coupon (pure discount) bond." msgstr "计算零息债券(纯贴现债券)的值。" -#: ../data/functions.xml.in.h:989 +#: ../data/functions.xml.in.h:1002 msgid "Face value" msgstr "票面价值" -#: ../data/functions.xml.in.h:990 +#: ../data/functions.xml.in.h:1003 msgid "Treasury Bill Yield" msgstr "短期债券收益" -#: ../data/functions.xml.in.h:991 +#: ../data/functions.xml.in.h:1004 msgid "r:tbillyield" msgstr "" -#: ../data/functions.xml.in.h:992 +#: ../data/functions.xml.in.h:1005 msgid "Returns the yield for a treasury bill." msgstr "返回短期债券的收益。" -#: ../data/functions.xml.in.h:993 +#: ../data/functions.xml.in.h:1006 msgid "Settlement date" msgstr "结算日期" -#: ../data/functions.xml.in.h:994 +#: ../data/functions.xml.in.h:1007 msgid "Maturity date" msgstr "到期日期" -#: ../data/functions.xml.in.h:995 +#: ../data/functions.xml.in.h:1008 msgid "Price per $100 face value" msgstr "每$100票面价值的价格" -#: ../data/functions.xml.in.h:996 +#: ../data/functions.xml.in.h:1009 msgid "Treasury Bill Price" msgstr "短期债券价格" -#: ../data/functions.xml.in.h:997 +#: ../data/functions.xml.in.h:1010 msgid "r:tbillprice" msgstr "" -#: ../data/functions.xml.in.h:998 +#: ../data/functions.xml.in.h:1011 msgid "Returns the price per $100 value for a treasury bill." msgstr "返回一支短期债券每100美元面值的价格。" -#: ../data/functions.xml.in.h:999 +#: ../data/functions.xml.in.h:1012 msgid "Discount rate" msgstr "贴现率" -#: ../data/functions.xml.in.h:1000 +#: ../data/functions.xml.in.h:1013 msgid "Treasury Bill Equivalent" msgstr "短期债券等价物" -#: ../data/functions.xml.in.h:1001 +#: ../data/functions.xml.in.h:1014 msgid "r:tbilleq" msgstr "" -#: ../data/functions.xml.in.h:1002 +#: ../data/functions.xml.in.h:1015 msgid "Returns the bond equivalent for a treasury bill." msgstr "返回与一支短期债券等值的债券。" -#: ../data/functions.xml.in.h:1003 +#: ../data/functions.xml.in.h:1016 msgid "Interest paid on a given period of an investment (ISPMT)" msgstr "给定投资期内要支付的利息(ISPMT)" -#: ../data/functions.xml.in.h:1004 +#: ../data/functions.xml.in.h:1017 msgid "r:ispmt" msgstr "" -#: ../data/functions.xml.in.h:1005 +#: ../data/functions.xml.in.h:1018 msgid "Calculates the interest paid on a given period of an investment." msgstr "计算一项投资在给定周期内支付的利息。" -#: ../data/functions.xml.in.h:1006 +#: ../data/functions.xml.in.h:1019 msgid "Periodic interest rate" msgstr "周期利率" -#: ../data/functions.xml.in.h:1007 +#: ../data/functions.xml.in.h:1020 msgid "Amortizement period" msgstr "偿还期" -#: ../data/functions.xml.in.h:1008 +#: ../data/functions.xml.in.h:1021 msgid "Present value" msgstr "现值" -#: ../data/functions.xml.in.h:1009 +#: ../data/functions.xml.in.h:1022 msgid "Payment for a loan" msgstr "贷款偿还" -#: ../data/functions.xml.in.h:1010 +#: ../data/functions.xml.in.h:1023 msgid "r:pmt" msgstr "" -#: ../data/functions.xml.in.h:1011 +#: ../data/functions.xml.in.h:1024 #, fuzzy msgid "" "Returns the amount of payment (negative) each period for a loan based on a " @@ -7194,19 +7264,19 @@ "型\" 定义了到期日期。\"1\"代表在每个周期的开头支付; \"0\"(缺省值)代表在每个周" "期末尾支付。" -#: ../data/functions.xml.in.h:1012 +#: ../data/functions.xml.in.h:1025 msgid "Rate" msgstr "利率" -#: ../data/functions.xml.in.h:1013 +#: ../data/functions.xml.in.h:1026 msgid "Periods of an investment" msgstr "投资的期数" -#: ../data/functions.xml.in.h:1014 +#: ../data/functions.xml.in.h:1027 msgid "r:nper" msgstr "" -#: ../data/functions.xml.in.h:1015 +#: ../data/functions.xml.in.h:1028 msgid "" "Calculates number of periods of an investment based on periodic constant " "payments and a constant interest rate. Type defines the due date. 1 " @@ -7216,29 +7286,29 @@ "计算基于周期性固定支付和固定利率的投资的周期数目。 \"类型\" 定义了到" "期日期。\"1\"代表在每个周期的开头支付;\"0\"(缺省值)代表在 每个周期末尾支付。" -#: ../data/functions.xml.in.h:1016 +#: ../data/functions.xml.in.h:1029 msgid "Periods for investment to attain desired value" msgstr "要获得想要的值,需要的投资期数" -#: ../data/functions.xml.in.h:1017 +#: ../data/functions.xml.in.h:1030 msgid "r:g_duration" msgstr "" -#: ../data/functions.xml.in.h:1018 +#: ../data/functions.xml.in.h:1031 msgid "" "Returns the number of periods needed for an investment to attain a desired " "value." msgstr "返回一项投资要得到想要的金额,所需要的期数。" -#: ../data/functions.xml.in.h:1019 +#: ../data/functions.xml.in.h:1032 msgid "Payment of an annuity going towards principal (PPMT)" msgstr "本金的年金支付额(PPMT)" -#: ../data/functions.xml.in.h:1020 +#: ../data/functions.xml.in.h:1033 msgid "r:ppmt" msgstr "" -#: ../data/functions.xml.in.h:1021 +#: ../data/functions.xml.in.h:1034 msgid "" "Calculates the amount of a payment of an annuity going towards principal." " Type defines the due date. 1 for payment at the beginning of a " @@ -7247,35 +7317,35 @@ "计算关于本金的年金支付额。 \"类型\" 定义了到期日期。\"1\"代表在每个" "周期的开头支付; \"0\"(缺省值)代表在每个周期末尾支付。" -#: ../data/functions.xml.in.h:1022 +#: ../data/functions.xml.in.h:1035 msgid "Desired future value" msgstr "期望的未来价值" -#: ../data/functions.xml.in.h:1023 +#: ../data/functions.xml.in.h:1036 msgid "Effective Interest Rate" msgstr "有效利率" -#: ../data/functions.xml.in.h:1024 +#: ../data/functions.xml.in.h:1037 msgid "r:effect" msgstr "" -#: ../data/functions.xml.in.h:1025 +#: ../data/functions.xml.in.h:1038 msgid "Calculates the effective interest for a given nominal rate." msgstr "根据给定的名义利率计算有效利息。" -#: ../data/functions.xml.in.h:1026 +#: ../data/functions.xml.in.h:1039 msgid "Nominal interest rate" msgstr "名义利率" -#: ../data/functions.xml.in.h:1027 +#: ../data/functions.xml.in.h:1040 msgid "Future Value" msgstr "未来值" -#: ../data/functions.xml.in.h:1028 +#: ../data/functions.xml.in.h:1041 msgid "r:fv" msgstr "" -#: ../data/functions.xml.in.h:1029 +#: ../data/functions.xml.in.h:1042 msgid "" "Computes the future value of an investment. This is based on periodic, " "constant payments and a constant interest rate. If type = 1 then " @@ -7286,51 +7356,51 @@ " \"type\"说明了到期日期。\"1\"代表在每个周期的开头支付; \"0\"(缺省值)代" "表在每个周期末尾支付。" -#: ../data/functions.xml.in.h:1030 +#: ../data/functions.xml.in.h:1043 msgid "Return on continuously compounded interest" msgstr "根据连续复合利率的回报" -#: ../data/functions.xml.in.h:1031 +#: ../data/functions.xml.in.h:1044 msgid "r:continuous" msgstr "" -#: ../data/functions.xml.in.h:1032 +#: ../data/functions.xml.in.h:1045 msgid "" "Calculates the return on continuously compounded interest, given the " "principal, nominal rate and time in years." msgstr "根据给定的本金、名义利率和以年为单位的时间,计算连续复合利率的回报。" -#: ../data/functions.xml.in.h:1033 +#: ../data/functions.xml.in.h:1046 msgid "Principal" msgstr "本金" -#: ../data/functions.xml.in.h:1034 +#: ../data/functions.xml.in.h:1047 msgid "Compound" msgstr "复合值" -#: ../data/functions.xml.in.h:1035 +#: ../data/functions.xml.in.h:1048 msgid "r:compound" msgstr "" -#: ../data/functions.xml.in.h:1036 +#: ../data/functions.xml.in.h:1049 msgid "" "Returns the value of an investment, given the principal, nominal interest " "rate, compounding frequency and time." msgstr "根据给定的本金、名义利率、复合频率和时间计算并返回投资的值。" -#: ../data/functions.xml.in.h:1037 +#: ../data/functions.xml.in.h:1050 msgid "Periods per year" msgstr "每年的期数" -#: ../data/functions.xml.in.h:1038 +#: ../data/functions.xml.in.h:1051 msgid "Payment of an annuity going towards interest (IPMT)" msgstr "利息的年金支付额(IPMT)" -#: ../data/functions.xml.in.h:1039 +#: ../data/functions.xml.in.h:1052 msgid "r:ipmt" msgstr "" -#: ../data/functions.xml.in.h:1040 +#: ../data/functions.xml.in.h:1053 msgid "" "Calculates the amount of a payment of an annuity going towards interest. " " Type defines the due date. 1 for payment at the beginning of a period " @@ -7339,15 +7409,15 @@ "计算关于本金的年金利息支付额. \"类型\" 定义了到期日期。\"1\"代表在" "每个周期的开头支付; \"0\"(缺省值)代表在每个周期末尾支付。" -#: ../data/functions.xml.in.h:1041 +#: ../data/functions.xml.in.h:1054 msgid "Interest rate for a fully invested security" msgstr "一项已充分投资证券的利率" -#: ../data/functions.xml.in.h:1042 +#: ../data/functions.xml.in.h:1055 msgid "r:intrate" msgstr "" -#: ../data/functions.xml.in.h:1043 +#: ../data/functions.xml.in.h:1056 msgid "" "Returns the interest rate for a fully invested security. Basis is " "the type of day counting you want to use: 0: US 30/360 (default), 1: real " @@ -7357,62 +7427,62 @@ "0: 美式 30/360 (缺省值), 1: 真实天数, 2: 真实天数/360, 3: 真实天数/365 or " "4: 欧式 30/360。" -#: ../data/functions.xml.in.h:1044 +#: ../data/functions.xml.in.h:1057 msgid "Investment" msgstr "投资" -#: ../data/functions.xml.in.h:1045 +#: ../data/functions.xml.in.h:1058 msgid "Redemption" msgstr "偿还" -#: ../data/functions.xml.in.h:1046 +#: ../data/functions.xml.in.h:1059 msgid "Dollar Fraction" msgstr "美元分数" -#: ../data/functions.xml.in.h:1047 +#: ../data/functions.xml.in.h:1060 msgid "r:dollarfr" msgstr "" -#: ../data/functions.xml.in.h:1048 +#: ../data/functions.xml.in.h:1061 msgid "" "Converts a decimal dollar price into a dollar price expressed as a fraction." msgstr "将用小数表示的美元价格转化为用分数表示的价格。" -#: ../data/functions.xml.in.h:1049 +#: ../data/functions.xml.in.h:1062 msgid "Decimal dollar" msgstr "小数表示的美元" -#: ../data/functions.xml.in.h:1050 +#: ../data/functions.xml.in.h:1063 msgid "Denominator of fraction" msgstr "分数的分母" -#: ../data/functions.xml.in.h:1051 +#: ../data/functions.xml.in.h:1064 msgid "Dollar Decimal" msgstr "美元小数" -#: ../data/functions.xml.in.h:1052 +#: ../data/functions.xml.in.h:1065 msgid "r:dollarde" msgstr "" -#: ../data/functions.xml.in.h:1053 +#: ../data/functions.xml.in.h:1066 msgid "" "Converts a dollar price expressed as a fraction into a dollar price " "expressed as a decimal number." msgstr "将用分数表示的美元价格转化为用小数表示的价格。" -#: ../data/functions.xml.in.h:1054 +#: ../data/functions.xml.in.h:1067 msgid "Fractional dollar" msgstr "分数表示的美元" -#: ../data/functions.xml.in.h:1055 +#: ../data/functions.xml.in.h:1068 msgid "Amount received at maturity for a security bond" msgstr "债券到期时获得的金额" -#: ../data/functions.xml.in.h:1056 +#: ../data/functions.xml.in.h:1069 msgid "r:received" msgstr "" -#: ../data/functions.xml.in.h:1057 +#: ../data/functions.xml.in.h:1070 msgid "" "Returns the amount received at the maturity date for an invested security." " Basis is the type of day counting you want to use: 0: US 30/360 " @@ -7423,15 +7493,15 @@ "0: 美式 30/360 (缺省值), 1: 真实天数, 2: 真实天数/360, 3: 真实天数/365 or " "4: 欧式 30/360。" -#: ../data/functions.xml.in.h:1058 +#: ../data/functions.xml.in.h:1071 msgid "Discount rate for a security" msgstr "证券的贴现率" -#: ../data/functions.xml.in.h:1059 +#: ../data/functions.xml.in.h:1072 msgid "r:disc" msgstr "" -#: ../data/functions.xml.in.h:1060 +#: ../data/functions.xml.in.h:1073 msgid "" "Returns the discount rate for a security. Basis is the type of day " "counting you want to use: 0: US 30/360 (default), 1: real days, 2: real " @@ -7441,15 +7511,15 @@ "30/360 (缺省值), 1: 真实天数, 2: 真实天数/360, 3: 真实天数/365 or 4: 欧式 " "30/360。" -#: ../data/functions.xml.in.h:1061 +#: ../data/functions.xml.in.h:1074 msgid "Accrued interest of security paying at maturity" msgstr "到期时支付的证券应计利息" -#: ../data/functions.xml.in.h:1062 +#: ../data/functions.xml.in.h:1075 msgid "r:accrintm" msgstr "" -#: ../data/functions.xml.in.h:1063 +#: ../data/functions.xml.in.h:1076 msgid "" "Returns the accrued interest for a security which pays interest at maturity " "date. Basis is the type of day counting you want to use: 0: US " @@ -7460,27 +7530,27 @@ "数计算类型:0: 美式 30/360 (缺省值), 1: 真实天数, 2: 真实天数/360, 3: 真实" "天数/365 or 4: 欧式 30/360。" -#: ../data/functions.xml.in.h:1064 +#: ../data/functions.xml.in.h:1077 msgid "Issue date" msgstr "发表日期" -#: ../data/functions.xml.in.h:1065 +#: ../data/functions.xml.in.h:1078 msgid "Annual rate of security" msgstr "证券年利率" -#: ../data/functions.xml.in.h:1066 +#: ../data/functions.xml.in.h:1079 msgid "Par value" msgstr "面值" -#: ../data/functions.xml.in.h:1067 +#: ../data/functions.xml.in.h:1080 msgid "Accrued interest of security with periodic interest payments" msgstr "分期支付的证券应计利息" -#: ../data/functions.xml.in.h:1068 +#: ../data/functions.xml.in.h:1081 msgid "r:accrint" msgstr "" -#: ../data/functions.xml.in.h:1069 +#: ../data/functions.xml.in.h:1082 msgid "" "Returns accrued interest for a security which pays periodic interest. " " Allowed frequencies are 1 - annual, 2 - semi-annual or 4 - quarterly. " @@ -7491,23 +7561,23 @@ "2 - 半年付 或 4 - 季付。 \"基准\"是您想使用的天数计算类型:0: 美式 30/360 (缺" "省值), 1: 真实天数, 2: 真实天数/360, 3: 真实天数/365 or 4: 欧式 30/360。" -#: ../data/functions.xml.in.h:1070 +#: ../data/functions.xml.in.h:1083 msgid "First interest" msgstr "第一笔利息" -#: ../data/functions.xml.in.h:1071 +#: ../data/functions.xml.in.h:1084 msgid "Frequency" msgstr "频率" -#: ../data/functions.xml.in.h:1072 +#: ../data/functions.xml.in.h:1085 msgid "Number of coupons to be paid" msgstr "要支付的息票数量" -#: ../data/functions.xml.in.h:1073 +#: ../data/functions.xml.in.h:1086 msgid "r:coupnum" msgstr "" -#: ../data/functions.xml.in.h:1074 +#: ../data/functions.xml.in.h:1087 msgid "" "Returns the number of coupons to be paid between the settlement and the " "maturity. Basis is the type of day counting you want to use: 0: US " @@ -7518,16 +7588,16 @@ "数计算类型:0: 美式 30/360 (缺省值), 1: 真实天数, 2: 真实天数/360, 3: 真实" "天数/365 or 4: 欧式 30/360。" -#: ../data/functions.xml.in.h:1075 +#: ../data/functions.xml.in.h:1088 #, fuzzy msgid "Price per $100 face value of a discounted security" msgstr "一支证券每$100票面价值的价格" -#: ../data/functions.xml.in.h:1076 +#: ../data/functions.xml.in.h:1089 msgid "r:pricedisc" msgstr "" -#: ../data/functions.xml.in.h:1077 +#: ../data/functions.xml.in.h:1090 #, fuzzy msgid "" "Calculates and returns the price per $100 face value of a discounted " @@ -7539,19 +7609,19 @@ " \"基准\"是您想使用的天数计算类型:0: 美式 30/360 (缺省值), 1: 真实天" "数, 2: 真实天数/360, 3: 真实天数/365 or 4: 欧式 30/360。" -#: ../data/functions.xml.in.h:1078 +#: ../data/functions.xml.in.h:1091 msgid "Discount" msgstr "贴现" -#: ../data/functions.xml.in.h:1079 +#: ../data/functions.xml.in.h:1092 msgid "Price per $100 face value of a security" msgstr "一支证券每$100票面价值的价格" -#: ../data/functions.xml.in.h:1080 +#: ../data/functions.xml.in.h:1093 msgid "r:pricemat" msgstr "" -#: ../data/functions.xml.in.h:1081 +#: ../data/functions.xml.in.h:1094 msgid "" "Calculates and returns the price per $100 face value of a security. The " "security pays interest at maturity. Basis is the type of day " @@ -7562,31 +7632,31 @@ " \"基准\"是您想使用的天数计算类型:0: 美式 30/360 (缺省值), 1: 真实天" "数, 2: 真实天数/360, 3: 真实天数/365 or 4: 欧式 30/360。" -#: ../data/functions.xml.in.h:1082 +#: ../data/functions.xml.in.h:1095 msgid "Annual yield" msgstr "年收益" -#: ../data/functions.xml.in.h:1083 +#: ../data/functions.xml.in.h:1096 msgid "Level-Coupon Bond" msgstr "息票债券" -#: ../data/functions.xml.in.h:1084 +#: ../data/functions.xml.in.h:1097 msgid "r:level_coupon" msgstr "r:level_coupon" -#: ../data/functions.xml.in.h:1085 +#: ../data/functions.xml.in.h:1098 msgid "Calculates the value of a level-coupon bond." msgstr "计算息票债券的值。" -#: ../data/functions.xml.in.h:1086 +#: ../data/functions.xml.in.h:1099 msgid "Coupon rate" msgstr "息票利率" -#: ../data/functions.xml.in.h:1087 +#: ../data/functions.xml.in.h:1100 msgid "Coupons per year" msgstr "息票数每年" -#: ../data/functions.xml.in.h:1088 +#: ../data/functions.xml.in.h:1101 msgid "Market interest rate" msgstr "市场利率" @@ -10917,10 +10987,6 @@ #~ msgstr "黄金比例" #, fuzzy -#~ msgid "Belarusian Ruble" -#~ msgstr "俄罗斯卢布" - -#, fuzzy #~ msgid "Mauritania" #~ msgstr "到期日期" diff -Nru libqalculate-3.6.0/src/defs2doc.cc libqalculate-3.7.0/src/defs2doc.cc --- libqalculate-3.6.0/src/defs2doc.cc 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/src/defs2doc.cc 2020-01-21 22:54:40.000000000 +0000 @@ -430,7 +430,7 @@ if(is_answer_variable(v)) { value = _("a previous result"); } else if(v->isKnown()) { - if(v == CALCULATOR->v_precision) { + if(v->id() == VARIABLE_ID_PRECISION) { value = _("current precision"); } else if(((KnownVariable*) v)->isExpression()) { value = fix(CALCULATOR->localizeExpression(((KnownVariable*) v)->expression())); @@ -483,7 +483,7 @@ } } if(v->isApproximate() && !is_relative && value.find(SIGN_PLUSMINUS) == string::npos) { - if(v == CALCULATOR->v_pi || v == CALCULATOR->v_e || v == CALCULATOR->v_euler || v == CALCULATOR->v_catalan) { + if(v->id() == VARIABLE_ID_PI || v->id() == VARIABLE_ID_E || v->id() == VARIABLE_ID_EULER || v->id() == VARIABLE_ID_CATALAN) { value += " ("; value += _("variable precision"); value += ")"; diff -Nru libqalculate-3.6.0/src/Makefile.am libqalculate-3.7.0/src/Makefile.am --- libqalculate-3.6.0/src/Makefile.am 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/src/Makefile.am 2020-01-21 22:54:43.000000000 +0000 @@ -19,7 +19,6 @@ @LIBCURL_LIBS@ \ @ICU_LIBS@ \ @READLINE_LIBS@ \ - @LTLIBINTL@ \ @LTLIBICONV@ \ ../libqalculate/libqalculate.la @@ -29,7 +28,6 @@ @LIBXML_LIBS@ \ @LIBCURL_LIBS@ \ @ICU_LIBS@ \ - @LTLIBINTL@ \ @LTLIBICONV@ \ ../libqalculate/libqalculate.la @@ -39,7 +37,6 @@ @LIBXML_LIBS@ \ @LIBCURL_LIBS@ \ @ICU_LIBS@ \ - @LTLIBINTL@ \ @LTLIBICONV@ \ ../libqalculate/libqalculate.la diff -Nru libqalculate-3.6.0/src/qalc.cc libqalculate-3.7.0/src/qalc.cc --- libqalculate-3.6.0/src/qalc.cc 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/src/qalc.cc 2020-01-21 22:54:40.000000000 +0000 @@ -28,6 +28,8 @@ # include #endif +#include + using std::string; using std::cout; using std::vector; @@ -104,7 +106,6 @@ bool display_errors(bool goto_input = false, int cols = 0); void replace_quotation_marks(string &result_text); void replace_result_cis(string &resstr); -extern int has_information_unit(const MathStructure &m, bool top = true); FILE *cfile; @@ -739,18 +740,18 @@ else if(EQUALS_IGNORECASE_AND_LOCAL(svar, "lowercase e", _("lowercase e")) || svar == "lowe") SET_BOOL_D(printops.lower_case_e) else if(EQUALS_IGNORECASE_AND_LOCAL(svar, "lowercase numbers", _("lowercase numbers")) || svar == "lownum") SET_BOOL_D(printops.lower_case_numbers) else if(EQUALS_IGNORECASE_AND_LOCAL(svar, "imaginary j", _("imaginary j")) || svar == "imgj") { - bool b = CALCULATOR->v_i->hasName("j") > 0; + bool b = CALCULATOR->getVariableById(VARIABLE_ID_I)->hasName("j") > 0; SET_BOOL(b) - if(b != (CALCULATOR->v_i->hasName("j") > 0)) { + if(b != (CALCULATOR->getVariableById(VARIABLE_ID_I)->hasName("j") > 0)) { if(b) { - ExpressionName ename = CALCULATOR->v_i->getName(1); + ExpressionName ename = CALCULATOR->getVariableById(VARIABLE_ID_I)->getName(1); ename.name = "j"; ename.reference = false; - CALCULATOR->v_i->addName(ename, 1, true); - CALCULATOR->v_i->setChanged(false); + CALCULATOR->getVariableById(VARIABLE_ID_I)->addName(ename, 1, true); + CALCULATOR->getVariableById(VARIABLE_ID_I)->setChanged(false); } else { - CALCULATOR->v_i->clearNonReferenceNames(); - CALCULATOR->v_i->setChanged(false); + CALCULATOR->getVariableById(VARIABLE_ID_I)->clearNonReferenceNames(); + CALCULATOR->getVariableById(VARIABLE_ID_I)->setChanged(false); } result_display_updated(); } @@ -1467,7 +1468,7 @@ value += "..."; } FPUTS_UNICODE(value.c_str(), stdout); - if(!is_relative && ((KnownVariable*) v)->uncertainty().empty() && v->isApproximate() && ((KnownVariable*) v)->expression().find(SIGN_PLUSMINUS) == string::npos && ((KnownVariable*) v)->expression().find(CALCULATOR->f_interval->referenceName()) == string::npos) { + if(!is_relative && ((KnownVariable*) v)->uncertainty().empty() && v->isApproximate() && ((KnownVariable*) v)->expression().find(SIGN_PLUSMINUS) == string::npos && ((KnownVariable*) v)->expression().find(CALCULATOR->getFunctionById(FUNCTION_ID_INTERVAL)->referenceName()) == string::npos) { fputs(" (", stdout); FPUTS_UNICODE(_("approximate"), stdout); fputs(")", stdout); @@ -1573,7 +1574,7 @@ if(list_type == 'v') item = CALCULATOR->variables[i]; if(list_type == 'u') item = CALCULATOR->units[i]; if(list_type == 'c') item = CALCULATOR->units[i]; - if((!item->isHidden() || list_type == 'c') && item->isActive() && (list_type != 'u' || (item->subtype() != SUBTYPE_COMPOSITE_UNIT && ((Unit*) item)->baseUnit() != CALCULATOR->u_euro)) && (list_type != 'c' || ((Unit*) item)->isCurrency())) { + if((!item->isHidden() || list_type == 'c') && item->isActive() && (list_type != 'u' || (item->subtype() != SUBTYPE_COMPOSITE_UNIT && ((Unit*) item)->baseUnit() != CALCULATOR->getUnitById(UNIT_ID_EURO))) && (list_type != 'c' || ((Unit*) item)->isCurrency())) { const ExpressionName &ename1 = item->preferredInputName(false, false); name_str = ename1.name; size_t name_i = 1; @@ -1913,12 +1914,12 @@ //load local definitions CALCULATOR->loadLocalDefinitions(); - if(do_imaginary_j && CALCULATOR->v_i->hasName("j") == 0) { - ExpressionName ename = CALCULATOR->v_i->getName(1); + if(do_imaginary_j && CALCULATOR->getVariableById(VARIABLE_ID_I)->hasName("j") == 0) { + ExpressionName ename = CALCULATOR->getVariableById(VARIABLE_ID_I)->getName(1); ename.name = "j"; ename.reference = false; - CALCULATOR->v_i->addName(ename, 1, true); - CALCULATOR->v_i->setChanged(false); + CALCULATOR->getVariableById(VARIABLE_ID_I)->addName(ename, 1, true); + CALCULATOR->getVariableById(VARIABLE_ID_I)->setChanged(false); } if(!result_only) { @@ -3043,7 +3044,7 @@ } CHECK_IF_SCREEN_FILLED_PUTS(str.c_str()) PRINT_AND_COLON_TABS(_("hexadecimal two's"), "hextwos"); str += b2oo(printops.hexadecimal_twos_complement, false); CHECK_IF_SCREEN_FILLED_PUTS(str.c_str()) - PRINT_AND_COLON_TABS(_("imaginary j"), "imgj"); str += b2oo(CALCULATOR->v_i->hasName("j") > 0, false); CHECK_IF_SCREEN_FILLED_PUTS(str.c_str()) + PRINT_AND_COLON_TABS(_("imaginary j"), "imgj"); str += b2oo(CALCULATOR->getVariableById(VARIABLE_ID_I)->hasName("j") > 0, false); CHECK_IF_SCREEN_FILLED_PUTS(str.c_str()) PRINT_AND_COLON_TABS(_("interval display"), "ivdisp"); if(adaptive_interval_display) { str += _("adaptive"); @@ -3104,7 +3105,7 @@ if(CALCULATOR->getDecimalPoint() != DOT) { PRINT_AND_COLON_TABS(_("ignore dot"), ""); str += b2oo(evalops.parse_options.dot_as_separator, false); CHECK_IF_SCREEN_FILLED_PUTS(str.c_str()) } - PRINT_AND_COLON_TABS(_("imaginary j"), "imgj"); str += b2oo(CALCULATOR->v_i->hasName("j") > 0, false); CHECK_IF_SCREEN_FILLED_PUTS(str.c_str()) + PRINT_AND_COLON_TABS(_("imaginary j"), "imgj"); str += b2oo(CALCULATOR->getVariableById(VARIABLE_ID_I)->hasName("j") > 0, false); CHECK_IF_SCREEN_FILLED_PUTS(str.c_str()) PRINT_AND_COLON_TABS(_("input base"), "inbase"); switch(evalops.parse_options.base) { case BASE_ROMAN_NUMERALS: {str += _("roman"); break;} @@ -3562,7 +3563,7 @@ bool b_approx = item->isApproximate(); if(b_approx && v->isKnown()) { if(((KnownVariable*) v)->isExpression()) { - b_approx = ((KnownVariable*) v)->expression().find(SIGN_PLUSMINUS) == string::npos && ((KnownVariable*) v)->expression().find(CALCULATOR->f_interval->referenceName()) == string::npos; + b_approx = ((KnownVariable*) v)->expression().find(SIGN_PLUSMINUS) == string::npos && ((KnownVariable*) v)->expression().find(CALCULATOR->getFunctionById(FUNCTION_ID_INTERVAL)->referenceName()) == string::npos; } else { b_approx = ((KnownVariable*) v)->get().containsInterval(true, false, false, 0, true) <= 0; } @@ -3741,7 +3742,7 @@ if(!printops.restrict_fraction_length && printops.number_fraction_format == FRACTION_FRACTIONAL) nff = 4; STR_AND_TABS_4(_("fractions"), "fr", _("Determines how rational numbers are displayed (e.g. 5/4 = 1 + 1/4 = 1.25). 'long' removes limits on the size of the numerator and denonimator."), nff, _("off"), _("exact"), _("on"), _("mixed"), _("long")); STR_AND_TABS_BOOL(_("hexadecimal two's"), "hextwos", _("Enables two's complement representation for display of negative hexadecimal numbers."), printops.twos_complement); - STR_AND_TABS_BOOL(_("imaginary j"), "imgj", _("Use 'j' (instead of 'i') as default symbol for the imaginary unit."), (CALCULATOR->v_i->hasName("j") > 0)); + STR_AND_TABS_BOOL(_("imaginary j"), "imgj", _("Use 'j' (instead of 'i') as default symbol for the imaginary unit."), (CALCULATOR->getVariableById(VARIABLE_ID_I)->hasName("j") > 0)); STR_AND_TABS_7(_("interval display"), "ivdisp", "", (adaptive_interval_display ? 0 : printops.interval_display + 1), _("adaptive"), _("significant"), _("interval"), _("plusminus"), _("midpoint"), _("upper"), _("lower")) STR_AND_TABS_BOOL(_("lowercase e"), "lowe", _("Use lowercase e for E-notation (5e2 = 5 * 10^2)."), printops.lower_case_e); STR_AND_TABS_BOOL(_("lowercase numbers"), "lownum", _("Use lowercase letters for number bases > 10."), printops.lower_case_numbers); @@ -3800,7 +3801,7 @@ if(CALCULATOR->getDecimalPoint() != DOT) { STR_AND_TABS_BOOL(_("ignore dot"), "", _("Allows use of '.' as thousands separator."), evalops.parse_options.dot_as_separator); } - STR_AND_TABS_BOOL(_("imaginary j"), "imgj", _("Use 'j' (instead of 'i') as default symbol for the imaginary unit."), (CALCULATOR->v_i->hasName("j") > 0)); + STR_AND_TABS_BOOL(_("imaginary j"), "imgj", _("Use 'j' (instead of 'i') as default symbol for the imaginary unit."), (CALCULATOR->getVariableById(VARIABLE_ID_I)->hasName("j") > 0)); STR_AND_TABS_SET(_("input base"), "inbase"); str += "(-1114112 - 1114112"; str += ", "; str += _("bin"); if(evalops.parse_options.base == BASE_BINARY) str += "*"; str += ", "; str += _("oct"); @@ -4301,8 +4302,8 @@ } if(update_parse) { if(adaptive_interval_display) { - if((parsed_mstruct && parsed_mstruct->containsFunction(CALCULATOR->f_uncertainty)) || expression_str.find("+/-") != string::npos || expression_str.find("+/" SIGN_MINUS) != string::npos || expression_str.find("±") != string::npos) printops.interval_display = INTERVAL_DISPLAY_PLUSMINUS; - else if(parsed_mstruct && parsed_mstruct->containsFunction(CALCULATOR->f_interval)) printops.interval_display = INTERVAL_DISPLAY_INTERVAL; + if((parsed_mstruct && parsed_mstruct->containsFunctionId(FUNCTION_ID_UNCERTAINTY)) || expression_str.find("+/-") != string::npos || expression_str.find("+/" SIGN_MINUS) != string::npos || expression_str.find("±") != string::npos) printops.interval_display = INTERVAL_DISPLAY_PLUSMINUS; + else if(parsed_mstruct && parsed_mstruct->containsFunctionId(FUNCTION_ID_INTERVAL)) printops.interval_display = INTERVAL_DISPLAY_INTERVAL; else printops.interval_display = INTERVAL_DISPLAY_SIGNIFICANT_DIGITS; } if(!view_thread->write((void *) parsed_mstruct)) {b_busy = false; view_thread->cancel(); return;} @@ -5029,6 +5030,8 @@ size_t stack_size = 0; CALCULATOR->resetExchangeRatesUsed(); + + MathStructure to_struct; if(do_stack) { stack_size = CALCULATOR->RPNStackSize(); @@ -5053,7 +5056,7 @@ case '&': {CALCULATOR->calculateRPN(OPERATION_BITWISE_AND, 0, evalops, parsed_mstruct); break;} case '|': {CALCULATOR->calculateRPN(OPERATION_BITWISE_OR, 0, evalops, parsed_mstruct); break;} case '~': {CALCULATOR->calculateRPNBitwiseNot(0, evalops, parsed_mstruct); break;} - case '!': {CALCULATOR->calculateRPN(CALCULATOR->f_factorial, 0, evalops, parsed_mstruct); break;} + case '!': {CALCULATOR->calculateRPN(CALCULATOR->getFunctionById(FUNCTION_ID_FACTORIAL), 0, evalops, parsed_mstruct); break;} case '>': {CALCULATOR->calculateRPN(OPERATION_GREATER, 0, evalops, parsed_mstruct); break;} case '<': {CALCULATOR->calculateRPN(OPERATION_LESS, 0, evalops, parsed_mstruct); break;} case '=': {CALCULATOR->calculateRPN(OPERATION_EQUALS, 0, evalops, parsed_mstruct); break;} @@ -5071,7 +5074,7 @@ CALCULATOR->calculateRPN(OPERATION_RAISE, 0, evalops, parsed_mstruct); do_mathoperation = true; } else if(str2 == "!!") { - CALCULATOR->calculateRPN(CALCULATOR->f_factorial2, 0, evalops, parsed_mstruct); + CALCULATOR->calculateRPN(CALCULATOR->getFunctionById(FUNCTION_ID_DOUBLE_FACTORIAL), 0, evalops, parsed_mstruct); do_mathoperation = true; } else if(str2 == "!=" || str == "=!" || str == "<>") { CALCULATOR->calculateRPN(OPERATION_NOT_EQUALS, 0, evalops, parsed_mstruct); @@ -5148,8 +5151,10 @@ } } } else { - CALCULATOR->calculate(mstruct, CALCULATOR->unlocalizeExpression(str, evalops.parse_options), 0, evalops, parsed_mstruct, NULL); + CALCULATOR->calculate(mstruct, CALCULATOR->unlocalizeExpression(str, evalops.parse_options), 0, evalops, parsed_mstruct, &to_struct); } + + calculation_wait: bool has_printed = false; @@ -5224,6 +5229,28 @@ } if(has_printed) printf("\n"); } + + if(!avoid_recalculation && !do_mathoperation && to_struct.containsType(STRUCT_UNIT, true) && !mstruct->containsType(STRUCT_UNIT, false, true, true) && !parsed_mstruct->containsType(STRUCT_UNIT, false, true, true)) { + to_struct = CALCULATOR->convertToBaseUnits(to_struct); + fix_to_struct(to_struct); + if(!to_struct.isZero()) { + string from_str = str, to_str; + if(CALCULATOR->separateToExpression(from_str, to_str, evalops, true)) { + mstruct->multiply(to_struct); + to_struct.format(printops); + if(to_struct.isMultiplication() && to_struct.size() >= 2) { + if(to_struct[0].isOne()) to_struct.delChild(1, true); + else if(to_struct[1].isOne()) to_struct.delChild(2, true); + } + parsed_mstruct->multiply(to_struct); + to_struct.clear(); + CALCULATOR->calculate(mstruct, 0, evalops, CALCULATOR->unlocalizeExpression(to_str, evalops.parse_options)); + bool had_printed = has_printed; + goto calculation_wait; + if(had_printed) has_printed = true; + } + } + } b_busy = false; @@ -5234,7 +5261,7 @@ else mstruct->ref(); } - if(!do_mathoperation && check_exrates && check_exchange_rates()) { + if(!avoid_recalculation && !do_mathoperation && check_exrates && check_exchange_rates()) { execute_expression(goto_input, do_mathoperation, op, f, rpn_mode, do_stack ? stack_index : 0, false); return; } @@ -5524,7 +5551,7 @@ #endif - int version_numbers[] = {3, 6, 0}; + int version_numbers[] = {3, 7, 0}; if(file) { char line[10000]; @@ -5817,7 +5844,7 @@ fprintf(file, "use_unicode_signs=%i\n", printops.use_unicode_signs); fprintf(file, "lower_case_numbers=%i\n", printops.lower_case_numbers); fprintf(file, "lower_case_e=%i\n", printops.lower_case_e); - fprintf(file, "imaginary_j=%i\n", CALCULATOR->v_i->hasName("j") > 0); + fprintf(file, "imaginary_j=%i\n", CALCULATOR->getVariableById(VARIABLE_ID_I)->hasName("j") > 0); fprintf(file, "base_display=%i\n", printops.base_display); fprintf(file, "twos_complement=%i\n", printops.twos_complement); fprintf(file, "hexadecimal_twos_complement=%i\n", printops.hexadecimal_twos_complement); diff -Nru libqalculate-3.6.0/src/test.cc libqalculate-3.7.0/src/test.cc --- libqalculate-3.6.0/src/test.cc 2019-11-25 12:11:04.000000000 +0000 +++ libqalculate-3.7.0/src/test.cc 2020-01-21 22:54:40.000000000 +0000 @@ -1058,12 +1058,13 @@ if(!allow_function && !allow_unknown && !allow_variable && rand() % 2 == 0) str = rnd_number(true, only_integers, false, allow_complex, allow_interval); else str = rnd_var(); } else { +#define LAST_FUNC 31 if(!allow_unknown) { - if(allow_function) r = rand() % 19 + 4; + if(allow_function) r = rand() % (LAST_FUNC - 4) + 4; else r = rand() % 2 + 4; } else { int au2 = 3 - allow_unknown % 3; - r = (rand() % ((allow_function ? 22 + allow_unknown : 5) - au2)) + 4 - allow_unknown; + r = (rand() % ((allow_function ? LAST_FUNC - 1 + allow_unknown : 5) - au2)) + 4 - allow_unknown; if(r < 4 - allow_unknown % 3) { if(r < 0) r = -r; if(allow_unknown % 3 == 1) r = 3; @@ -1091,20 +1092,20 @@ str += ')'; return str; } - case 8: {str = "sin("; break;} - case 9: {str = "cos("; break;} - case 10: {str = "tan("; break;} - case 11: {str = "sinh("; break;} - case 12: {str = "cosh("; break;} - case 13: {str = "tanh("; break;} - case 14: {str = "asin("; break;} - case 15: {str = "acos("; break;} - case 16: {str = "atan("; break;} - case 17: {str = "asinh("; break;} - case 18: {str = "acosh("; break;} - case 19: {str = "atanh("; break;} - case 20: {str = "ln("; break;} - case 21: {str = "abs("; break;} + case 8: {str = "ln("; break;} + case 9: {str = "abs("; break;} + case 10: {str = "sin("; break;} + case 11: {str = "cos("; break;} + case 12: {str = "tan("; break;} + case 13: {str = "sinh("; break;} + case 14: {str = "cosh("; break;} + case 15: {str = "tanh("; break;} + case 16: {str = "asin("; break;} + case 17: {str = "acos("; break;} + case 18: {str = "atan("; break;} + case 19: {str = "asinh("; break;} + case 20: {str = "acosh("; break;} + case 21: {str = "atanh("; break;} case 22: {str = "sqrt("; break;} case 23: {str = "cbrt("; break;} case 24: {str = "erf("; break;} @@ -1114,8 +1115,8 @@ case 28: {str = "Ci("; break;} case 29: {str = "Chi("; break;} case 30: {str = "sinc("; break;} - case 31: {str = "lambertw("; break;} - case 32: {str = "li("; break;} + case 31: {str = "li("; break;} + case 32: {str = "lambertw("; break;} case 33: {str = "digamma("; break;} case 34: {str = "im("; break;} case 35: {str = "re("; break;} @@ -1834,15 +1835,15 @@ CALCULATOR->useIntervalArithmetic(); PrintOptions po = CALCULATOR->messagePrintOptions(); - po.interval_display = INTERVAL_DISPLAY_SIGNIFICANT_DIGITS; + /*po.interval_display = INTERVAL_DISPLAY_SIGNIFICANT_DIGITS; po.show_ending_zeroes = true; po.number_fraction_format = FRACTION_FRACTIONAL; - po.restrict_fraction_length = true; - /*po.interval_display = INTERVAL_DISPLAY_SIGNIFICANT_DIGITS; + po.restrict_fraction_length = true;*/ + po.interval_display = INTERVAL_DISPLAY_SIGNIFICANT_DIGITS; po.show_ending_zeroes = false; po.number_fraction_format = FRACTION_DECIMAL; po.restrict_fraction_length = true; - po.min_exp = 1;*/ + po.min_exp = 1; //po.max_decimals = 1; //po.use_max_decimals = true; CALCULATOR->setMessagePrintOptions(po); @@ -1866,6 +1867,12 @@ evalops.auto_post_conversion = POST_CONVERSION_OPTIMAL_SI; evalops.structuring = STRUCTURING_SIMPLIFY; evalops.approximation = APPROXIMATION_EXACT; + + /*MathStructure m; + for(size_t i = 0; i < 100000L; i++) { + CALCULATOR->parse(&m, "mm", evalops.parse_options); + } + return 0;*/ /*MathStructure mstruct = CALCULATOR->calculate("atanh(2x^2+5)*x^2", evalops); cout << mstruct.integrate(CALCULATOR->v_x, evalops) << endl; @@ -1955,12 +1962,12 @@ } return 0;*/ /*for(size_t i = 0; i < 50000;) { - str = rnd_expression(10, true, 6, 4, false, true, false, false, false, 5, false); + str = rnd_expression(10, true, 6, 4, false, false, false, false, false, 5, false); CALCULATOR->parse(&mp, str, evalops.parse_options); cerr << str << endl; if(mp.contains(CALCULATOR->v_x)) { - a.set(rnd_number(false, true, false, false, false)); - b.set(rnd_number(false, true, false, false, false)); + a.set(rnd_number(false, false, false, false, false)); + b.set(rnd_number(false, false, false, false, false)); cerr << "A" << endl; if(a < b) test_integration5(mp, a, b); else test_integration5(mp, b, a); @@ -1976,7 +1983,7 @@ //CALCULATOR->defaultAssumptions()->setType(ASSUMPTION_TYPE_NUMBER); //CALCULATOR->useIntervalArithmetic(); - for(size_t i = 0; i <= 5000; i++) { + for(size_t i = 0; i <= 15000; i++) { /*string str = rnd_expression(17, false, 20, 4, false, false, false, false, true); cout << str << endl; MathStructure mstruct; @@ -1985,7 +1992,7 @@ cout << mstruct.print() << endl; if(mstruct.isAborted()) break;*/ //if(mstruct.isPower() || (mstruct.isMultiplication() && !mstruct.containsType(STRUCT_DIVISION))) cout << str << "\n" << mstruct << endl; - rnd_test(evalops, 4, true, false, true, false, false, true); + rnd_test(evalops, 4, true, false, true, false, false, false); if(i % 1000 == 0) cout << endl << rt1 << ":" << rt2 << ":" << rt3 << ":" << rt4 << ":" << rt5 << ":" << rt6 << ":" << rt7 << ":" << rt8 << ":" << rt9 << endl << endl; } cout << endl << endl << "-----------------------------------------" << endl << endl << endl;